import {
	assertContrast,
	checkContrast,
	getComputedColors,
	WCAG_CONTRAST,
} from "../../fixtures/accessibility";
import { SELECTORS } from "../../fixtures/selectors";
import { expect, test } from "../../fixtures/test";
import { THEMES, Theme } from "../../fixtures/themes";

test.describe("Color Contrast Across Themes", () => {
	test.beforeEach(async ({ gotoApp, waitForAppReady }) => {
		await gotoApp();
		await waitForAppReady();
	});

	for (const theme of THEMES) {
		test(`hero text has sufficient contrast in ${theme} theme @smoke`, async ({
			page,
			setTheme,
			waitForHero,
		}) => {
			// Set theme
			await setTheme(theme);

			const hero = await waitForHero();

			// Check headline contrast
			const headline = hero.locator(SELECTORS.hero.headline);
			await assertContrast(page, headline, WCAG_CONTRAST.largeText);

			// Check summary contrast
			const summary = hero.locator(SELECTORS.hero.summary);
			await assertContrast(page, summary, WCAG_CONTRAST.normalText);
		});

		test(`feed card text has sufficient contrast in ${theme} theme`, async ({
			page,
			setTheme,
			waitForFeed,
		}) => {
			// Set theme
			await setTheme(theme);

			const feed = await waitForFeed();
			const firstArticle = feed.locator(SELECTORS.feed.articles).first();

			// Check headline contrast
			const headline = firstArticle.locator("h3");
			await assertContrast(page, headline, WCAG_CONTRAST.largeText);

			// Check summary contrast
			const summary = firstArticle.locator(SELECTORS.feed.articleSummary);
			await assertContrast(page, summary, WCAG_CONTRAST.normalText);
		});

		test(`modal text has sufficient contrast in ${theme} theme`, async ({
			page,
			setTheme,
			waitForHero,
		}) => {
			// Set theme
			await setTheme(theme);

			// Open modal
			const hero = await waitForHero();
			await hero.locator(SELECTORS.hero.readButton).click();

			const modal = page.locator(SELECTORS.summaryModal.root);
			await expect(modal).toBeVisible();

			// Check headline contrast
			const headline = modal.locator(SELECTORS.summaryModal.headline);
			await assertContrast(page, headline, WCAG_CONTRAST.largeText);

			// Check body text contrast
			const bodyText = modal.locator(SELECTORS.summaryModal.summaryBody);
			await assertContrast(page, bodyText, WCAG_CONTRAST.normalText);

			// Check TL;DR list contrast
			const tldrList = modal.locator(SELECTORS.summaryModal.tldrList);
			await assertContrast(page, tldrList, WCAG_CONTRAST.normalText);
		});

		test(`link colors have sufficient contrast in ${theme} theme`, async ({
			page,
			setTheme,
			waitForFeed,
		}) => {
			// Set theme
			await setTheme(theme);

			const feed = await waitForFeed();
			const firstArticle = feed.locator(SELECTORS.feed.articles).first();

			// Check source link contrast
			const sourceLink = firstArticle.locator(SELECTORS.feed.articleSource);
			const hasSourceLink = (await sourceLink.count()) > 0;

			if (hasSourceLink) {
				await assertContrast(page, sourceLink, WCAG_CONTRAST.normalText);
			}
		});

		test(`button text has sufficient contrast in ${theme} theme`, async ({
			page,
			setTheme,
			waitForHero,
		}) => {
			// Set theme
			await setTheme(theme);

			const hero = await waitForHero();

			// Check read button contrast
			const readButton = hero.locator(SELECTORS.hero.readButton);
			await assertContrast(page, readButton, WCAG_CONTRAST.normalText);
		});
	}
});

test.describe("Interactive State Contrast", () => {
	test.beforeEach(async ({ gotoApp, waitForAppReady }) => {
		await gotoApp();
		await waitForAppReady();
	});

	test("hover state maintains sufficient contrast", async ({
		page,
		waitForFeed,
	}) => {
		const feed = await waitForFeed();
		const firstArticle = feed.locator(SELECTORS.feed.articles).first();
		const readButton = firstArticle.locator(SELECTORS.feed.articleReadButton);

		// Get normal state colors
		const normalColors = await getComputedColors(page, readButton);

		// Hover over button
		await readButton.hover();
		await page.waitForTimeout(300); // Wait for transition

		// Get hover state colors
		const hoverColors = await getComputedColors(page, readButton);

		// Both states should have sufficient contrast
		const normalRatio = checkContrast(
			normalColors.color,
			normalColors.backgroundColor,
		);
		const hoverRatio = checkContrast(
			hoverColors.color,
			hoverColors.backgroundColor,
		);

		expect(normalRatio).toBeGreaterThanOrEqual(WCAG_CONTRAST.normalText);
		expect(hoverRatio).toBeGreaterThanOrEqual(WCAG_CONTRAST.normalText);
	});

	test("focus state maintains sufficient contrast @smoke", async ({
		page,
		waitForFeed,
	}) => {
		const feed = await waitForFeed();
		const firstArticle = feed.locator(SELECTORS.feed.articles).first();
		const readButton = firstArticle.locator(SELECTORS.feed.articleReadButton);

		// Get normal state colors
		const normalColors = await getComputedColors(page, readButton);

		// Focus the button
		await readButton.focus();

		// Get focus state colors
		const focusColors = await getComputedColors(page, readButton);

		// Both states should have sufficient contrast
		const normalRatio = checkContrast(
			normalColors.color,
			normalColors.backgroundColor,
		);
		const focusRatio = checkContrast(
			focusColors.color,
			focusColors.backgroundColor,
		);

		expect(normalRatio).toBeGreaterThanOrEqual(WCAG_CONTRAST.normalText);
		expect(focusRatio).toBeGreaterThanOrEqual(WCAG_CONTRAST.normalText);
	});
});

test.describe("High Contrast Theme", () => {
	test.beforeEach(async ({ gotoApp, waitForAppReady }) => {
		await gotoApp();
		await waitForAppReady();
	});

	test("contrast theme provides enhanced visibility @smoke", async ({
		page,
		setTheme,
		waitForHero,
		waitForFeed,
	}) => {
		// Set high contrast theme
		await setTheme("contrast");

		// Check hero
		const hero = await waitForHero();
		const headline = hero.locator(SELECTORS.hero.headline);
		const headlineColors = await getComputedColors(page, headline);
		const headlineRatio = checkContrast(
			headlineColors.color,
			headlineColors.backgroundColor,
		);

		// High contrast should provide very strong contrast (7:1 or better)
		expect(headlineRatio).toBeGreaterThanOrEqual(7);

		// Check feed
		const feed = await waitForFeed();
		const firstArticle = feed.locator(SELECTORS.feed.articles).first();
		const articleHeadline = firstArticle.locator("h3");
		const articleColors = await getComputedColors(page, articleHeadline);
		const articleRatio = checkContrast(
			articleColors.color,
			articleColors.backgroundColor,
		);

		expect(articleRatio).toBeGreaterThanOrEqual(7);
	});
});
