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);

// Extract port from PLAYWRIGHT_BASE_URL or use default (4173 matches playwright.config.ts)
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}`;

// Test credentials
const ADMIN_EMAIL = 'e2e-class-detail-admin@example.com';
const ADMIN_PASSWORD = 'ClassDetail123';

test.describe('Admin Class Detail Page [P1]', () => {
	test.describe.configure({ mode: 'serial' });

	// Class name used for the test class (shared across serial tests)
	const CLASS_NAME = `DetailTest-${Date.now()}`;

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

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

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

	// Helper to open "Nouvelle classe" dialog with proper wait
	async function openNewClassDialog(page: import('@playwright/test').Page) {
		const button = page.getByRole('button', { name: /nouvelle classe/i });
		await button.waitFor({ state: 'visible' });
		await page.waitForLoadState('networkidle');

		await button.click();

		const dialog = page.getByRole('dialog');
		try {
			await expect(dialog).toBeVisible({ timeout: 5000 });
		} catch {
			// Retry once - webkit sometimes needs a second click
			await button.click();
			await expect(dialog).toBeVisible({ timeout: 10000 });
		}
	}

	// Helper to create a class and navigate to its detail page
	async function createClassAndNavigateToDetail(page: import('@playwright/test').Page, name: string) {
		await page.goto(`${ALPHA_URL}/admin/classes`);
		await expect(page.getByRole('heading', { name: /gestion des classes/i })).toBeVisible();

		await openNewClassDialog(page);
		await page.locator('#class-name').fill(name);
		await page.locator('#class-level').selectOption('CM1');
		await page.locator('#class-capacity').fill('25');
		await page.getByRole('button', { name: /créer la classe/i }).click();
		await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 10000 });

		// Click modify to go to detail page
		const classCard = page.locator('.class-card', { hasText: name });
		await expect(classCard).toBeVisible();
		await classCard.getByRole('button', { name: /modifier/i }).click();

		// Verify we are on the edit page
		await expect(page).toHaveURL(/\/admin\/classes\/[\w-]+/);
	}

	// ============================================================================
	// Navigate to class detail page and see edit form
	// ============================================================================
	test('[P1] navigates to class detail page and sees edit form', async ({ page }) => {
		await loginAsAdmin(page);
		await createClassAndNavigateToDetail(page, CLASS_NAME);

		// Should show the edit form heading
		await expect(
			page.getByRole('heading', { name: /modifier la classe/i })
		).toBeVisible();

		// Form fields should be pre-populated
		await expect(page.locator('#class-name')).toHaveValue(CLASS_NAME);
		await expect(page.locator('#class-level')).toHaveValue('CM1');
		await expect(page.locator('#class-capacity')).toHaveValue('25');

		// Breadcrumb should be visible
		await expect(page.locator('.breadcrumb')).toBeVisible();
		await expect(
			page.getByRole('main').getByRole('link', { name: 'Classes' })
		).toBeVisible();
	});

	// ============================================================================
	// Modify class name and save successfully
	// ============================================================================
	test('[P1] modifies class name and saves successfully', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/classes`);

		// Create a fresh class for this test
		const originalName = `ModName-${Date.now()}`;
		await openNewClassDialog(page);
		await page.locator('#class-name').fill(originalName);
		await page.getByRole('button', { name: /créer la classe/i }).click();
		await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 10000 });

		// Navigate to edit page
		const classCard = page.locator('.class-card', { hasText: originalName });
		await classCard.getByRole('button', { name: /modifier/i }).click();
		await expect(page).toHaveURL(/\/admin\/classes\/[\w-]+/);

		// Modify the name
		const newName = `Renamed-${Date.now()}`;
		await page.locator('#class-name').fill(newName);

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

		// Should show success message
		await expect(page.getByText(/modifiée avec succès/i)).toBeVisible({ timeout: 10000 });

		// Go back to list and verify the new name appears
		await page.goto(`${ALPHA_URL}/admin/classes`);
		await expect(page.getByText(newName)).toBeVisible();
		await expect(page.getByText(originalName)).not.toBeVisible();
	});

	// ============================================================================
	// Modify class level and save
	// ============================================================================
	test('[P1] modifies class level and saves successfully', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/classes`);

		// Create a class with specific level
		const className = `ModLevel-${Date.now()}`;
		await openNewClassDialog(page);
		await page.locator('#class-name').fill(className);
		await page.locator('#class-level').selectOption('CE1');
		await page.getByRole('button', { name: /créer la classe/i }).click();
		await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 10000 });

		// Navigate to edit page
		const classCard = page.locator('.class-card', { hasText: className });
		await classCard.getByRole('button', { name: /modifier/i }).click();
		await expect(page).toHaveURL(/\/admin\/classes\/[\w-]+/);

		// Change level from CE1 to CM2
		await page.locator('#class-level').selectOption('CM2');

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

		// Should show success message
		await expect(page.getByText(/modifiée avec succès/i)).toBeVisible({ timeout: 10000 });

		// Go back and verify the level changed in the card
		// Search for the class by name to find it regardless of pagination
		await page.goto(`${ALPHA_URL}/admin/classes`);
		const searchInput = page.locator('input[type="search"]');
		await searchInput.fill(className);
		await page.waitForTimeout(500);
		await page.waitForLoadState('networkidle');
		const updatedCard = page.locator('.class-card', { hasText: className });
		await expect(updatedCard).toBeVisible({ timeout: 10000 });
		await expect(updatedCard.getByText('CM2')).toBeVisible({ timeout: 5000 });
	});

	// ============================================================================
	// Cancel modification preserves original values
	// ============================================================================
	test('[P1] cancelling modification preserves original values', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/classes`);

		// Create a class
		const originalName = `NoCancel-${Date.now()}`;
		await openNewClassDialog(page);
		await page.locator('#class-name').fill(originalName);
		await page.locator('#class-level').selectOption('6ème');
		await page.getByRole('button', { name: /créer la classe/i }).click();
		await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 10000 });

		// Navigate to edit page
		const classCard = page.locator('.class-card', { hasText: originalName });
		await classCard.getByRole('button', { name: /modifier/i }).click();
		await expect(page).toHaveURL(/\/admin\/classes\/[\w-]+/);

		// Modify the name but cancel
		await page.locator('#class-name').fill('Should-Not-Persist');
		await page.locator('#class-level').selectOption('CM2');

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

		// Should go back to the classes list
		await expect(page).toHaveURL(/\/admin\/classes$/);

		// The original name should still be visible, modified name should not
		await expect(page.getByText(originalName)).toBeVisible();
		await expect(page.getByText('Should-Not-Persist')).not.toBeVisible();
	});

	// ============================================================================
	// Breadcrumb navigation back to classes list
	// ============================================================================
	test('[P1] breadcrumb navigates back to classes list', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/classes`);

		// Create a class
		const className = `Breadcrumb-${Date.now()}`;
		await openNewClassDialog(page);
		await page.locator('#class-name').fill(className);
		await page.getByRole('button', { name: /créer la classe/i }).click();
		await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 10000 });

		// Navigate to edit page
		const classCard = page.locator('.class-card', { hasText: className });
		await classCard.getByRole('button', { name: /modifier/i }).click();
		await expect(page).toHaveURL(/\/admin\/classes\/[\w-]+/);

		// Click breadcrumb "Classes" link (scoped to main to avoid nav link)
		await page.getByRole('main').getByRole('link', { name: 'Classes' }).click();

		// Should navigate back to the classes list
		await expect(page).toHaveURL(/\/admin\/classes$/);
		await expect(
			page.getByRole('heading', { name: /gestion des classes/i })
		).toBeVisible();
	});

	// ============================================================================
	// Empty required field (name) prevents submission
	// ============================================================================
	test('[P1] empty required field (name) prevents submission', async ({ page }) => {
		await loginAsAdmin(page);
		await page.goto(`${ALPHA_URL}/admin/classes`);

		// Create a class
		const className = `EmptyField-${Date.now()}`;
		await openNewClassDialog(page);
		await page.locator('#class-name').fill(className);
		await page.getByRole('button', { name: /créer la classe/i }).click();
		await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 10000 });

		// Navigate to edit page
		const classCard = page.locator('.class-card', { hasText: className });
		await classCard.getByRole('button', { name: /modifier/i }).click();
		await expect(page).toHaveURL(/\/admin\/classes\/[\w-]+/);

		// Clear the required name field
		await page.locator('#class-name').fill('');

		// Submit button should be disabled when name is empty
		const submitButton = page.getByRole('button', { name: /enregistrer/i });
		await expect(submitButton).toBeDisabled();
	});
});
