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-homework-rules-admin@example.com';
const ADMIN_PASSWORD = 'HomeworkRulesAdmin123';
const TENANT_ID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';

test.describe('Homework Rules Configuration', () => {
	// Serial: les tests d'historique dépendent des entrées créées par les tests précédents
	test.describe.configure({ mode: 'serial' });

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

		// Clear rate limiter to prevent login throttling across serial tests
		try {
			execSync(
				`docker compose -f "${composeFile}" exec -T php php bin/console cache:pool:clear cache.rate_limiter --env=dev 2>&1`,
				{ encoding: 'utf-8' }
			);
		} catch {
			// Cache pool may not exist
		}

		// Create admin user
		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' }
		);

		// Clean up homework rules from previous test runs
		execSync(
			`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "DELETE FROM homework_rules_history WHERE tenant_id = '${TENANT_ID}'" 2>&1`,
			{ encoding: 'utf-8' }
		);
		execSync(
			`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "DELETE FROM homework_rules WHERE tenant_id = '${TENANT_ID}'" 2>&1`,
			{ encoding: 'utf-8' }
		);

		try {
			execSync(
				`docker compose -f "${composeFile}" exec -T php php bin/console cache:pool:clear paginated_queries.cache 2>&1`,
				{ encoding: 'utf-8' }
			);
		} catch {
			// Cache pool may not exist
		}
	});

	test.beforeEach(async () => {
		const projectRoot = join(__dirname, '../..');
		const composeFile = join(projectRoot, 'compose.yaml');
		try {
			execSync(
				`docker compose -f "${composeFile}" exec -T php php bin/console cache:pool:clear cache.rate_limiter --env=dev 2>&1`,
				{ encoding: 'utf-8' }
			);
		} catch {
			// Cache pool may not exist
		}
	});

	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: 60000 }),
			page.getByRole('button', { name: /se connecter/i }).click()
		]);
	}

	async function waitForPageLoaded(page: import('@playwright/test').Page) {
		await expect(
			page.getByRole('heading', { name: /règles de devoirs/i })
		).toBeVisible({ timeout: 15000 });

		await expect(
			page.locator('.card').first()
		).toBeVisible({ timeout: 15000 });
	}

	// AC1: Page configuration pédagogique → section "Règles de devoirs" accessible
	test('page affiche la configuration des règles de devoirs', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/homework-rules`);
		await waitForPageLoaded(page);

		await expect(
			page.getByRole('heading', { name: /règles de devoirs/i })
		).toBeVisible();

		// Mode selector visible
		await expect(page.getByRole('radio', { name: /avertissement/i })).toBeVisible();
		await expect(page.getByRole('radio', { name: /blocage/i })).toBeVisible();
		await expect(page.getByRole('radio', { name: /désactivé/i })).toBeVisible();
	});

	// AC5: Mode par défaut = "Soft"
	test('mode par défaut est Avertissement (soft)', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/homework-rules`);
		await waitForPageLoaded(page);

		const softRadio = page.getByRole('radio', { name: /avertissement/i });
		await expect(softRadio).toHaveAttribute('aria-checked', 'true');
	});

	// AC2: Règle définissable : délai minimum
	test('configurer la règle de délai minimum', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/homework-rules`);
		await waitForPageLoaded(page);

		// Enable minimum delay rule
		const delayCheckbox = page.getByRole('checkbox', { name: /délai minimum/i });
		await delayCheckbox.check();

		// Set 3 days
		const daysInput = page.locator('input[type="number"]');
		await daysInput.fill('3');

		// Save
		await page.getByRole('button', { name: /enregistrer/i }).click();

		// Success message
		await expect(page.getByText(/mises à jour avec succès/i)).toBeVisible({ timeout: 10000 });
	});

	// AC2: Règle définissable : jours concernés (pas de devoir pour lundi)
	test('configurer la règle pas de devoir pour lundi', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/homework-rules`);
		await waitForPageLoaded(page);

		// Enable no-monday rule
		const mondayCheckbox = page.getByRole('checkbox', { name: /pas de devoir pour lundi/i });
		await mondayCheckbox.check();

		// Save
		await page.getByRole('button', { name: /enregistrer/i }).click();

		await expect(page.getByText(/mises à jour avec succès/i)).toBeVisible({ timeout: 10000 });
	});

	// AC5: Choix mode Hard (blocage)
	test('changer le mode en Blocage', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/homework-rules`);
		await waitForPageLoaded(page);

		// Select hard mode
		await page.getByRole('radio', { name: /blocage/i }).click();

		// Save
		await page.getByRole('button', { name: /enregistrer/i }).click();

		await expect(page.getByText(/mises à jour avec succès/i)).toBeVisible({ timeout: 10000 });
	});

	// AC7: Règles désactivables complètement
	test('désactiver les règles complètement', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/homework-rules`);
		await waitForPageLoaded(page);

		// Select disabled mode
		await page.getByRole('radio', { name: /désactivé/i }).click();

		// Rules section should disappear
		await expect(page.getByText(/les enseignants peuvent créer des devoirs librement/i)).toBeVisible();

		// Save
		await page.getByRole('button', { name: /enregistrer/i }).click();

		await expect(page.getByText(/mises à jour avec succès/i)).toBeVisible({ timeout: 10000 });
	});

	// AC6: Historique des changements conservé
	test('voir l\'historique des changements avec contenu', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/homework-rules`);
		await waitForPageLoaded(page);

		// Click history button
		await page.getByRole('button', { name: /voir l'historique/i }).click();

		// Modal should appear
		const dialog = page.getByRole('dialog', { name: /historique des changements/i });
		await expect(dialog).toBeVisible({ timeout: 10000 });

		// Verify history is not empty (previous tests created entries)
		await expect(dialog.getByText(/aucun changement/i)).not.toBeVisible();

		// Verify at least one history entry with mode and date
		const firstEntry = dialog.locator('.history-entry').first();
		await expect(firstEntry).toBeVisible();
		await expect(firstEntry.locator('.history-mode')).toBeVisible();
		await expect(firstEntry.locator('.history-date')).toBeVisible();
	});
});
