// pdx-teams.jsx — Trainer Teams as a roguelite "run map" + hover tooltip + detail modal.
const { useState: useST, useMemo: useMT, useEffect: useET, useRef: useRT } = React;

function statusKind(s) { return s === "ace" ? "ace" : s === "unfused-no-sprite" ? "unfused" : null; }
function bandOf(lv) { return lv <= 30 ? "Early" : lv <= 60 ? "Mid" : lv <= 84 ? "Late" : "Boss"; }
const BAND_COLOR = { Early: "#52c66a", Mid: "#5fd0e0", Late: "#b07cff", Boss: "#ff4b4b" };

// ── Hover tooltip (sprite-first team peek) ──────────────────────────────────
function TipMember({ m }) {
  const kind = statusKind(m.status);
  return (
    <div className="tip-mem">
      <window.Sprite src={m.sprite ? "/if-fusions/" + m.sprite : null} alt={m.name} kind={kind} />
      <div className="tip-mem-name">{m.name}</div>
      <window.RolePill archetype={m.archetype} role={m.role} />
      <div className="tip-mem-peek">{m.signatureSet[0]?.name}</div>
    </div>
  );
}

function RunTooltip({ team, rect }) {
  const spec = team.specialty ? `var(--type-${team.specialty.toLowerCase()})` : "var(--glow)";
  const name = window.prettify(team.key);
  const tipW = Math.min(540, window.innerWidth - 24);
  const rows = Math.ceil(team.members.length / 3);
  const estH = 168 + rows * 188;
  let left = rect.right + 16;
  if (left + tipW > window.innerWidth - 12) left = rect.left - tipW - 16;
  if (left < 12) left = 12;
  let top = rect.top + rect.height / 2 - estH / 2;
  top = Math.max(12, Math.min(top, window.innerHeight - estH - 12));
  return (
    <div className="run-tip" style={{ left, top, width: tipW, "--spec": spec }}>
      <div className="tip-head">
        <div className="tip-head-main">
          <div className="row gap2 wrap" style={{ alignItems: "center" }}>
            <span className="tip-name">{name}</span>
            {team.specialty && <window.TypeBadge type={team.specialty} />}
          </div>
          {team.title && <div className="tip-title">{team.title}</div>}
        </div>
        <div style={{ textAlign: "right", display: "flex", flexDirection: "column", gap: 4, alignItems: "flex-end" }}>
          <span className="tip-lv">Lv{team.level}</span>
          {team._final ? <span className="tip-flair">★ FINAL BOSS</span> : team.isBoss && <span className="tip-flair">BOSS</span>}
        </div>
      </div>
      <div className="tip-team">{team.members.map((m) => <TipMember key={m.slot} m={m} />)}</div>
      <div className="tip-tags">
        {team.cores.map((c) => <span className="core-tag" key={c}><window.IcoBolt s={10} />{c}</span>)}
        {team.roles.slice(0, 3).map((rr) => <span className="role" key={rr}>{rr}</span>)}
      </div>
      <div className="tip-hint">Click to open full team breakdown</div>
    </div>
  );
}

// ── The run map ─────────────────────────────────────────────────────────────
function TrainerMap({ teams, matches, onOpen }) {
  const [tip, setTip] = useST(null);
  const N = teams.length;
  const SP = 152, PAD = 96, AMP = 286, CX = 500;
  const pts = teams.map((t, i) => ({ x: Math.max(140, Math.min(860, CX + AMP * Math.sin(i * 0.72))), y: PAD + i * SP }));
  const H = PAD * 2 + (N - 1) * SP;

  let d = pts.length ? `M ${pts[0].x.toFixed(1)} ${pts[0].y}` : "";
  for (let i = 1; i < N; i++) {
    const a = pts[i - 1], b = pts[i], my = (a.y + b.y) / 2;
    d += ` C ${a.x.toFixed(1)} ${my} ${b.x.toFixed(1)} ${my} ${b.x.toFixed(1)} ${b.y}`;
  }

  const dividers = [];
  teams.forEach((t, i) => {
    const band = bandOf(t.level);
    const prevBand = i > 0 ? bandOf(teams[i - 1].level) : null;
    if (band !== prevBand) dividers.push({ y: i === 0 ? PAD / 2 : (pts[i - 1].y + pts[i].y) / 2, band });
  });

  const show = (team, e) => setTip({ team, rect: e.currentTarget.getBoundingClientRect() });
  const hide = () => setTip(null);

  return (
    <div className="runmap" style={{ height: H }}>
      <div className="map-bg" /><div className="map-scrim" />
      <svg className="run-svg" viewBox={`0 0 1000 ${H}`} preserveAspectRatio="none" aria-hidden="true">
        <path className="run-path-base" d={d} />
        <path className="run-path-lit" d={d} pathLength="626" />
      </svg>

      {dividers.map((dv, i) => (
        <div className="band-divider" key={i} style={{ top: dv.y, "--bc": BAND_COLOR[dv.band] }}>
          <span className="ln" /><span className="lbl">{dv.band}</span><span className="ln" />
        </div>
      ))}

      {teams.map((t, i) => {
        const spec = t.specialty ? `var(--type-${t.specialty.toLowerCase()})` : "var(--glow)";
        const dim = matches && !matches(t);
        return (
          <button key={t.key}
            className={"rnode" + (t.isBoss ? " boss" : "") + (t._final ? " final" : "") + (i === 0 ? " start" : "") + (dim ? " dim" : "")}
            style={{ left: (pts[i].x / 10) + "%", top: pts[i].y + "px", "--spec": spec, "--d": (Math.min(i, 16) * 0.06).toFixed(2) + "s" }}
            onMouseEnter={(e) => show(t, e)} onMouseLeave={hide} onFocus={(e) => show(t, e)} onBlur={hide}
            onClick={() => onOpen(t)} aria-label={window.prettify(t.key) + ", level " + t.level}>
            {t._final && <span className="rnode-crown">♔</span>}
            <span className="rnode-disc"><span className="rnode-emblem" /></span>
            <span className="rnode-lv">{t.level}</span>
            {t._final ? <span className="rnode-flair">FINAL BOSS</span> : <span className="rnode-name">{window.prettify(t.key)}</span>}
          </button>
        );
      })}

      {tip && <RunTooltip team={tip.team} rect={tip.rect} />}
    </div>
  );
}

// ── Trainer detail modal (opened on node click) ─────────────────────────────
function TrainerDetail({ team, onClose }) {
  const ref = useRT(null);
  const name = window.prettify(team.key);
  const spec = team.specialty ? `var(--type-${team.specialty.toLowerCase()})` : "var(--glow)";
  useET(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    const prev = document.activeElement; ref.current?.focus(); document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = ""; prev?.focus?.(); };
  }, [onClose]);
  return (
    <div className="backdrop" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="detail" role="dialog" aria-modal="true" aria-label={name} ref={ref} tabIndex={-1} style={{ "--rc": spec }}>
        <button className="detail-x" onClick={onClose} aria-label="Close"><window.IcoX s={16} /></button>
        <div className="detail-scroll scrl">
          <div className="dh" style={{ paddingRight: 44 }}>
            <div className="dh-body">
              <div className="dh-dex mono">LV {team.level} · {bandOf(team.level)} GAUNTLET</div>
              <h2 className="dh-name">{name}</h2>
              {team.title && <div className="dh-parents" style={{ fontStyle: "italic" }}>{team.title}</div>}
              <div className="dh-types row gap2 wrap" style={{ alignItems: "center" }}>
                {team.specialty && <window.TypeBadge type={team.specialty} />}
                {team._final ? <span className="tr-boss-flair">★ FINAL BOSS</span> : team.isBoss && <span className="tr-boss-flair">BOSS</span>}
                {team.cores.map((c) => <span className="core-tag" key={c}><window.IcoBolt s={11} />{c}</span>)}
              </div>
            </div>
          </div>

          <div className="d-block">
            <div className="d-section-k">Roles covered <span className="n">{team.roles.length}</span></div>
            <div className="row gap1 wrap">{team.roles.map((rr) => <span className="role-pill" key={rr} style={{ "--rc": "var(--ink-2)" }}>{rr}</span>)}</div>
          </div>

          <div className="d-section-k" style={{ marginTop: "calc(var(--u)*6)" }}>Team breakdown <span className="n">{team.members.length} members</span></div>
          <div className="tm-grid">
            {team.members.map((m) => {
              const kind = statusKind(m.status);
              return (
                <div className={"tmember" + (m.status === "ace" ? " ace" : "")} key={m.slot}>
                  <div className="tm-head">
                    <window.Sprite src={m.sprite ? "/if-fusions/" + m.sprite : null} alt={m.name} kind={kind} />
                    <div className="tm-id">
                      <div className="tm-name">{m.name}</div>
                      <div className="tm-parents">{m.bodyName ? <>{m.headName} + {m.bodyName}</> : m.headName}</div>
                      <div className="row gap1 wrap" style={{ marginTop: 5 }}><window.TypeBadges types={m.types} sm /></div>
                    </div>
                  </div>
                  <div className="kvs" style={{ marginTop: "calc(var(--u)*3)" }}>
                    <div className="kv"><span className="k">Ability</span><span className="v" style={{ fontSize: 13 }}>{m.ability}</span></div>
                    <div className="kv"><span className="k">Role</span><span className="v"><window.RolePill archetype={m.archetype} role={m.role} /></span></div>
                  </div>
                  {m.signatureAxis && <div className="d-role-axis" style={{ marginTop: "calc(var(--u)*2)" }}>{m.signatureAxis}</div>}
                  <div style={{ marginTop: "calc(var(--u)*3)" }}><window.MoveList moves={m.signatureSet} sig /></div>
                  <div style={{ marginTop: "calc(var(--u)*3)" }}><window.StatBlock stats={m.stats} bst={m.bst} animate /></div>
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}

function TeamsDropdown({ value, onChange, options, placeholder }) {
  return <div className="sel"><select value={value} onChange={(e) => onChange(e.target.value)}>
    <option value="">{placeholder}</option>{options.map((o) => <option key={o.v ?? o} value={o.v ?? o}>{o.l ?? o}</option>)}
  </select></div>;
}

function TeamsView() {
  const all = useMT(() => {
    const sorted = [...(window.MAP_TEAMS || window.TEAMS)].sort((a, b) => a.level - b.level);
    if (sorted.length) sorted[sorted.length - 1]._final = true;
    return sorted;
  }, []);
  const [q, setQ] = useST(""); const [type, setType] = useST(""); const [role, setRole] = useST(""); const [band, setBand] = useST("");
  const [open, setOpen] = useST(null);

  const matches = (t) => {
    if (type && t.specialty !== type && !t.members.some((m) => m.types.includes(type))) return false;
    if (role && !t.members.some((m) => window.ARCH_TO_ROLE[m.archetype] === role)) return false;
    if (band && bandOf(t.level) !== band) return false;
    if (q) {
      const hay = [window.prettify(t.key), t.title, t.specialty, ...t.roles, ...t.cores,
        ...t.members.flatMap((m) => [m.name, m.headName, m.bodyName, m.role, ...m.types])].filter(Boolean).join(" ").toLowerCase();
      if (!hay.includes(q.toLowerCase())) return false;
    }
    return true;
  };
  const active = !!(q || type || role || band);
  const hitCount = useMT(() => all.filter(matches).length, [all, q, type, role, band]);

  return (
    <div className="view">
      <div className="filterbar">
        <div className="search"><window.IcoSearch s={16} />
          <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search the run — trainer, type, role, or mon…" /></div>
        <TeamsDropdown value={type} onChange={setType} options={window.TYPE_LIST} placeholder="Type" />
        <TeamsDropdown value={role} onChange={setRole} options={window.ROLE_ORDER.map((k) => ({ v: k, l: window.ROLES[k].label }))} placeholder="Role" />
        <TeamsDropdown value={band} onChange={setBand} options={["Early", "Mid", "Late", "Boss"]} placeholder="Level band" />
        <span className="count">{active ? <><b>{hitCount}</b> lit · {all.length} on route</> : <><b>{all.length}</b> trainers · start → champion</>}</span>
      </div>
      <div className="view-scroll scrl">
        <TrainerMap teams={all} matches={active ? matches : null} onOpen={setOpen} />
      </div>
      {open && <TrainerDetail team={open} onClose={() => setOpen(null)} />}
    </div>
  );
}

Object.assign(window, { TeamsView, TrainerMap, TrainerDetail });
