// planner.jsx — Wisselplan: raster + bank + wisselinstructies + speelminuten
const { useState: useState_P, useMemo: useMemo_P, useRef: useRef_P, useEffect: useEffect_P } = React;

function PlannerView() {
  const { state } = useStore();
  const { match, formation, players } = state;

  if (players.length === 0 || formation.length === 0 || !match.homeTeam) {
    return (
      <div className="planner-empty">
        <div className="planner-empty-inner">
          <h2>Vul eerst de wedstrijd in.</h2>
          <p>Je hebt een ploegnaam, minstens één positie en spelers nodig om te plannen.</p>
        </div>
      </div>
    );
  }

  return (
    <div className="planner-view">
      <div className="planner-main">
        <PlannerHeader />
        <TeamFocus />
        <PlanningGrid />
        <SubInstructions />
        <WerkpuntenPanel />
      </div>
      <StatsSidebar />
    </div>
  );
}

function PlannerHeader() {
  const { state, setMatch, resetGameplan } = useStore();
  const { match } = state;
  const us = match.isUserHomeTeam ? match.homeTeam : match.awayTeam;
  const them = match.isUserHomeTeam ? match.awayTeam : match.homeTeam;
  return (
    <header className="planner-header">
      <div className="ph-left">
        <h1>
          <span className="ph-us">{us}</span>
          <span className="ph-vs">tegen</span>
          <span className="ph-them">{them}</span>
          {match.location && <span className="ph-loc">({match.location})</span>}
        </h1>
        <input
          className="ph-loc-input"
          placeholder="+ Locatie / adres…"
          value={match.location || ""}
          onChange={(e) => setMatch({ location: e.target.value })}
        />
      </div>
      <div className="ph-right">
        <span className="ph-meta">{match.periods} × {match.periodMinutes}m</span>
        <button
          className="btn ghost sm"
          onClick={() => {
            if (confirm("Gameplan resetten? Spelers en posities blijven; wissels, aandachtspunten en werkpunten worden gewist.")) {
              resetGameplan();
            }
          }}
          title="Wis wissels, aandachtspunten en werkpunten"
        >
          ↻ Reset Gameplan
        </button>
      </div>
    </header>
  );
}

function PlanningGrid() {
  const { state, assignPlayer } = useStore();
  const { match, formation, gamePlan, players, positionLabels } = state;
  const [openCell, setOpenCell] = useState_P(null);

  const columns = useMemo_P(() => {
    const cols = [];
    for (let p = 0; p < match.periods; p++) {
      cols.push({ p, h: 0 });
      cols.push({ p, h: 1 });
    }
    return cols;
  }, [match.periods]);

  const playerName = (id) => players.find((p) => p.id === id)?.name || null;

  // For each cell, determine if the assigned player is IN (new this half) or OUT (gone next half)
  // - IN: was not playing in the previous half (and there IS a previous half)
  // - OUT: is not playing in the next half (and there IS a next half)
  // - First half starters are NOT marked IN. Last half players are NOT marked OUT.
  const cellState = useMemo_P(() => {
    const get = (p, h) => {
      const c = gamePlan?.[p]?.[h] || {};
      const set = new Set(Object.values(c));
      return set;
    };
    const totalHalves = match.periods * 2;
    const out = {};
    for (let idx = 0; idx < totalHalves; idx++) {
      const p = Math.floor(idx / 2);
      const h = idx % 2;
      const curr = gamePlan?.[p]?.[h] || {};
      const prevPlayers = idx > 0 ? get(Math.floor((idx - 1) / 2), (idx - 1) % 2) : null;
      const nextPlayers = idx < totalHalves - 1 ? get(Math.floor((idx + 1) / 2), (idx + 1) % 2) : null;
      for (const pos of formation) {
        const pid = curr[pos];
        if (!pid) continue;
        const isIn = prevPlayers && !prevPlayers.has(pid);
        const isOut = nextPlayers && !nextPlayers.has(pid);
        out[`${p}-${h}-${pos}`] = { isIn, isOut };
      }
    }
    return out;
  }, [gamePlan, formation, match.periods]);

  return (
    <>
      <section className="grid-wrap">
        <header className="grid-header">
          <h2>Wisselraster</h2>
        </header>
        <div className="grid-scroll">
          <table className="plan-grid">
            <thead>
              <tr>
                <th className="pg-corner">POS</th>
                {columns.map(({ p, h }) => (
                  <th key={`${p}-${h}`} className={"pg-col-h " + (h === 0 ? "first-half" : "second-half")}>
                    <span className="pg-col-period">P{p + 1}</span>
                    <span className="pg-col-half">H{h + 1}</span>
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {formation.map((pos) => (
                <tr key={pos}>
                  <th className="pg-row-h">
                    <span className="pg-pos-num">{pos}</span>
                    {positionLabels[pos] && <span className="pg-pos-role">{positionLabels[pos]}</span>}
                  </th>
                  {columns.map(({ p, h }) => {
                    const pid = getAssignment(gamePlan, p, h, pos);
                    const name = playerName(pid);
                    const cs = cellState[`${p}-${h}-${pos}`] || {};
                    const classes = [
                      "pg-cell",
                      h === 0 ? "first-half" : "second-half",
                      name ? "filled" : "",
                      cs.isIn && cs.isOut ? "cell-cameo" : cs.isIn ? "cell-in" : cs.isOut ? "cell-out" : "",
                    ].filter(Boolean).join(" ");
                    return (
                      <td key={`${p}-${h}-${pos}`} className={classes}>
                        <button className="cell-btn" onClick={(e) => {
                          const r = e.currentTarget.getBoundingClientRect();
                          setOpenCell({ p, h, pos, anchor: { x: r.left + r.width / 2, y: r.bottom } });
                        }}>
                          {name ? (
                            <span className="cell-name">{name}</span>
                          ) : (
                            <span className="cell-empty">+</span>
                          )}
                        </button>
                      </td>
                    );
                  })}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </section>

      {openCell && (
        <AssignSheet
          cell={openCell}
          onClose={() => setOpenCell(null)}
          onAssign={(pid) => {
            assignPlayer(openCell.p, openCell.h, openCell.pos, pid);
            setOpenCell(null);
          }}
        />
      )}
    </>
  );
}

function AssignSheet({ cell, onClose, onAssign }) {
  const { state } = useStore();
  const { players, gamePlan, formation, match, positionLabels } = state;
  const [query, setQuery] = useState_P("");
  const popRef = useRef_P(null);
  const [pos, setPos] = useState_P(null);
  const isMobile = typeof window !== "undefined" && window.matchMedia("(max-width: 720px)").matches;

  const halfMinutes = match.periodMinutes / 2;
  const stats = useMemo_P(() => computePlayerStats(state), [state]);

  const cellMap = gamePlan?.[cell.p]?.[cell.h] || {};
  const occupiedInThisHalf = new Set();
  for (const p of Object.keys(cellMap)) {
    if (parseInt(p, 10) !== cell.pos) occupiedInThisHalf.add(cellMap[p]);
  }
  const currentPid = cellMap[cell.pos] || null;

  const hasPrev = cell.p > 0 || cell.h > 0;
  let playedInPrevHalf = new Set();
  if (hasPrev) {
    const prevP = cell.h === 0 ? cell.p - 1 : cell.p;
    const prevH = cell.h === 0 ? 1 : 0;
    const prevCell = gamePlan?.[prevP]?.[prevH] || {};
    for (const p of Object.keys(prevCell)) playedInPrevHalf.add(prevCell[p]);
  }

  const filtered = players.filter((p) => p.name.toLowerCase().includes(query.toLowerCase()));

  useEffect_P(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);

  useEffect_P(() => {
    if (isMobile || !cell.anchor || !popRef.current) return;
    const compute = () => {
      const el = popRef.current;
      if (!el) return;
      const w = el.offsetWidth;
      const h = el.offsetHeight;
      const margin = 12;
      const vw = window.innerWidth;
      const vh = window.innerHeight;
      const { x, y } = cell.anchor;

      let placement = "below";
      let top = y + 6;
      if (top + h + margin > vh) {
        placement = "above";
        top = y - h - 6 - 46;
        if (top < margin) {
          placement = "side";
          top = Math.max(margin, vh - h - margin);
        }
      }
      let left = x - w / 2;
      left = Math.max(margin, Math.min(left, vw - w - margin));
      setPos({ left, top, placement });
    };
    compute();
    const onResize = () => compute();
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, [cell.anchor, isMobile]);

  const popStyle = isMobile || !pos ? undefined : {
    position: "fixed",
    left: pos.left,
    top: pos.top,
    margin: 0,
  };
  const popVisibility = isMobile || pos ? "visible" : "hidden";

  return (
    <div className={"sheet-backdrop " + (isMobile ? "" : "popover-mode")} onClick={onClose}>
      <div
        ref={popRef}
        className={"sheet " + (isMobile ? "" : "sheet-popover")}
        style={{ ...popStyle, visibility: popVisibility }}
        onClick={(e) => e.stopPropagation()}
      >
        <div className="sheet-grip" />
        <header className="sheet-h">
          <div>
            <div className="sheet-eyebrow">Periode {cell.p + 1} · Helft {cell.h + 1} · {halfMinutes}m</div>
            <h3 className="sheet-title">Positie <span className="pos-pill">{cell.pos}</span> {positionLabels[cell.pos] && <span className="pos-role-lg">{positionLabels[cell.pos]}</span>}</h3>
          </div>
          <button className="icon-btn ghost" onClick={onClose} aria-label="Sluiten">×</button>
        </header>
        <div className="sheet-search">
          <input
            className="input"
            placeholder="Zoek speler…"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            autoFocus
          />
          <button
            className="btn ghost"
            onClick={() => onAssign(null)}
            disabled={!currentPid}
          >
            Wissen
          </button>
        </div>
        <div className="sheet-list">
          {hasPrev && (
            <div className="sheet-legend">
              <span className="sheet-legend-dot fresh" /> fris — speelde vorige helft niet
            </div>
          )}
          {filtered.map((p) => {
            const conflict = occupiedInThisHalf.has(p.id);
            const isCurrent = p.id === currentPid;
            const fresh = hasPrev && !playedInPrevHalf.has(p.id) && !isCurrent && !conflict;
            const st = stats[p.id];
            return (
              <button
                key={p.id}
                className={"sheet-row " + (isCurrent ? "current " : "") + (conflict ? "conflict " : "") + (fresh ? "fresh" : "")}
                onClick={() => !conflict && onAssign(p.id)}
                disabled={conflict}
              >
                <span className="sheet-row-name">
                  {fresh && <span className="fresh-mark" aria-hidden="true" />}
                  {p.name}
                </span>
                <span className="sheet-row-stats">
                  <span className="chip mono">{st.totalMinutes}m</span>
                  <span className="chip mono">{st.halves.length}H</span>
                </span>
                <span className="sheet-row-status">
                  {isCurrent ? <span className="tag tag-now">huidig</span>
                    : conflict ? <span className="tag tag-conflict">elders deze helft</span>
                    : fresh ? <span className="tag tag-fresh">fris →</span>
                    : <span className="tag tag-pick">kies →</span>}
                </span>
              </button>
            );
          })}
          {filtered.length === 0 && (
            <div className="sheet-empty">Geen spelers gevonden voor “{query}”.</div>
          )}
        </div>
      </div>
    </div>
  );
}

// --- Pair IN/OUT events at the same position into "swap" cards.
//     Switches are kept separate. Unpaired INs/OUTs stay standalone.
function pairEvents(events) {
  const outs = events.filter((e) => e.type === "out");
  const ins = events.filter((e) => e.type === "in");
  const switches = events.filter((e) => e.type === "switch");

  const swaps = [];
  const remainingOuts = [...outs];
  const remainingIns = [...ins];

  // 1) Pair by same position (OUT from pos X paired with IN to pos X)
  for (let i = remainingIns.length - 1; i >= 0; i--) {
    const inEv = remainingIns[i];
    const outIdx = remainingOuts.findIndex((o) => o.fromPos === inEv.toPos);
    if (outIdx >= 0) {
      const outEv = remainingOuts.splice(outIdx, 1)[0];
      swaps.push({ in: inEv, out: outEv, sharedPos: inEv.toPos });
      remainingIns.splice(i, 1);
    }
  }
  // 2) Pair remaining by order (positional mismatch — still a swap)
  while (remainingIns.length && remainingOuts.length) {
    swaps.push({ in: remainingIns.shift(), out: remainingOuts.shift() });
  }
  return {
    swaps,
    standaloneIns: remainingIns,
    standaloneOuts: remainingOuts,
    switches,
  };
}

function SubInstructions() {
  const { state } = useStore();
  const instructions = useMemo_P(() => computeSubInstructions(state), [state]);
  const halfMinutes = state.match.periodMinutes / 2;
  const { match, formation, gamePlan } = state;

  const minuteMark = (p, h) => (p * 2 + h) * halfMinutes;

  // A half is "filled" only when every position has a player
  const isHalfFilled = (p, h) => {
    const cell = gamePlan?.[p]?.[h] || {};
    return formation.every((pos) => !!cell[pos]);
  };

  const totalEvents = instructions.reduce((s, x) => s + x.events.length, 0);

  return (
    <section className="subs-wrap">
      <header className="subs-h">
        <h2>Wisselinstructies</h2>
        <span className="subs-meta">{totalEvents} wissel{totalEvents === 1 ? "" : "s"}</span>
      </header>
      <div className="subs-grid">
        {instructions.map(({ periodIdx, halfIdx, events }) => {
          const prevP = halfIdx === 0 ? periodIdx - 1 : periodIdx;
          const prevH = halfIdx === 0 ? 1 : 0;
          const currFilled = isHalfFilled(periodIdx, halfIdx);
          const prevFilled = isHalfFilled(prevP, prevH);
          const ready = currFilled && prevFilled;
          const { swaps, standaloneIns, standaloneOuts, switches } = ready
            ? pairEvents(events)
            : { swaps: [], standaloneIns: [], standaloneOuts: [], switches: [] };
          const noEvents = ready && events.length === 0;
          return (
            <article key={`${periodIdx}-${halfIdx}`} className="sub-col">
              <header className="sub-col-h">
                <span className="sub-col-tag mono">@{minuteMark(periodIdx, halfIdx)}m</span>
                <span className="sub-col-title">P{periodIdx + 1} · H{halfIdx + 1}</span>
              </header>
              {!ready ? (
                <div className="sub-pending">
                  <span className="mono">—</span>
                  <span className="sub-pending-l">helft nog niet volledig</span>
                </div>
              ) : noEvents ? (
                <div className="sub-nochange">Geen wissels</div>
              ) : (
                <ul className="sub-events">
                  {swaps.map((s, i) => (
                    <li key={"sw" + i} className="swap-row">
                      <div className="swap-side in">
                        <div className="swap-tag">IN</div>
                        <div className="swap-name">{s.in.name}</div>
                        <div className="swap-pos"><span className="pos-pill sm">{s.in.toPos}</span></div>
                      </div>
                      <div className="swap-arrow">⇄</div>
                      <div className="swap-side out">
                        <div className="swap-tag">UIT</div>
                        <div className="swap-name">{s.out.name}</div>
                        <div className="swap-pos"><span className="pos-pill sm ghost">{s.out.fromPos}</span></div>
                      </div>
                    </li>
                  ))}
                  {standaloneIns.map((e, i) => (
                    <li key={"in" + i} className="sub-card sub-in solo">
                      <div className="sub-card-tag">IN</div>
                      <div className="sub-card-name">{e.name}</div>
                      <div className="sub-card-detail">naar <span className="pos-pill sm">{e.toPos}</span></div>
                    </li>
                  ))}
                  {standaloneOuts.map((e, i) => (
                    <li key={"ou" + i} className="sub-card sub-out solo">
                      <div className="sub-card-tag">UIT</div>
                      <div className="sub-card-name">{e.name}</div>
                      <div className="sub-card-detail">van <span className="pos-pill sm">{e.fromPos}</span></div>
                    </li>
                  ))}
                  {switches.map((e, i) => (
                    <li key={"sx" + i} className="sub-card sub-switch solo">
                      <div className="sub-card-tag">VERPLAATS</div>
                      <div className="sub-card-name">{e.name}</div>
                      <div className="sub-card-detail">
                        <span className="pos-pill sm ghost">{e.fromPos}</span>
                        <span className="arrow">→</span>
                        <span className="pos-pill sm">{e.toPos}</span>
                      </div>
                    </li>
                  ))}
                </ul>
              )}
            </article>
          );
        })}
      </div>
    </section>
  );
}

function StatsSidebar() {
  const { state } = useStore();
  const { players, match } = state;
  const stats = useMemo_P(() => computePlayerStats(state), [state]);
  const fairnessMin = useMemo_P(() => computeFairMinutes(state), [state]);
  const totalHalves = match.periods * 2;

  const sorted = [...players].sort((a, b) => stats[b.id].totalMinutes - stats[a.id].totalMinutes);

  return (
    <aside className="stats-sidebar">
      <header className="ss-h">
        <h2>Speelminuten</h2>
        <span className="ss-meta">{players.length} spelers</span>
      </header>
      <div className="ss-fair">
        <div className="ss-fair-l">Eerlijke speeltijd</div>
        <div className="ss-fair-v"><span className="mono">{fairnessMin}m</span> per speler</div>
      </div>
      <ul className="ss-list">
        {sorted.map((p) => {
          const st = stats[p.id];
          const minutes = st.totalMinutes;
          const halves = st.halves.length;
          const bench = totalHalves - halves;
          const belowFair = minutes < fairnessMin;

          return (
            <li key={p.id} className={"ss-row " + (belowFair ? "below" : "")}>
              <div className="ss-row-top">
                <span className="ss-name">{p.name}</span>
                <span className="ss-mins mono">{minutes}<span className="mono dim">m</span></span>
              </div>
              <div className="ss-halves">
                {Array.from({ length: match.periods }, (_, p_i) => (
                  <span key={p_i} className="ss-half-group">
                    {[0, 1].map((h_i) => {
                      const halfRec = st.halves.find((x) => x.p === p_i && x.h === h_i);
                      const played = !!halfRec;
                      const wasGK = played && halfRec.pos === 1;
                      return <span key={h_i} className={"ss-half-dot " + (wasGK ? "gk" : played ? "on" : "")} />;
                    })}
                  </span>
                ))}
              </div>
              <div className="ss-row-meta">
                <span className="ss-meta-chip">{halves}H</span>
                {bench > 0 && <span className="ss-meta-chip dim">{bench} bank</span>}
                {belowFair && <span className="ss-meta-chip warn">onder doel</span>}
                {halves === 0 && <span className="ss-meta-chip alert">niet gespeeld</span>}
              </div>
            </li>
          );
        })}
      </ul>
    </aside>
  );
}

function TeamFocus() {
  const { state, setTeamFocus } = useStore();
  const focus = state.teamFocus || { ballPlus: ["", ""], ballMinus: ["", ""] };
  return (
    <section className="focus-wrap" aria-label="Team aandachtspunten">
      <div className="focus-col plus">
        <header className="focus-col-h">
          <span className="focus-tag plus">B+</span>
          <span className="focus-title">Balbezit</span>
        </header>
        <div className="focus-fields">
          {[0, 1].map((i) => (
            <input
              key={i}
              className="focus-input"
              placeholder={`Aandachtspunt ${i + 1}…`}
              value={focus.ballPlus?.[i] || ""}
              onChange={(e) => setTeamFocus("ballPlus", i, e.target.value)}
            />
          ))}
        </div>
      </div>
      <div className="focus-col minus">
        <header className="focus-col-h">
          <span className="focus-tag minus">B−</span>
          <span className="focus-title">Balverlies</span>
        </header>
        <div className="focus-fields">
          {[0, 1].map((i) => (
            <input
              key={i}
              className="focus-input"
              placeholder={`Aandachtspunt ${i + 1}…`}
              value={focus.ballMinus?.[i] || ""}
              onChange={(e) => setTeamFocus("ballMinus", i, e.target.value)}
            />
          ))}
        </div>
      </div>
    </section>
  );
}

function WerkpuntenPanel() {
  const { state, setPlayerNote } = useStore();
  const { players, playerNotes = {} } = state;
  const withNotes = players.filter((p) => (playerNotes[p.id] || "").trim().length > 0);

  return (
    <section className="werk-wrap">
      <header className="werk-h">
        <h2>Werkpunten per speler</h2>
        <span className="werk-meta">{withNotes.length} ingevuld · {players.length} spelers</span>
      </header>
      <ul className="werk-list">
        {players.map((p) => {
          const note = playerNotes[p.id] || "";
          const filled = note.trim().length > 0;
          return (
            <li key={p.id} className={"werk-row " + (filled ? "filled" : "empty")}>
              <span className="werk-name">{p.name}</span>
              <input
                className="werk-input"
                placeholder="+ opdracht of werkpunt…"
                value={note}
                onChange={(e) => setPlayerNote(p.id, e.target.value)}
              />
            </li>
          );
        })}
      </ul>
    </section>
  );
}

Object.assign(window, { PlannerView, pairEvents });
