import { NZAP_TEST_ID } from "~/db/seed/constants";
import { ADMIN_ID } from "~/features/admin/admin-constants";
import {
	SENDOUQ_LOOKING_PAGE,
	SENDOUQ_PAGE,
	SENDOUQ_PREPARING_PAGE,
	sendouQInviteLink,
} from "~/utils/urls";
import {
	expect,
	impersonate,
	navigate,
	seed,
	submit,
	test,
} from "./helpers/playwright";

test.describe("SendouQ", () => {
	test("Group preparation flow - add friends and users via invite link", async ({
		page,
	}) => {
		await seed(page, "NO_SQ_GROUPS");
		await impersonate(page, ADMIN_ID);

		// Create preparing group
		await navigate({ page, url: SENDOUQ_PAGE });
		await page.getByRole("button", { name: "Join with mates" }).click();

		// Verify group card visible with 1 member
		const groupCard = page.getByTestId("sendouq-group-card").first();
		await expect(
			groupCard.getByTestId("sendouq-group-card-member"),
		).toHaveCount(1);

		// -----------------

		// Verify prepared groups not visible on looking page
		// Impersonate a different user
		await impersonate(page, 3);
		await navigate({ page, url: SENDOUQ_PAGE });
		await submit(page, "join-solo-button");

		await expect(page.getByTestId("sendouq-group-card")).toBeVisible();
		// Verify ADMIN's preparing group is NOT visible
		// Only ACTIVE groups should be shown
		const sendouGroupCard = page
			.getByTestId("sendouq-group-card")
			.filter({ hasText: "Sendou" });
		await expect(sendouGroupCard).not.toBeVisible();

		// -----------------

		// Add friend
		await impersonate(page, ADMIN_ID);
		await navigate({ page, url: SENDOUQ_PREPARING_PAGE });
		const friendUserSelect = page.locator('select[name="id"]');
		await friendUserSelect.selectOption({ index: 1 }); // Select first friend

		// Find the add button with ADD_FRIEND action and wait for it to be enabled
		const addMemberButton = page.locator(
			'button[type="submit"][value="ADD_FRIEND"]',
		);
		await expect(addMemberButton).toBeEnabled();
		await addMemberButton.click();

		// Wait for 2 members to appear
		await expect(
			groupCard.getByTestId("sendouq-group-card-member"),
		).toHaveCount(2);

		// Extract invite code
		const inviteCodeInput = page.locator('input[id="invite"]');
		const inviteLink = await inviteCodeInput.inputValue();
		const inviteCode = inviteLink.split("?join=")[1];
		expect(inviteCode).toBeTruthy();

		// Join as NZAP user via invite link
		await impersonate(page, NZAP_TEST_ID);
		await navigate({ page, url: sendouQInviteLink(inviteCode) });

		// Verify join form appears and submit
		await expect(page.getByRole("dialog")).toBeVisible();
		await page.getByRole("button", { name: "Join", exact: true }).click();

		// Verify redirected to preparing page and NZAP added to group (3 members total)
		await expect(page).toHaveURL(SENDOUQ_PREPARING_PAGE);
		const prepGroupCard = page.getByTestId("sendouq-group-card").first();
		await expect(
			prepGroupCard.getByTestId("sendouq-group-card-member"),
		).toHaveCount(3);

		await page.getByRole("button", { name: "Join the queue" }).click();
		await expect(page).toHaveURL(SENDOUQ_LOOKING_PAGE);
	});

	test("Request flow - partial groups morph together", async ({ page }) => {
		await seed(page, "NO_SQ_GROUPS");

		// ADMIN creates a solo group
		await impersonate(page, ADMIN_ID);
		await navigate({ page, url: SENDOUQ_PAGE });
		await submit(page, "join-solo-button");

		// User 3 creates a solo group
		await impersonate(page, 3);
		await navigate({ page, url: SENDOUQ_PAGE });
		await submit(page, "join-solo-button");

		// Send request as ADMIN
		await impersonate(page, ADMIN_ID);
		await navigate({ page, url: SENDOUQ_LOOKING_PAGE });

		// Find user 3's group
		const groupCards = page.getByTestId("sendouq-group-card");
		const user3GroupCard = groupCards.nth(1); // Skip own group (index 0)
		await expect(user3GroupCard).toBeVisible();

		// Send request
		await submit(page, "group-card-action-button");

		// Accept request as user 3
		await impersonate(page, 3);
		await navigate({ page, url: SENDOUQ_LOOKING_PAGE });

		// Find ADMIN's group in the invitations
		const adminInviteCard = page
			.getByTestId("sendouq-group-card")
			.filter({ hasText: "Sendou" });
		await expect(adminInviteCard).toBeVisible();

		// Accept and merge
		await submit(page, "group-card-action-button");

		// Verify still on looking page (not redirected to match)
		await expect(page).toHaveURL(SENDOUQ_LOOKING_PAGE);

		// Verify combined group has 2 members
		const combinedGroup = page.getByTestId("sendouq-group-card").first();
		await expect(
			combinedGroup.getByTestId("sendouq-group-card-member"),
		).toHaveCount(2);
	});
});
