<script lang="ts">
  import { etichettaStato, etichettaTipo, etichettaIscrizione, formattaPunti, plurale } from '$lib/labels';
  import { enhance } from '$app/forms';
  import type { SubmitFunction } from '@sveltejs/kit';
  let { data, form }: { data: import('./$types').PageData; form: import('./$types').ActionData } = $props();

  // Alcune operazioni (generare il calendario, importare) durano parecchi secondi.
  // Senza un segnale l'admin pensa che il click non abbia fatto nulla e riclicca,
  // e rigenerare cancella i risultati già inseriti.
  let azione = $state<string | null>(null);
  const inCorso = (nome: string) => azione === nome;
  const conAttesa =
    (nome: string): SubmitFunction =>
    () => {
      azione = nome;
      return async ({ update }) => {
        await update();
        azione = null;
      };
    };

  const statoBadge: Record<string, string> = {
    bozza: 'var(--color-sepia)',
    iscrizioni: 'var(--color-verderame)',
    in_corso: 'var(--color-bronzo)',
    concluso: 'var(--color-inchiostro)'
  };
  const nextStates: Record<string, [string, string][]> = {
    bozza: [['iscrizioni', 'Apri iscrizioni']],
    iscrizioni: [['in_corso', 'Avvia (in corso)'], ['bozza', 'Torna a bozza']],
    in_corso: [['concluso', 'Concludi'], ['iscrizioni', 'Riapri iscrizioni']],
    concluso: []
  };

  // L'anteprima dell'import CGE torna solo da quella action: restringo il tipo invece di assumerlo.
  const cgePreview = $derived(form && 'cgePreview' in form ? form.cgePreview : null);
  const cgeCsv = $derived(form && 'cgeCsv' in form ? form.cgeCsv : '');

  const confermati = $derived(data.registrations.filter((r) => r.stato === 'confermata').length);
  const hasGironi = $derived(data.gironi.length > 0);
  const aRischio = $derived(data.datiARischio.partiteConcluse + data.datiARischio.classifiche);
  const hasImportCge = $derived(data.gironi.some((g) => g.daCge));
  // Le proposte promo/retro arrivano con il solo playerId: il nome sta nelle classifiche.
  const nomiPlayer = $derived(
    new Map(
      data.gironi.flatMap((g) => g.standings.map((s) => [s.playerId, s.nomeAppTta] as const))
    )
  );
  const card = 'p-5 rounded-[var(--radius-card)] mb-6';
  const cardStyle = 'background:var(--color-carta);box-shadow:var(--shadow-soft)';
  const h2 = 'text-lg font-[var(--font-display)] mb-3';
</script>

<svelte:head>
  <title>{data.event.nome} · Tornei TtA Tana dei Goblin</title>
</svelte:head>

<a href="/admin" class="text-sm hover:underline" style="color:var(--color-bronzo)">← Eventi</a>

<div class="flex flex-wrap items-center gap-3 my-3">
  <h1 class="text-2xl font-[var(--font-display)]" style="color:var(--color-inchiostro)">{data.event.nome}</h1>
  <span class="text-xs px-2 py-1 rounded-full" style="background:color-mix(in srgb, {statoBadge[data.event.stato]} 18%, transparent);color:{statoBadge[data.event.stato]}">{etichettaStato(data.event.stato)}</span>
  <span class="text-sm" style="color:var(--color-sepia)">{etichettaTipo(data.event.tipo)}</span>
</div>

<div aria-live="polite">
  {#if form?.msg}
    <p class="mb-4 text-sm p-3 rounded" role="status" style="background:color-mix(in srgb, var(--color-verderame) 12%, transparent);color:var(--color-verderame)">{form.msg}</p>
  {/if}
  {#if form?.error}
    <p class="mb-4 text-sm p-3 rounded" role="alert" style="background:color-mix(in srgb, var(--color-oxblood) 10%, transparent);color:var(--color-oxblood)">{form.error}</p>
  {/if}
</div>

<!-- Stato / transizioni -->
{#if nextStates[data.event.stato]?.length}
  <div class="flex flex-wrap gap-2 mb-6">
    {#each nextStates[data.event.stato] as [stato, label]}
      <form method="POST" action="?/stato" use:enhance={conAttesa('stato')}>
        <input type="hidden" name="stato" value={stato} />
        <button class="px-3 py-1.5 rounded text-sm border disabled:opacity-50" style="border-color:var(--color-bronzo);color:var(--color-bronzo)" disabled={azione !== null}>{label}</button>
      </form>
    {/each}
  </div>
{/if}

<!-- Iscritti -->
<section class={card} style={cardStyle}>
  <h2 class={h2} style="color:var(--color-bronzo)">Iscritti ({data.registrations.length}, di cui {confermati} confermati)</h2>
  {#if data.registrations.length}
    <div class="overflow-x-auto mb-4">
      <table class="w-full text-sm">
        <tbody>
          {#each data.registrations as r}
            <tr style="border-bottom:1px solid color-mix(in srgb, var(--color-sepia) 12%, transparent)">
              <td class="py-1.5" style="color:var(--color-inchiostro)">{r.nomeAppTta}</td>
              <td class="py-1.5" style="color:var(--color-sepia)">{etichettaIscrizione(r.stato)}</td>
              <td class="py-1.5 text-right">
                {#if r.stato !== 'confermata'}
                  <form method="POST" action="?/regStato" use:enhance={conAttesa('reg')} class="inline">
                    <input type="hidden" name="regId" value={r.id} /><input type="hidden" name="stato" value="confermata" />
                    <button class="text-xs hover:underline" style="color:var(--color-verderame)">conferma</button>
                  </form>
                {/if}
                {#if r.stato !== 'in_coda'}
                  <form method="POST" action="?/regStato" use:enhance={conAttesa('reg')} class="inline ml-2">
                    <input type="hidden" name="regId" value={r.id} /><input type="hidden" name="stato" value="in_coda" />
                    <button class="text-xs hover:underline" style="color:var(--color-sepia)">→ coda</button>
                  </form>
                {/if}
                <form method="POST" action="?/regStato" use:enhance={conAttesa('reg')} class="inline ml-2">
                  <input type="hidden" name="regId" value={r.id} /><input type="hidden" name="stato" value="rifiutata" />
                  <button class="text-xs hover:underline" style="color:var(--color-oxblood)">rifiuta</button>
                </form>
              </td>
            </tr>
          {/each}
        </tbody>
      </table>
    </div>
  {:else}
    <p class="text-sm mb-4" style="color:var(--color-sepia)">Nessun iscritto.</p>
  {/if}

  {#if data.players.length}
    <form method="POST" action="?/addReg" use:enhance={conAttesa('addReg')} class="flex items-center gap-2">
      <select name="playerId" class="border p-2 rounded text-sm" style="border-color:color-mix(in srgb, var(--color-sepia) 40%, transparent)">
        {#each data.players as p}<option value={p.id}>{p.nomeAppTta}</option>{/each}
      </select>
      <button class="px-3 py-2 rounded text-white text-sm disabled:opacity-50" style="background:var(--color-verderame)" disabled={azione !== null}>{inCorso('addReg') ? 'Aggiungo…' : '+ Aggiungi (confermato)'}</button>
    </form>
  {/if}
</section>

<!-- Generazione -->
<section class={card} style={cardStyle}>
  <h2 class={h2} style="color:var(--color-bronzo)">Gironi e calendario</h2>
  <form method="POST" action="?/genera" use:enhance={conAttesa('genera')} class="flex flex-col gap-3">
    {#if aRischio > 0}
      <p class="text-sm p-3 rounded" style="background:color-mix(in srgb, var(--color-oxblood) 10%, transparent);color:var(--color-oxblood)">
        Attenzione: rigenerare cancella
        {#if data.datiARischio.partiteConcluse}<strong>{plurale(data.datiARischio.partiteConcluse, 'partita già conclusa', 'partite già concluse')}</strong>{/if}
        {#if data.datiARischio.partiteConcluse && data.datiARischio.classifiche} e {/if}
        {#if data.datiARischio.classifiche}<strong>{plurale(data.datiARischio.classifiche, 'riga di classifica', 'righe di classifica')}</strong>{/if}.
        Non si torna indietro.
      </p>
      <label class="flex items-center gap-1.5 text-sm" style="color:var(--color-inchiostro)">
        <input type="checkbox" name="forza" />
        Ho capito, cancella e rigenera
      </label>
    {/if}
    <div>
      <button class="px-4 py-2 rounded text-white text-sm disabled:opacity-50" style="background:var(--color-bronzo)" disabled={confermati === 0 || azione !== null}>
        {#if inCorso('genera')}Genero gironi e calendario…{:else}{hasGironi ? 'Rigenera' : 'Seeding + genera'} gironi e calendario{/if}
      </button>
      {#if confermati === 0}<span class="ml-2 text-xs" style="color:var(--color-sepia)">(servono iscritti confermati)</span>{/if}
    </div>
  </form>
</section>

<!-- Import classifiche da CGE Online: inutile finché l'evento è in bozza o non ha una fase -->
{#if data.phase && data.event.stato !== 'bozza'}
<section class={card} style={cardStyle}>
  <h2 class={h2} style="color:var(--color-bronzo)">Import classifiche da CGE Online</h2>
  <p class="text-sm mb-3" style="color:var(--color-sepia)">
    Su CGE, dalla pagina del torneo: <strong>Manage → Download results</strong> (lo vede solo chi modera
    il torneo). Il file è una fotografia dello stato corrente, quindi si può ricaricare quante volte
    serve: ogni import <strong>sostituisce</strong> le classifiche di questa fase.
  </p>

  <form method="POST" action="?/cgeAnteprima" enctype="multipart/form-data" use:enhance={conAttesa('cgeAnteprima')} class="flex flex-col gap-2">
    <input type="file" name="file" accept=".csv,text/csv" class="text-sm" aria-label="File CSV esportato da CGE" />
    <textarea
      name="csv"
      rows="3"
      placeholder="…oppure incolla qui il contenuto del CSV"
      aria-label="Contenuto del CSV"
      class="w-full border rounded p-2 text-sm font-mono"
      style="border-color:color-mix(in srgb, var(--color-sepia) 40%, transparent)"
      value={cgeCsv}
    ></textarea>
    <div>
      <button class="px-4 py-2 rounded text-white text-sm disabled:opacity-50" style="background:var(--color-bronzo)" disabled={azione !== null}>{inCorso('cgeAnteprima') ? 'Leggo il file…' : 'Anteprima'}</button>
    </div>
  </form>

  {#if cgePreview}
    <div class="mt-4 p-3 rounded text-sm" style="background:color-mix(in srgb, var(--color-pergamena) 60%, transparent)">
      <p style="color:var(--color-inchiostro)">
        <strong>{cgePreview.totaleRighe}</strong> righe in <strong>{cgePreview.gruppi.length}</strong> {cgePreview.gruppi.length === 1 ? 'girone' : 'gironi'}.
        Giocatori riconosciuti: <strong>{cgePreview.giocatoriRiconosciuti}</strong>.
      </p>

      <ul class="mt-2 flex flex-wrap gap-x-3 gap-y-1 text-xs" style="color:var(--color-sepia)">
        {#each cgePreview.gruppi as g}
          <li>{g.etichetta}: {g.dimensione} giocatori {g.gironeEsistente ? '(girone esistente)' : '(nuovo)'}</li>
        {/each}
      </ul>

      {#if cgePreview.classificheDaSostituire > 0}
        <p class="mt-2" style="color:var(--color-oxblood)">
          Verranno sostituite {cgePreview.classificheDaSostituire} righe di classifica già presenti.
        </p>
      {/if}

      {#if cgePreview.giocatoriNuovi.length}
        <p class="mt-2" style="color:var(--color-oxblood)">
          Da creare {cgePreview.giocatoriNuovi.length} giocatori mai visti: {cgePreview.giocatoriNuovi.join(', ')}.
          Se sono tanti, controlla di aver preso il file del torneo giusto.
        </p>
      {/if}

      {#if cgePreview.partiteConcluseIgnorate > 0}
        <p class="mt-2" style="color:var(--color-oxblood)">
          Questa fase ha {cgePreview.partiteConcluseIgnorate} partite già concluse nel portale: dopo l'import
          la classifica arriva da CGE e i risultati manuali restano lì senza più contare.
        </p>
      {/if}

      {#if cgePreview.gironiSenzaDatiNelCsv.length}
        <p class="mt-2" style="color:var(--color-sepia)">
          Gironi già presenti ma assenti dal file: {cgePreview.gironiSenzaDatiNelCsv.join(', ')}. Resteranno senza classifica.
        </p>
      {/if}

      {#each cgePreview.warnings as w}
        <p class="mt-2" style="color:var(--color-oxblood)">⚠ {w}</p>
      {/each}

      <form method="POST" action="?/cgeImporta" use:enhance={conAttesa('cgeImporta')} class="mt-3 flex flex-wrap items-center gap-3">
        <input type="hidden" name="csv" value={cgeCsv} />
        <label class="flex items-center gap-1.5 text-sm" style="color:var(--color-inchiostro)">
          <input type="checkbox" name="conferma" />
          Confermo la sostituzione
        </label>
        <button class="px-4 py-2 rounded text-white text-sm disabled:opacity-50" style="background:var(--color-verderame)" disabled={azione !== null}>{inCorso('cgeImporta') ? 'Importo…' : 'Importa'}</button>
      </form>
    </div>
  {/if}

  {#if hasImportCge}
    <form method="POST" action="?/cgeSvuota" use:enhance={conAttesa('cgeSvuota')} class="mt-4 pt-4" style="border-top:1px solid color-mix(in srgb, var(--color-sepia) 15%, transparent)">
      <p class="text-sm mb-2" style="color:var(--color-sepia)">
        Finché la classifica arriva da CGE, i risultati delle singole partite non si possono inserire a mano
        (li cancellerebbe). Se preferisci gestirli qui, svuota l'import.
      </p>
      <button class="px-3 py-1.5 rounded text-sm border disabled:opacity-50" style="border-color:var(--color-oxblood);color:var(--color-oxblood)" disabled={azione !== null}>
        {inCorso('cgeSvuota') ? 'Rimuovo…' : 'Svuota le classifiche importate'}
      </button>
    </form>
  {/if}
</section>
{/if}

<!-- Gironi -->
{#each data.gironi as g}
  <section class={card} style={cardStyle}>
    <h2 class={h2} style="color:var(--color-inchiostro)">
      Serie {g.livello} <span class="text-sm font-normal" style="color:var(--color-sepia)">· {g.dimensione} giocatori · ranking da {g.rankBase}{g.isCoda ? ' · Coda' : ''}</span>
    </h2>

    {#if g.standings.length}
      <h3 class="text-sm font-semibold mb-1" style="color:var(--color-bronzo)">Classifica</h3>
      <table class="w-full text-sm mb-4">
        <thead><tr style="color:var(--color-sepia)"><th class="text-left">#</th><th class="text-left">Giocatore</th><th class="text-right">Punti</th><th class="text-right">Spareggio</th></tr></thead>
        <tbody>
          {#each g.standings as s}
            <tr><td>{s.posizioneFinale}</td><td style="color:var(--color-inchiostro)">{s.nomeAppTta}</td><td class="text-right">{formattaPunti(s.puntiTorneo)}</td><td class="text-right" style="color:var(--color-sepia)">{s.puntiSpareggio?.toFixed(2)}</td></tr>
          {/each}
        </tbody>
      </table>
    {/if}

    {#if g.daCge}
      <p class="text-sm p-3 rounded" style="background:color-mix(in srgb, var(--color-bronzo) 10%, transparent);color:var(--color-bronzo)">
        Classifica importata da CGE Online. Per aggiornarla ricarica il CSV: i risultati inseriti qui
        verrebbero ignorati e cancellerebbero quello che CGE ha già deciso.
      </p>
    {:else if g.matches.length}
      <h3 class="text-sm font-semibold mb-2" style="color:var(--color-bronzo)">Partite ({g.matches.length})</h3>
      <div class="flex flex-col gap-2">
        {#each g.matches as m}
          <form method="POST" action="?/risultato" use:enhance={conAttesa('match-' + m.id)} class="flex flex-wrap items-center gap-2 p-2 rounded text-sm" style="background:color-mix(in srgb, var(--color-pergamena) 60%, transparent)">
            <input type="hidden" name="matchId" value={m.id} />
            <span class="text-xs px-1.5 py-0.5 rounded" style="background:color-mix(in srgb, var(--color-bronzo) 14%, transparent);color:var(--color-bronzo)">{m.nGiocatori}p · {m.stato}</span>
            {#each m.partecipanti as p}
              <input type="hidden" name="participantId" value={p.id} />
              <span class="flex items-center gap-1">
                <span style="color:var(--color-inchiostro)">{p.nomeAppTta ?? 'bot'}</span>
                <input name={`cultura_${p.id}`} type="number" aria-label={`Punti cultura di ${p.nomeAppTta ?? 'bot'}`} class="w-16 border rounded px-1 py-0.5" style="border-color:color-mix(in srgb, var(--color-sepia) 40%, transparent)" value={p.puntiCultura ?? ''} placeholder="cult." />
                <label class="text-xs flex items-center gap-0.5" style="color:var(--color-sepia)"><input name={`resign_${p.id}`} type="checkbox" checked={p.resign} aria-label={`Resa di ${p.nomeAppTta ?? 'bot'}`} />res</label>
              </span>
            {/each}
            <button class="px-2 py-1 rounded text-white text-xs disabled:opacity-50" style="background:var(--color-verderame)" disabled={azione !== null}>{inCorso('match-' + m.id) ? 'salvo…' : 'salva'}</button>
          </form>
        {/each}
      </div>
    {:else if !g.isCoda}
      <p class="text-sm" style="color:var(--color-sepia)">Calendario non ancora generato.</p>
    {/if}
  </section>
{/each}

<!-- Promo/retro -->
{#if data.promoRetro.some((p) => p.mossa !== 'stay')}
  <section class={card} style={cardStyle}>
    <h2 class={h2} style="color:var(--color-bronzo)">Proposte promo/retrocessione (assistite)</h2>
    <table class="w-full text-sm">
      <thead><tr style="color:var(--color-sepia)"><th class="text-left">Serie</th><th class="text-left">Pos</th><th class="text-left">Giocatore</th><th class="text-left">Mossa</th></tr></thead>
      <tbody>
        {#each data.promoRetro.filter((p) => p.mossa !== 'stay') as p}
          <tr>
            <td>{p.livello}</td><td>{p.posizione}</td><td style="color:var(--color-inchiostro)">{nomiPlayer.get(p.playerId) ?? `#${p.playerId}`}</td>
            <td style="color:{p.mossa === 'promo' ? 'var(--color-verderame)' : 'var(--color-oxblood)'}">{p.mossa === 'promo' ? '▲ promo' : '▼ retro'}</td>
          </tr>
        {/each}
      </tbody>
    </table>
    <p class="text-xs mt-2" style="color:var(--color-sepia)">In V1 le promo/retro sono proposte (l'admin valuta). Le regole definitive sono in mano all'organizzazione.</p>
  </section>
{/if}

<!-- Chiusura stagione (solo da 'in corso') -->
{#if hasGironi && data.event.stato === 'in_corso'}
  <section class={card} style={cardStyle}>
    <h2 class={h2} style="color:var(--color-bronzo)">Chiusura stagione</h2>
    <p class="text-sm mb-3" style="color:var(--color-sepia)">Scrive il Ranking persistente dalle classifiche finali e marca l'evento come concluso.</p>
    <form method="POST" action="?/chiudi" use:enhance={conAttesa('chiudi')}>
      <button class="px-4 py-2 rounded text-white text-sm disabled:opacity-50" style="background:var(--color-oxblood)" disabled={azione !== null}>{inCorso('chiudi') ? 'Chiudo la stagione…' : 'Chiudi stagione e scrivi ranking'}</button>
    </form>
  </section>
{/if}
