import { SELECTORS } from "../../fixtures/selectors";
import { expect, test } from "../../fixtures/test";
import {
	hasHorizontalOverflow,
	isClipped,
	VIEWPORT_SIZES,
	type ViewportSize,
} from "../../fixtures/viewports";

test.describe("Responsive Breakpoint Tests @smoke", () => {
	for (const viewport of VIEWPORT_SIZES) {
		test.describe(`${viewport} viewport`, () => {
			test.beforeEach(async ({ gotoApp, waitForAppReady, setViewport }) => {
				await setViewport(viewport);
				await gotoApp();
				await waitForAppReady();
			});

			test("page has no horizontal overflow", async ({ page }) => {
				// Check body for overflow
				const bodyOverflow = await hasHorizontalOverflow(page, "body");
				expect(bodyOverflow).toBe(false);

				// Check main content
				const mainOverflow = await hasHorizontalOverflow(page, "main");
				expect(mainOverflow).toBe(false);

				// Check hero section
				const heroOverflow = await hasHorizontalOverflow(
					page,
					SELECTORS.hero.root,
				);
				expect(heroOverflow).toBe(false);

				// Check feed section
				const feedOverflow = await hasHorizontalOverflow(
					page,
					SELECTORS.feed.root,
				);
				expect(feedOverflow).toBe(false);
			});

			test("hero section is not clipped", async ({ page, waitForHero }) => {
				const hero = await waitForHero();
				const isHeroClipped = await isClipped(page, SELECTORS.hero.root);
				expect(isHeroClipped).toBe(false);
			});

			test("feed articles are not clipped", async ({ page, waitForFeed }) => {
				const feed = await waitForFeed();
				const isFeedClipped = await isClipped(page, SELECTORS.feed.root);
				expect(isFeedClipped).toBe(false);
			});

			test("modal fits within viewport", async ({
				page,
				waitForHero,
				setViewport,
			}) => {
				// Open modal
				const hero = await waitForHero();
				await hero.locator(SELECTORS.hero.readButton).click();

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

				// Get viewport dimensions
				const viewport = await page.evaluate(() => ({
					width: window.innerWidth,
					height: window.innerHeight,
				}));

				// Get modal dimensions
				const modalBox = await modal.boundingBox();
				expect(modalBox).not.toBeNull();

				// Modal should fit within viewport (with some padding)
				expect(modalBox!.width).toBeLessThanOrEqual(viewport.width);
				expect(modalBox!.height).toBeLessThanOrEqual(viewport.height * 0.96); // max-h-[96vh]
			});

			test("interactive controls are reachable", async ({
				page,
				waitForFeed,
			}) => {
				const feed = await waitForFeed();
				const firstArticle = feed.locator(SELECTORS.feed.articles).first();

				// Check read button is visible and clickable
				const readButton = firstArticle.locator(
					SELECTORS.feed.articleReadButton,
				);
				await expect(readButton).toBeVisible();
				await expect(readButton).toBeEnabled();

				// Check source link is visible if present
				const sourceLink = firstArticle.locator(SELECTORS.feed.articleSource);
				const hasSourceLink = (await sourceLink.count()) > 0;
				if (hasSourceLink) {
					await expect(sourceLink).toBeVisible();
				}
			});

			test("header controls remain accessible", async ({ page }) => {
				// Check logo is visible
				const logo = page.locator(SELECTORS.header.logo);
				await expect(logo).toBeVisible();

				// Check theme button is visible
				const themeButton = page.locator(SELECTORS.header.themeMenuButton);
				await expect(themeButton).toBeVisible();
				await expect(themeButton).toBeEnabled();

				// Check language select is visible (may be hidden on very small screens)
				const languageSelect = page.locator(SELECTORS.header.languageSelect);
				const isVisible = await languageSelect.isVisible().catch(() => false);

				if (isVisible) {
					await expect(languageSelect).toBeEnabled();
				}
			});
		});
	}
});

test.describe("Responsive Layout Adaptations", () => {
	test("mobile shows single column feed", async ({
		gotoApp,
		waitForAppReady,
		setViewport,
		waitForFeed,
	}) => {
		await setViewport("mobile");
		await gotoApp();
		await waitForAppReady();

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

		// Articles should be in single column (full width)
		const firstArticle = articles.first();
		const articleBox = await firstArticle.boundingBox();

		// Get feed container width
		const feedBox = await feed.boundingBox();

		// Article should take most of the width (single column)
		expect(articleBox!.width).toBeGreaterThan(feedBox!.width * 0.8);
	});

	test("tablet shows appropriate layout", async ({
		gotoApp,
		waitForAppReady,
		setViewport,
		waitForFeed,
	}) => {
		await setViewport("tablet");
		await gotoApp();
		await waitForAppReady();

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

		// Should have multiple articles visible
		const count = await articles.count();
		expect(count).toBeGreaterThanOrEqual(2);

		// Articles should be side by side (multi-column)
		const firstArticle = articles.first();
		const secondArticle = articles.nth(1);

		const firstBox = await firstArticle.boundingBox();
		const secondBox = await secondArticle.boundingBox();

		// Second article should be to the right of first (or below in some layouts)
		expect(secondBox!.x).not.toBe(firstBox!.x);
	});

	test("desktop shows multi-column feed", async ({
		gotoApp,
		waitForAppReady,
		setViewport,
		waitForFeed,
	}) => {
		await setViewport("desktop");
		await gotoApp();
		await waitForAppReady();

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

		// Should have multiple articles in a row
		const count = await articles.count();
		expect(count).toBeGreaterThanOrEqual(3);

		// First three articles should be in a row
		const articleBoxes = await articles
			.slice(0, 3)
			.evaluateAll((els) => els.map((el) => el.getBoundingClientRect()));

		// Articles should be at different x positions (side by side)
		const xPositions = articleBoxes.map((box) => box.x);
		const uniqueXPositions = [...new Set(xPositions)];
		expect(uniqueXPositions.length).toBeGreaterThanOrEqual(2);
	});

	test("hero image maintains aspect ratio", async ({
		gotoApp,
		waitForAppReady,
		setViewport,
		waitForHero,
	}) => {
		for (const viewport of ["mobile", "tablet", "desktop"] as ViewportSize[]) {
			await setViewport(viewport);
			await gotoApp();
			await waitForAppReady();

			const hero = await waitForHero();
			const image = hero.locator(SELECTORS.hero.image);

			const box = await image.boundingBox();
			expect(box).not.toBeNull();

			// Image should have reasonable dimensions
			expect(box!.width).toBeGreaterThan(0);
			expect(box!.height).toBeGreaterThan(0);

			// Aspect ratio should be roughly maintained (wider than tall)
			expect(box!.width / box!.height).toBeGreaterThan(1);
			expect(box!.width / box!.height).toBeLessThan(5);
		}
	});
});
