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-pedagogy-admin@example.com';
const ADMIN_PASSWORD = 'PedagogyTest123';

test.describe('Pedagogy - Grading Mode Configuration (Story 2.4)', () => {
	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' }
		);

		// Reset grading mode to default (numeric_20) to ensure clean state
		try {
			execSync(
				`docker compose -f "${composeFile}" exec -T php php -r "
					require 'vendor/autoload.php';
					\\$kernel = new App\\Kernel('dev', true);
					\\$kernel->boot();
					\\$conn = \\$kernel->getContainer()->get('doctrine')->getConnection();
					\\$conn->executeStatement('DELETE FROM school_grading_configurations');
				" 2>&1`,
				{ encoding: 'utf-8' }
			);
		} catch {
			// Table might not exist yet, that's OK — default mode applies
		}
	});

	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()
		]);
	}

	// =========================================================================
	// Navigation
	// =========================================================================

	test('pedagogy link is visible in admin navigation', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/classes`);

		const pedagogyLink = page.getByRole('link', { name: /pédagogie/i });
		await expect(pedagogyLink).toBeVisible();
	});

	test('pedagogy link navigates to pedagogy page', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/classes`);

		await page.getByRole('link', { name: /pédagogie/i }).click();
		await expect(page).toHaveURL(/\/admin\/pedagogy/, { timeout: 10000 });
	});

	test('pedagogy card is visible on admin dashboard', async ({ page }) => {
		await loginAsAdmin(page);

		// Authenticated admin sees admin dashboard directly via role context
		await page.goto(`${ALPHA_URL}/dashboard`);

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

		const pedagogyCard = page.getByRole('link', { name: /pédagogie/i });
		await expect(pedagogyCard).toBeVisible();
	});

	// =========================================================================
	// AC1: Display grading mode options
	// =========================================================================

	test('shows page title and subtitle', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await expect(page.getByRole('heading', { name: /mode de notation/i })).toBeVisible();
		await expect(page.getByText(/système d'évaluation/i)).toBeVisible();
	});

	test('shows current mode banner', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		// Wait for loading to finish
		await page.waitForLoadState('networkidle');

		// Should show "Mode actuel" banner
		await expect(page.getByText(/mode actuel/i)).toBeVisible({ timeout: 10000 });
	});

	test('displays all five grading modes', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await page.waitForLoadState('networkidle');

		// All 5 mode cards should be visible (scope to .mode-card to avoid ambiguous matches)
		const modeCards = page.locator('.mode-card');
		await expect(modeCards).toHaveCount(5, { timeout: 10000 });
		await expect(modeCards.filter({ hasText: /notes \/20/i })).toBeVisible();
		await expect(modeCards.filter({ hasText: /notes \/10/i })).toBeVisible();
		await expect(modeCards.filter({ hasText: /lettres/i })).toBeVisible();
		await expect(modeCards.filter({ hasText: /compétences/i })).toBeVisible();
		await expect(modeCards.filter({ hasText: /sans notes/i })).toBeVisible();
	});

	test('default mode is Notes sur 20', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await page.waitForLoadState('networkidle');

		// The "Notes /20" mode card should be selected (has mode-selected class)
		const selectedCard = page.locator('.mode-card.mode-selected');
		await expect(selectedCard).toBeVisible({ timeout: 10000 });
		await expect(selectedCard).toContainText(/notes \/20/i);
	});

	// =========================================================================
	// AC1: Year selector
	// =========================================================================

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

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

		// Wait for page to load
		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 });

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

	// =========================================================================
	// AC2-4: Mode selection and preview
	// =========================================================================

	test('selecting a different mode shows save button', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await page.waitForLoadState('networkidle');

		// Save button should not be visible initially
		await expect(page.getByRole('button', { name: /enregistrer/i })).not.toBeVisible();

		// Click a different mode
		const competenciesCard = page.locator('.mode-card').filter({ hasText: /compétences/i });
		await competenciesCard.click();

		// Save and cancel buttons should appear
		await expect(page.getByRole('button', { name: /enregistrer/i })).toBeVisible();
		await expect(page.getByRole('button', { name: /annuler/i })).toBeVisible();
	});

	test('cancel button reverts mode selection', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await page.waitForLoadState('networkidle');

		// Select a different mode
		const lettersCard = page.locator('.mode-card').filter({ hasText: /lettres/i });
		await lettersCard.click();

		// Click cancel
		await page.getByRole('button', { name: /annuler/i }).click();

		// Save button should disappear
		await expect(page.getByRole('button', { name: /enregistrer/i })).not.toBeVisible();
	});

	test('selecting competencies mode shows competency-specific description', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await page.waitForLoadState('networkidle');
		await expect(page.getByText(/mode actuel/i)).toBeVisible({ timeout: 10000 });

		const competenciesCard = page.locator('.mode-card').filter({ hasText: /compétences/i });
		await competenciesCard.click();

		// Check description inside the card (scoped to avoid matching bulletin impact text)
		await expect(competenciesCard.locator('.mode-description')).toContainText(
			/acquis.*en cours.*non acquis/i
		);
	});

	test('selecting sans notes mode shows no-grades description', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await page.waitForLoadState('networkidle');
		await expect(page.getByText(/mode actuel/i)).toBeVisible({ timeout: 10000 });

		const noGradesCard = page.locator('.mode-card').filter({ hasText: /sans notes/i });
		await noGradesCard.click();

		// Check description inside the card (scoped to avoid matching bulletin impact text)
		await expect(noGradesCard.locator('.mode-description')).toContainText(
			/appréciations textuelles/i
		);
	});

	test('shows bulletin impact preview when mode is selected', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await page.waitForLoadState('networkidle');

		// Impact section should be visible
		await expect(page.getByText(/impact sur les bulletins/i)).toBeVisible({ timeout: 10000 });
	});

	// =========================================================================
	// AC2: Can change to a different mode
	// =========================================================================

	test('can save a new grading mode', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/pedagogy`);

		await page.waitForLoadState('networkidle');
		await expect(page.getByText(/mode actuel/i)).toBeVisible({ timeout: 10000 });

		// Select "Notes sur 10"
		const numeric10Card = page.locator('.mode-card').filter({ hasText: /notes \/10/i });
		await numeric10Card.click();

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

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

		// The selected mode should now be "Notes /10"
		const selectedCard = page.locator('.mode-card.mode-selected');
		await expect(selectedCard).toContainText(/notes \/10/i);

		// Reload the page to verify server-side persistence
		await page.reload();
		await page.waitForLoadState('networkidle');
		await expect(page.locator('.mode-card.mode-selected')).toContainText(/notes \/10/i, {
			timeout: 10000
		});

		// Restore default mode for other tests
		const numeric20Card = page.locator('.mode-card').filter({ hasText: /notes \/20/i });
		await numeric20Card.click();
		await page.getByRole('button', { name: /enregistrer/i }).click();
		await expect(page.getByText(/mis à jour avec succès/i)).toBeVisible({ timeout: 10000 });
	});
});
