/*
 * Queue - A Queueing system that can be used to handle labs in higher education
 * Copyright (C) 2016-2024  Delft University of Technology
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package e2e;

import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import static e2e.script.AssignmentScripts.createAssignment;
import static e2e.script.EditionScripts.*;
import static e2e.script.ModuleEndToEnd.createModule;
import static e2e.script.RequestScripts.*;
import static e2e.script.SessionScripts.createRegularSession;
import static e2e.script.SessionScripts.enqueueForSession;
import static e2e.script.UserScripts.login;

import java.util.List;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;

import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.AriaRole;

import e2e.data.RequestInfo;

public class RegularLabRequestWorkflowTest extends AccessibilityEndToEndTest {

	record CreatedSession(String sessionName, long editionId, String moduleName, String assignmentName) {
	}

	@Test
	void requestWorkflow() {
		login(this, "cseteacher1");

		long editionId = createEdition(this, uniqueName("edition"));

		List<String> moduleNames = Stream.iterate(0, i -> i < 2, i -> i + 1).map(__ -> {
			String moduleName = uniqueName("module");
			createModule(this, editionId, moduleName);
			return moduleName;
		}).toList();

		List<String> assignmentNames = moduleNames.stream()
				.flatMap(moduleName -> Stream.iterate(0, i -> i < 2, i -> i + 1).map(__ -> {
					String assignmentName = uniqueName("assignment");
					createAssignment(this, editionId, moduleName, assignmentName);
					return assignmentName;
				})).toList();

		String sessionName = uniqueName("session");
		createRegularSession(this, editionId, sessionName, moduleNames, assignmentNames);

		assertThat(page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName(sessionName)))
				.isVisible();

		for (int i = 1; i <= 4; i++) {
			login(this, "csestudent" + (i + 4));

			enrolForEdition(this, editionId);
			String question = "I have a very important question about trees (" + i + ")";
			enqueueForSession(this, sessionName, assignmentNames.getFirst(), "Boole", question);

			assertThat(page().locator("#inputQuestion")).hasValue(question);
			assertThat(
					page().getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Revoke request")))
					.isVisible();

			assertThat(page().locator("#position")).hasText(Integer.toString(i));
		}

		login(this, "cseteacher1");

		addParticipantToEdition(this, editionId, "csestudent1", "TA");
		addParticipantToEdition(this, editionId, "csestudent2", "TA");

		login(this, "csestudent1");

		page.navigate(withPath("/requests"));

		RequestInfo requestInfo = getNextRequest(this, sessionName);
		assertThat(requestInfo.requester()).isEqualTo("CSE Student 5");
		// Get next returns current request
		assertThat(getNextRequest(this, sessionName).requester()).isEqualTo("CSE Student 5");

		approveRequest(this, requestInfo.id());
		assertThat(getRequestInfo(this, requestInfo.id()).status()).isEqualTo("Approved");

		requestInfo = getNextRequest(this, sessionName);
		assertThat(requestInfo.requester()).isEqualTo("CSE Student 6");
		rejectRequest(this, requestInfo.id(), "Question bad");
		assertThat(getRequestInfo(this, requestInfo.id()).status()).isEqualTo("Rejected");

		requestInfo = getNextRequest(this, sessionName);
		assertThat(requestInfo.requester()).isEqualTo("CSE Student 7");
		forwardRequest(this, requestInfo.id(), "CSE Student 2", "Don't know the answer");
		assertThat(getRequestInfo(this, requestInfo.id()).status()).isEqualTo("Forwarded");

		requestInfo = getNextRequest(this, sessionName);
		assertThat(requestInfo.requester()).isEqualTo("CSE Student 8");
		notFoundRequest(this, requestInfo.id());
		assertThat(getRequestInfo(this, requestInfo.id()).status()).isEqualTo("Not found");

	}

}
