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

const projectRoot = join(__dirname, '../..');
const composeFile = join(projectRoot, 'compose.yaml');

test.describe('Admin Search & Pagination (Story 2.8b)', () => {
	test.beforeAll(async () => {
		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()
		]);
	}

	// ============================================================================
	// USERS PAGE - Search & Pagination
	// ============================================================================
	test.describe('Users Page', () => {
		test('displays search input on users page', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/users`);
			await page.waitForLoadState('networkidle');

			const searchInput = page.locator('input[type="search"]');
			await expect(searchInput).toBeVisible({ timeout: 10000 });
			await expect(searchInput).toHaveAttribute('placeholder', /rechercher/i);
		});

		test('search filters users and shows results', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/users`);
			await page.waitForLoadState('networkidle');

			// Wait for initial load
			await expect(
				page.locator('.users-table, .empty-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('e2e-search-admin');

			// Wait for debounce + API response
			await page.waitForTimeout(500);
			await page.waitForLoadState('networkidle');

			// Should find our test admin user
			await expect(page.locator('.users-table')).toBeVisible({ timeout: 10000 });
		});

		test('search with no results shows empty state', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/users`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.users-table, .empty-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('zzz-nonexistent-user-xyz');

			// Wait for debounce + API response
			await page.waitForTimeout(500);
			await page.waitForLoadState('networkidle');

			// Should show "Aucun résultat" empty state
			await expect(page.locator('.empty-state')).toBeVisible({ timeout: 10000 });
			await expect(page.locator('.empty-state')).toContainText(/aucun résultat/i);
		});

		test('search term is synced to URL', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/users`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.users-table, .empty-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('test-search');

			// Wait for debounce
			await page.waitForTimeout(500);

			// URL should contain search param
			await expect(page).toHaveURL(/[?&]search=test-search/);
		});

		test('search term from URL is restored on page load', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/users?search=admin`);
			await page.waitForLoadState('networkidle');

			const searchInput = page.locator('input[type="search"]');
			await expect(searchInput).toHaveValue('admin');
		});

		test('clear search button resets results', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/users`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.users-table, .empty-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('test');

			// Wait for debounce
			await page.waitForTimeout(500);

			// Clear button should appear
			const clearButton = page.locator('.search-clear');
			await expect(clearButton).toBeVisible();
			await clearButton.click();

			// Search input should be empty
			await expect(searchInput).toHaveValue('');
		});

		test('Escape key clears search', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/users`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.users-table, .empty-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('test');
			await page.waitForTimeout(500);

			await searchInput.press('Escape');
			await expect(searchInput).toHaveValue('');
		});

		test('filters work together with search', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/users`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.users-table, .empty-state')
			).toBeVisible({ timeout: 10000 });

			// Apply a role filter
			await page.locator('#filter-role').selectOption('ROLE_ADMIN');
			await page.getByRole('button', { name: /filtrer/i }).click();
			await page.waitForLoadState('networkidle');

			// Then search
			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('e2e-search');
			await page.waitForTimeout(500);
			await page.waitForLoadState('networkidle');

			// URL should have both params
			await expect(page).toHaveURL(/search=e2e-search/);
		});
	});

	// ============================================================================
	// CLASSES PAGE - Search & Pagination
	// ============================================================================
	test.describe('Classes Page', () => {
		test('displays search input on classes page', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/classes`);
			await page.waitForLoadState('networkidle');

			const searchInput = page.locator('input[type="search"]');
			await expect(searchInput).toBeVisible({ timeout: 10000 });
			await expect(searchInput).toHaveAttribute('placeholder', /rechercher/i);
		});

		test('search with no results shows empty state', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/classes`);
			await page.waitForLoadState('networkidle');

			// Wait for initial load
			await expect(
				page.locator('.classes-grid, .empty-state, .loading-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('zzz-nonexistent-class-xyz');

			await page.waitForTimeout(500);
			await page.waitForLoadState('networkidle');

			await expect(page.locator('.empty-state')).toBeVisible({ timeout: 10000 });
			await expect(page.locator('.empty-state')).toContainText(/aucun résultat/i);
		});

		test('search term is synced to URL', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/classes`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.classes-grid, .empty-state, .loading-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('6eme');
			await page.waitForTimeout(500);

			await expect(page).toHaveURL(/[?&]search=6eme/);
		});
	});

	// ============================================================================
	// SUBJECTS PAGE - Search & Pagination
	// ============================================================================
	test.describe('Subjects Page', () => {
		test('displays search input on subjects page', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/subjects`);
			await page.waitForLoadState('networkidle');

			const searchInput = page.locator('input[type="search"]');
			await expect(searchInput).toBeVisible({ timeout: 10000 });
			await expect(searchInput).toHaveAttribute('placeholder', /rechercher/i);
		});

		test('search with no results shows empty state', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/subjects`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.subjects-grid, .empty-state, .loading-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('zzz-nonexistent-subject-xyz');

			await page.waitForTimeout(500);
			await page.waitForLoadState('networkidle');

			await expect(page.locator('.empty-state')).toBeVisible({ timeout: 10000 });
			await expect(page.locator('.empty-state')).toContainText(/aucun résultat/i);
		});

		test('search term is synced to URL', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/subjects`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.subjects-grid, .empty-state, .loading-state')
			).toBeVisible({ timeout: 10000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('MATH');
			await page.waitForTimeout(500);

			await expect(page).toHaveURL(/[?&]search=MATH/);
		});
	});

	// ============================================================================
	// ASSIGNMENTS PAGE - Search & Pagination
	// ============================================================================
	test.describe('Assignments Page', () => {
		test('displays search input on assignments page', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/assignments`);
			await page.waitForLoadState('networkidle');

			const searchInput = page.locator('input[type="search"]');
			await expect(searchInput).toBeVisible({ timeout: 15000 });
			await expect(searchInput).toHaveAttribute('placeholder', /rechercher/i);
		});

		test('search with no results shows empty state', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/assignments`);
			await page.waitForLoadState('networkidle');

			// Wait for initial load
			await expect(
				page.locator('.table-container, .empty-state, .loading-state')
			).toBeVisible({ timeout: 15000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('zzz-nonexistent-teacher-xyz');

			await page.waitForTimeout(500);
			await page.waitForLoadState('networkidle');

			await expect(page.locator('.empty-state')).toBeVisible({ timeout: 10000 });
			await expect(page.locator('.empty-state')).toContainText(/aucun résultat/i);
		});

		test('search term is synced to URL', async ({ page }) => {
			await loginAsAdmin(page);
			await page.goto(`${ALPHA_URL}/admin/assignments`);
			await page.waitForLoadState('networkidle');

			await expect(
				page.locator('.table-container, .empty-state, .loading-state')
			).toBeVisible({ timeout: 15000 });

			const searchInput = page.locator('input[type="search"]');
			await searchInput.fill('Dupont');
			await page.waitForTimeout(500);

			await expect(page).toHaveURL(/[?&]search=Dupont/);
		});
	});
});
