<script lang="ts">
	import { page } from '$app/state';
	import Seo from '$lib/components/Seo.svelte';
	import { chemin, t } from '$lib/i18n';
	import { FRUITS, entreesJouables, photosValidees } from '$lib/data';
	import { melanger, propositions } from '$lib/jeu/tirage';
	import { ordreRevision, repondre } from '$lib/jeu/progression.svelte';
	import { compte } from '$lib/motion/countup';
	import type { Entree, Media } from '$lib/data/types';

	const { data } = $props();
	const locale = $derived(data.locale);

	const QUESTIONS = 8;
	const POINTS = 25;

	interface Question {
		cible: Entree;
		photo: Media;
		choix: Entree[];
	}

	/**
	 * Le bassin ne contient que les espèces disposant d'une photographie de filière A,
	 * validée par un humain nommé et portant l'usage « épreuve ». C'est la même règle
	 * que `tools/data/validate.mjs`, qui fait échouer le build si elle est violée.
	 *
	 * Aujourd'hui ce bassin est vide, et c'est le comportement correct : personne n'a
	 * encore validé de photo. Le mode ne triche pas avec une image générée.
	 */
	const jouables = entreesJouables();

	function fabriquer(): Question[] {
		return ordreRevision(jouables.map((e) => e.id))
			.slice(0, QUESTIONS)
			.map((id) => {
				const cible = jouables.find((e) => e.id === id) as Entree;
				const photos = photosValidees(cible).filter((m) => m.usages.includes('epreuve'));
				return {
					cible,
					photo: melanger(photos)[0],
					choix: propositions(cible, jouables)
				};
			});
	}

	let questions = $state<Question[]>(jouables.length >= 4 ? fabriquer() : []);
	let index = $state(0);
	let reponse = $state<Entree | null>(null);
	let score = $state(0);
	let bonnes = $state(0);

	const q = $derived(questions[index]);
	const fini = $derived(questions.length > 0 && index >= questions.length);
	const correct = $derived(reponse?.id === q?.cible.id);

	function choisir(e: Entree) {
		if (reponse || !q) return;
		reponse = e;
		const juste = e.id === q.cible.id;
		if (juste) {
			bonnes += 1;
			score += POINTS;
		}
		repondre(q.cible.id, juste, juste ? POINTS : 0);
	}

	function suivant() {
		reponse = null;
		index += 1;
	}

	function rejouer() {
		questions = fabriquer();
		index = 0;
		reponse = null;
		score = 0;
		bonnes = 0;
	}
</script>

<Seo {locale} pathname={page.url.pathname} titre={t(locale, 'jeu.rekonet')} />

<div class="container section jeu">
	<p class="fil"><a href={chemin(locale, 'je')}>{t(locale, 'jeu.quitter')}</a></p>

	{#if questions.length === 0}
		<!-- État designé, pas page d'erreur : le manque est une information (ADR 0006). -->
		<section class="bloque" aria-labelledby="bloque-titre">
			<span class="flag-chip" aria-hidden="true"></span>
			<h1 id="bloque-titre">{t(locale, 'jeu.indisponible.titre')}</h1>
			<p>{t(locale, 'jeu.indisponible.texte')}</p>
			<p class="chiffre">
				<strong>{jouables.length}</strong> espèce{jouables.length > 1 ? 's' : ''} sur {FRUITS.length}
				dispose d’une photographie validée. Il en faut au moins quatre pour poser une question
				honnête.
			</p>
			<p class="muted">
				Ce mode fonctionne uniquement sur des photographies réelles, validées par un humain. Il ne
				se rabattra jamais sur une image générée : ce serait apprendre à reconnaître ce qu’un
				modèle invente.
			</p>
			<p class="actions">
				<a class="btn" href={chemin(locale, 'kontribiye')}>{t(locale, 'manques.aider')}</a>
				<a class="btn btn--sobre" href={chemin(locale, 'je', 'kache')}>{t(locale, 'jeu.kache')}</a>
			</p>
		</section>
	{:else if fini}
		<section class="bilan" aria-labelledby="bilan-titre">
			<h1 id="bilan-titre">{t(locale, 'jeu.termine')}</h1>
			<p class="gros">
				<span use:compte={score} aria-hidden="true">0</span>
				<span class="sr-only">{score}</span>
			</p>
			<p>{t(locale, 'jeu.resultat', { bons: bonnes, total: questions.length })}</p>
			<p class="actions">
				<button class="btn" onclick={rejouer}>{t(locale, 'jeu.rejouer')}</button>
				<a class="btn" href={chemin(locale, 'je', 'lakou')}>{t(locale, 'jeu.album')}</a>
			</p>
		</section>
	{:else if q}
		<header class="entete">
			<h1 lang="gcf">{t(locale, 'jeu.rekonet')}</h1>
			<p class="muted">{index + 1} / {questions.length} — {t(locale, 'jeu.score')} : {score}</p>
		</header>

		<figure class="photo">
			<img src={q.photo.fichier_local ?? ''} alt={t(locale, 'jeu.question')} />
			<figcaption class="muted petit">
				{q.photo.auteur} — {q.photo.licence}
			</figcaption>
		</figure>

		<section aria-labelledby="question-titre">
			<h2 id="question-titre">{t(locale, 'jeu.question')}</h2>
			<ul class="choix">
				{#each q.choix as choix (choix.id)}
					<li>
						<button
							class="btn reponse"
							class:juste={reponse && choix.id === q.cible.id}
							class:faux={reponse === choix && choix.id !== q.cible.id}
							disabled={!!reponse}
							onclick={() => choisir(choix)}
						>
							<span lang="gcf">{choix.noms.gcf}</span>
						</button>
					</li>
				{/each}
			</ul>
		</section>

		<div class="revelation" aria-live="polite">
			{#if reponse}
				<p class="verdict" class:ok={correct}>
					{correct ? t(locale, 'jeu.bonne-reponse') : t(locale, 'jeu.mauvaise-reponse')}
				</p>
				<p>{t(locale, 'jeu.reponse-etait', { nom: q.cible.noms.gcf })}</p>
				<p class="actions">
					<button class="btn" onclick={suivant}>{t(locale, 'jeu.suivant')}</button>
					<a href={chemin(locale, 'zerbaj', q.cible.id)}>{t(locale, 'zerbaj.voir')}</a>
				</p>
			{/if}
		</div>
	{/if}
</div>

<style>
	.jeu {
		max-width: 44rem;
	}

	.fil {
		font-size: 0.85rem;
	}

	.bloque {
		padding: var(--space-3);
		background: var(--card-bg);
		border: var(--border-card);
		border-left: 4px solid var(--or-oki);
		border-radius: var(--radius-sm);
	}

	.chiffre strong {
		font-family: var(--font-display);
		font-size: 1.3rem;
		color: var(--or-oki);
	}

	.photo {
		margin: 0 0 var(--space-3);
	}

	.photo img {
		width: 100%;
		border-radius: var(--radius-sm);
		border: var(--border-card);
	}

	.choix {
		display: grid;
		gap: var(--space-1);
		grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
		list-style: none;
		margin: 0;
		padding: 0;
	}

	.reponse {
		width: 100%;
		font-size: 1.05rem;
	}
	.reponse.juste {
		border-color: var(--vert-oki);
		color: var(--vert-oki);
	}
	.reponse.juste::after {
		background: var(--vert-oki);
	}
	.reponse.faux {
		border-color: var(--rouge-oki);
		color: var(--rouge-oki);
	}
	.reponse.faux::after {
		background: var(--rouge-oki);
	}
	.reponse[disabled] {
		opacity: 1;
	}

	.revelation {
		margin-top: var(--space-3);
		min-height: 6rem;
	}

	.verdict {
		font-family: var(--font-display);
		font-size: 1.2rem;
		text-transform: uppercase;
		color: var(--rouge-oki);
		margin-bottom: 0.25rem;
	}
	.verdict.ok {
		color: var(--vert-oki);
	}

	.actions {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: var(--space-2);
		margin-top: var(--space-2);
	}

	.btn--sobre {
		color: var(--blanc-creme);
		border-color: var(--line);
	}

	.bilan {
		text-align: center;
	}

	.gros {
		font-family: var(--font-display);
		font-size: clamp(3rem, 12vw, 6rem);
		color: var(--or-oki);
		margin: var(--space-2) 0;
		line-height: 1;
	}

	.petit {
		font-size: 0.85rem;
	}
</style>
