/* global React, Icon, EINHEIT_SUGGESTIONS, SEASON_MONTHS, WEEKDAYS_DE, WEEKDAYS_SHORT, weekdayOf, formatDateDE */
const { useState: useStateJP, useMemo: useMemoJP, useEffect: useEffectJP } = React;

function initials(name) {
  return name.split(/\s+/).map(s => s[0]).filter(Boolean).slice(0, 2).join("").toUpperCase();
}

// Build the trainer columns: assigned trainers (key = id) + guests (key = id)
function buildColumns(trainers, guests) {
  const cols = [];
  trainers.forEach(t => cols.push({ key: t.id, name: t.name, kuerzel: initials(t.name), guest: false }));
  (guests || []).forEach(g => cols.push({ key: g.id, name: g.name, kuerzel: (g.kuerzel || initials(g.name)), guest: true }));
  return cols;
}

function JahresplanPage({ className, yearPlan, onChange, trainers, einheiten, onEinheitenChange, players }) {
  const [tab, setTab] = useStateJP("plan");
  const [showSeries, setShowSeries] = useStateJP(false);
  const [showGuest, setShowGuest] = useStateJP(false);
  const [showEinheiten, setShowEinheiten] = useStateJP(false);
  const [pickerId, setPickerId] = useStateJP(null);
  const [lineupId, setLineupId] = useStateJP(null);
  const [pendingDel, setPendingDel] = useStateJP(null);

  const plan = yearPlan || { guests: [], sessions: [] };
  const guests = plan.guests || [];
  const sessions = plan.sessions || [];
  const einheitList = einheiten || [];
  const playerList = players || [];
  const cols = useMemoJP(() => buildColumns(trainers, guests), [trainers, guests]);

  const lineupCount = (s) => (s.lineup && s.lineup.teams ? s.lineup.teams.reduce((a, t) => a + (t.playerIds ? t.playerIds.length : 0), 0) : 0);
  const lineupTeams = (s) => (s.lineup && s.lineup.teams ? s.lineup.teams.length : 0);

  const sorted = useMemoJP(
    () => sessions.slice().sort((a, b) => (a.date || "").localeCompare(b.date || "")),
    [sessions]
  );

  const update = (patch) => onChange({ ...plan, ...patch });
  const setSessions = (next) => update({ sessions: next });

  const addSession = (date) => {
    const d = date || new Date().toISOString().slice(0, 10);
    setSessions([...sessions, { id: "s_" + Date.now() + "_" + Math.random().toString(36).slice(2, 6), date: d, einheit: "", zyklus: 1, bemerkung: "", attendance: {} }]);
  };
  const patchSession = (id, patch) => setSessions(sessions.map(s => s.id === id ? { ...s, ...patch } : s));
  const removeSession = (id) => setSessions(sessions.filter(s => s.id !== id));

  // Cycle attendance: undefined → present → cancelled → undefined
  const cycleAttendance = (sessionId, key) => {
    const s = sessions.find(x => x.id === sessionId);
    if (!s) return;
    const cur = (s.attendance || {})[key];
    const nextVal = cur === "present" ? "cancelled" : cur === "cancelled" ? undefined : "present";
    const att = { ...(s.attendance || {}) };
    if (nextVal === undefined) delete att[key]; else att[key] = nextVal;
    patchSession(sessionId, { attendance: att });
  };

  const addGuest = (name, kuerzel) => {
    const n = name.trim();
    if (!n) return;
    update({ guests: [...guests, { id: "g_" + Date.now(), name: n, kuerzel: (kuerzel.trim() || initials(n)).toUpperCase() }] });
  };
  const removeGuest = (id) => {
    // also strip their attendance marks
    const cleaned = sessions.map(s => {
      if (!s.attendance || !(id in s.attendance)) return s;
      const att = { ...s.attendance }; delete att[id];
      return { ...s, attendance: att };
    });
    onChange({ ...plan, guests: guests.filter(g => g.id !== id), sessions: cleaned });
  };

  return (
    <div>
      <div className="page-header">
        <div>
          <h1 className="page-title">Jahresplan</h1>
          <p className="page-subtitle">Trainingsübersicht & Trainer-Anwesenheit der Spielklasse {className}.</p>
        </div>
        <div className="view-tabs">
          <button className={"view-tab" + (tab === "plan" ? " active" : "")} onClick={() => setTab("plan")}>Plan</button>
          <button className={"view-tab" + (tab === "stats" ? " active" : "")} onClick={() => setTab("stats")}>Statistik</button>
        </div>
      </div>

      {tab === "plan" && (
        <div>
          <div className="matrix-toolbar">
            <button className="btn" onClick={() => addSession()}><Icon.Plus /> Termin hinzufügen</button>
            <button className="btn btn-secondary" onClick={() => setShowSeries(true)}><Icon.Calendar /> Serie erstellen</button>
            <button className="btn btn-secondary" onClick={() => setShowGuest(true)}><Icon.Users /> Gast-Trainer</button>
            <button className="btn btn-secondary" onClick={() => setShowEinheiten(true)}><Icon.Cog /> Einheiten</button>
            <span className="flex-1" />
            <span className="muted text-sm">{sorted.length} Termine</span>
            <button className="btn btn-secondary btn-sm" onClick={() => window.print()}>Drucken</button>
          </div>

          {sorted.length === 0 ? (
            <div className="card card-pad-lg"><div className="empty-state">
              <h3>Noch keine Termine</h3>
              <p>Füge einzelne Termine hinzu oder generiere eine ganze Serie (z.B. jeden Dienstag + Donnerstag).</p>
            </div></div>
          ) : (
            <div className="matrix-table-wrap">
              <table className="matrix-table jp-table">
                <thead>
                  <tr>
                    <th style={{ minWidth: 130, textAlign: "left", paddingLeft: 14 }}>Datum</th>
                    <th style={{ minWidth: 80 }}>Wochentag</th>
                    <th style={{ minWidth: 150, textAlign: "left" }}>Typ</th>
                    <th style={{ minWidth: 180, textAlign: "left" }}>Einheit</th>
                    <th style={{ width: 64 }}>Zyklus</th>
                    <th style={{ minWidth: 160, textAlign: "left" }}>Bemerkung</th>
                    {cols.map(c => (
                      <th key={c.key} title={c.name} className="jp-trainer-h">
                        {c.kuerzel}{c.guest ? " *" : ""}
                      </th>
                    ))}
                    <th style={{ width: 44 }}></th>
                  </tr>
                </thead>
                <tbody>
                  {sorted.map(s => (
                    <tr key={s.id}>
                      <td style={{ textAlign: "left", paddingLeft: 14 }}>
                        <input type="date" className={"jp-input" + (s.date && s.date < new Date().toISOString().slice(0,10) ? " jp-past" : "")} value={s.date || ""} onChange={(e) => patchSession(s.id, { date: e.target.value })} />
                      </td>
                      <td className="col-num">{weekdayOf(s.date, true)}</td>
                      <td style={{ textAlign: "left" }}>
                        <select className="jp-input" value={s.type || "training"} onChange={(e) => patchSession(s.id, { type: e.target.value })}>
                          <option value="training">Training</option>
                          <option value="turnier">Turnier/Spieltag</option>
                        </select>
                        {s.type === "turnier" && (
                          <React.Fragment>
                            <button className="jp-lineup-btn" onClick={() => setLineupId(s.id)}>
                              <Icon.Shield /> Aufstellung{lineupTeams(s) ? ` · ${lineupTeams(s)} Mannschaften · ${lineupCount(s)} Spieler` : ""}
                            </button>
                            {s.lineup && s.lineup.ort && <div className="text-xs muted" style={{ marginTop: 2 }}>Ort: {s.lineup.ort}</div>}
                          </React.Fragment>
                        )}
                      </td>
                      <td style={{ textAlign: "left" }}>
                        <button className="jp-input jp-einheit-btn" onClick={() => setPickerId(s.id)} title="Einheiten wählen">
                          {s.einheit
                            ? <span className="jp-einheit-chips">{s.einheit.split(",").map(x => x.trim()).filter(Boolean).map((e, i) => <span key={i} className="jp-chip">{e}</span>)}</span>
                            : <span className="muted">Einheit…</span>}
                        </button>
                      </td>
                      <td>
                        <select className="jp-input jp-zyklus" value={s.zyklus || ""} onChange={(e) => patchSession(s.id, { zyklus: e.target.value ? +e.target.value : "" })}>
                          <option value="">–</option>
                          {[1,2,3,4].map(z => <option key={z} value={z}>{z}</option>)}
                        </select>
                      </td>
                      <td style={{ textAlign: "left" }}>
                        <input className="jp-input" placeholder="–" value={s.bemerkung || ""} onChange={(e) => patchSession(s.id, { bemerkung: e.target.value })} />
                      </td>
                      {cols.map(c => {
                        const st = (s.attendance || {})[c.key];
                        return (
                          <td key={c.key}>
                            <button
                              className={"jp-att" + (st === "present" ? " present" : st === "cancelled" ? " cancelled" : "")}
                              onClick={() => cycleAttendance(s.id, c.key)}
                              title={st === "present" ? "Anwesend" : st === "cancelled" ? "Abgesagt" : "Nicht eingetragen"}
                            >
                              {st === "present" ? <Icon.Check /> : st === "cancelled" ? "abg." : ""}
                            </button>
                          </td>
                        );
                      })}
                      <td>
                        <button className="btn btn-icon btn-danger" onClick={() => setPendingDel(s)} title="Termin löschen"><Icon.Trash /></button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}

          {/* legend */}
          <div className="card card-pad mt-3">
            <div className="row gap-3" style={{ flexWrap: "wrap", fontSize: 13 }}>
              <span className="row gap-2"><span className="jp-att present" style={{ pointerEvents: "none" }}><Icon.Check /></span> Anwesend</span>
              <span className="row gap-2"><span className="jp-att cancelled" style={{ pointerEvents: "none" }}>abg.</span> Abgesagt</span>
              <span className="muted">Zelle antippen zum Wechseln · <b>*</b> = Gast-Trainer</span>
              {cols.length > 0 && <span className="muted" style={{ marginLeft: "auto" }}>{cols.map(c => c.kuerzel + " = " + c.name).join(" · ")}</span>}
            </div>
          </div>
        </div>
      )}

      {tab === "stats" && <JahresStats cols={cols} sessions={sessions} players={playerList} />}

      {lineupId && (
        <LineupEditor
          session={sessions.find(s => s.id === lineupId)}
          players={playerList}
          trainers={cols}
          onApply={(lineup) => { patchSession(lineupId, { lineup }); setLineupId(null); }}
          onClose={() => setLineupId(null)}
        />
      )}
      {pickerId && (
        <EinheitPicker
          session={sessions.find(s => s.id === pickerId)}
          einheiten={einheitList}
          onApply={(val) => { patchSession(pickerId, { einheit: val }); setPickerId(null); }}
          onClose={() => setPickerId(null)}
        />
      )}
      {showEinheiten && (
        <EinheitenManager einheiten={einheitList} onChange={onEinheitenChange} onClose={() => setShowEinheiten(false)} />
      )}
      {showSeries && <SeriesModal einheiten={einheitList} onClose={() => setShowSeries(false)} onCreate={(rows) => { setSessions([...sessions, ...rows]); setShowSeries(false); }} />}
      {showGuest && <GuestModal guests={guests} onAdd={addGuest} onRemove={removeGuest} onClose={() => setShowGuest(false)} />}

      {pendingDel && (
        <div className="modal-backdrop" onClick={() => setPendingDel(null)}>
          <div className="modal" style={{ maxWidth: 400 }} onClick={(e) => e.stopPropagation()}>
            <div className="modal-head"><h3>Termin löschen?</h3></div>
            <div className="modal-body"><p style={{ margin: 0, fontSize: 14, lineHeight: 1.5 }}>Termin <strong>{formatDateDE(pendingDel.date)}</strong>{pendingDel.einheit ? <> — {pendingDel.einheit}</> : null} wirklich löschen?</p></div>
            <div className="modal-foot">
              <button className="btn btn-secondary" onClick={() => setPendingDel(null)}>Abbrechen</button>
              <button className="btn" style={{ background: "var(--danger)" }} onClick={() => { removeSession(pendingDel.id); setPendingDel(null); }}>Löschen</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ===== Statistics =====
function JahresStats({ cols, sessions, players }) {
  const stats = useMemoJP(() => {
    return cols.map(c => {
      const monthly = new Array(12).fill(0);
      let present = 0, cancelled = 0;
      sessions.forEach(s => {
        const st = (s.attendance || {})[c.key];
        if (st === "present") {
          present++;
          const d = s.date ? new Date(s.date + "T12:00:00") : null;
          if (d && !isNaN(d)) {
            const idx = SEASON_MONTHS.findIndex(sm => sm.m === d.getMonth());
            if (idx >= 0) monthly[idx]++;
          }
        } else if (st === "cancelled") cancelled++;
      });
      return { ...c, monthly, present, cancelled };
    });
  }, [cols, sessions]);

  const totalSessions = sessions.length;
  const maxPresent = Math.max(1, ...stats.map(s => s.present));

  // ===== Player lineup stats (Turnier/Spieltag) =====
  const playerStats = useMemoJP(() => {
    const pl = players || [];
    const byId = {};
    pl.forEach(p => { byId[p.id] = { id: p.id, name: p.name, einsaetze: 0, mates: {} }; });
    let turnierCount = 0;
    sessions.forEach(s => {
      if (s.type !== "turnier" || !s.lineup || !s.lineup.teams) return;
      turnierCount++;
      s.lineup.teams.forEach(t => {
        const ids = (t.playerIds || []).filter(id => byId[id]);
        ids.forEach(id => { byId[id].einsaetze++; });
        // co-lineup within the same team
        for (let i = 0; i < ids.length; i++) {
          for (let j = i + 1; j < ids.length; j++) {
            byId[ids[i]].mates[ids[j]] = (byId[ids[i]].mates[ids[j]] || 0) + 1;
            byId[ids[j]].mates[ids[i]] = (byId[ids[j]].mates[ids[i]] || 0) + 1;
          }
        }
      });
    });
    const list = Object.values(byId);
    return { list, turnierCount, nameById: (id) => (byId[id] ? byId[id].name : "?") };
  }, [players, sessions]);

  const maxEinsatz = Math.max(1, ...playerStats.list.map(p => p.einsaetze));
  const activePlayers = playerStats.list.filter(p => p.einsaetze > 0).sort((a, b) => b.einsaetze - a.einsaetze);

  if (cols.length === 0) {
    return <div className="card card-pad-lg"><div className="empty-state"><h3>Keine Trainer</h3><p>Dieser Spielklasse sind noch keine Trainer zugeordnet. Lege das in der Administration fest oder füge Gast-Trainer hinzu.</p></div></div>;
  }

  return (
    <div>
      <div className="stat-grid">
        <div className="stat">
          <div className="stat-label">Termine gesamt</div>
          <div className="stat-value">{totalSessions}</div>
          <div className="stat-meta">in dieser Saison</div>
        </div>
        <div className="stat">
          <div className="stat-label">Trainer</div>
          <div className="stat-value">{cols.length}</div>
          <div className="stat-meta">inkl. Gäste</div>
        </div>
        <div className="stat">
          <div className="stat-label">Einsätze gesamt</div>
          <div className="stat-value">{stats.reduce((a, s) => a + s.present, 0)}</div>
          <div className="stat-meta">Summe aller Anwesenheiten</div>
        </div>
      </div>

      {/* Ranking */}
      <div className="card card-pad-lg mb-4">
        <div className="section-h" style={{ margin: "0 0 14px" }}><h3>Anwesenheit pro Trainer</h3><span className="section-meta">Saison gesamt</span></div>
        <div style={{ display: "grid", gap: 10 }}>
          {stats.slice().sort((a, b) => b.present - a.present).map(s => (
            <div key={s.key} className="row gap-3">
              <div className="profile-avatar" style={{ width: 32, height: 32, fontSize: 11 }}>{s.kuerzel}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="row" style={{ justifyContent: "space-between" }}>
                  <span className="fw-600 text-sm">{s.name}{s.guest ? " *" : ""}</span>
                  <span className="text-sm muted">{s.present}× anwesend{s.cancelled ? ` · ${s.cancelled}× abgesagt` : ""}</span>
                </div>
                <div className="history-bar" style={{ flex: "unset", width: "100%", marginTop: 4 }}>
                  <div className="history-bar-fill" style={{ width: ((s.present / maxPresent) * 100) + "%" }} />
                </div>
              </div>
              <div className="fw-700" style={{ fontVariantNumeric: "tabular-nums", minWidth: 28, textAlign: "right" }}>{s.present}</div>
            </div>
          ))}
        </div>
      </div>

      {/* Monthly matrix */}
      <div className="matrix-table-wrap">
        <table className="matrix-table">
          <thead>
            <tr>
              <th style={{ textAlign: "left", paddingLeft: 14, minWidth: 160 }}>Trainer</th>
              {SEASON_MONTHS.map(sm => <th key={sm.label} style={{ width: 42 }}>{sm.label}</th>)}
              <th style={{ width: 56 }}>Summe</th>
            </tr>
          </thead>
          <tbody>
            {stats.map(s => (
              <tr key={s.key}>
                <td className="col-name" style={{ paddingLeft: 14 }}>{s.name}{s.guest ? " *" : ""}</td>
                {s.monthly.map((v, i) => (
                  <td key={i} style={{ color: v ? "var(--text)" : "var(--text-soft)", fontWeight: v ? 700 : 400 }}>{v || "·"}</td>
                ))}
                <td className="fw-700" style={{ background: "var(--ink-50)" }}>{s.present}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {/* ===== Player lineup stats ===== */}
      <div className="section-h" style={{ margin: "28px 0 12px" }}>
        <h3>Spieler-Einsätze</h3>
        <span className="section-meta">{playerStats.turnierCount} Turniere / Spieltage mit Aufstellung</span>
      </div>
      {activePlayers.length === 0 ? (
        <div className="card card-pad-lg"><div className="empty-state">
          <h3>Noch keine Aufstellungen</h3>
          <p>Markiere im Plan einen Termin als „Turnier/Spieltag" und stelle per Drag & Drop Mannschaften auf — dann erscheinen hier die Einsätze.</p>
        </div></div>
      ) : (
        <div>
          <div className="card card-pad-lg mb-4">
            <div style={{ display: "grid", gap: 10 }}>
              {activePlayers.map(p => (
                <div key={p.id} className="row gap-3">
                  <div className="profile-avatar" style={{ width: 30, height: 30, fontSize: 11 }}>{(p.name || "?").split(" ").map(s => s[0]).slice(0,2).join("")}</div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div className="row" style={{ justifyContent: "space-between" }}>
                      <span className="fw-600 text-sm">{p.name}</span>
                      <span className="text-sm muted">{p.einsaetze}× aufgestellt</span>
                    </div>
                    <div className="history-bar" style={{ flex: "unset", width: "100%", marginTop: 4 }}>
                      <div className="history-bar-fill" style={{ width: ((p.einsaetze / maxEinsatz) * 100) + "%" }} />
                    </div>
                  </div>
                  <div className="fw-700" style={{ fontVariantNumeric: "tabular-nums", minWidth: 28, textAlign: "right" }}>{p.einsaetze}</div>
                </div>
              ))}
            </div>
          </div>

          <div className="section-h" style={{ margin: "0 0 12px" }}>
            <h3>Häufigste Mitspieler</h3>
            <span className="section-meta">Wer stand am öftesten zusammen in einer Mannschaft</span>
          </div>
          <div className="history-grid">
            {activePlayers.map(p => {
              const mates = Object.entries(p.mates).map(([id, count]) => ({ id, count, name: playerStats.nameById(id) })).sort((a, b) => b.count - a.count).slice(0, 5);
              const maxMate = Math.max(1, ...mates.map(m => m.count));
              return (
                <div key={p.id} className="history-card">
                  <div className="history-card-head">
                    <div className="profile-avatar" style={{ background: "var(--primary)", width: 32, height: 32, fontSize: 12 }}>{(p.name || "?").split(" ").map(s => s[0]).slice(0,2).join("")}</div>
                    <div className="flex-1">
                      <div className="fw-700 text-sm">{p.name}</div>
                      <div className="text-xs muted">{p.einsaetze} Einsätze · {mates.length} Mitspieler</div>
                    </div>
                  </div>
                  {mates.length === 0 ? (
                    <div className="muted text-xs">Noch keine gemeinsamen Aufstellungen.</div>
                  ) : mates.map(m => (
                    <div key={m.id} className="history-mate">
                      <div className="history-mate-name">{m.name}</div>
                      <div className="history-bar"><div className="history-bar-fill" style={{ width: ((m.count / maxMate) * 100) + "%" }} /></div>
                      <div className="history-count">{m.count}</div>
                    </div>
                  ))}
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}

// ===== Series generator modal =====
function SeriesModal({ onClose, onCreate, einheiten }) {
  const today = new Date().toISOString().slice(0, 10);
  const [from, setFrom] = useStateJP(today);
  const [to, setTo] = useStateJP(today);
  const [days, setDays] = useStateJP({ 2: true, 4: true }); // Di + Do default
  const [einheit, setEinheit] = useStateJP("");
  const [zyklus, setZyklus] = useStateJP(1);

  const toggleDay = (d) => setDays(prev => ({ ...prev, [d]: !prev[d] }));

  const preview = useMemoJP(() => {
    if (!from || !to || from > to) return [];
    const out = [];
    const start = new Date(from + "T12:00:00");
    const end = new Date(to + "T12:00:00");
    for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
      if (days[d.getDay()]) out.push(new Date(d).toISOString().slice(0, 10));
    }
    return out;
  }, [from, to, days]);

  const create = () => {
    const rows = preview.map((date, i) => ({
      id: "s_" + Date.now() + "_" + i,
      date, einheit, zyklus: zyklus || "", bemerkung: "", attendance: {},
    }));
    onCreate(rows);
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 460 }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head"><h3>Termin-Serie erstellen</h3><button className="btn btn-icon btn-ghost" onClick={onClose}><Icon.X /></button></div>
        <div className="modal-body" style={{ display: "grid", gap: 14 }}>
          <div className="row gap-3" style={{ flexWrap: "wrap" }}>
            <div style={{ flex: 1, minWidth: 130 }}><label className="label">Von</label><input type="date" className="input" value={from} onChange={(e) => setFrom(e.target.value)} /></div>
            <div style={{ flex: 1, minWidth: 130 }}><label className="label">Bis</label><input type="date" className="input" value={to} onChange={(e) => setTo(e.target.value)} /></div>
          </div>
          <div>
            <label className="label">Wochentage</label>
            <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
              {[1,2,3,4,5,6,0].map(d => (
                <button key={d} className={"chip-toggle" + (days[d] ? " on" : "")} onClick={() => toggleDay(d)}>{WEEKDAYS_SHORT[d]}</button>
              ))}
            </div>
          </div>
          <div className="row gap-3" style={{ flexWrap: "wrap" }}>
            <div style={{ flex: 1, minWidth: 150 }}><label className="label">Einheit (optional)</label>
              <select className="select" value={einheit} onChange={(e) => setEinheit(e.target.value)}>
                <option value="">– keine –</option>
                {(einheiten || []).map(e => <option key={e} value={e}>{e}</option>)}
              </select>
            </div>
            <div style={{ width: 90 }}><label className="label">Zyklus</label>
              <select className="select" value={zyklus} onChange={(e) => setZyklus(e.target.value ? +e.target.value : "")}>
                <option value="">–</option>{[1,2,3,4].map(z => <option key={z} value={z}>{z}</option>)}
              </select>
            </div>
          </div>
          <div style={{ padding: 12, background: "var(--primary-pale)", borderRadius: 10, fontSize: 13 }}>
            <strong>{preview.length}</strong> Termine werden erstellt{preview.length > 0 ? <> ({formatDateDE(preview[0])} – {formatDateDE(preview[preview.length - 1])})</> : null}.
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn btn-secondary" onClick={onClose}>Abbrechen</button>
          <button className="btn" onClick={create} disabled={preview.length === 0}>{preview.length} Termine anlegen</button>
        </div>
      </div>
    </div>
  );
}

// ===== Guest trainer modal =====
function GuestModal({ guests, onAdd, onRemove, onClose }) {
  const [name, setName] = useStateJP("");
  const [kuerzel, setKuerzel] = useStateJP("");
  const submit = () => { onAdd(name, kuerzel); setName(""); setKuerzel(""); };
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 440 }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head"><h3>Gast-Trainer</h3><button className="btn btn-icon btn-ghost" onClick={onClose}><Icon.X /></button></div>
        <div className="modal-body">
          <p className="muted text-sm" style={{ marginTop: 0 }}>Gäste erscheinen als zusätzliche Spalte (mit *). Die fixen Trainer kommen aus der Administration.</p>
          <div className="row gap-2" style={{ flexWrap: "wrap", marginBottom: 14 }}>
            <input className="input" style={{ flex: 1, minWidth: 160 }} placeholder="Name" value={name} onChange={(e) => setName(e.target.value)} onKeyDown={(e) => e.key === "Enter" && submit()} />
            <input className="input" style={{ width: 80 }} placeholder="Kürzel" value={kuerzel} onChange={(e) => setKuerzel(e.target.value)} maxLength={4} />
            <button className="btn" onClick={submit}><Icon.Plus /></button>
          </div>
          <div style={{ display: "grid", gap: 6 }}>
            {guests.length === 0 && <div className="muted text-sm">Noch keine Gast-Trainer.</div>}
            {guests.map(g => (
              <div key={g.id} className="admin-row" style={{ padding: "8px 12px" }}>
                <div className="profile-avatar" style={{ width: 30, height: 30, fontSize: 11 }}>{g.kuerzel || g.name.slice(0,2)}</div>
                <span className="flex-1 fw-600 text-sm">{g.name}</span>
                <button className="btn btn-icon btn-danger" onClick={() => onRemove(g.id)}><Icon.Trash /></button>
              </div>
            ))}
          </div>
        </div>
        <div className="modal-foot"><button className="btn btn-secondary" onClick={onClose}>Schließen</button></div>
      </div>
    </div>
  );
}

// ===== Einheit picker (multi-select per session) =====
function EinheitPicker({ session, einheiten, onApply, onClose }) {
  const initialSel = (session && session.einheit ? session.einheit.split(",").map(s => s.trim()).filter(Boolean) : []);
  const [selected, setSelected] = useStateJP(initialSel);
  const [custom, setCustom] = useStateJP("");

  const toggle = (e) => setSelected(sel => sel.includes(e) ? sel.filter(x => x !== e) : [...sel, e]);
  const removeSel = (e) => setSelected(sel => sel.filter(x => x !== e));
  const addCustom = () => {
    const n = custom.trim();
    if (!n) return;
    if (!selected.includes(n)) setSelected([...selected, n]);
    setCustom("");
  };

  // predefined not yet selected
  const available = (einheiten || []).filter(e => !selected.includes(e));

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 480 }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3>Einheiten {session && session.date ? "· " + formatDateDE(session.date) : ""}</h3>
          <button className="btn btn-icon btn-ghost" onClick={onClose}><Icon.X /></button>
        </div>
        <div className="modal-body" style={{ display: "grid", gap: 16 }}>
          <div>
            <label className="label">Ausgewählt</label>
            {selected.length === 0 ? (
              <div className="muted text-sm">Noch nichts gewählt — unten antippen oder eigene Einheit eingeben.</div>
            ) : (
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                {selected.map(e => (
                  <button key={e} className="chip-toggle on" onClick={() => removeSel(e)} title="Entfernen">
                    {e} <span style={{ marginLeft: 4, opacity: 0.8 }}>✕</span>
                  </button>
                ))}
              </div>
            )}
          </div>
          <div>
            <label className="label">Vordefiniert hinzufügen</label>
            {available.length === 0 ? (
              <div className="muted text-sm">Alle vordefinierten Einheiten sind gewählt.</div>
            ) : (
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                {available.map(e => (
                  <button key={e} className="chip-toggle" onClick={() => toggle(e)}>{e}</button>
                ))}
              </div>
            )}
          </div>
          <div>
            <label className="label">Eigene Einheit (nur für diesen Termin)</label>
            <div className="row gap-2" style={{ flexWrap: "wrap" }}>
              <input className="input" style={{ flex: 1, minWidth: 180 }} placeholder="z.B. Koordinationsparcours" value={custom}
                onChange={(e) => setCustom(e.target.value)} onKeyDown={(e) => e.key === "Enter" && addCustom()} />
              <button className="btn btn-secondary" onClick={addCustom}><Icon.Plus /></button>
            </div>
          </div>
          <div style={{ padding: 12, background: "var(--primary-pale)", borderRadius: 10, fontSize: 13 }}>
            Gespeichert als: <strong>{selected.join(", ") || "—"}</strong>
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn btn-secondary" onClick={onClose}>Abbrechen</button>
          <button className="btn" onClick={() => onApply(selected.join(", "))}>Übernehmen</button>
        </div>
      </div>
    </div>
  );
}

// ===== Manage the class's predefined Einheiten =====
function EinheitenManager({ einheiten, onChange, onClose }) {
  const [name, setName] = useStateJP("");
  const list = einheiten || [];
  const add = () => {
    const n = name.trim();
    if (!n || list.includes(n)) { setName(""); return; }
    onChange([...list, n]);
    setName("");
  };
  const remove = (e) => onChange(list.filter(x => x !== e));
  const move = (i, dir) => {
    const j = i + dir;
    if (j < 0 || j >= list.length) return;
    const next = list.slice();
    [next[i], next[j]] = [next[j], next[i]];
    onChange(next);
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 460 }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3>Einheiten verwalten</h3>
          <button className="btn btn-icon btn-ghost" onClick={onClose}><Icon.X /></button>
        </div>
        <div className="modal-body">
          <p className="muted text-sm" style={{ marginTop: 0 }}>Diese vordefinierten Einheiten stehen beim Eintragen zur schnellen Auswahl bereit — gilt nur für diese Spielklasse.</p>
          <div className="row gap-2" style={{ flexWrap: "wrap", marginBottom: 14 }}>
            <input className="input" style={{ flex: 1, minWidth: 200 }} placeholder="Neue Einheit (z.B. Ballschule TE11)" value={name}
              onChange={(e) => setName(e.target.value)} onKeyDown={(e) => e.key === "Enter" && add()} />
            <button className="btn" onClick={add}><Icon.Plus /> Hinzufügen</button>
          </div>
          <div style={{ display: "grid", gap: 6, maxHeight: 320, overflowY: "auto" }}>
            {list.length === 0 && <div className="muted text-sm">Noch keine Einheiten definiert.</div>}
            {list.map((e, i) => (
              <div key={e} className="admin-row" style={{ padding: "6px 10px" }}>
                <div className="inv-reorder">
                  <button className="inv-move" onClick={() => move(i, -1)} disabled={i === 0} aria-label="Nach oben">
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
                  </button>
                  <button className="inv-move" onClick={() => move(i, 1)} disabled={i === list.length - 1} aria-label="Nach unten">
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
                  </button>
                </div>
                <span className="flex-1 fw-600 text-sm">{e}</span>
                <button className="btn btn-icon btn-danger" onClick={() => remove(e)} title="Entfernen"><Icon.Trash /></button>
              </div>
            ))}
          </div>
        </div>
        <div className="modal-foot"><button className="btn btn-secondary" onClick={onClose}>Schließen</button></div>
      </div>
    </div>
  );
}

// ===== Lineup editor (Turnier/Spieltag) — drag & drop from pool into teams =====
const LINEUP_COLORS = ["#E63946","#2A9D8F","#F4A261","#7B61FF","#5BAEE0","#06A77D","#E76F51"];

function LineupEditor({ session, players, trainers, onApply, onClose }) {
  const makeTeam = (i) => ({ id: "lt_" + Date.now() + "_" + i + "_" + Math.random().toString(36).slice(2,5), name: "Mannschaft " + (i + 1), color: LINEUP_COLORS[i % LINEUP_COLORS.length], playerIds: [] });
  const initTeams = (session && session.lineup && session.lineup.teams && session.lineup.teams.length)
    ? session.lineup.teams.map(t => ({ ...t, playerIds: [...(t.playerIds || [])] }))
    : [makeTeam(0), makeTeam(1)];
  const [teams, setTeams] = useStateJP(initTeams);
  const [ort, setOrt] = useStateJP((session && session.lineup && session.lineup.ort) || "");
  const [dragId, setDragId] = useStateJP(null);
  const [overTeam, setOverTeam] = useStateJP(null);
  // Mobile tap-to-assign: actively selected target team
  const [target, setTarget] = useStateJP(initTeams[0] ? initTeams[0].id : null);
  const [isMobile, setIsMobile] = useStateJP(typeof window !== "undefined" && window.matchMedia ? window.matchMedia("(max-width: 900px)").matches : false);
  useEffectJP(() => {
    if (!window.matchMedia) return;
    const mq = window.matchMedia("(max-width: 900px)");
    const onChange = (e) => setIsMobile(e.matches);
    mq.addEventListener ? mq.addEventListener("change", onChange) : mq.addListener(onChange);
    return () => { mq.removeEventListener ? mq.removeEventListener("change", onChange) : mq.removeListener(onChange); };
  }, []);

  const playerById = (id) => (players || []).find(p => p.id === id);
  const assignedIds = new Set(teams.flatMap(t => t.playerIds));
  const pool = (players || []).filter(p => !assignedIds.has(p.id));
  const coachOptions = [...new Set((trainers || []).map(t => t.name).filter(Boolean))];

  const setTeamCount = (n) => {
    n = Math.max(2, Math.min(8, n));
    if (n > teams.length) {
      const add = [];
      for (let i = teams.length; i < n; i++) add.push(makeTeam(i));
      setTeams([...teams, ...add]);
    } else if (n < teams.length) {
      setTeams(teams.slice(0, n)); // removed teams' players fall back to pool
    }
  };
  // Keep the target valid as the team count changes
  useEffectJP(() => {
    if (!teams.length) { if (target !== null) setTarget(null); return; }
    if (!teams.find(t => t.id === target)) setTarget(teams[0].id);
  }, [teams, target]);
  const targetTeam = teams.find(t => t.id === target);

  const updateTeam = (id, patch) => setTeams(teams.map(t => t.id === id ? { ...t, ...patch } : t));
  const assign = (playerId, teamId) => {
    setTeams(teams.map(t => {
      const without = (t.playerIds || []).filter(id => id !== playerId);
      if (t.id === teamId) return { ...t, playerIds: [...without, playerId] };
      return { ...t, playerIds: without };
    }));
  };
  const unassign = (playerId) => setTeams(teams.map(t => ({ ...t, playerIds: (t.playerIds || []).filter(id => id !== playerId) })));

  const autoDistribute = () => {
    const fresh = teams.map(t => ({ ...t, playerIds: [] }));
    (players || []).forEach((p, i) => { fresh[i % fresh.length].playerIds.push(p.id); });
    setTeams(fresh);
  };
  const clearAll = () => setTeams(teams.map(t => ({ ...t, playerIds: [] })));

  const printLineup = () => {
    const esc = (s) => String(s == null ? "" : s).replace(/[&<>"]/g, c => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" }[c]));
    const dateStr = session && session.date ? formatDateDE(session.date) : "";
    const totalPlayers = teams.reduce((a, t) => a + (t.playerIds || []).length, 0);
    const teamsHtml = teams.map((t, i) => {
      const ps = (t.playerIds || []).map(pid => playerById(pid)).filter(Boolean);
      const rows = ps.length
        ? ps.map((p, idx) => `<li><span class="n">${idx + 1}</span><span>${esc(p.name)}</span></li>`).join("")
        : `<li class="empty">— keine Spieler —</li>`;
      return `<section class="team">
        <div class="thead" style="background:${esc(t.color)}"><span class="badge">${i + 1}</span><span class="tname">${esc(t.name)}</span><span class="cnt">${ps.length} Spieler</span></div>
        ${t.coach ? `<div class="coach">Betreuer: ${esc(t.coach)}</div>` : ""}
        <ol class="roster">${rows}</ol>
      </section>`;
    }).join("");
    const html = `<!doctype html><html lang="de"><head><meta charset="utf-8"><title>Aufstellung${dateStr ? " " + esc(dateStr) : ""}</title>
<style>
  * { box-sizing: border-box; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  body { font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 28px; color: #1a2230; background: #fff; }
  header { display:flex; align-items:flex-end; justify-content:space-between; gap:16px; border-bottom:3px solid #1E5BA8; padding-bottom:12px; margin-bottom:22px; }
  header h1 { font-size:26px; margin:0; letter-spacing:-0.01em; }
  header .meta { font-size:13px; color:#5a6675; text-align:right; line-height:1.5; }
  header .meta b { color:#1a2230; }
  .teams { display:grid; grid-template-columns: repeat(auto-fill, minmax(250px,1fr)); gap:16px; }
  .team { border:1px solid #dde3ec; border-radius:10px; overflow:hidden; break-inside:avoid; }
  .thead { color:#fff; font-weight:700; font-size:15px; padding:10px 14px; display:flex; align-items:center; gap:10px; }
  .thead .badge { background:rgba(255,255,255,.28); min-width:24px; height:24px; border-radius:6px; display:inline-flex; align-items:center; justify-content:center; font-weight:800; padding:0 6px; }
  .thead .tname { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .thead .cnt { font-weight:600; font-size:12px; opacity:.92; white-space:nowrap; }
  .coach { padding:7px 14px; font-size:12px; font-weight:600; color:#3a4656; background:#f5f8fc; border-bottom:1px solid #eef1f6; }
  .roster { list-style:none; margin:0; padding:4px 0; }
  .roster li { display:flex; align-items:center; gap:10px; padding:7px 14px; font-size:14px; border-top:1px solid #f0f3f8; }
  .roster li:first-child { border-top:none; }
  .roster li .n { color:#9aa5b5; font-variant-numeric:tabular-nums; width:16px; font-size:12px; font-weight:700; text-align:right; }
  .roster li.empty { color:#9aa5b5; font-style:italic; }
  footer { margin-top:26px; padding-top:10px; border-top:1px solid #eef1f6; font-size:11px; color:#9aa5b5; }
  @page { margin: 12mm; }
  @media print { body { margin: 0; } }
</style></head><body>
  <header>
    <h1>Aufstellung</h1>
    <div class="meta">
      ${dateStr ? `<div><b>${esc(dateStr)}</b></div>` : ""}
      ${ort ? `<div>Ort: ${esc(ort)}</div>` : ""}
      <div>${teams.length} Mannschaften · ${totalPlayers} Spieler</div>
    </div>
  </header>
  <div class="teams">${teamsHtml}</div>
  <footer>SC Admira Dornbirn · gedruckt am ${new Date().toLocaleDateString("de-AT")}</footer>
  <script>window.onload=function(){setTimeout(function(){window.print();},250);};<\/script>
</body></html>`;
    const w = window.open("", "_blank");
    if (!w) { alert("Bitte Popups für diese Seite erlauben, um die Aufstellung zu drucken."); return; }
    w.document.open();
    w.document.write(html);
    w.document.close();
    w.focus();
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 880, width: "96%" }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3>Aufstellung{session && session.date ? " · " + formatDateDE(session.date) : ""}</h3>
          <button className="btn btn-icon btn-ghost" onClick={onClose}><Icon.X /></button>
        </div>
        <div className="modal-body" style={{ maxHeight: "70vh", overflowY: "auto" }}>
          <div className="mb-3">
            <label className="label">Turnierort</label>
            <input className="input" style={{ maxWidth: 360 }} placeholder="z.B. Sportplatz Altach" value={ort} onChange={(e) => setOrt(e.target.value)} />
          </div>
          <div className="row gap-2 mb-3" style={{ flexWrap: "wrap" }}>
            <span className="label" style={{ margin: 0, alignSelf: "center" }}>Anzahl Mannschaften</span>
            <div className="stepper">
              <button onClick={() => setTeamCount(teams.length - 1)}>−</button>
              <input value={teams.length} readOnly />
              <button onClick={() => setTeamCount(teams.length + 1)}>+</button>
            </div>
            <span className="flex-1" />
            <button className="btn btn-secondary btn-sm" onClick={autoDistribute}><Icon.Sparkles /> Auto-Verteilen</button>
            <button className="btn btn-secondary btn-sm" onClick={clearAll}>Leeren</button>
          </div>

          {/* Mobile-only: pick an active target team, then tap players to add them */}
          <div className="lineup-target-bar card card-pad mb-3">
            <div className="assign-bar">
              <span className="assign-bar-label">Zielmannschaft</span>
              <div className="assign-chips">
                {teams.map((t, ti) => (
                  <button
                    key={t.id}
                    className={"assign-chip" + (target === t.id ? " active" : "")}
                    onClick={() => setTarget(t.id)}
                  >
                    <span className="assign-chip-dot" style={{ background: t.color }}>{ti + 1}</span>
                    <span className="assign-chip-name">{t.name}</span>
                    <span className="assign-chip-count">{(t.playerIds || []).length}</span>
                  </button>
                ))}
              </div>
            </div>
            <div className="section-meta" style={{ marginTop: 10 }}>
              {targetTeam ? <>Spieler antippen → <b style={{ color: "var(--text)" }}>{targetTeam.name}</b></> : "Wähle eine Mannschaft"}
            </div>
          </div>

          {/* Pool */}
          <div className="card card-pad mb-3"
            onDragOver={(e) => { if (dragId) { e.preventDefault(); setOverTeam("pool"); } }}
            onDrop={() => { if (dragId) { unassign(dragId); setDragId(null); setOverTeam(null); } }}
            style={overTeam === "pool" ? { outline: "2px dashed var(--primary)", outlineOffset: -4 } : null}
          >
            <div className="section-h" style={{ margin: "0 0 10px" }}>
              <h3>Spielerpool ({pool.length})</h3>
              <span className="section-meta">Spieler in eine Mannschaft ziehen</span>
            </div>
            {pool.length === 0 ? (
              <div className="muted text-sm" style={{ padding: 6 }}>Alle Spieler sind aufgestellt.</div>
            ) : (
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                {pool.map(p => (
                  <div key={p.id} className="lineup-chip" draggable
                    onDragStart={() => setDragId(p.id)} onDragEnd={() => { setDragId(null); setOverTeam(null); }}
                    onClick={() => assign(p.id, (isMobile && target) ? target : teams[0].id)}
                    title={isMobile && targetTeam ? "Antippen → " + targetTeam.name : "Ziehen oder klicken (→ Mannschaft 1)"}>
                    <span className="team-dot" style={{ background: "var(--ink-300)" }} />{p.name}
                    <span className="lineup-chip-add">+</span>
                  </div>
                ))}
              </div>
            )}
          </div>

          {/* Teams */}
          <datalist id="lineup-coach-list">
            {coachOptions.map(n => <option key={n} value={n} />)}
          </datalist>
          <div className="lineup-teams">
            {teams.map(t => (
              <div key={t.id} className={"team-card" + (overTeam === t.id ? " dragging-over" : "")}
                onDragOver={(e) => { if (dragId) { e.preventDefault(); setOverTeam(t.id); } }}
                onDragLeave={() => setOverTeam(null)}
                onDrop={() => { if (dragId) { assign(dragId, t.id); setDragId(null); setOverTeam(null); } }}
              >
                <div className="team-card-head" style={{ background: t.color + "12" }}>
                  <div className="team-letter" style={{ background: t.color }}>{(players ? teams.indexOf(t) + 1 : 1)}</div>
                  <input className="team-name-input" value={t.name} onChange={(e) => updateTeam(t.id, { name: e.target.value })} />
                  <div className="row gap-1">
                    {LINEUP_COLORS.map(c => (
                      <button key={c} onClick={() => updateTeam(t.id, { color: c })}
                        style={{ width: 16, height: 16, borderRadius: 4, background: c, border: t.color === c ? "2px solid var(--text)" : "1px solid var(--border)", cursor: "pointer" }} />
                    ))}
                  </div>
                </div>
                <div className="team-coach-row">
                  <span className="team-coach-icon" style={{ color: t.color }}><Icon.Shield /></span>
                  <input className="team-coach-input" list="lineup-coach-list" placeholder="Betreuer wählen oder eingeben…" value={t.coach || ""} onChange={(e) => updateTeam(t.id, { coach: e.target.value })} />
                </div>
                <div className="team-roster">
                  {(t.playerIds || []).length === 0 ? (
                    <div className="team-empty">Spieler hierher ziehen</div>
                  ) : t.playerIds.map(pid => {
                    const p = playerById(pid);
                    if (!p) return null;
                    return (
                      <div key={pid} className={"team-player" + (isMobile && target && target !== t.id ? " movable" : "")} draggable
                        onDragStart={() => setDragId(pid)} onDragEnd={() => { setDragId(null); setOverTeam(null); }}
                        onClick={() => { if (isMobile && target && target !== t.id) assign(pid, target); }}
                        title={isMobile && target && target !== t.id ? "Antippen → " + (targetTeam ? targetTeam.name : "") : ""}>
                        <span className="team-dot" style={{ background: t.color }} />
                        <span className="flex-1">{p.name}</span>
                        <button className="btn-ghost" style={{ border: "none", background: "transparent", padding: 4, color: "var(--text-soft)" }} onClick={() => unassign(pid)} title="Zurück in den Pool"><Icon.X /></button>
                      </div>
                    );
                  })}
                </div>
                <div style={{ padding: "8px 14px", borderTop: "1px solid var(--border)", fontSize: 12, color: "var(--text-muted)", background: "var(--ink-50)" }}>
                  {(t.playerIds || []).length} Spieler
                </div>
              </div>
            ))}
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn btn-secondary" onClick={printLineup}><Icon.Printer /> Drucken</button>
          <span className="flex-1" />
          <button className="btn btn-secondary" onClick={onClose}>Abbrechen</button>
          <button className="btn" onClick={() => onApply({ teams, ort })}>Aufstellung speichern</button>
        </div>
      </div>
    </div>
  );
}

window.JahresplanPage = JahresplanPage;