/**
 * T-series: Dark mode (Fase 9.1).
 *
 *   T-01 picking "Dark" on /settings persists across a hard reload.
 *   T-02 "System" follows the emulated prefers-color-scheme.
 *   T-03 a refresh in dark mode never renders a light first frame
 *        (anti-FOUC inline script in app.html). We also check /logged-out
 *        which lives outside the (app) group and would otherwise miss
 *        any layout-level theme hydration.
 */
import { test, expect } from '@playwright/test';
import { USERS } from '../fixtures/users.js';
import { loginAs } from '../fixtures/login.js';

test.describe('Theme — three modes, persistence, anti-FOUC', () => {
	test('T-01: picking Dark on /settings persists across reload', async ({ page }) => {
		await loginAs(page, USERS.ana);
		await page.goto('/settings');

		// Reset to a known starting state.
		await page.evaluate(() => localStorage.removeItem('theme'));

		const darkButton = page
			.getByRole('radiogroup', { name: /appearance|apariencia/i })
			.getByRole('radio', { name: /dark|oscuro/i });
		await expect(darkButton).toBeVisible({ timeout: 10_000 });
		await darkButton.click();

		// Immediate effect: <html data-theme="dark">.
		await expect.poll(() => page.evaluate(() => document.documentElement.dataset.theme)).toBe(
			'dark'
		);
		await expect.poll(() => page.evaluate(() => localStorage.getItem('theme'))).toBe('dark');

		// Hard reload → still dark, no flash to light.
		await page.reload();
		await expect.poll(() => page.evaluate(() => document.documentElement.dataset.theme)).toBe(
			'dark'
		);
		// Sanity: the toggle still reflects the choice.
		await expect(
			page
				.getByRole('radiogroup', { name: /appearance|apariencia/i })
				.getByRole('radio', { name: /dark|oscuro/i, checked: true })
		).toBeVisible({ timeout: 10_000 });
	});

	test('T-02: "System" follows the emulated prefers-color-scheme', async ({ browser }) => {
		// Two contexts — one emulates dark OS, the other light. Both pick
		// "System" and we assert each resolves to the matching theme.
		const darkCtx = await browser.newContext({ colorScheme: 'dark' });
		const darkPage = await darkCtx.newPage();
		await loginAs(darkPage, USERS.ana);
		await darkPage.goto('/settings');
		await darkPage.evaluate(() => localStorage.removeItem('theme'));
		await darkPage
			.getByRole('radiogroup', { name: /appearance|apariencia/i })
			.getByRole('radio', { name: /system|sistema/i })
			.click();
		await expect
			.poll(() => darkPage.evaluate(() => document.documentElement.dataset.theme))
			.toBe('dark');
		await darkCtx.close();

		const lightCtx = await browser.newContext({ colorScheme: 'light' });
		const lightPage = await lightCtx.newPage();
		await loginAs(lightPage, USERS.borja);
		await lightPage.goto('/settings');
		await lightPage.evaluate(() => localStorage.removeItem('theme'));
		await lightPage
			.getByRole('radiogroup', { name: /appearance|apariencia/i })
			.getByRole('radio', { name: /system|sistema/i })
			.click();
		await expect
			.poll(() => lightPage.evaluate(() => document.documentElement.dataset.theme))
			.toBe('light');
		await lightCtx.close();
	});

	test('T-03: refresh in dark mode never paints a light first frame (anti-FOUC)', async ({
		browser
	}) => {
		const ctx = await browser.newContext();
		const page = await ctx.newPage();
		await loginAs(page, USERS.ana);

		// Lock the preference into localStorage so the inline app.html script
		// has to do the work on the next navigation.
		await page.evaluate(() => localStorage.setItem('theme', 'dark'));

		// Hard reload of /settings (an authed page).
		await page.goto('/settings');
		const themeAttr = await page.evaluate(() =>
			document.documentElement.getAttribute('data-theme')
		);
		expect(themeAttr).toBe('dark');

		// /logged-out lives outside the (app) group — no layout hydration
		// helps it. The inline script in app.html must still kick in.
		await page.goto('/logged-out');
		const themeAttrLoggedOut = await page.evaluate(() =>
			document.documentElement.getAttribute('data-theme')
		);
		expect(themeAttrLoggedOut).toBe('dark');

		// Also assert there is no visible light flash by reading the actual
		// computed background colour. The dark token resolves to rgb(2, 6, 23).
		const bg = await page.evaluate(() => getComputedStyle(document.body).backgroundColor);
		expect(bg.replace(/\s/g, '')).toBe('rgb(2,6,23)');

		await ctx.close();
	});
});
