import { test, expect } from '@playwright/test';
import { execWithRetry, runSql, clearCache, resolveDeterministicIds, createTestUser, composeFile } from './helpers';

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 STUDENT_EMAIL = 'e2e-sub-student@example.com';
const STUDENT_PASSWORD = 'SubStudent123';
const TEACHER_EMAIL = 'e2e-sub-teacher@example.com';
const TEACHER_PASSWORD = 'SubTeacher123';
const TENANT_ID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';

function getNextWeekday(daysFromNow: number): string {
	const date = new Date();
	date.setDate(date.getDate() + daysFromNow);
	const day = date.getDay();
	if (day === 0) date.setDate(date.getDate() + 1);
	if (day === 6) date.setDate(date.getDate() + 2);
	const y = date.getFullYear();
	const m = String(date.getMonth() + 1).padStart(2, '0');
	const d = String(date.getDate()).padStart(2, '0');
	return `${y}-${m}-${d}`;
}

function getPastDate(daysAgo: number): string {
	const date = new Date();
	date.setDate(date.getDate() - daysAgo);
	const y = date.getFullYear();
	const m = String(date.getMonth() + 1).padStart(2, '0');
	const d = String(date.getDate()).padStart(2, '0');
	return `${y}-${m}-${d}`;
}

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

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

test.describe('Homework Submission (Story 5.10)', () => {
	test.describe.configure({ mode: 'serial' });

	const dueDate = getNextWeekday(7);
	const pastDueDate = getPastDate(3);

	test.beforeAll(async () => {
		try {
			execWithRetry(
				`docker compose -f "${composeFile}" exec -T php php bin/console cache:pool:clear cache.rate_limiter users.cache --env=dev 2>&1`
			);
		} catch {
			// Cache pools may not exist
		}

		// Create student user
		createTestUser('ecole-alpha', STUDENT_EMAIL, STUDENT_PASSWORD, 'ROLE_ELEVE');

		// Create teacher user
		createTestUser('ecole-alpha', TEACHER_EMAIL, TEACHER_PASSWORD, 'ROLE_PROF');

		const { schoolId, academicYearId } = resolveDeterministicIds(TENANT_ID);

		// Ensure class exists
		try {
			runSql(
				`INSERT INTO school_classes (id, tenant_id, school_id, academic_year_id, name, level, status, created_at, updated_at) ` +
					`VALUES (gen_random_uuid(), '${TENANT_ID}', '${schoolId}', '${academicYearId}', 'E2E-Sub-6A', '6ème', 'active', NOW(), NOW()) ON CONFLICT DO NOTHING`
			);
		} catch {
			// May already exist
		}

		// Ensure subject exists
		try {
			runSql(
				`INSERT INTO subjects (id, tenant_id, school_id, name, code, color, status, created_at, updated_at) ` +
					`VALUES (gen_random_uuid(), '${TENANT_ID}', '${schoolId}', 'E2E-Sub-Maths', 'E2ESUBMAT', '#3b82f6', 'active', NOW(), NOW()) ON CONFLICT DO NOTHING`
			);
		} catch {
			// May already exist
		}

		// Assign student to class
		runSql(
			`INSERT INTO class_assignments (id, tenant_id, user_id, school_class_id, academic_year_id, assigned_at, created_at, updated_at) ` +
				`SELECT gen_random_uuid(), '${TENANT_ID}', u.id, c.id, '${academicYearId}', NOW(), NOW(), NOW() ` +
				`FROM users u, school_classes c ` +
				`WHERE u.email = '${STUDENT_EMAIL}' AND u.tenant_id = '${TENANT_ID}' ` +
				`AND c.name = 'E2E-Sub-6A' AND c.tenant_id = '${TENANT_ID}' ` +
				`ON CONFLICT DO NOTHING`
		);

		// Clean up submissions and homework
		try {
			runSql(
				`DELETE FROM submission_attachments WHERE submission_id IN ` +
					`(SELECT hs.id FROM homework_submissions hs JOIN homework h ON h.id = hs.homework_id ` +
					`WHERE h.tenant_id = '${TENANT_ID}' AND h.class_id IN ` +
					`(SELECT id FROM school_classes WHERE name = 'E2E-Sub-6A' AND tenant_id = '${TENANT_ID}'))`
			);
			runSql(
				`DELETE FROM homework_submissions WHERE homework_id IN ` +
					`(SELECT id FROM homework WHERE tenant_id = '${TENANT_ID}' AND class_id IN ` +
					`(SELECT id FROM school_classes WHERE name = 'E2E-Sub-6A' AND tenant_id = '${TENANT_ID}'))`
			);
			runSql(
				`DELETE FROM homework_attachments WHERE homework_id IN ` +
					`(SELECT id FROM homework WHERE tenant_id = '${TENANT_ID}' AND class_id IN ` +
					`(SELECT id FROM school_classes WHERE name = 'E2E-Sub-6A' AND tenant_id = '${TENANT_ID}'))`
			);
			runSql(
				`DELETE FROM homework WHERE tenant_id = '${TENANT_ID}' AND class_id IN ` +
					`(SELECT id FROM school_classes WHERE name = 'E2E-Sub-6A' AND tenant_id = '${TENANT_ID}')`
			);
		} catch {
			// Tables may not exist
		}

		// Seed homework (future due date)
		runSql(
			`INSERT INTO homework (id, tenant_id, class_id, subject_id, teacher_id, title, description, due_date, status, created_at, updated_at) ` +
				`SELECT gen_random_uuid(), '${TENANT_ID}', c.id, s.id, t.id, 'E2E Devoir à rendre', 'Rédigez un texte libre.', '${dueDate}', 'published', NOW(), NOW() ` +
				`FROM school_classes c, ` +
				`(SELECT id FROM subjects WHERE code = 'E2ESUBMAT' AND tenant_id = '${TENANT_ID}' LIMIT 1) s, ` +
				`(SELECT id FROM users WHERE email = '${TEACHER_EMAIL}' AND tenant_id = '${TENANT_ID}') t ` +
				`WHERE c.name = 'E2E-Sub-6A' AND c.tenant_id = '${TENANT_ID}'`
		);

		// Seed homework (past due date for late submission test)
		runSql(
			`INSERT INTO homework (id, tenant_id, class_id, subject_id, teacher_id, title, description, due_date, status, created_at, updated_at) ` +
				`SELECT gen_random_uuid(), '${TENANT_ID}', c.id, s.id, t.id, 'E2E Devoir en retard', 'Devoir déjà dû.', '${pastDueDate}', 'published', NOW(), NOW() ` +
				`FROM school_classes c, ` +
				`(SELECT id FROM subjects WHERE code = 'E2ESUBMAT' AND tenant_id = '${TENANT_ID}' LIMIT 1) s, ` +
				`(SELECT id FROM users WHERE email = '${TEACHER_EMAIL}' AND tenant_id = '${TENANT_ID}') t ` +
				`WHERE c.name = 'E2E-Sub-6A' AND c.tenant_id = '${TENANT_ID}'`
		);

		clearCache();
	});

	// ======================================================================
	// AC1 + AC3: Draft and Submission
	// ======================================================================
	test.describe('AC1+AC3: Write and submit homework', () => {
		test('student sees "Rendre mon devoir" button in homework detail', async ({ page }) => {
			await loginAsStudent(page);
			await page.goto(`${ALPHA_URL}/dashboard/homework`);
			await expect(page.locator('.homework-card')).toHaveCount(2, { timeout: 15000 });

			// Click on the homework
			await page.locator('.homework-card', { hasText: 'E2E Devoir à rendre' }).click();
			await expect(page.locator('.homework-detail')).toBeVisible({ timeout: 10000 });

			// Verify "Rendre mon devoir" button is visible
			await expect(page.getByRole('button', { name: /rendre mon devoir/i })).toBeVisible();
		});

		test('student can save a draft', async ({ page }) => {
			await loginAsStudent(page);
			await page.goto(`${ALPHA_URL}/dashboard/homework`);
			await page.locator('.homework-card', { hasText: 'E2E Devoir à rendre' }).click();
			await expect(page.locator('.homework-detail')).toBeVisible({ timeout: 10000 });

			// Click "Rendre mon devoir"
			await page.getByRole('button', { name: /rendre mon devoir/i }).click();
			await expect(page.locator('.submission-form')).toBeVisible({ timeout: 10000 });

			// Wait for editor and type
			const editor = page.locator('.ProseMirror');
			await expect(editor).toBeVisible({ timeout: 10000 });
			await editor.click();
			await page.keyboard.type('Mon brouillon de reponse');

			// Save draft
			await page.getByRole('button', { name: /sauvegarder le brouillon/i }).click();
			await expect(page.locator('.success-banner')).toContainText('Brouillon sauvegardé', {
				timeout: 10000
			});
		});

		test('student can upload a file attachment', async ({ page }) => {
			await loginAsStudent(page);
			await page.goto(`${ALPHA_URL}/dashboard/homework`);
			await page.locator('.homework-card', { hasText: 'E2E Devoir à rendre' }).click();
			await expect(page.locator('.homework-detail')).toBeVisible({ timeout: 10000 });

			await page.getByRole('button', { name: /rendre mon devoir/i }).click();
			await expect(page.locator('.submission-form')).toBeVisible({ timeout: 10000 });

			// Upload a PDF file
			const fileInput = page.locator('input[type="file"]');
			await fileInput.setInputFiles({
				name: 'devoir-eleve.pdf',
				mimeType: 'application/pdf',
				buffer: Buffer.from('Fake PDF content for E2E test')
			});

			// Wait for file to appear in the list
			await expect(page.locator('.file-item')).toBeVisible({ timeout: 10000 });
			await expect(page.getByText('devoir-eleve.pdf')).toBeVisible();
		});

		test('student can submit homework with confirmation', async ({ page }) => {
			await loginAsStudent(page);
			await page.goto(`${ALPHA_URL}/dashboard/homework`);
			await page.locator('.homework-card', { hasText: 'E2E Devoir à rendre' }).click();
			await expect(page.locator('.homework-detail')).toBeVisible({ timeout: 10000 });

			await page.getByRole('button', { name: /rendre mon devoir/i }).click();
			await expect(page.locator('.submission-form')).toBeVisible({ timeout: 10000 });

			// Click submit
			await page.getByRole('button', { name: /soumettre mon devoir/i }).click();

			// Confirmation dialog should appear
			await expect(page.locator('[role="alertdialog"]')).toBeVisible({ timeout: 5000 });
			await expect(page.locator('[role="alertdialog"]')).toContainText(
				'Confirmer la soumission'
			);

			// Confirm submission
			await page.getByRole('button', { name: /confirmer/i }).click();

			// Should show success
			await expect(page.locator('.success-banner')).toContainText('rendu avec succès', {
				timeout: 10000
			});
		});
	});

	// ======================================================================
	// AC4: Status in homework list
	// ======================================================================
	test.describe('AC4: Submission status in list', () => {
		test('student sees submitted status in homework list', async ({ page }) => {
			await loginAsStudent(page);
			await page.goto(`${ALPHA_URL}/dashboard/homework`);
			await expect(page.locator('.homework-card')).toHaveCount(2, { timeout: 15000 });

			const card = page.locator('.homework-card', { hasText: 'E2E Devoir à rendre' });
			await expect(card.locator('.submission-submitted')).toContainText('Rendu');
		});
	});

	// ======================================================================
	// AC4: Late submission
	// ======================================================================
	test.describe('AC4: Late submission', () => {
		test('late submission shows en retard status', async ({ page }) => {
			await loginAsStudent(page);
			await page.goto(`${ALPHA_URL}/dashboard/homework`);
			await expect(page.locator('.homework-card')).toHaveCount(2, { timeout: 15000 });
			await page.locator('.homework-card', { hasText: 'E2E Devoir en retard' }).click();
			await expect(page.locator('.homework-detail')).toBeVisible({ timeout: 10000 });

			await page.getByRole('button', { name: /rendre mon devoir/i }).click();
			await expect(page.locator('.submission-form')).toBeVisible({ timeout: 10000 });

			// Wait for editor to be ready then type
			const editor = page.locator('.ProseMirror');
			await expect(editor).toBeVisible({ timeout: 10000 });
			await editor.click();
			await page.keyboard.type('Rendu en retard');

			// Save draft first
			await page.getByRole('button', { name: /sauvegarder le brouillon/i }).click();
			await expect(page.locator('.success-banner')).toBeVisible({ timeout: 10000 });

			// Wait for success to appear then submit
			await page.getByRole('button', { name: /soumettre mon devoir/i }).click();
			await expect(page.locator('[role="alertdialog"]')).toBeVisible({ timeout: 5000 });
			await page.getByRole('button', { name: /confirmer/i }).click();
			await expect(page.locator('.success-banner')).toContainText('rendu', {
				timeout: 15000
			});

			// Go back to list and check status
			await page.goto(`${ALPHA_URL}/dashboard/homework`);
			await page.waitForLoadState('networkidle');
			await expect(page.locator('.homework-card')).toHaveCount(2, { timeout: 15000 });
			const card = page.locator('.homework-card', { hasText: 'E2E Devoir en retard' });
			await expect(card.locator('.submission-late')).toContainText('retard', {
				timeout: 15000
			});
		});
	});

	// ======================================================================
	// AC5 + AC6: Teacher views submissions and stats
	// ======================================================================
	test.describe('AC5+AC6: Teacher submission views', () => {
		test('teacher can view submissions list and stats', async ({ page }) => {
			await loginAsTeacher(page);

			// Get the homework ID from the database
			const homeworkIdOutput = execWithRetry(
				`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "SELECT id FROM homework WHERE title = 'E2E Devoir à rendre' AND tenant_id = '${TENANT_ID}' LIMIT 1" 2>&1`
			);

			const idMatch = homeworkIdOutput.match(
				/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
			);
			if (!idMatch) {
				throw new Error('Could not find homework ID');
			}
			const homeworkId = idMatch[0];

			// Navigate to submissions page
			await page.goto(
				`${ALPHA_URL}/dashboard/teacher/homework/${homeworkId}/submissions`
			);

			// Should see stats
			await expect(page.locator('.stat-value')).toContainText('1', { timeout: 15000 });

			// Should see the submission in the table
			await expect(page.locator('tbody tr')).toHaveCount(1, { timeout: 10000 });

			// Should see "Voir" button
			await expect(page.getByRole('button', { name: 'Voir', exact: true })).toBeVisible();

			// Click to view detail
			await page.getByRole('button', { name: 'Voir', exact: true }).click();
			await expect(page.locator('.detail-header')).toBeVisible({ timeout: 10000 });
			await expect(page.locator('.response-content')).toBeVisible();
		});
	});
});
