// historie.jsx — Archiv (#archiv): Ergebnisse vergangener Auflagen.
// Uebersicht: eine typografische Jahres-Karte je Auflage (archiv/index.json,
// bewusst OHNE Foto, damit es sich von der Fotogalerie abhebt). Auflage
// (#archiv/<id>): Meldeliste + Tableau der Auflage, read-only, aus den
// statischen JSON-Dateien in archiv/<id>/ (Export per
// tools/archive_edition.py aus registrations_public + bracket_state).
// Kein Supabase, kein Admin: die Live-Tabellen gehoeren dem laufenden
// Turnier, das Archiv ist eingefroren und liegt im Repo.

// 2026 hatte eine Konkurrenz; die Archiv-Daten liegen unter 'A'.
const ARCHIVE_COMPS = [{ id: 'A', label: 'Herren', row: 1 }];

async function loadArchiveIndex() {
  try {
    const res = await fetch('archiv/index.json?v=' + Date.now());
    if (!res.ok) throw new Error(res.status);
    return await res.json();
  } catch (e) { console.error('Ergebnisse laden fehlgeschlagen', e); return null; }
}

async function loadArchiveEdition(edition) {
  try {
    const [r, b] = await Promise.all([
      fetch(edition.files.registrations + '?v=' + Date.now()),
      fetch(edition.files.bracket + '?v=' + Date.now()),
    ]);
    if (!r.ok || !b.ok) throw new Error(r.status + '/' + b.status);
    return { rows: await r.json(), bracket: await b.json() };
  } catch (e) { console.error('Auflage laden fehlgeschlagen', e); return null; }
}

// registrations_public-Zeilen (birth_year statt birthdate) -> App-Format.
function archiveRegs(rows) {
  return rows.map((row) => {
    const r = regFromRow(row);
    r.p1.birthdate = row.p1_birth_year ? row.p1_birth_year + '-01-01' : '';
    r.p2.birthdate = row.p2_birth_year ? row.p2_birth_year + '-01-01' : '';
    return r;
  });
}

function regsIndex(regs) {
  const o = {};
  regs.forEach((r) => { o[r.id] = r; });
  return o;
}

// Sieger eines Buckets (Finale = letzte Runde, Match 0), sonst null.
function archiveWinner(bracket, bucket, regsById) {
  const rounds = bracket && bracket[bucket];
  if (!rounds || !rounds.length) return null;
  const fin = rounds[rounds.length - 1][0];
  if (!fin || fin.winner == null) return null;
  const id = fin.winner === 0 ? fin.p1 : fin.p2;
  const reg = regsById[id];
  return reg ? pairLabel(reg) : null;
}

// Auflage komplett laden und aufbereiten (fuer Karte und Detailseite).
async function loadEditionSummary(edition) {
  const d = await loadArchiveEdition(edition);
  if (d === null) return null;
  const regs = archiveRegs(d.rows);
  const byId = regsIndex(regs);
  return {
    regs,
    bracket: d.bracket,
    winner: archiveWinner(d.bracket, 'main', byId),
    consWinner: archiveWinner(d.bracket, 'cons', byId),
  };
}

// Karte im gleichen Aufbau wie die Galerie-Alben: dunkler Titelbalken mit
// Icon, statt Foto ein Panel mit Sieger, Pille oben rechts (Paarungen),
// Beschreibung darunter.
function EditionCard({ edition, summary, onOpen }) {
  return (
    <article
      className="album-card ed-card"
      role="link"
      tabIndex={0}
      onClick={onOpen}
      onKeyDown={(e) => { if (e.key === 'Enter') onOpen(); }}
    >
      <div className="album-bar"><Icon name="trophy" size={26}/><span>{edition.title}</span></div>
      <div className={'album-cover ed-panel' + (edition.photo ? ' has-photo' : '')} style={edition.photo ? { backgroundImage: `url(${edition.photo})` } : undefined}>
        <div className="ed-panel-inner">
          <div className="ed-year">{edition.id}</div>
          <div className="ed-main">Meldeliste &amp; Tableau <Icon name="arrow-right" size={18}/></div>
        </div>
      </div>
      {summary && summary.winner && (
        <div className="ed-winner-bar">
          <Icon name="award" size={18}/>
          <span className="ed-winner-lbl">Sieger</span>
          <span className="ed-winner-names">{summary.winner}</span>
        </div>
      )}
      {edition.subtitle ? <div className="album-meta"><div className="album-sub ed-date"><Icon name="calendar" size={16}/><span>{edition.subtitle}</span></div></div> : null}
    </article>
  );
}

function EditionView({ edition, summary, onBack }) {
  const [tab, setTab] = React.useState('tableau'); // 'tableau' | 'meldeliste'
  // Phone: keine Tabs, Tableau und Meldeliste einfach untereinander.
  const [stacked, setStacked] = React.useState(() => window.matchMedia('(max-width: 600px)').matches);
  React.useEffect(() => {
    const mq = window.matchMedia('(max-width: 600px)');
    const onChange = (e) => setStacked(e.matches);
    mq.addEventListener('change', onChange);
    return () => mq.removeEventListener('change', onChange);
  }, []);
  const showTableau = stacked || tab === 'tableau';
  const showMeldeliste = stacked || tab === 'meldeliste';
  // Setzliste: manuelle seed-Werte, sonst (Archiv 2026) wie damals nach LK.
  const seeds = React.useMemo(() => {
    if (!summary) return {};
    const size = bracketSize(summary.bracket);
    const manual = seedsFor(summary.regs, size);
    if (Object.keys(manual).length) return manual;
    const out = {};
    sortedBySeed(mainFieldRegs(summary.regs, size)).slice(0, seedCountFor(size)).forEach((r, i) => { out[r.id] = i + 1; });
    return out;
  }, [summary]);

  return (
    <React.Fragment>
      <div className="page hist-head">
        <div className="page-eyebrow">
          <button type="button" className="album-back" onClick={onBack}><Icon name="arrow-left" size={16}/> Zurück zum Archiv</button>
        </div>
        <h1 className="page-title">{edition.title}</h1>
        {summary === null && <p className="page-sub">Archiv konnte nicht geladen werden. Bitte Seite neu laden.</p>}
        {summary === undefined && <p className="page-sub">Archiv wird geladen …</p>}
        {summary && !stacked && (
          <div className="tab-toggle comp-switch hist-tabs" role="tablist">
            <button className={tab === 'tableau' ? 'on' : ''} onClick={() => setTab('tableau')}>Tableau</button>
            <button className={tab === 'meldeliste' ? 'on' : ''} onClick={() => setTab('meldeliste')}>Meldeliste</button>
          </div>
        )}
      </div>
      {summary && showTableau && (
        <TableauPage brackets={{ A: summary.bracket }} registrations={summary.regs} seedsByComp={{ A: seeds }}
                     bracketPublished={{ A: true }} competitions={ARCHIVE_COMPS} isAdmin={false} loaded={true} archive={true} />
      )}
      {summary && showMeldeliste && (
        <MeldelistePage registrations={summary.regs} seedsByComp={{ A: seeds }} fieldSize={{ A: bracketSize(summary.bracket) }}
                        competitions={ARCHIVE_COMPS} isAdmin={false} loaded={true} archive={true} />
      )}
    </React.Fragment>
  );
}

function HistoriePage({ editionId, onNav }) {
  const [editions, setEditions] = React.useState(null);
  const [summaries, setSummaries] = React.useState({}); // id -> summary | null (Fehler)
  const [failed, setFailed] = React.useState(false);

  React.useEffect(() => {
    let alive = true;
    loadArchiveIndex().then(async (list) => {
      if (!alive) return;
      if (list === null) { setFailed(true); return; }
      setEditions(list);
      // Alle Auflagen nachladen (statische JSON, klein): Sieger + Anzahl fuer
      // die Karten, komplette Daten fuer die Detailseite.
      const results = await Promise.all(list.map((e) => loadEditionSummary(e)));
      if (!alive) return;
      const map = {};
      list.forEach((e, i) => { map[e.id] = results[i]; });
      setSummaries(map);
    });
    return () => { alive = false; };
  }, []);

  const shell = (text) => (
    <div className="page">
      <div className="page-eyebrow">Turnierarchiv</div>
      <h1 className="page-title">Archiv</h1>
      <p className="page-sub">{text}</p>
    </div>
  );
  if (failed) return shell('Archiv konnte nicht geladen werden. Bitte Seite neu laden.');
  if (editions === null) return shell('Archiv wird geladen …');

  const edition = editionId ? editions.find((e) => e.id === editionId) : null;
  if (edition) {
    return <EditionView edition={edition} summary={summaries[edition.id]} onBack={() => onNav('archiv')} />;
  }

  return (
    <div className="page">
      <div className="page-eyebrow">Turnierarchiv</div>
      <h1 className="page-title">Archiv</h1>
      <MediaSwitch active="archiv" onNav={onNav} />
      <p className="page-sub">Meldelisten, Tableaus und Sieger aller bisherigen Paartal Open.</p>
      {editionId && <p className="page-sub">Turnier nicht gefunden.</p>}
      <div className="ed-grid">
        {editions.map((e) => (
          <EditionCard key={e.id} edition={e} summary={summaries[e.id]} onOpen={() => onNav('archiv/' + e.id)} />
        ))}
      </div>
    </div>
  );
}

// Design-Archiv (#design, dezent im Footer verlinkt): Screenshots der
// Startseiten frueherer Auflagen, damit die alten Styles anschaubar bleiben.
function DesignArchivPage() {
  const [editions, setEditions] = React.useState(null);
  React.useEffect(() => { loadArchiveIndex().then((list) => setEditions(list || [])); }, []);
  const withDesign = (editions || []).filter((e) => e.design);
  return (
    <div className="page page-narrow">
      <div className="page-eyebrow">Archiv</div>
      <h1 className="page-title">Design-Archiv</h1>
      <p className="page-sub">So sah paartal-open.de bei den bisherigen Auflagen aus.</p>
      {editions === null && <p className="page-sub">Wird geladen …</p>}
      {editions !== null && withDesign.length === 0 && <p className="page-sub">Noch keine Einträge.</p>}
      {withDesign.map((e) => (
        <section key={e.id} className="hist-design">
          <h2 className="hist-design-title">{e.title} ({e.id})</h2>
          {e.designNote ? <p className="page-sub">{e.designNote}</p> : null}
          <div className="hist-design-frame">
            <img src={e.design} alt={'Website ' + e.title} loading="lazy" />
          </div>
        </section>
      ))}
    </div>
  );
}

Object.assign(window, { HistoriePage, DesignArchivPage });
