<script lang="ts">
	import { goto } from '$app/navigation';
	import { page } from '$app/state';
	import { getApiBaseUrl } from '$lib/api/config';
	import { authenticatedFetch } from '$lib/auth';
	import Pagination from '$lib/components/molecules/Pagination/Pagination.svelte';
	import SearchInput from '$lib/components/molecules/SearchInput/SearchInput.svelte';
	import { untrack } from 'svelte';

	// Types
	interface TeacherAssignment {
		id: string;
		teacherId: string;
		classId: string;
		subjectId: string;
		academicYearId: string;
		status: string;
		startDate: string;
		endDate: string | null;
		createdAt: string;
		teacherFirstName: string | null;
		teacherLastName: string | null;
		className: string | null;
		subjectName: string | null;
	}

	interface User {
		id: string;
		firstName: string;
		lastName: string;
		email: string;
		roles: string[];
	}

	interface SchoolClass {
		id: string;
		name: string;
		level: string | null;
		status: string;
	}

	interface Subject {
		id: string;
		name: string;
		code: string;
		color: string | null;
		status: string;
	}

	// State
	let assignments = $state<TeacherAssignment[]>([]);
	let teachers = $state<User[]>([]);
	let classes = $state<SchoolClass[]>([]);
	let subjects = $state<Subject[]>([]);
	let isLoading = $state(true);
	let error = $state<string | null>(null);
	let successMessage = $state<string | null>(null);

	// Pagination & Search
	let currentPage = $state(Number(page.url.searchParams.get('page')) || 1);
	let searchTerm = $state(page.url.searchParams.get('search') ?? '');
	let totalItems = $state(0);
	const itemsPerPage = 30;
	let totalPages = $derived(Math.ceil(totalItems / itemsPerPage));

	// Create modal
	let showCreateModal = $state(false);
	let selectedTeacherId = $state('');
	let selectedClassId = $state('');
	let selectedSubjectId = $state('');
	let isSubmitting = $state(false);

	// Delete state
	let showDeleteModal = $state(false);
	let assignmentToDelete = $state<TeacherAssignment | null>(null);
	let isDeleting = $state(false);

	// Load everything on mount
	$effect(() => {
		untrack(() => loadAll());
	});

	async function loadAll() {
		try {
			isLoading = true;
			error = null;
			const apiUrl = getApiBaseUrl();

			// Load reference data and assignments in parallel
			const [teachersRes, classesRes, subjectsRes] = await Promise.all([
				authenticatedFetch(`${apiUrl}/users?role=ROLE_PROF&itemsPerPage=100`),
				authenticatedFetch(`${apiUrl}/classes?itemsPerPage=100`),
				authenticatedFetch(`${apiUrl}/subjects?itemsPerPage=100`)
			]);

			if (!teachersRes.ok) throw new Error('Erreur lors du chargement des enseignants');
			if (!classesRes.ok) throw new Error('Erreur lors du chargement des classes');
			if (!subjectsRes.ok) throw new Error('Erreur lors du chargement des matières');

			const [teachersData, classesData, subjectsData] = await Promise.all([
				teachersRes.json(),
				classesRes.json(),
				subjectsRes.json()
			]);

			teachers = extractCollection(teachersData);
			classes = extractCollection(classesData);
			subjects = extractCollection(subjectsData);

			await loadAssignments();
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isLoading = false;
		}
	}

	let assignmentsAbortController: AbortController | null = null;

	async function loadAssignments() {
		assignmentsAbortController?.abort();
		const controller = new AbortController();
		assignmentsAbortController = controller;

		const apiUrl = getApiBaseUrl();
		const params = new URLSearchParams();
		params.set('page', String(currentPage));
		params.set('itemsPerPage', String(itemsPerPage));
		if (searchTerm) params.set('search', searchTerm);
		const response = await authenticatedFetch(`${apiUrl}/teacher-assignments?${params.toString()}`, { signal: controller.signal });

		if (controller.signal.aborted) return;

		if (!response.ok) {
			throw new Error('Erreur lors du chargement des affectations');
		}

		const data = await response.json();
		assignments = data['hydra:member'] ?? data['member'] ?? [];
		totalItems = data['hydra:totalItems'] ?? data['totalItems'] ?? assignments.length;
	}

	function extractCollection<T>(data: Record<string, unknown>): T[] {
		const hydra = data['hydra:member'];
		if (Array.isArray(hydra)) return hydra as T[];
		const member = data['member'];
		if (Array.isArray(member)) return member as T[];
		if (Array.isArray(data)) return data as T[];
		return [];
	}

	function getSubjectColor(subjectId: string): string | null {
		const subject = subjects.find((s) => s.id === subjectId);
		return subject?.color ?? null;
	}

	function updateUrl() {
		const params = new URLSearchParams();
		if (currentPage > 1) params.set('page', String(currentPage));
		if (searchTerm) params.set('search', searchTerm);
		const query = params.toString();
		goto(`?${query}`, { replaceState: true, noScroll: true, keepFocus: true });
	}

	function handleSearch(value: string) {
		searchTerm = value;
		currentPage = 1;
		updateUrl();
		reloadAssignments();
	}

	function handlePageChange(newPage: number) {
		currentPage = newPage;
		updateUrl();
		reloadAssignments();
	}

	async function reloadAssignments() {
		try {
			isLoading = true;
			error = null;
			await loadAssignments();
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isLoading = false;
		}
	}

	function openCreateModal() {
		showCreateModal = true;
		selectedTeacherId = '';
		selectedClassId = '';
		selectedSubjectId = '';
		error = null;
	}

	function closeCreateModal() {
		showCreateModal = false;
	}

	async function handleCreate() {
		if (!selectedTeacherId || !selectedClassId || !selectedSubjectId) return;

		try {
			isSubmitting = true;
			error = null;
			const apiUrl = getApiBaseUrl();

			const response = await authenticatedFetch(`${apiUrl}/teacher-assignments`, {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({
					teacherId: selectedTeacherId,
					classId: selectedClassId,
					subjectId: selectedSubjectId,
					academicYearId: 'current'
				})
			});

			if (!response.ok) {
				const data = await response.json().catch(() => null);
				const message =
					data?.['hydra:description'] ?? data?.message ?? data?.detail ?? `Erreur (${response.status})`;
				throw new Error(message);
			}

			successMessage = 'Affectation créée avec succès';
			closeCreateModal();
			await reloadAssignments();
			globalThis.setTimeout(() => {
				successMessage = null;
			}, 3000);
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur lors de la création';
		} finally {
			isSubmitting = false;
		}
	}

	function openDeleteModal(assignment: TeacherAssignment) {
		assignmentToDelete = assignment;
		showDeleteModal = true;
	}

	function closeDeleteModal() {
		showDeleteModal = false;
		assignmentToDelete = null;
	}

	async function handleDelete() {
		if (!assignmentToDelete) return;

		try {
			isDeleting = true;
			error = null;
			const apiUrl = getApiBaseUrl();

			const response = await authenticatedFetch(
				`${apiUrl}/teacher-assignments/${assignmentToDelete.id}`,
				{ method: 'DELETE' }
			);

			if (!response.ok) {
				const data = await response.json().catch(() => null);
				const message =
					data?.['hydra:description'] ?? data?.message ?? data?.detail ?? `Erreur (${response.status})`;
				throw new Error(message);
			}

			successMessage = 'Affectation retirée avec succès';
			closeDeleteModal();
			await reloadAssignments();
			globalThis.setTimeout(() => {
				successMessage = null;
			}, 3000);
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur lors de la suppression';
		} finally {
			isDeleting = false;
		}
	}
</script>

<svelte:head>
	<title>Affectations enseignants - Classeo</title>
</svelte:head>

<div class="assignments-page">
	<header class="page-header">
		<div class="header-content">
			<h1>Affectations enseignants</h1>
			<p class="subtitle">Affectez les enseignants à leurs classes et matières</p>
		</div>
		<button class="btn-primary" onclick={openCreateModal}>
			<span class="btn-icon">+</span>
			Nouvelle affectation
		</button>
	</header>

	{#if error}
		<div class="alert alert-error">
			<span class="alert-icon">!</span>
			{error}
			<button class="alert-close" onclick={() => (error = null)}>x</button>
		</div>
	{/if}

	{#if successMessage}
		<div class="alert alert-success">
			{successMessage}
		</div>
	{/if}

	<SearchInput
		value={searchTerm}
		onSearch={handleSearch}
		placeholder="Rechercher par enseignant, classe, matière..."
	/>

	{#if isLoading}
		<div class="loading-state" aria-live="polite" role="status">
			<div class="spinner"></div>
			<p>Chargement des affectations...</p>
		</div>
	{:else if assignments.length === 0}
		<div class="empty-state">
			<span class="empty-icon">&#x1F4CB;</span>
			{#if searchTerm}
				<h2>Aucun résultat</h2>
				<p>Aucune affectation ne correspond à votre recherche</p>
				<button class="btn-secondary" onclick={() => handleSearch('')}>Effacer la recherche</button>
			{:else}
				<h2>Aucune affectation</h2>
				<p>Commencez par affecter un enseignant à une classe et une matière</p>
				<button class="btn-primary" onclick={openCreateModal}>Nouvelle affectation</button>
			{/if}
		</div>
	{:else}
		<div class="table-container">
			<table class="assignments-table">
				<thead>
					<tr>
						<th>Enseignant</th>
						<th>Classe</th>
						<th>Matière</th>
						<th>Statut</th>
						<th>Depuis le</th>
						<th>Actions</th>
					</tr>
				</thead>
				<tbody>
					{#each assignments as assignment (assignment.id)}
						<tr>
							<td data-label="Enseignant" class="teacher-cell">
								<span class="teacher-name">{assignment.teacherFirstName} {assignment.teacherLastName}</span>
							</td>
							<td data-label="Classe">{assignment.className}</td>
							<td data-label="Matière">
								{#if getSubjectColor(assignment.subjectId)}
									<span
										class="subject-badge"
										style="background-color: {getSubjectColor(assignment.subjectId)}; color: white"
									>
										{assignment.subjectName}
									</span>
								{:else}
									{assignment.subjectName}
								{/if}
							</td>
							<td data-label="Statut">
								<span class="status-badge status-active">Active</span>
							</td>
							<td data-label="Depuis le" class="date-cell">
								{new Date(assignment.startDate).toLocaleDateString('fr-FR')}
							</td>
							<td data-label="Actions" class="actions-cell">
								<button
									class="btn-remove"
									onclick={() => openDeleteModal(assignment)}
								>
									Retirer
								</button>
							</td>
						</tr>
					{/each}
				</tbody>
			</table>
		</div>
		<Pagination {currentPage} {totalPages} onPageChange={handlePageChange} />
	{/if}
</div>

<!-- Create Modal -->
{#if showCreateModal}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeCreateModal} role="presentation">
		<div
			class="modal"
			role="dialog"
			aria-modal="true"
			aria-labelledby="create-modal-title"
			tabindex="-1"
			onclick={(e) => e.stopPropagation()}
			onkeydown={(e) => { if (e.key === 'Escape') closeCreateModal(); }}
		>
			<header class="modal-header">
				<h2 id="create-modal-title">Nouvelle affectation</h2>
				<button class="modal-close" onclick={closeCreateModal} aria-label="Fermer">x</button>
			</header>

			<form
				class="modal-body"
				onsubmit={(e) => {
					e.preventDefault();
					handleCreate();
				}}
			>
				<div class="form-group">
					<label for="assignment-teacher">Enseignant *</label>
					<select id="assignment-teacher" bind:value={selectedTeacherId} required>
						<option value="">-- Sélectionner un enseignant --</option>
						{#each teachers as teacher (teacher.id)}
							<option value={teacher.id}>{teacher.firstName} {teacher.lastName}</option>
						{/each}
					</select>
				</div>

				<div class="form-group">
					<label for="assignment-class">Classe *</label>
					<select id="assignment-class" bind:value={selectedClassId} required>
						<option value="">-- Sélectionner une classe --</option>
						{#each classes as cls (cls.id)}
							<option value={cls.id}>{cls.name}{cls.level ? ` (${cls.level})` : ''}</option>
						{/each}
					</select>
				</div>

				<div class="form-group">
					<label for="assignment-subject">Matière *</label>
					<select id="assignment-subject" bind:value={selectedSubjectId} required>
						<option value="">-- Sélectionner une matière --</option>
						{#each subjects as subject (subject.id)}
							<option value={subject.id}>{subject.name} ({subject.code})</option>
						{/each}
					</select>
				</div>

				<div class="form-hint">
					L'affectation sera créée pour l'année scolaire en cours.
				</div>

				<div class="modal-actions">
					<button type="button" class="btn-secondary" onclick={closeCreateModal} disabled={isSubmitting}>
						Annuler
					</button>
					<button
						type="submit"
						class="btn-primary"
						disabled={isSubmitting || !selectedTeacherId || !selectedClassId || !selectedSubjectId}
					>
						{#if isSubmitting}
							Création...
						{:else}
							Affecter
						{/if}
					</button>
				</div>
			</form>
		</div>
	</div>
{/if}

<!-- Delete Confirmation Modal -->
{#if showDeleteModal && assignmentToDelete}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeDeleteModal} role="presentation">
		<div
			class="modal modal-confirm"
			role="alertdialog"
			aria-modal="true"
			aria-labelledby="delete-modal-title"
			aria-describedby="delete-modal-description"
			tabindex="-1"
			onclick={(e) => e.stopPropagation()}
			onkeydown={(e) => { if (e.key === 'Escape') closeDeleteModal(); }}
		>
			<header class="modal-header modal-header-danger">
				<h2 id="delete-modal-title">Retirer l'affectation</h2>
				<button class="modal-close" onclick={closeDeleteModal} aria-label="Fermer">x</button>
			</header>

			<div class="modal-body">
				<p id="delete-modal-description">
					Retirer <strong>{assignmentToDelete.teacherFirstName} {assignmentToDelete.teacherLastName}</strong>
					de <strong>{assignmentToDelete.subjectName}</strong>
					en <strong>{assignmentToDelete.className}</strong> ?
				</p>
				<p class="delete-warning">
					Les notes existantes seront conservées, mais l'enseignant ne pourra plus en ajouter.
				</p>
			</div>

			<div class="modal-actions modal-actions-padded">
				<button type="button" class="btn-secondary" onclick={closeDeleteModal} disabled={isDeleting}>
					Annuler
				</button>
				<button type="button" class="btn-danger" onclick={handleDelete} disabled={isDeleting}>
					{#if isDeleting}
						Retrait...
					{:else}
						Retirer
					{/if}
				</button>
			</div>
		</div>
	</div>
{/if}

<style>
	.assignments-page {
		padding: 1.5rem;
		max-width: 1200px;
		margin: 0 auto;
	}

	.page-header {
		display: flex;
		justify-content: space-between;
		align-items: flex-start;
		gap: 1rem;
		margin-bottom: 1.5rem;
		flex-wrap: wrap;
	}

	.header-content h1 {
		margin: 0;
		font-size: 1.5rem;
		font-weight: 700;
		color: #1f2937;
	}

	.subtitle {
		margin: 0.25rem 0 0;
		color: #6b7280;
		font-size: 0.875rem;
	}

	/* Buttons */
	.btn-primary {
		display: inline-flex;
		align-items: center;
		gap: 0.5rem;
		padding: 0.75rem 1.25rem;
		background: var(--btn-primary-bg, #3b82f6);
		color: white;
		border: none;
		border-radius: 0.5rem;
		font-weight: 600;
		cursor: pointer;
		transition: background 0.2s;
	}

	.btn-primary:hover:not(:disabled) {
		background: var(--btn-primary-hover-bg, #2563eb);
	}

	.btn-primary:disabled {
		opacity: 0.6;
		cursor: not-allowed;
	}

	.btn-secondary {
		padding: 0.5rem 1rem;
		background: white;
		color: #374151;
		border: 1px solid #d1d5db;
		border-radius: 0.375rem;
		font-weight: 500;
		cursor: pointer;
		transition: all 0.2s;
	}

	.btn-secondary:hover:not(:disabled) {
		background: #f3f4f6;
	}

	.btn-danger {
		display: inline-flex;
		align-items: center;
		gap: 0.5rem;
		padding: 0.5rem 1rem;
		background: #dc2626;
		color: white;
		border: none;
		border-radius: 0.375rem;
		font-weight: 500;
		cursor: pointer;
		transition: background 0.2s;
	}

	.btn-danger:hover:not(:disabled) {
		background: #b91c1c;
	}

	.btn-danger:disabled {
		opacity: 0.6;
		cursor: not-allowed;
	}

	.btn-remove {
		padding: 0.375rem 0.75rem;
		font-size: 0.75rem;
		background: #fef2f2;
		border: 1px solid #fecaca;
		color: #991b1b;
		border-radius: 0.25rem;
		cursor: pointer;
		transition: background 0.15s;
	}

	.btn-remove:hover {
		background: #fee2e2;
	}

	.btn-icon {
		font-size: 1.25rem;
		line-height: 1;
	}

	/* Alerts */
	.alert {
		display: flex;
		align-items: center;
		gap: 0.75rem;
		padding: 1rem;
		border-radius: 0.5rem;
		margin-bottom: 1rem;
	}

	.alert-error {
		background: #fef2f2;
		border: 1px solid #fecaca;
		color: #dc2626;
	}

	.alert-success {
		background: #f0fdf4;
		border: 1px solid #bbf7d0;
		color: #16a34a;
	}

	.alert-icon {
		flex-shrink: 0;
		font-weight: bold;
	}

	.alert-close {
		margin-left: auto;
		padding: 0.25rem 0.5rem;
		background: none;
		border: none;
		font-size: 1.25rem;
		cursor: pointer;
		opacity: 0.6;
	}

	.alert-close:hover {
		opacity: 1;
	}

	/* Loading & Empty */
	.loading-state,
	.empty-state {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		padding: 3rem;
		text-align: center;
		background: white;
		border-radius: 0.75rem;
		border: 2px dashed #e5e7eb;
	}

	.spinner {
		width: 2rem;
		height: 2rem;
		border: 3px solid #e5e7eb;
		border-top-color: #3b82f6;
		border-radius: 50%;
		animation: spin 0.8s linear infinite;
	}

	@keyframes spin {
		to {
			transform: rotate(360deg);
		}
	}

	.empty-icon {
		font-size: 3rem;
		margin-bottom: 1rem;
	}

	.empty-state h2 {
		margin: 0 0 0.5rem;
		font-size: 1.25rem;
		color: #1f2937;
	}

	.empty-state p {
		margin: 0 0 1.5rem;
		color: #6b7280;
	}

	/* Table */
	.table-container {
		background: white;
		border: 1px solid #e5e7eb;
		border-radius: 0.75rem;
		overflow-x: auto;
	}

	.assignments-table {
		width: 100%;
		border-collapse: collapse;
	}

	.assignments-table th {
		text-align: left;
		padding: 0.75rem 1rem;
		font-size: 0.75rem;
		font-weight: 600;
		color: #6b7280;
		text-transform: uppercase;
		letter-spacing: 0.05em;
		border-bottom: 1px solid #e5e7eb;
		background: #f9fafb;
	}

	.assignments-table td {
		padding: 0.75rem 1rem;
		font-size: 0.875rem;
		color: #374151;
		border-bottom: 1px solid #f3f4f6;
	}

	.assignments-table tr:last-child td {
		border-bottom: none;
	}

	.assignments-table tr:hover td {
		background: #f9fafb;
	}

	.teacher-cell {
		white-space: nowrap;
	}

	.teacher-name {
		font-weight: 500;
		color: #1f2937;
	}

	.subject-badge {
		display: inline-block;
		padding: 0.125rem 0.5rem;
		border-radius: 9999px;
		font-size: 0.75rem;
		font-weight: 500;
	}

	.status-badge {
		display: inline-block;
		padding: 0.125rem 0.5rem;
		border-radius: 9999px;
		font-size: 0.75rem;
		font-weight: 500;
	}

	.status-active {
		background: #f0fdf4;
		color: #16a34a;
	}

	.date-cell {
		white-space: nowrap;
		color: #6b7280;
	}

	.actions-cell {
		white-space: nowrap;
	}

	/* Modal */
	.modal-overlay {
		position: fixed;
		inset: 0;
		background: rgba(0, 0, 0, 0.5);
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 1rem;
		z-index: 100;
	}

	.modal {
		background: white;
		border-radius: 0.75rem;
		width: 100%;
		max-width: 28rem;
		max-height: 90vh;
		overflow: auto;
		box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
	}

	.modal-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 1.25rem 1.5rem;
		border-bottom: 1px solid #e5e7eb;
	}

	.modal-header h2 {
		margin: 0;
		font-size: 1.125rem;
		font-weight: 600;
		color: #1f2937;
	}

	.modal-close {
		padding: 0.25rem 0.5rem;
		background: none;
		border: none;
		font-size: 1.5rem;
		line-height: 1;
		color: #6b7280;
		cursor: pointer;
	}

	.modal-close:hover {
		color: #1f2937;
	}

	.modal-body {
		padding: 1.5rem;
	}

	.form-group {
		margin-bottom: 1.25rem;
	}

	.form-group label {
		display: block;
		margin-bottom: 0.5rem;
		font-weight: 500;
		color: #374151;
	}

	.form-group select {
		width: 100%;
		padding: 0.75rem 1rem;
		border: 1px solid #d1d5db;
		border-radius: 0.375rem;
		font-size: 1rem;
		transition: border-color 0.2s;
		background: white;
	}

	.form-group select:focus {
		outline: none;
		border-color: #3b82f6;
		box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
	}

	.form-hint {
		padding: 0.75rem 1rem;
		background: #eff6ff;
		border-radius: 0.375rem;
		font-size: 0.875rem;
		color: #3b82f6;
		margin-bottom: 1.25rem;
	}

	.modal-actions {
		display: flex;
		justify-content: flex-end;
		gap: 0.75rem;
		padding-top: 1rem;
		border-top: 1px solid #e5e7eb;
	}

	.modal-actions-padded {
		padding: 1rem 1.5rem;
	}

	/* Delete confirmation modal */
	.modal-confirm {
		max-width: 24rem;
	}

	.modal-header-danger {
		background: #fef2f2;
		border-bottom-color: #fecaca;
	}

	.modal-header-danger h2 {
		color: #dc2626;
	}

	.delete-warning {
		margin: 0.75rem 0 0;
		font-size: 0.875rem;
		color: #6b7280;
	}

	@media (max-width: 767px) {
		.table-container {
			background: transparent;
			border: none;
		}

		.assignments-table thead {
			display: none;
		}

		.assignments-table tbody tr {
			display: block;
			background: white;
			border: 1px solid #e5e7eb;
			border-radius: 0.75rem;
			margin-bottom: 0.75rem;
			padding: 0.25rem 0;
		}

		.assignments-table tr:hover td {
			background: transparent;
		}

		.assignments-table td {
			display: flex;
			justify-content: space-between;
			align-items: baseline;
			padding: 0.5rem 1rem;
			border-bottom: none;
			text-align: right;
		}

		.assignments-table td::before {
			content: attr(data-label);
			font-weight: 600;
			font-size: 0.75rem;
			color: #6b7280;
			text-transform: uppercase;
			letter-spacing: 0.05em;
			text-align: left;
			margin-right: 1rem;
			flex-shrink: 0;
		}

		.teacher-cell {
			white-space: normal;
		}

		.actions-cell {
			justify-content: flex-end;
			padding-top: 0.75rem;
			border-top: 1px solid #f3f4f6;
		}
	}
</style>
