<script lang="ts">
	import { getApiBaseUrl } from '$lib/api/config';
	import { authenticatedFetch } from '$lib/auth';

	// Types
	interface AvailableMode {
		value: string;
		label: string;
	}

	interface GradingModeConfig {
		academicYearId: string;
		mode: string;
		label: string;
		scaleMax: number | null;
		isNumeric: boolean;
		calculatesAverage: boolean;
		hasExistingGrades: boolean;
		availableModes: AvailableMode[];
	}

	// State
	let config = $state<GradingModeConfig | null>(null);
	let isLoading = $state(true);
	let error = $state<string | null>(null);
	let successMessage = $state<string | null>(null);
	let isSubmitting = $state(false);
	let selectedMode = $state<string | null>(null);

	// Academic year selector
	type YearKey = 'previous' | 'current' | 'next';
	const yearOptions: { key: YearKey; offset: number }[] = [
		{ key: 'previous', offset: -1 },
		{ key: 'current', offset: 0 },
		{ key: 'next', offset: 1 }
	];
	let selectedYear = $state<YearKey>('current');
	let academicYearId = $derived(selectedYear);

	function baseStartYear(): number {
		const now = new Date();
		return now.getMonth() >= 8 ? now.getFullYear() : now.getFullYear() - 1;
	}

	function schoolYearLabel(offset: number): string {
		const sy = baseStartYear() + offset;
		return `${sy}-${sy + 1}`;
	}

	// Derived
	let isLocked = $derived(config?.hasExistingGrades === true);
	let hasChanges = $derived(selectedMode !== null && config !== null && selectedMode !== config.mode);

	// Version counter to discard stale responses on quick year switches
	let loadVersion = 0;

	// Reload when year changes
	$effect(() => {
		void selectedYear;
		loadConfig();
	});

	async function loadConfig() {
		const myVersion = ++loadVersion;

		try {
			isLoading = true;
			error = null;
			successMessage = null;
			const apiUrl = getApiBaseUrl();
			const response = await authenticatedFetch(
				`${apiUrl}/academic-years/${academicYearId}/grading-mode`
			);

			if (myVersion !== loadVersion) return;

			if (!response.ok) {
				throw new Error('Erreur lors du chargement de la configuration');
			}

			const data: GradingModeConfig = await response.json();
			config = data;
			selectedMode = data.mode;
		} catch (e) {
			if (myVersion !== loadVersion) return;
			error = e instanceof Error ? e.message : 'Erreur inconnue';
			config = null;
		} finally {
			if (myVersion === loadVersion) {
				isLoading = false;
			}
		}
	}

	async function handleSave() {
		if (!selectedMode || !hasChanges) return;

		try {
			isSubmitting = true;
			error = null;
			successMessage = null;
			const apiUrl = getApiBaseUrl();
			const response = await authenticatedFetch(
				`${apiUrl}/academic-years/${academicYearId}/grading-mode`,
				{
					method: 'PUT',
					headers: { 'Content-Type': 'application/json' },
					body: JSON.stringify({ mode: selectedMode })
				}
			);

			if (response.status === 409) {
				error =
					'Impossible de changer le mode de notation : des notes existent pour cette année scolaire. Veuillez attendre la prochaine année.';
				selectedMode = config?.mode ?? null;
				await loadConfig();
				return;
			}

			if (!response.ok) {
				const errorData = await response.json();
				throw new Error(
					errorData['hydra:description'] || errorData.message || 'Erreur lors de la configuration'
				);
			}

			const data: GradingModeConfig = await response.json();
			config = data;
			selectedMode = data.mode;
			successMessage = 'Mode de notation mis à jour avec succès.';
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isSubmitting = false;
		}
	}

	function modeDescription(mode: string): string {
		const descriptions: Record<string, string> = {
			numeric_20: 'Notes sur 20 points. Les moyennes sont calculées classiquement.',
			numeric_10: 'Notes sur 10 points. Les moyennes sont calculées classiquement.',
			letters: 'Lettres A, B, C, D, E. Les moyennes sont calculées avec un barème.',
			competencies:
				'Acquis, En cours, Non acquis. Pas de moyenne numérique. Le Score Sérénité utilise un mapping adapté.',
			no_grades:
				'Appréciations textuelles uniquement. Le Score Sérénité est basé sur les absences et devoirs.'
		};
		return descriptions[mode] ?? '';
	}

	function modeBulletinImpact(mode: string): string {
		const impacts: Record<string, string> = {
			numeric_20: 'Bulletins avec moyennes sur 20, classements et appréciations.',
			numeric_10: 'Bulletins avec moyennes sur 10, classements et appréciations.',
			letters:
				'Bulletins avec lettres (A-E) et moyennes converties selon le barème.',
			competencies:
				'Bulletins avec niveaux de compétences : Acquis, En cours, Non acquis. Pas de moyenne.',
			no_grades: 'Bulletins avec appréciations textuelles uniquement. Aucune note ni compétence.'
		};
		return impacts[mode] ?? '';
	}
</script>

<svelte:head>
	<title>Pédagogie - Classeo</title>
</svelte:head>

<div class="pedagogy-page">
	<header class="page-header">
		<div class="header-content">
			<h1>Mode de notation</h1>
			<p class="subtitle">
				Choisissez le système d'évaluation de votre établissement
			</p>
		</div>
		<div class="header-actions">
			<div class="year-selector" role="tablist" aria-label="Année scolaire">
				{#each yearOptions as { key, offset } (key)}
					<button
						role="tab"
						class="year-tab"
						class:year-tab-active={selectedYear === key}
						aria-selected={selectedYear === key}
						onclick={() => (selectedYear = key as YearKey)}
					>
						{schoolYearLabel(offset)}
					</button>
				{/each}
			</div>
		</div>
	</header>

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

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

	{#if isLoading}
		<div class="loading-state">
			<div class="spinner"></div>
			<p>Chargement de la configuration...</p>
		</div>
	{:else if config}
		{#if isLocked}
			<div class="alert alert-warning">
				<strong>Mode verrouillé :</strong> des notes existent pour cette année scolaire.
				Le changement de mode de notation sera possible lors de la configuration de la prochaine année.
			</div>
		{/if}

		<!-- Current mode summary -->
		<div class="current-mode-banner">
			<div class="banner-content">
				<span class="banner-label">Mode actuel</span>
				<span class="banner-mode">{config.label}</span>
			</div>
			{#if config.scaleMax}
				<div class="banner-detail">
					<span class="detail-number">{config.scaleMax}</span>
					<span class="detail-label">points</span>
				</div>
			{/if}
		</div>

		<!-- Mode selector -->
		<div class="modes-section">
			<h2 class="section-title">Modes disponibles</h2>
			<div class="modes-grid">
				{#each config.availableModes as mode (mode.value)}
					<button
						class="mode-card"
						class:mode-selected={selectedMode === mode.value}
						class:mode-locked={isLocked && mode.value !== config.mode}
						disabled={isLocked && mode.value !== config.mode}
						onclick={() => (selectedMode = mode.value)}
						aria-pressed={selectedMode === mode.value}
					>
						<div class="mode-header">
							<span class="mode-radio" class:mode-radio-checked={selectedMode === mode.value}
							></span>
							<span class="mode-label">{mode.label}</span>
						</div>
						<p class="mode-description">{modeDescription(mode.value)}</p>
					</button>
				{/each}
			</div>
		</div>

		<!-- Bulletin impact preview -->
		{#if selectedMode}
			<div class="preview-section">
				<h2 class="section-title">Impact sur les bulletins</h2>
				<div class="preview-card">
					<p class="preview-text">{modeBulletinImpact(selectedMode)}</p>
				</div>
			</div>
		{/if}

		<!-- Save button -->
		{#if hasChanges}
			<div class="save-bar">
				<button
					class="btn-secondary"
					onclick={() => (selectedMode = config?.mode ?? null)}
					disabled={isSubmitting}
				>
					Annuler
				</button>
				<button class="btn-primary" onclick={handleSave} disabled={isSubmitting}>
					{#if isSubmitting}
						Enregistrement...
					{:else}
						Enregistrer le mode
					{/if}
				</button>
			</div>
		{/if}
	{/if}
</div>

<style>
	.pedagogy-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;
	}

	.header-actions {
		display: flex;
		align-items: center;
		gap: 1rem;
		flex-wrap: wrap;
	}

	.year-selector {
		display: flex;
		background: #f3f4f6;
		border-radius: 0.5rem;
		padding: 0.25rem;
	}

	.year-tab {
		padding: 0.5rem 1rem;
		border: none;
		background: transparent;
		border-radius: 0.375rem;
		font-size: 0.875rem;
		font-weight: 500;
		color: #6b7280;
		cursor: pointer;
		transition: all 0.2s;
	}

	.year-tab-active {
		background: white;
		color: #1f2937;
		box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
	}

	.year-tab:hover:not(.year-tab-active) {
		color: #374151;
	}

	/* Current mode banner */
	.current-mode-banner {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 1.25rem 1.5rem;
		background: linear-gradient(135deg, #8b5cf6, #7c3aed);
		border-radius: 0.75rem;
		color: white;
		margin-bottom: 1.5rem;
	}

	.banner-label {
		font-size: 0.875rem;
		opacity: 0.9;
	}

	.banner-mode {
		display: block;
		font-size: 1.5rem;
		font-weight: 700;
		margin-top: 0.25rem;
	}

	.banner-detail {
		text-align: right;
	}

	.detail-number {
		display: block;
		font-size: 2rem;
		font-weight: 700;
	}

	.detail-label {
		font-size: 0.75rem;
		opacity: 0.9;
	}

	/* Modes section */
	.modes-section {
		margin-bottom: 1.5rem;
	}

	.section-title {
		font-size: 1.125rem;
		font-weight: 600;
		color: #1f2937;
		margin: 0 0 1rem;
	}

	.modes-grid {
		display: grid;
		grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
		gap: 1rem;
	}

	.mode-card {
		padding: 1.25rem;
		background: white;
		border: 2px solid #e5e7eb;
		border-radius: 0.75rem;
		cursor: pointer;
		transition: all 0.2s;
		text-align: left;
		width: 100%;
	}

	.mode-card:hover:not(:disabled) {
		border-color: #8b5cf6;
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
	}

	.mode-selected {
		border-color: #8b5cf6;
		background: #f5f3ff;
	}

	.mode-locked {
		opacity: 0.5;
		cursor: not-allowed;
	}

	.mode-header {
		display: flex;
		align-items: center;
		gap: 0.75rem;
		margin-bottom: 0.75rem;
	}

	.mode-radio {
		width: 1.25rem;
		height: 1.25rem;
		border: 2px solid #d1d5db;
		border-radius: 50%;
		flex-shrink: 0;
		transition: all 0.2s;
		position: relative;
	}

	.mode-radio-checked {
		border-color: #8b5cf6;
	}

	.mode-radio-checked::after {
		content: '';
		position: absolute;
		top: 3px;
		left: 3px;
		width: 10px;
		height: 10px;
		background: #8b5cf6;
		border-radius: 50%;
	}

	.mode-label {
		font-weight: 600;
		color: #1f2937;
		font-size: 1rem;
	}

	.mode-description {
		margin: 0;
		font-size: 0.875rem;
		color: #6b7280;
		line-height: 1.5;
	}

	/* Preview section */
	.preview-section {
		margin-bottom: 1.5rem;
	}

	.preview-card {
		padding: 1.25rem;
		background: #f9fafb;
		border: 1px solid #e5e7eb;
		border-radius: 0.75rem;
	}

	.preview-text {
		margin: 0;
		font-size: 0.9375rem;
		color: #374151;
		line-height: 1.6;
	}

	/* Save bar */
	.save-bar {
		display: flex;
		justify-content: flex-end;
		gap: 0.75rem;
		padding: 1rem 0;
		border-top: 1px solid #e5e7eb;
	}

	/* 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-warning {
		padding: 1rem;
		background: #fffbeb;
		border: 1px solid #fcd34d;
		border-radius: 0.5rem;
		color: #92400e;
		margin-bottom: 1rem;
	}

	.alert-icon {
		flex-shrink: 0;
		width: 1.5rem;
		height: 1.5rem;
		display: flex;
		align-items: center;
		justify-content: center;
		background: #dc2626;
		color: white;
		border-radius: 50%;
		font-size: 0.75rem;
		font-weight: 700;
	}

	.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;
	}

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

	.btn-primary:hover:not(:disabled) {
		background: #7c3aed;
	}

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

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

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

	/* Loading */
	.loading-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: #8b5cf6;
		border-radius: 50%;
		animation: spin 0.8s linear infinite;
	}

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

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

		.modes-grid {
			grid-template-columns: 1fr;
		}

		.current-mode-banner {
			flex-direction: column;
			gap: 1rem;
			text-align: center;
		}

		.banner-detail {
			text-align: center;
		}
	}
</style>
