import { test, expect } from '@playwright/test';
import { execSync } from 'child_process';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const baseUrl = process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:4173';
const urlMatch = baseUrl.match(/:(\d+)$/);
const PORT = urlMatch ? urlMatch[1] : '4173';
const ALPHA_URL = `http://ecole-alpha.classeo.local:${PORT}`;

const ADMIN_EMAIL = 'e2e-periods-admin@example.com';
const ADMIN_PASSWORD = 'PeriodsTest123';
const TENANT_ID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';

// Force serial execution — empty state must run first
test.describe.configure({ mode: 'serial' });

test.describe('Periods Management (Story 2.3)', () => {
	test.beforeAll(async () => {
		const projectRoot = join(__dirname, '../..');
		const composeFile = join(projectRoot, 'compose.yaml');

		execSync(
			`docker compose -f "${composeFile}" exec -T php php bin/console app:dev:create-test-user --tenant=ecole-alpha --email=${ADMIN_EMAIL} --password=${ADMIN_PASSWORD} --role=ROLE_ADMIN 2>&1`,
			{ encoding: 'utf-8' }
		);

		execSync(
			`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "DELETE FROM academic_periods WHERE tenant_id = '${TENANT_ID}'" 2>&1`,
			{ encoding: 'utf-8' }
		);
	});

	async function loginAsAdmin(page: import('@playwright/test').Page) {
		await page.goto(`${ALPHA_URL}/login`);
		await page.locator('#email').fill(ADMIN_EMAIL);
		await page.locator('#password').fill(ADMIN_PASSWORD);
		await Promise.all([
			page.waitForURL(/\/dashboard/, { timeout: 30000 }),
			page.getByRole('button', { name: /se connecter/i }).click()
		]);
	}

	// ============================================================================
	// Empty State
	// ============================================================================
	test.describe('Empty State', () => {
		test('shows empty state when no periods configured', async ({ page }) => {
			// Clean up right before test to avoid race conditions
			const projectRoot = join(__dirname, '../..');
			const composeFile = join(projectRoot, 'compose.yaml');
			try {
				execSync(
					`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "DELETE FROM academic_periods WHERE tenant_id = '${TENANT_ID}'" 2>&1`,
					{ encoding: 'utf-8' }
				);
			} catch {
				// Ignore cleanup errors
			}

			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			await expect(page.getByRole('heading', { name: /périodes scolaires/i })).toBeVisible();
			await expect(page.getByText(/aucune période configurée/i)).toBeVisible();
			await expect(
				page.getByRole('button', { name: /configurer les périodes/i })
			).toBeVisible();
		});
	});

	// ============================================================================
	// Year Selector Tabs
	// ============================================================================
	test.describe('Year Selector', () => {
		test('displays three year tabs', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			const tabs = page.getByRole('tab');
			await expect(tabs).toHaveCount(3);
		});

		test('current year tab is active by default', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			const tabs = page.getByRole('tab');
			// Middle tab (current) should be active
			await expect(tabs.nth(1)).toHaveAttribute('aria-selected', 'true');
		});

		test('can switch between year tabs', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			const tabs = page.getByRole('tab');

			// Wait for Svelte hydration and initial load to complete
			await expect(tabs.nth(1)).toHaveAttribute('aria-selected', 'true', { timeout: 10000 });
			await page.waitForLoadState('networkidle');

			// Click next year tab
			await tabs.nth(2).click();
			await expect(tabs.nth(2)).toHaveAttribute('aria-selected', 'true', { timeout: 10000 });

			// Wait for load triggered by tab switch
			await page.waitForLoadState('networkidle');

			// Click previous year tab
			await tabs.nth(0).click();
			await expect(tabs.nth(0)).toHaveAttribute('aria-selected', 'true', { timeout: 10000 });
		});
	});

	// ============================================================================
	// Period Configuration
	// ============================================================================
	test.describe('Period Configuration', () => {
		test('can configure trimesters', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			// Click "Configurer les périodes" button
			await page.getByRole('button', { name: /configurer les périodes/i }).click();

			// Modal should open
			const dialog = page.getByRole('dialog');
			await expect(dialog).toBeVisible({ timeout: 5000 });

			// Select trimester (should be default)
			await expect(dialog.locator('#period-type')).toHaveValue('trimester');

			// Verify preview shows 3 trimesters
			await expect(dialog.getByText(/T1/)).toBeVisible();
			await expect(dialog.getByText(/T2/)).toBeVisible();
			await expect(dialog.getByText(/T3/)).toBeVisible();

			// Submit
			await dialog.getByRole('button', { name: /configurer$/i }).click();

			// Modal should close
			await expect(dialog).not.toBeVisible({ timeout: 10000 });

			// Period cards should appear
			await expect(page.getByRole('heading', { name: 'T1' })).toBeVisible({ timeout: 10000 });
			await expect(page.getByRole('heading', { name: 'T2' })).toBeVisible();
			await expect(page.getByRole('heading', { name: 'T3' })).toBeVisible();
		});

		test('shows trimester badge after configuration', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			await expect(page.getByText('Trimestres', { exact: true })).toBeVisible({ timeout: 10000 });
		});

		test('shows dates on each period card', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			// Wait for periods to load
			await expect(page.getByRole('heading', { name: 'T1' })).toBeVisible({ timeout: 10000 });

			// Each period card should have start and end dates
			const periodCards = page.locator('.period-card');
			const count = await periodCards.count();
			expect(count).toBe(3);

			// Verify date labels exist
			await expect(page.getByText(/début/i).first()).toBeVisible();
			await expect(page.getByText(/fin/i).first()).toBeVisible();
		});

		test('configure button no longer visible when periods exist', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			// Wait for periods to load
			await expect(page.getByRole('heading', { name: 'T1' })).toBeVisible({ timeout: 10000 });

			// Configure button should not be visible
			await expect(
				page.getByRole('button', { name: /configurer les périodes/i })
			).not.toBeVisible();
		});

		test('can configure semesters on next year', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			// Wait for initial load to complete before switching tab
			const tabs = page.getByRole('tab');
			await expect(tabs.nth(1)).toHaveAttribute('aria-selected', 'true', { timeout: 10000 });
			await page.waitForLoadState('networkidle');

			// Switch to next year tab
			await tabs.nth(2).click();

			// Should show empty state for next year
			await expect(page.getByText(/aucune période configurée/i)).toBeVisible({
				timeout: 10000
			});

			// Configure semesters for next year
			await page.getByRole('button', { name: /configurer les périodes/i }).click();

			const dialog = page.getByRole('dialog');
			await expect(dialog).toBeVisible({ timeout: 5000 });

			// Select semester
			await dialog.locator('#period-type').selectOption('semester');

			// Verify preview shows 2 semesters
			await expect(dialog.getByText(/S1/)).toBeVisible();
			await expect(dialog.getByText(/S2/)).toBeVisible();

			// Submit
			await dialog.getByRole('button', { name: /configurer$/i }).click();

			// Modal should close and period cards appear
			await expect(dialog).not.toBeVisible({ timeout: 10000 });
			await expect(page.getByRole('heading', { name: 'S1' })).toBeVisible({ timeout: 10000 });
			await expect(page.getByRole('heading', { name: 'S2' })).toBeVisible();
		});
	});

	// ============================================================================
	// Period Date Modification
	// ============================================================================
	test.describe('Period Date Modification', () => {
		test('each period card has a modify button', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			await expect(page.getByRole('heading', { name: 'T1' })).toBeVisible({ timeout: 10000 });

			const modifyButtons = page.getByRole('button', { name: /modifier les dates/i });
			await expect(modifyButtons).toHaveCount(3);
		});

		test('opens edit modal when clicking modify', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			await expect(page.getByRole('heading', { name: 'T1' })).toBeVisible({ timeout: 10000 });

			// Click modify on first period
			const modifyButtons = page.getByRole('button', { name: /modifier les dates/i });
			await modifyButtons.first().click();

			// Edit modal should open
			const dialog = page.getByRole('dialog');
			await expect(dialog).toBeVisible({ timeout: 5000 });
			await expect(dialog.getByText(/modifier T1/i)).toBeVisible();

			// Date fields should be present
			await expect(dialog.locator('#edit-start-date')).toBeVisible();
			await expect(dialog.locator('#edit-end-date')).toBeVisible();
		});

		test('can cancel date modification', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			await expect(page.getByRole('heading', { name: 'T1' })).toBeVisible({ timeout: 10000 });

			const modifyButtons = page.getByRole('button', { name: /modifier les dates/i });
			await modifyButtons.first().click();

			const dialog = page.getByRole('dialog');
			await expect(dialog).toBeVisible({ timeout: 5000 });

			// Cancel
			await dialog.getByRole('button', { name: /annuler/i }).click();
			await expect(dialog).not.toBeVisible({ timeout: 5000 });
		});
	});

	// ============================================================================
	// Navigation
	// ============================================================================
	test.describe('Navigation', () => {
		test('can access periods page from admin dashboard', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin`);

			// Click on periods card
			await page.getByRole('link', { name: /périodes scolaires/i }).click();

			await expect(page).toHaveURL(/\/admin\/academic-year\/periods/);
			await expect(page.getByRole('heading', { name: /périodes scolaires/i })).toBeVisible();
		});

		test('can access periods page directly', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/academic-year/periods`);

			await expect(page).toHaveURL(/\/admin\/academic-year\/periods/);
			await expect(page.getByRole('heading', { name: /périodes scolaires/i })).toBeVisible();
		});
	});
});
