<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 { onMount } from 'svelte';

	interface StudentImageRights {
		id: string;
		firstName: string;
		lastName: string;
		email: string;
		imageRightsStatus: string;
		imageRightsStatusLabel: string;
		imageRightsUpdatedAt: string | null;
		className: string | null;
	}

	const STATUS_OPTIONS = [
		{ value: 'authorized', label: 'Autorisé' },
		{ value: 'refused', label: 'Refusé' },
		{ value: 'not_specified', label: 'Non renseigné' }
	];

	const itemsPerPage = 30;

	// State
	let students = $state<StudentImageRights[]>([]);
	let isLoading = $state(true);
	let error = $state<string | null>(null);
	let successMessage = $state<string | null>(null);
	let totalItems = $state(0);
	let currentPage = $state(Number(page.url.searchParams.get('page')) || 1);

	// Filters
	let filterStatus = $state<string>(page.url.searchParams.get('status') ?? '');
	let searchTerm = $state(page.url.searchParams.get('search') ?? '');

	// Derived
	let totalPages = $derived(Math.ceil(totalItems / itemsPerPage));
	let authorizedStudents = $derived(
		students.filter((s) => s.imageRightsStatus === 'authorized')
	);
	let unauthorizedStudents = $derived(
		students.filter((s) => s.imageRightsStatus !== 'authorized')
	);

	// Updating state
	let updatingId = $state<string | null>(null);
	let isExporting = $state(false);

	let loadAbortController: AbortController | null = null;

	onMount(() => {
		loadStudents();
	});

	async function loadStudents() {
		loadAbortController?.abort();
		const controller = new AbortController();
		loadAbortController = controller;

		try {
			isLoading = true;
			error = null;
			const apiUrl = getApiBaseUrl();
			const params = new URLSearchParams();
			params.set('page', String(currentPage));
			params.set('itemsPerPage', String(itemsPerPage));
			if (filterStatus) params.set('status', filterStatus);
			if (searchTerm) params.set('search', searchTerm);
			const query = params.toString();
			const url = `${apiUrl}/students/image-rights?${query}`;
			const response = await authenticatedFetch(url, { signal: controller.signal });

			if (controller.signal.aborted) return;

			if (!response.ok) {
				throw new Error("Erreur lors du chargement des droits à l'image");
			}

			const data = await response.json();
			students = data['hydra:member'] ?? data['member'] ?? (Array.isArray(data) ? data : []);
			totalItems = data['hydra:totalItems'] ?? data['totalItems'] ?? students.length;
		} catch (e) {
			if (e instanceof DOMException && e.name === 'AbortError') return;
			error = e instanceof Error ? e.message : 'Erreur inconnue';
			students = [];
			totalItems = 0;
		} finally {
			if (!controller.signal.aborted) {
				isLoading = false;
			}
		}
	}

	function updateUrl() {
		const params = new URLSearchParams();
		if (currentPage > 1) params.set('page', String(currentPage));
		if (filterStatus) params.set('status', filterStatus);
		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();
		loadStudents();
	}

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

	function applyFilters() {
		currentPage = 1;
		updateUrl();
		loadStudents();
	}

	function resetFilters() {
		filterStatus = '';
		searchTerm = '';
		currentPage = 1;
		updateUrl();
		loadStudents();
	}

	async function updateStatus(studentId: string, newStatus: string) {
		try {
			updatingId = studentId;
			error = null;
			const apiUrl = getApiBaseUrl();
			const response = await authenticatedFetch(`${apiUrl}/students/${studentId}/image-rights`, {
				method: 'PATCH',
				headers: { 'Content-Type': 'application/merge-patch+json' },
				body: JSON.stringify({ imageRightsStatus: newStatus })
			});

			if (!response.ok) {
				let errorMessage = `Erreur (${response.status})`;
				try {
					const errorData = await response.json();
					errorMessage =
						errorData['hydra:description'] ?? errorData.detail ?? errorMessage;
				} catch {
					// Ignore JSON parse errors, use default message
				}
				throw new Error(errorMessage);
			}

			const updated = await response.json();
			students = students.map((s) =>
				s.id === studentId
					? {
							...s,
							imageRightsStatus: updated.imageRightsStatus ?? newStatus,
							imageRightsStatusLabel:
								updated.imageRightsStatusLabel ??
								STATUS_OPTIONS.find((o) => o.value === newStatus)?.label ??
								newStatus,
							imageRightsUpdatedAt: updated.imageRightsUpdatedAt ?? new Date().toISOString()
						}
					: s
			);
			successMessage = 'Statut mis à jour avec succès.';
			window.setTimeout(() => (successMessage = null), 3000);
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur lors de la mise à jour';
		} finally {
			updatingId = null;
		}
	}

	async function exportCsv() {
		try {
			isExporting = true;
			error = null;
			const apiUrl = getApiBaseUrl();
			const params = new URLSearchParams();
			if (filterStatus) params.set('status', filterStatus);
			const query = params.toString();
			const url = `${apiUrl}/students/image-rights/export${query ? `?${query}` : ''}`;
			const response = await authenticatedFetch(url);

			if (!response.ok) {
				throw new Error("Erreur lors de l'export");
			}

			const blob = await response.blob();
			const downloadUrl = URL.createObjectURL(blob);
			const a = document.createElement('a');
			a.href = downloadUrl;
			a.download = 'droits-image.csv';
			document.body.appendChild(a);
			a.click();
			document.body.removeChild(a);
			URL.revokeObjectURL(downloadUrl);

			successMessage = 'Export CSV téléchargé.';
			window.setTimeout(() => (successMessage = null), 3000);
		} catch (e) {
			error = e instanceof Error ? e.message : "Erreur lors de l'export";
		} finally {
			isExporting = false;
		}
	}

	function statusBadgeClass(status: string): string {
		return status === 'authorized'
			? 'status-active'
			: status === 'refused'
				? 'status-suspended'
				: 'status-pending';
	}
</script>

<div class="admin-page">
	<header class="page-header">
		<div class="header-content">
			<h1>Droit à l'image</h1>
			<p class="subtitle">
				Consultez et gérez les autorisations de droit à l'image des élèves
			</p>
		</div>
		<button class="btn-primary" onclick={exportCsv} disabled={isExporting}>
			{isExporting ? 'Export...' : 'Exporter CSV'}
		</button>
	</header>

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

	{#if successMessage}
		<div class="alert alert-success" role="status">
			<span>{successMessage}</span>
			<button class="alert-close" onclick={() => (successMessage = null)}>×</button>
		</div>
	{/if}

	<div class="filters-bar">
		<div class="filter-group">
			<SearchInput
				value={searchTerm}
				onSearch={handleSearch}
				placeholder="Rechercher un élève..."
			/>
		</div>
		<div class="filter-group">
			<label for="filter-status">Statut</label>
			<select id="filter-status" bind:value={filterStatus}>
				<option value="">Tous les statuts</option>
				{#each STATUS_OPTIONS as option}
					<option value={option.value}>{option.label}</option>
				{/each}
			</select>
		</div>
		<div class="filter-actions">
			<button class="btn-secondary btn-sm" onclick={applyFilters}>Filtrer</button>
			<button class="btn-text btn-sm" onclick={resetFilters}>Réinitialiser</button>
		</div>
	</div>

	{#if isLoading}
		<div class="loading-state">
			<div class="spinner"></div>
			<p>Chargement...</p>
		</div>
	{:else if students.length === 0 && !searchTerm && !filterStatus}
		<div class="empty-state">
			<div class="empty-icon">📷</div>
			<h2>Aucun élève inscrit</h2>
			<p>Commencez par créer des comptes élèves pour pouvoir gérer leurs autorisations de droit à l'image.</p>
			<a class="btn-primary" href="/admin/users">Gérer les utilisateurs</a>
		</div>
	{:else if students.length === 0}
		<div class="empty-state">
			<div class="empty-icon">🔍</div>
			<h2>Aucun résultat</h2>
			<p>Aucun élève ne correspond aux critères de recherche. Essayez de modifier vos filtres.</p>
			<button class="btn-secondary" onclick={resetFilters}>Réinitialiser les filtres</button>
		</div>
	{:else}
		<div class="stats-bar">
			<span class="stat">
				<span class="stat-count stat-total">{totalItems}</span> élève{totalItems > 1 ? 's' : ''} au total
			</span>
		</div>

		{#if authorizedStudents.length > 0}
			<div class="section">
				<h2>Élèves autorisés ({authorizedStudents.length})</h2>
				<div class="table-wrapper">
					<table>
						<thead>
							<tr>
								<th>Nom</th>
								<th>Prénom</th>
								<th>Classe</th>
								<th>Statut</th>
								<th>Actions</th>
							</tr>
						</thead>
						<tbody>
							{#each authorizedStudents as student}
								<tr>
									<td data-label="Nom">{student.lastName}</td>
									<td data-label="Prénom">{student.firstName}</td>
									<td data-label="Classe">{student.className ?? '—'}</td>
									<td data-label="Statut">
										<span class="badge {statusBadgeClass(student.imageRightsStatus)}">
											{student.imageRightsStatusLabel}
										</span>
									</td>
									<td data-label="Actions">
										<select
											value={student.imageRightsStatus}
											onchange={(e) => updateStatus(student.id, e.currentTarget.value)}
											disabled={updatingId === student.id}
										>
											{#each STATUS_OPTIONS as option}
												<option value={option.value}>{option.label}</option>
											{/each}
										</select>
									</td>
								</tr>
							{/each}
						</tbody>
					</table>
				</div>
			</div>
		{/if}

		{#if unauthorizedStudents.length > 0}
			<div class="section">
				<h2>Élèves non autorisés ({unauthorizedStudents.length})</h2>
				<div class="table-wrapper">
					<table>
						<thead>
							<tr>
								<th>Nom</th>
								<th>Prénom</th>
								<th>Classe</th>
								<th>Statut</th>
								<th>Actions</th>
							</tr>
						</thead>
						<tbody>
							{#each unauthorizedStudents as student}
								<tr>
									<td data-label="Nom">{student.lastName}</td>
									<td data-label="Prénom">{student.firstName}</td>
									<td data-label="Classe">{student.className ?? '—'}</td>
									<td data-label="Statut">
										<span class="badge {statusBadgeClass(student.imageRightsStatus)}">
											{student.imageRightsStatusLabel}
										</span>
									</td>
									<td data-label="Actions">
										<select
											value={student.imageRightsStatus}
											onchange={(e) => updateStatus(student.id, e.currentTarget.value)}
											disabled={updatingId === student.id}
										>
											{#each STATUS_OPTIONS as option}
												<option value={option.value}>{option.label}</option>
											{/each}
										</select>
									</td>
								</tr>
							{/each}
						</tbody>
					</table>
				</div>
			</div>
		{/if}

		<Pagination {currentPage} {totalPages} onPageChange={handlePageChange} />
	{/if}
</div>

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

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

	.page-header h1 {
		font-size: 1.5rem;
		font-weight: 700;
		color: var(--text-primary, #1a1a2e);
		margin: 0;
	}

	.subtitle {
		color: var(--text-secondary, #666);
		margin: 0.25rem 0 0;
		font-size: 0.875rem;
	}

	.btn-primary {
		padding: 0.5rem 1rem;
		background: var(--accent-primary, #4361ee);
		color: white;
		border: none;
		border-radius: 0.5rem;
		cursor: pointer;
		font-size: 0.875rem;
		font-weight: 500;
		white-space: nowrap;
	}

	.btn-primary:hover {
		opacity: 0.9;
	}

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

	.btn-secondary {
		padding: 0.5rem 1rem;
		background: var(--surface-secondary, #f0f0f0);
		color: var(--text-primary, #333);
		border: 1px solid var(--border-color, #ddd);
		border-radius: 0.5rem;
		cursor: pointer;
		font-size: 0.875rem;
	}

	.btn-text {
		padding: 0.5rem 1rem;
		background: none;
		color: var(--text-secondary, #666);
		border: none;
		cursor: pointer;
		font-size: 0.875rem;
	}

	.btn-sm {
		padding: 0.375rem 0.75rem;
		font-size: 0.8125rem;
	}

	.alert {
		padding: 0.75rem 1rem;
		border-radius: 0.5rem;
		margin-bottom: 1rem;
		display: flex;
		justify-content: space-between;
		align-items: center;
	}

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

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

	.alert-close {
		background: none;
		border: none;
		font-size: 1.25rem;
		cursor: pointer;
		color: inherit;
		padding: 0 0.25rem;
	}

	.filters-bar {
		display: flex;
		gap: 1rem;
		align-items: flex-end;
		margin-bottom: 1.5rem;
		flex-wrap: wrap;
	}

	.filter-group {
		display: flex;
		flex-direction: column;
		gap: 0.25rem;
	}

	.filter-group label {
		font-size: 0.75rem;
		font-weight: 600;
		color: var(--text-secondary, #666);
		text-transform: uppercase;
	}

	.filter-group select {
		padding: 0.5rem 0.75rem;
		border: 1px solid var(--border-color, #ddd);
		border-radius: 0.375rem;
		font-size: 0.875rem;
		min-width: 160px;
	}

	.filter-actions {
		display: flex;
		gap: 0.5rem;
		align-items: flex-end;
	}

	.stats-bar {
		display: flex;
		gap: 1.5rem;
		margin-bottom: 1.5rem;
		padding: 0.75rem 1rem;
		background: var(--surface-secondary, #f8f9fa);
		border-radius: 0.5rem;
	}

	.stat {
		font-size: 0.875rem;
		color: var(--text-secondary, #666);
	}

	.stat-count {
		font-weight: 700;
	}

	.stat-count.stat-total {
		color: var(--text-primary, #333);
	}

	.section {
		margin-bottom: 2rem;
	}

	.section h2 {
		font-size: 1.125rem;
		font-weight: 600;
		margin-bottom: 0.75rem;
		color: var(--text-primary, #1a1a2e);
	}

	.table-wrapper {
		overflow-x: auto;
	}

	table {
		width: 100%;
		border-collapse: collapse;
		font-size: 0.875rem;
	}

	thead {
		background: var(--surface-secondary, #f8f9fa);
	}

	th {
		text-align: left;
		padding: 0.75rem 1rem;
		font-weight: 600;
		color: var(--text-secondary, #666);
		border-bottom: 2px solid var(--border-color, #e5e7eb);
	}

	td {
		padding: 0.75rem 1rem;
		border-bottom: 1px solid var(--border-color, #f0f0f0);
		color: var(--text-primary, #333);
	}

	tr:hover {
		background: var(--surface-hover, #f9fafb);
	}

	.badge {
		display: inline-block;
		padding: 0.25rem 0.625rem;
		border-radius: 999px;
		font-size: 0.75rem;
		font-weight: 600;
	}

	.status-active {
		background: #dcfce7;
		color: #166534;
	}

	.status-suspended {
		background: #fef2f2;
		color: #991b1b;
	}

	.status-pending {
		background: #fef9c3;
		color: #854d0e;
	}

	td select {
		padding: 0.375rem 0.5rem;
		border: 1px solid var(--border-color, #ddd);
		border-radius: 0.375rem;
		font-size: 0.8125rem;
		min-width: 140px;
	}

	td select:disabled {
		opacity: 0.5;
	}

	.loading-state {
		text-align: center;
		padding: 3rem 1rem;
		color: var(--text-secondary, #666);
	}

	.empty-state {
		text-align: center;
		padding: 3rem 1.5rem;
		background: var(--surface-elevated, #fff);
		border: 1px solid var(--border-subtle, #e2e8f0);
		border-radius: 0.75rem;
	}

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

	.empty-state h2 {
		font-size: 1.125rem;
		font-weight: 600;
		color: var(--text-primary, #1f2937);
		margin: 0 0 0.5rem;
	}

	.empty-state p {
		font-size: 0.875rem;
		color: var(--text-secondary, #64748b);
		margin: 0 0 1.5rem;
		max-width: 400px;
		margin-left: auto;
		margin-right: auto;
	}

	.spinner {
		width: 2rem;
		height: 2rem;
		border: 3px solid var(--border-color, #e5e7eb);
		border-top-color: var(--accent-primary, #4361ee);
		border-radius: 50%;
		animation: spin 0.8s linear infinite;
		margin: 0 auto 1rem;
	}

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

	@media (max-width: 768px) {
		.page-header {
			flex-direction: column;
		}

		.filters-bar {
			flex-direction: column;
		}

		.stats-bar {
			flex-direction: column;
			gap: 0.5rem;
		}

		thead {
			display: none;
		}

		tr {
			display: block;
			margin-bottom: 1rem;
			border: 1px solid var(--border-color, #e5e7eb);
			border-radius: 0.5rem;
			padding: 0.5rem;
		}

		td {
			display: flex;
			justify-content: space-between;
			align-items: center;
			border-bottom: none;
			padding: 0.375rem 0.5rem;
		}

		td::before {
			content: attr(data-label);
			font-weight: 600;
			color: var(--text-secondary, #666);
			font-size: 0.75rem;
		}
	}
</style>
