function buildStartSitSlots(config) {
  const cfg = {
    QB: 1, RB: 2, WR: 2, TE: 1, FLEX: 1, SUPERFLEX: 0, DST: 1, K: 1,
    ...(config || window.DEFAULT_ROSTER_CONFIG || {}),
  };
  const order = [
    { key: "QB", accept: ["QB"] },
    { key: "RB", accept: ["RB"] },
    { key: "WR", accept: ["WR"] },
    { key: "TE", accept: ["TE"] },
    { key: "FLEX", accept: ["RB", "WR", "TE"] },
    { key: "SUPERFLEX", accept: ["QB", "RB", "WR", "TE"] },
    { key: "DST", accept: ["DST"] },
    { key: "K", accept: ["K"] },
  ];
  const slots = [];
  order.forEach(({ key, accept }) => {
    const n = Number(cfg[key]) || 0;
    for (let i = 0; i < n; i += 1) {
      slots.push({
        id: n === 1 ? key.toLowerCase() : `${key.toLowerCase()}${i + 1}`,
        label: key,
        accept,
      });
    }
  });
  return slots;
}

function LineupView({ onSelectPlayer, activeLeague, session }) {
  const live = window.useLiveLeague ? window.useLiveLeague(activeLeague) : null;
  const { PLAYERS } = window;
  const loggedIn = !!session || !!activeLeague;
  const rosterConfig = live?.rosterConfig
    || activeLeague?.rosterConfig
    || (window.resolveRosterConfig ? window.resolveRosterConfig(activeLeague) : window.DEFAULT_ROSTER_CONFIG);
  const SLOTS = React.useMemo(
    () => buildStartSitSlots(rosterConfig),
    [rosterConfig?.FLEX, rosterConfig?.RB, rosterConfig?.WR, rosterConfig?.TE, rosterConfig?.SUPERFLEX, rosterConfig?.DST, rosterConfig?.K],
  );
  const builtRoster = React.useMemo(() => {
    if (!activeLeague) return [];
    try {
      return (window.buildLiveLeagueContext && window.buildLiveLeagueContext(activeLeague)?.roster) || [];
    } catch (error) {
      console.warn("Roster build failed", error);
      return [];
    }
  }, [activeLeague?.id, activeLeague?.picks?.length, activeLeague?.draftPosition, activeLeague?.teams?.length]);
  const liveRoster = live?.roster?.length ? live.roster : builtRoster;
  const roster = liveRoster.length
    ? liveRoster
    : (loggedIn
      ? []
        : (window.getDemoRosterPlayers
        ? window.getDemoRosterPlayers({ forceSeed: true })
        : (window.ROSTER_IDS || []).map((id) => PLAYERS.find((p) => p.id === id)).filter(Boolean)));

  function buildInitialLineup(source) {
    const used = new Set();
    const next = {};
    const slotByLabel = {};
    SLOTS.forEach((slot) => {
      if (!slotByLabel[slot.label]) slotByLabel[slot.label] = [];
      slotByLabel[slot.label].push(slot.id);
    });
    source.forEach((player) => {
      const label = player.lineupSlot;
      if (!label || label === "BENCH") return;
      const mapped = slotByLabel[label] || [];
      const open = mapped.find((id) => !next[id]);
      if (open) {
        next[open] = player.id;
        used.add(player.id);
      }
    });
    SLOTS.forEach((slot) => {
      if (next[slot.id]) return;
      const pick = source
        .filter((p) => slot.accept.includes(p.pos) && !used.has(p.id))
        .sort((a, b) => (b.proj || 0) - (a.proj || 0))[0];
      if (pick) {
        next[slot.id] = pick.id;
        used.add(pick.id);
      }
    });
    return next;
  }

  const demoInitial = (() => {
    if (loggedIn) return buildInitialLineup(roster);
    const source = window.getDemoRosterPlayers
      ? window.getDemoRosterPlayers({ forceSeed: true })
      : roster;
    return buildInitialLineup(source);
  })();

  const [lineup, setLineup] = React.useState(() => buildInitialLineup(roster));
  const [optimized, setOptimized] = React.useState(false);
  const [openSlot, setOpenSlot] = React.useState(null);

  React.useEffect(() => {
    setLineup(buildInitialLineup(roster));
    setOptimized(false);
  }, [activeLeague?.id, roster.map((p) => p.id).join("|"), SLOTS.map((s) => s.id).join("|")]);

  const playerById = (id) => roster.find((p) => p.id === id) || (!loggedIn ? PLAYERS.find((p) => p.id === id) : null);
  const usedIds = new Set(Object.values(lineup).filter(Boolean));
  const bench = roster.filter((p) => !usedIds.has(p.id));

  const total = Object.values(lineup).reduce((s, id) => {
    const p = playerById(id);
    return s + (p ? (p.proj || 0) : 0);
  }, 0);
  const ceiling = Object.values(lineup).reduce((s, id) => {
    const p = playerById(id);
    return s + (p ? (p.proj || 0) * 1.5 : 0);
  }, 0);
  const floor = Object.values(lineup).reduce((s, id) => {
    const p = playerById(id);
    return s + (p ? (p.proj || 0) * 0.55 : 0);
  }, 0);

  const weekLabel = live || loggedIn ? `Week ${live?.currentWeek || 1} · Lineup builder` : "Week 11 · Lineup builder";
  const subcopy = live || loggedIn
    ? `${live?.teamName || activeLeague?.teamName || "My Team"} · ${(live?.scoring || activeLeague?.scoring || "ppr").toUpperCase()} scoring`
    : "Drag players, tap to swap, or hit Auto-optimize. Locks Sunday 1pm ET.";

  function optimize() {
    const owned = roster.slice();
    const used = new Set();
    const newLineup = {};
    for (const slot of SLOTS) {
      const eligible = owned
        .filter((p) => slot.accept.includes(p.pos) && !used.has(p.id))
        .sort((a, b) => (b.proj || 0) - (a.proj || 0));
      if (eligible[0]) {
        newLineup[slot.id] = eligible[0].id;
        used.add(eligible[0].id);
      }
    }
    setLineup(newLineup);
    setOptimized(true);
  }

  function reset() {
    setLineup(roster.length ? buildInitialLineup(roster) : {});
    setOptimized(false);
  }

  function swap(slotId, newPlayerId) {
    setLineup((prev) => {
      const next = { ...prev };
      const otherSlot = Object.keys(next).find((k) => next[k] === newPlayerId && k !== slotId);
      if (otherSlot) next[otherSlot] = prev[slotId];
      next[slotId] = newPlayerId;
      return next;
    });
    setOpenSlot(null);
  }

  return (
    <div className="view-enter" style={{ maxWidth: 1280, margin: "0 auto", padding: 32 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", marginBottom: 24, flexWrap: "wrap", gap: 16 }}>
        <div>
          <div className="mono" style={{ fontSize: 11, color: "var(--mint)", textTransform: "uppercase", letterSpacing: "0.18em", marginBottom: 6 }}>{weekLabel}</div>
          <h1 className="display" style={{ margin: 0, fontSize: 40, color: "var(--mint-soft)" }}>Start / Sit Studio</h1>
          <p style={{ marginTop: 8, color: "var(--slate)", fontSize: 14 }}>{subcopy}</p>
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          <button className="btn ghost" onClick={reset}>Reset</button>
          <button className="btn" onClick={optimize} disabled={!roster.length}>
            <window.IconBolt size={14} stroke="var(--black)" />
            {optimized ? "Optimized" : "Auto-optimize"}
          </button>
        </div>
      </div>

      {(loggedIn && !roster.length) && (
        <div className="card" style={{ padding: 20, marginBottom: 16, color: "var(--slate)", fontSize: 13 }}>
          {activeLeague
            ? `No drafted players loaded for ${activeLeague.teamName || activeLeague.name}. Open Draft Live so we can read beta_draft_picks for this league.`
            : "No league loaded yet. Select a league in the header."}
        </div>
      )}

      <div className="card" style={{ padding: 24, marginBottom: 20, position: "relative", overflow: "hidden" }}>
        {optimized && (
          <div style={{ position: "absolute", top: 18, right: 18, padding: "6px 12px", borderRadius: 999, background: "rgba(149,249,174,0.1)", border: "1px solid rgba(149,249,174,0.4)", color: "var(--mint)", fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase" }}>Optimized</div>
        )}
        <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr 1fr", gap: 32, alignItems: "center" }}>
          <div>
            <div className="mono" style={{ fontSize: 10, color: "var(--slate)", textTransform: "uppercase", letterSpacing: "0.12em" }}>Projected total</div>
            <div className="num" style={{ marginTop: 8, fontSize: 56, color: "var(--mint)", lineHeight: 0.95 }}>{total.toFixed(1)}</div>
            <div className="mono" style={{ marginTop: 6, fontSize: 11, color: "var(--slate-dim)" }}>
              {live || loggedIn
                ? `${(live?.scoring || activeLeague?.scoring || "ppr").toUpperCase()} · ${live?.teamName || activeLeague?.teamName || "My Team"}`
                : "PPR scoring · vs opp proj 118.4"}
            </div>
          </div>
          <RangeStat label="Floor"   value={floor.toFixed(1)}    color="var(--slate)" sub="5th percentile" />
          <RangeStat label="Median"  value={total.toFixed(1)}    color="var(--mint-soft)" sub="50th percentile" />
          <RangeStat label="Ceiling" value={ceiling.toFixed(1)}  color="var(--mint)" sub="95th percentile" />
        </div>

        <div style={{ marginTop: 24 }}>
          <div style={{ position: "relative", height: 6, background: "var(--green-600)", borderRadius: 3 }}>
            <div style={{ position: "absolute", left: "30%", right: "20%", height: "100%", borderRadius: 3, background: "linear-gradient(to right, var(--slate), var(--mint))", opacity: 0.7 }} />
            <div style={{ position: "absolute", left: `${Math.min(90, Math.max(10, (total / 250) * 100))}%`, top: -4, width: 2, height: 14, background: "var(--mint)", borderRadius: 1 }} />
          </div>
          <div style={{ display: "flex", justifyContent: "space-between", marginTop: 8 }}>
            <span className="mono" style={{ fontSize: 10, color: "var(--slate)" }}>50 pts</span>
            <span className="mono" style={{ fontSize: 10, color: "var(--slate)" }}>250 pts</span>
          </div>
        </div>
      </div>

      <div className="card" style={{ padding: 24, marginBottom: 20 }}>
        <SectionTitle eyebrow="Starting Lineup">Active roster</SectionTitle>
        <div style={{ display: "grid", gap: 8 }}>
          {SLOTS.map((slot) => {
            const p = playerById(lineup[slot.id]);
            const expanded = openSlot === slot.id;
            const swapOptions = bench
              .filter((b) => slot.accept.includes(b.pos))
              .sort((a, b) => (b.proj || 0) - (a.proj || 0));
            if (!p) {
              return (
                <div key={slot.id} style={{
                  display: "grid", gridTemplateColumns: "70px 1fr", gap: 16, alignItems: "center",
                  padding: "12px 16px", borderRadius: 12, background: "var(--green-900)", border: "1px dashed var(--green-600)",
                }}>
                  <div className="mono" style={{ textAlign: "center", color: "var(--slate)", fontSize: 12 }}>{slot.label}</div>
                  <div style={{ color: "var(--slate)", fontSize: 13 }}>Empty slot</div>
                </div>
              );
            }
            return (
              <div key={slot.id}>
                <LineupSlot
                  slot={slot}
                  player={p}
                  swapOpen={expanded}
                  onClick={() => onSelectPlayer && onSelectPlayer(p)}
                  onSwapClick={() => setOpenSlot(expanded ? null : slot.id)}
                />
                {expanded && (
                  <div style={{
                    margin: "4px 0 10px",
                    padding: "8px 8px 8px 78px",
                    borderRadius: 12,
                    background: "rgba(149,249,174,0.04)",
                    border: "1px solid rgba(149,249,174,0.22)",
                  }}>
                    <div className="mono" style={{ fontSize: 9, color: "var(--mint)", letterSpacing: "0.12em", textTransform: "uppercase", marginBottom: 8 }}>
                      Bench options · {slot.label}{slot.label === "FLEX" ? " · WR / RB / TE" : slot.label === "SUPERFLEX" ? " · QB / WR / RB / TE" : ""}
                    </div>
                    {swapOptions.length ? swapOptions.map((opt) => (
                      <button
                        key={opt.id}
                        onClick={() => swap(slot.id, opt.id)}
                        style={{
                          width: "100%",
                          display: "grid",
                          gridTemplateColumns: "1fr 80px 70px",
                          alignItems: "center",
                          gap: 12,
                          padding: "8px 10px",
                          marginBottom: 6,
                          borderRadius: 10,
                          background: "var(--green-900)",
                          border: "1px solid var(--green-600)",
                          cursor: "pointer",
                          textAlign: "left",
                        }}
                      >
                        <PlayerCell player={opt} mini />
                        <MatchupBars rating={opt.matchupRating || 3} />
                        <div className="num" style={{ fontSize: 16, color: "var(--mint)", textAlign: "right" }}>{(opt.proj || 0).toFixed(1)}</div>
                      </button>
                    )) : (
                      <div style={{ color: "var(--slate)", fontSize: 12, padding: "6px 0 4px" }}>No bench players fit this slot.</div>
                    )}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>

      <div className="card" style={{ padding: 24 }}>
        <SectionTitle eyebrow="Bench" action={<span className="chip">{bench.length} players</span>}>Bench & reserves</SectionTitle>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 10 }}>
          {bench.map((p) => (
            <button key={p.id} onClick={() => onSelectPlayer && onSelectPlayer(p)} style={{
              display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10,
              padding: "10px 12px", borderRadius: 10,
              background: "var(--green-900)", border: "1px solid var(--green-600)",
              cursor: "pointer", textAlign: "left", transition: "border-color 0.12s",
            }}
              onMouseEnter={(e) => { e.currentTarget.style.borderColor = "var(--mint)"; }}
              onMouseLeave={(e) => { e.currentTarget.style.borderColor = "var(--green-600)"; }}>
              <PlayerCell player={p} mini />
              <div style={{ textAlign: "right" }}>
                <div className="num" style={{ fontSize: 14, color: "var(--mint-soft)" }}>{(p.proj || 0).toFixed(1)}</div>
                <div style={{ marginTop: 2 }}><MatchupBars rating={p.matchupRating || 3} /></div>
              </div>
            </button>
          ))}
          {!bench.length && (
            <div style={{ gridColumn: "1 / -1", padding: 16, color: "var(--slate)", fontSize: 13 }}>
              {live ? "No bench players yet." : "Bench empty."}
            </div>
          )}
        </div>
      </div>

      <div style={{ marginTop: 20 }}>
        <StadiumMap onSelectPlayer={onSelectPlayer} activeLeague={activeLeague} session={session} />
      </div>
    </div>
  );
}

function RangeStat({ label, value, color, sub }) {
  return (
    <div>
      <div className="mono" style={{ fontSize: 10, color: "var(--slate)", textTransform: "uppercase", letterSpacing: "0.12em" }}>{label}</div>
      <div className="num" style={{ marginTop: 6, fontSize: 28, color }}>{value}</div>
      <div className="mono" style={{ marginTop: 4, fontSize: 10, color: "var(--slate-dim)", letterSpacing: "0.03em" }}>{sub}</div>
    </div>
  );
}

function currentSeasonActuals(player) {
  const logs = (typeof window.currentSeasonGameLogs === "function"
    ? window.currentSeasonGameLogs(player)
    : (player?.historicalLogs || []).filter((log) => Number(log.season) === 2026))
    .filter((log) => Number.isFinite(Number(log.ppr ?? log.fantasyPoints)))
    .sort((a, b) => (Number(a.week) || 0) - (Number(b.week) || 0));
  if (logs.length) return logs.map((log) => Number(log.ppr ?? log.fantasyPoints));
  return [];
}

function LineupSlot({ slot, player, onClick, onSwapClick, swapOpen }) {
  const history = currentSeasonActuals(player);
  const hasHistory = history.length > 0;
  const avg = hasHistory ? history.reduce((a, b) => a + b, 0) / history.length : 0;
  const weekLabel = hasHistory
    ? `Avg · ${history.length} wk${history.length === 1 ? "" : "s"}`
    : "No games";
  const advice = (player.matchupRating || 3) >= 4 ? "Start" : (player.matchupRating || 3) <= 2 ? "Risk" : "Lean";
  const adviceColor = advice === "Start" ? "var(--mint)" : advice === "Risk" ? "var(--red)" : "var(--gold)";

  return (
    <div style={{
      display: "grid", gridTemplateColumns: "70px 1.4fr 1fr 100px 100px 110px",
      gap: 16, alignItems: "center",
      padding: "12px 16px", borderRadius: 12,
      background: "var(--green-900)", border: "1px solid var(--green-600)",
      transition: "border-color 0.12s",
    }}>
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "center",
        height: 44, borderRadius: 8,
        background: slot.label === "FLEX" ? "rgba(149,249,174,0.08)" : "var(--green-800)",
        border: slot.label === "FLEX" ? "1px dashed rgba(149,249,174,0.4)" : "1px solid var(--green-600)",
        color: slot.label === "FLEX" ? "var(--mint)" : "var(--mint-soft)",
        fontSize: 12, fontWeight: 700, fontFamily: "Space Grotesk", letterSpacing: "0.05em",
      }}>{slot.label}</div>

      <button onClick={onClick} style={{ background: "transparent", border: "none", padding: 0, cursor: "pointer", textAlign: "left" }}>
        <PlayerCell player={player} />
      </button>

      <div style={{ display: "flex", alignItems: "center", gap: 12, minHeight: 26 }}>
        {hasHistory
          ? <Sparkline data={history} width={70} height={26} fill={false} />
          : <div style={{ width: 70, height: 26, borderRadius: 4, border: "1px dashed var(--green-600)", background: "var(--green-800)" }} />}
        <div>
          <div className="mono" style={{ fontSize: 10, color: "var(--slate)", letterSpacing: "0.06em", textTransform: "uppercase" }}>{weekLabel}</div>
          <div className="mono" style={{ fontSize: 11, color: hasHistory ? "var(--mint-soft)" : "var(--slate-dim)", marginTop: 2 }}>
            {hasHistory ? avg.toFixed(1) : "—"}
          </div>
        </div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 4 }}>
        <span className="mono" style={{ fontSize: 9, color: "var(--slate)", letterSpacing: "0.1em", textTransform: "uppercase" }}>Matchup</span>
        <MatchupBars rating={player.matchupRating || 3} />
      </div>

      <div>
        <div className="mono" style={{ fontSize: 9, color: "var(--slate)", letterSpacing: "0.1em", textTransform: "uppercase" }}>Proj</div>
        <div className="num" style={{ fontSize: 22, color: "var(--mint)" }}>{(player.proj || 0).toFixed(1)}</div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", alignItems: "stretch", gap: 6 }}>
        <span style={{
          padding: "4px 10px", borderRadius: 6, fontSize: 11, fontWeight: 700,
          textAlign: "center", letterSpacing: "0.06em", textTransform: "uppercase",
          color: adviceColor, background: `${adviceColor}12`, border: `1px solid ${adviceColor}40`,
          fontFamily: "JetBrains Mono",
        }}>{advice}</span>
        <button onClick={onSwapClick} className="btn ghost" style={{ padding: "5px 8px", fontSize: 11, justifyContent: "center" }}>
          <window.IconSwap size={12} /> {swapOpen ? "Close" : "Swap"}
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { LineupView });
