/* ============================================================
   Header — top app bar with team chip, title, tool counter,
   action buttons (Trade Machine, Sign FA, Add Player), theme.
   ============================================================ */

function Header({ state, dispatch, derived, theme, setTheme, teams = [], tweaks, setTweak, tool, setTool, onOpenReset, onSnapshot }) {
  const team = teams.find(t => t.code === state.team)
            || teams.find(t => t.code === "LAL")
            || teams[0] || { code: state.team, name: state.team, logo: "" };
  const [teamMenu, setTeamMenu] = useState(false);
  const teamMenuRef = useRef(null);
  // Applied-trades count (active scenario) — drives the header "Trades" opener (B).
  const _scen = state && state.scenarios && state.activeScenario && state.scenarios[state.activeScenario];
  const appliedN = ((_scen && _scen.appliedTrades) || (state && state.appliedTrades) || []).length;

  useEffect(() => {
    function onDoc(e) {
      if (teamMenuRef.current && !teamMenuRef.current.contains(e.target)) setTeamMenu(false);
    }
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);

  return (
    <header className="appbar">
      <span className="team-skin-strip" />
      <div className="appbar-inner">
        <div className="wordmark">
          <a href="#" className="brand" onClick={(e) => e.preventDefault()} title="CapMVP">
            <BrandLogo height={26} />
          </a>
          {/* Roster/Calc switch lives in the gear (Settings) now — header is just the logo. */}
        </div>

        <span className="brand-divider" />

        <div style={{ position: "relative" }} ref={teamMenuRef}>
          <button className="team-chip" onClick={() => setTeamMenu(v => !v)} aria-haspopup="listbox" aria-expanded={teamMenu}>
            <span className="logo"><TeamLogo team={team} size={34} /></span>
            <span className="team-name">{team.shortName || team.code}</span>
            <Icon.Caret className="caret" style={{ width: 13, height: 13 }} />
          </button>
          {teamMenu && (
            <TeamMenu currentTeam={team} teams={teams} onPick={(t) => { dispatch({ type: "SET_TEAM", team: t.code }); setTeamMenu(false); }} onClose={() => setTeamMenu(false)} />
          )}
        </div>

        <div className="title-row">
          <span className="title">2026-27</span>
        </div>

        <span className="spacer" style={{ marginLeft: "auto" }} />

        <div className="appbar-actions">
          {/* [COLOUR rework] dev-only Palette Lab toggle, left of the gear. Remove before public launch. */}
          <button className="icon-btn" title="Palette Lab (colour tester)" aria-label="Palette Lab"
                  onClick={() => window.__paletteLab && window.__paletteLab.toggle()}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
              <rect x="3" y="3" width="8" height="8" rx="2" />
              <rect x="13" y="3" width="8" height="8" rx="2" opacity="0.55" />
              <rect x="3" y="13" width="8" height="8" rx="2" opacity="0.55" />
              <rect x="13" y="13" width="8" height="8" rx="2" />
            </svg>
          </button>
          {/* B: applied-trades opener — shows when trades are on the stack; opens the
              trade-undo window via a window event the App listens for. */}
          {appliedN > 0 && (
            <button className="icon-btn th-open-btn" title={`Applied trades (${appliedN}) — review / undo`}
                    aria-label="Applied trades"
                    onClick={() => window.dispatchEvent(new CustomEvent("open-trade-history"))}>
              <Icon.Trade />
              <span className="th-badge">{appliedN}</span>
            </button>
          )}
          {/* triage G: refresh/reset as a first-class header button (outside the gear), mirroring the Trade Machine. */}
          {onOpenReset && (
            <button className="icon-btn" title="Reset rosters" aria-label="Reset rosters" onClick={onOpenReset}>
              <Icon.Reset />
            </button>
          )}
          {tweaks && setTweak && <SettingsMenu tweaks={tweaks} setTweak={setTweak} state={state} dispatch={dispatch} onOpenReset={onOpenReset} onSnapshot={onSnapshot} theme={theme} setTheme={setTheme} tool={tool} setTool={setTool} />}
        </div>
      </div>
    </header>
  );
}

/* team logo — the 2ways / RealPlusMinus approach: just an <img> at the
   raw SVG file. No inline-and-scope (that washed colours out when many
   logos shared one DOM). Real full-colour logos; the theme-driven
   --logo-filter (see styles.css) brightens them in dark mode. */
function TeamLogo({ team, size = 24 }) {
  if (!team || !team.logo) {
    return <span style={{ width: size, height: size, display: "inline-block", flexShrink: 0 }} />;
  }
  return (
    <img
      className="team-logo"
      src={`assets/logos/${team.logo}`}
      alt={team.code || team.name || ""}
      width={size}
      height={size}
      style={{ width: size, height: size, objectFit: "contain", flexShrink: 0 }}
      onError={(e) => { e.currentTarget.style.visibility = "hidden"; }}
    />
  );
}

/* team picker dropdown — 2ways-style: 15 rows, West on left and East on right,
   rank number centered between. Teams are placed in their rank row, so gaps
   appear where the league has them. */
function TeamMenu({ currentTeam, teams = [], onPick, onClose, excludeCodes = [],
                   multi = false, selectedCodes = [], onToggle, selectedCount }) {
  const westByRank = {};
  const eastByRank = {};
  for (const t of teams) {
    (t.conf === "W" ? westByRank : eastByRank)[t.rank] = t;
  }
  const maxRank = 15;
  const cur = currentTeam ? currentTeam.code : null;
  // single-select (main-site switcher): current + excluded are disabled.
  // multi-select (Trade Machine): only the managed team is disabled; others toggle in/out.
  const isOff = (c) => multi ? (c === cur) : (c === cur || excludeCodes.includes(c));
  const isSel = (c) => selectedCodes.includes(c);
  const isLit = (c) => isSel(c) || (multi && c === cur);   // managed shows lit (locked) in multi
  const click = (t) => { if (multi) { onToggle && onToggle(t); } else { onPick && onPick(t); } };
  const Lock = (p) => (<svg {...p} viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round"><rect x="4" y="9" width="12" height="8" rx="2"/><path d="M7 9V6a3 3 0 0 1 6 0v3"/></svg>);
  // #1b: managed → lock (can't unselect); other selected → check; single-select → "current" text
  const indicator = (t) => {
    if (!multi) return t.code === cur ? <span className="curr-tag">current</span> : null;
    if (t.code === cur) return <span className="sel-check lock"><Lock /></span>;
    if (isSel(t.code)) return <span className="sel-check"><Icon.Check /></span>;
    return null;
  };

  const cell = (t, side) => (
    <button
      className={`team-menu-cell ${side} ${t && t.code === cur ? "current" : ""} ${t && isLit(t.code) ? "selected" : ""} ${t ? "" : "empty"}`}
      disabled={!t || isOff(t.code)}
      onClick={() => t && !isOff(t.code) && click(t)}>
      {t && (side === "west" ? (<>
        <span className="logo"><TeamLogo team={t} size={26} /></span>
        <span className="name">{shortTeam(t.name)}</span>
        {indicator(t)}
      </>) : (<>
        {indicator(t)}
        <span className="name">{shortTeam(t.name)}</span>
        <span className="logo"><TeamLogo team={t} size={26} /></span>
      </>))}
    </button>
  );

  return (
    <div className="team-menu">
      <div className="team-menu-head">
        <span>WEST</span>
        {multi && <span className="cnt">up to 6 teams</span>}
        <span>EAST</span>
      </div>
      <div className="team-menu-grid">
        {Array.from({ length: maxRank }).map((_, i) => (
          <div className="team-menu-row" key={i}>
            {cell(westByRank[i + 1], "west")}
            <span className="rank">{i + 1}</span>
            {cell(eastByRank[i + 1], "east")}
          </div>
        ))}
      </div>
    </div>
  );
}

function shortTeam(name) {
  return name.replace(/^(Los Angeles |New York |Oklahoma City |Golden State |LA |New Orleans |Portland |San Antonio |Memphis |Sacramento |Indiana |Cleveland |Detroit |Charlotte |Brooklyn |Washington |Philadelphia |Houston |Dallas |Denver |Atlanta |Boston |Chicago |Miami |Milwaukee |Minnesota |Orlando |Phoenix |Toronto |Utah )/, "");
}

/* Display settings — always-available, no-build affordance.
   The handoff's TweaksPanel only opens under the Claude-Design host
   (__activate_edit_mode), so outside it the salary-bar style / density /
   team-skin tweaks are unreachable. This drives the SAME tweaks/setTweak
   state app.jsx already applies (SalaryBar style + data-density +
   data-team-skin), so changes are live. (In-memory for the session;
   resets to defaults on reload — useTweaks has no localStorage.) */
function SettingsRow({ label, children }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: "0.04em",
        textTransform: "uppercase", color: "var(--text-faint)" }}>{label}</span>
      {children}
    </div>
  );
}

/* Site-styled palette dropdown — replaces the native <select> so it doesn't pop
   the OS (white Android) picker. Expands inline below its button (no clipping). */
const PALETTE_OPTIONS = [
  { value: "moody2",      label: "Moody 2 (default · bluest)" },
  { value: "moody",       label: "Moody 1" },
  { value: "navybright",  label: "Navy Bright (light · mid-blue)" },
  { value: "navysoft",    label: "Navy Soft (light · less blue)" },
  { value: "navymid",     label: "Navy Mid (mid · blue)" },
  { value: "navymiddeep", label: "Navy Mid-Deep (mid · bluer)" },
  { value: "deepsoft",    label: "Deep Soft (deep · less blue)" },
  { value: "navydeep",    label: "Navy Deep (deepest · blue)" },
  { value: "charcoal",    label: "Charcoal (neutral)" },
  { value: "moody3",      label: "Moody 3" },
  { value: "moody4",      label: "Moody 4" },
  { value: "moody5",      label: "Moody 5" },
  { value: "graphite",    label: "Graphite" },
  { value: "original",    label: "Original" },
];
const LIGHT_PALETTE_OPTIONS = [
  { value: "daylight", label: "Daylight (default)" },
  { value: "soft",     label: "Soft (cool grey)" },
  { value: "warm",     label: "Warm (cream)" },
  { value: "dim",      label: "Dim (muted)" },
];
function PaletteSelect({ value, onPick, options = PALETTE_OPTIONS }) {
  const [open, setOpen] = useState(false);
  const cur = options.find(o => o.value === value) || options[0];
  return (
    <div className="palette-select">
      <button type="button" className="palette-select-btn" aria-expanded={open}
              onClick={() => setOpen(v => !v)}>
        <span>{cur.label}</span>
        <Icon.Caret className={"caret" + (open ? " up" : "")} />
      </button>
      {open && (
        <div className="palette-select-list" role="listbox">
          {options.map(o => (
            <button type="button" key={o.value} role="option"
                    aria-selected={o.value === value}
                    className={"palette-opt" + (o.value === value ? " on" : "")}
                    onClick={() => { onPick(o.value); setOpen(false); }}>
              {o.label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function SettingsMenu({ tweaks, setTweak, state, dispatch, onOpenReset, onSnapshot, theme, setTheme, editLayout, setEditLayout, tool, setTool }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    function onDoc(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    function onKey(e) { if (e.key === "Escape") setOpen(false); }
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onKey);
    return () => { document.removeEventListener("mousedown", onDoc); document.removeEventListener("keydown", onKey); };
  }, []);

  const seg = (val, cur, label, onClick, disabled = false) => (
    <button key={String(val)} className={cur === val ? "on" : ""} onClick={onClick} disabled={disabled}>{label}</button>
  );

  // Palette-compare (dev): persisted + applied to <html data-palette>. Dark-only;
  // light stays Daylight. Locked scheme gets folded into html.dark later.
  const [darkPal, setDarkPal] = useState(() => {
    try { return localStorage.getItem("capmvp-palette") || "moody2"; } catch { return "moody2"; }
  });
  const [lightPal, setLightPal] = useState(() => {
    try { return localStorage.getItem("capmvp-palette-light") || "daylight"; } catch { return "daylight"; }
  });
  const palette = theme === "light" ? lightPal : darkPal;
  const paletteOptions = theme === "light" ? LIGHT_PALETTE_OPTIONS : PALETTE_OPTIONS;
  const applyPalette = (p) => {
    const root = document.documentElement;
    if (theme === "light") {
      setLightPal(p);
      try { localStorage.setItem("capmvp-palette-light", p); } catch {}
      if (p === "daylight") root.removeAttribute("data-palette");
      else root.dataset.palette = "light-" + p;
    } else {
      setDarkPal(p);
      try { localStorage.setItem("capmvp-palette", p); } catch {}
      if (p === "moody") root.removeAttribute("data-palette");
      else root.dataset.palette = "dark-" + p;
    }
  };

  return (
    <div style={{ position: "relative" }} ref={ref}>
      <button className="icon-btn" title="Display settings"
              aria-haspopup="true" aria-expanded={open}
              onClick={() => setOpen(v => !v)}>
        <Icon.Settings />
      </button>
      {open && (
        <div role="menu" style={{
          position: "absolute", top: "calc(100% + 8px)", right: 0, width: 248,
          background: "var(--bg-surface)", border: "1px solid var(--line-strong)",
          borderRadius: 14, boxShadow: "var(--shadow-lg)", zIndex: 100,
          padding: 14, display: "flex", flexDirection: "column", gap: 14,
        }}>
          {setTheme && (
            <SettingsRow label="Theme">
              <div className="sb-mode-toggle">
                {seg("light", theme, "Light", () => setTheme("light"))}
                {seg("dark",  theme, "Dark",  () => setTheme("dark"))}
              </div>
            </SettingsRow>
          )}
          <SettingsRow label="Palette (dev)">
            <PaletteSelect value={palette} onPick={applyPalette} options={paletteOptions} />
            <span style={{ fontSize: 10.5, color: "var(--text-faint)" }}>
              Per-theme — switch Light/Dark above to see each set.
            </span>
          </SettingsRow>
          {/* [tweak f] "Step bar" toggle removed — locked to Standard (the tweaks.stepBar default "mid"). */}
          <SettingsRow label="Density">
            <div className="sb-mode-toggle">
              {seg("compact",     tweaks.density, "Tight", () => setTweak("density", "compact"))}
              {seg("comfortable", tweaks.density, "Comfy", () => setTweak("density", "comfortable"))}
              {seg("roomy",       tweaks.density, "Roomy", () => setTweak("density", "roomy"))}
            </div>
          </SettingsRow>
          <SettingsRow label="Team skin">
            <div className="sb-mode-toggle">
              {seg("off", tweaks.teamSkin, "Off", () => setTweak("teamSkin", "off"))}
              {seg("a",   tweaks.teamSkin, "A",   () => setTweak("teamSkin", "a"))}
              {seg("b",   tweaks.teamSkin, "B",   () => setTweak("teamSkin", "b"))}
            </div>
          </SettingsRow>
          {/* Tombstone art toggle removed — Stone B (svg14) is the only headstone now. */}
          {/* Waiver guardrail toggle removed — the waive-panel nudge (A) is hard-wired on now. */}
          {state && dispatch && (
            <SettingsRow label="Cap-space mode">
              <div className="sb-mode-toggle">
                {seg(false, state.capForAllTeams, "Recommended", () => dispatch({ type: "SET_CAP_FOR_ALL", on: false }))}
                {seg(true,  state.capForAllTeams, "All teams",   () => dispatch({ type: "SET_CAP_FOR_ALL", on: true }))}
              </div>
              <span style={{ fontSize: 10.5, color: "var(--text-faint)" }}>
                Where "Use cap space" is offered. Only ~5 teams realistically have room. Pick a team's strategy from the chip by the roster header.
              </span>
            </SettingsRow>
          )}
          {/* Tool switch (Roster / Calc) removed for now — Calc has no access yet.
              The Calc code + its own back-switcher remain; just not reachable here. */}
          {/* [tweak f] "Adjust raises" toggle removed — always on (adjustRaises defaults true). */}
          {setEditLayout && (
            <SettingsRow label="Edit layout (trades)">
              <div className="sb-mode-toggle">
                {seg("inline-v1", editLayout || "inline-v2", "V1", () => setEditLayout("inline-v1"))}
                {seg("inline-v2", editLayout || "inline-v2", "V2", () => setEditLayout("inline-v2"))}
                {seg("drawer",    editLayout || "inline-v2", "V3", () => setEditLayout("drawer"))}
              </div>
            </SettingsRow>
          )}
          {onSnapshot && (
            <SettingsRow label="Snapshot">
              <button className="btn" onClick={() => { setOpen(false); onSnapshot(); }}>Changes image…</button>
            </SettingsRow>
          )}
          {onOpenReset && (
            <div style={{ borderTop: "1px solid var(--line)", paddingTop: 12 }}>
              <button className="reset-rosters-btn"
                      onClick={() => { setOpen(false); onOpenReset(); }}>
                <Icon.Trash /> Reset rosters…
              </button>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

/* App-level tool switch — a compact dropdown (shows only the current
   tool + caret) so it costs little header width. Built to grow: add
   future tools (Trade, Stats) to TOOL_LIST and they appear here. */
const TOOL_LIST = [
  { id: "roster", label: "Roster" },
  { id: "calc",   label: "Calculator" },
];
function ToolMenu({ tool, setTool }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    function onDoc(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    function onKey(e) { if (e.key === "Escape") setOpen(false); }
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onKey);
    return () => { document.removeEventListener("mousedown", onDoc); document.removeEventListener("keydown", onKey); };
  }, []);
  const cur = TOOL_LIST.find(t => t.id === tool) || TOOL_LIST[0];
  return (
    <div className="tool-menu-wrap" ref={ref} style={{ position: "relative" }}>
      <button className="tool-trigger" aria-haspopup="listbox" aria-expanded={open}
              onClick={() => setOpen(v => !v)}>
        <span>{cur.label}</span>
        <Icon.Caret className="caret" style={{ width: 13, height: 13 }} />
      </button>
      {open && (
        <div className="tool-menu" role="listbox">
          {TOOL_LIST.map(t => (
            <button key={t.id} role="option" aria-selected={t.id === tool}
                    className={`tool-menu-item ${t.id === tool ? "on" : ""}`}
                    onClick={() => { setTool(t.id); setOpen(false); }}>
              <span className="tool-menu-check">
                {t.id === tool && <Icon.Check style={{ width: 13, height: 13 }} />}
              </span>
              <span>{t.label}</span>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

/* Calculator view — the real CapMVP Salary Calculator embedded (its own
   Tailwind/theme/logic, isolated in an iframe). Our slim appbar on top
   keeps the brand, tool dropdown and theme toggle so the user can
   navigate without leaving. */
function CalcPlaceholder({ tool, setTool, theme, setTheme }) {
  return (
    <div className="calc-view">
      <header className="appbar">
        <div className="appbar-inner">
          <div className="wordmark">
            <a href="#" className="brand" onClick={(e) => e.preventDefault()} title="CapMVP">
              <BrandLogo height={26} />
            </a>
            <ToolMenu tool={tool} setTool={setTool} />
          </div>
          <span className="spacer" style={{ marginLeft: "auto" }} />
          <div className="appbar-actions">
            <button className="icon-btn" title="Toggle theme"
                    onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
              {theme === "dark" ? <Icon.Sun /> : <Icon.Moon />}
            </button>
          </div>
        </div>
      </header>
      <iframe className="calc-frame" src="calc/index.html?v=2"
              title="CapMVP Salary Calculator" />
    </div>
  );
}

Object.assign(window, { Header, TeamLogo, shortTeam, TeamMenu, SettingsMenu, ToolMenu, CalcPlaceholder, BrandLogo });
