/* ============================================================
   components.jsx — presentational UI for GTO Heads-Up
   Exposes components on window for app.jsx
   ============================================================ */
const { useState, useEffect, useRef } = React;
const E = window.Engine;

const fmt = (x) => {
  const r = Math.round(x * 10) / 10;
  return Number.isInteger(r) ? String(r) : r.toFixed(1);
};

/* ---------- Cards ---------- */
function Card({ c, back, muck, tiny }) {
  if (back) return <div className={"card back" + (tiny ? " tiny" : "")} />;
  if (c === null || c === undefined) return <div className="board-slot" />;
  const lab = E.cardLabel(c);
  const red = lab.s === "h" || lab.s === "d";
  const rank = lab.r === "T" ? "10" : lab.r;
  return (
    <div className={"card deal-in" + (red ? " red" : "") + (muck ? " muck" : "") + (tiny ? " tiny" : "")}>
      <div className={"r" + (rank === "10" ? " ten" : "")}>{rank}</div>
      <div className="s">{lab.sym}</div>
    </div>
  );
}

function Hole({ cards, hidden, muck, tiny }) {
  return (
    <div className="cards">
      {hidden
        ? [0, 1].map((i) => <Card key={i} back tiny={tiny} />)
        : cards.map((c, i) => <Card key={i} c={c} muck={muck} tiny={tiny} />)}
    </div>
  );
}

/* ---------- Seat ---------- */
function Seat({ player, isHero, active, position, reveal, bet }) {
  return (
    <div className={"seat compact" + (active ? " active" : "") + (isHero ? " hero" : "")}>
      <div className="avatar">{isHero ? "\u2665" : "\u25C6"}</div>
      <div className="seat-meta">
        <div className="seat-name">
          {player.name}
          <span className={"pos-badge" + (position === "BTN" ? " btn" : "")}>{position}</span>
        </div>
        <div className="seat-stack mono">{fmt(player.stack)} <span style={{ color: "var(--text-3)" }}>bb</span></div>
      </div>
      <Hole cards={player.hole} hidden={!isHero && !reveal} muck={player.folded} />
      {bet > 0 && <div className="bet-chip">{fmt(bet)} bb</div>}
    </div>
  );
}

/* ---------- Board + Pot ---------- */
function Board({ board }) {
  const slots = [];
  for (let i = 0; i < 5; i++) slots.push(i < board.length ? <Card key={i} c={board[i]} /> : <div key={i} className="board-slot" />);
  return <div className="board">{slots}</div>;
}
function Pot({ pot }) {
  return (
    <div className="pot">
      <span className="lab">Pot</span>
      <span className="val mono">{fmt(pot)} <span className="bb">bb</span></span>
    </div>
  );
}

/* ---------- Action bar ---------- */
function targetForFrac(hand, i, frac) {
  const myBet = E.streetInvest(hand, i);
  const oppBet = E.streetInvest(hand, 1 - i);
  const toCall = Math.max(0, oppBet - myBet);
  const pot = E.potNow(hand);
  let to;
  if (toCall > 0) { const potAfter = pot + toCall; to = oppBet + frac * potAfter; }
  else { to = myBet + frac * pot; }
  return to;
}

function ActionBar({ hand, hero, onAction, busy, waitingNext, onNext, dealing, mode, sizeRef }) {
  const i = hero;
  const me = hand.players[i];
  const myBet = E.streetInvest(hand, i);
  const oppBet = E.streetInvest(hand, 1 - i);
  const toCall = Math.max(0, oppBet - myBet);
  const pot = E.potNow(hand);
  const minTo = Math.min(E.minRaiseTo(hand), myBet + me.stack);
  const maxTo = myBet + me.stack;
  const canAggro = me.stack > toCall;

  const presets = hand.street === "preflop" && toCall > 0 && oppBet <= E.BB_SIZE + 0.01
    ? [["2.5x", null, 2.5], ["3x", null, 3], ["3.5x", null, 3.5], ["Pot", 1, null], ["All-in", null, maxTo]]
    : [["33%", 0.33], ["50%", 0.5], ["75%", 0.75], ["Pot", 1], ["All-in", null, maxTo]];

  const [to, setTo] = useState(minTo);
  const [activePreset, setActivePreset] = useState(null);

  useEffect(() => {
    // default sizing per street
    let def;
    if (hand.street === "preflop" && toCall > 0 && oppBet <= E.BB_SIZE + 0.01) def = Math.min(maxTo, 2.5 * E.BB_SIZE);
    else def = Math.min(maxTo, Math.max(minTo, targetForFrac(hand, i, 0.66)));
    setTo(Math.round(def * 10) / 10);
    setActivePreset(null);
    // eslint-disable-next-line
  }, [hand.street, hand.history.length, toCall, hand.toAct]);

  if (sizeRef) sizeRef.current = (!waitingNext && !busy && hand.toAct === hero && !hand.finished && canAggro) ? to : null;

  if (waitingNext) {
    return (
      <div className="actionbar">
        <div className="waiting">
          <button className="next-btn" onClick={onNext}>Next hand &rarr;</button>
        </div>
      </div>
    );
  }
  if (busy || hand.toAct !== hero || hand.finished) {
    return (
      <div className="actionbar">
        <div className="waiting">
          <span className="mono" style={{ color: "var(--text-3)" }}>
            {hand.finished ? "Hand complete" : `${(hand.players[1 - hero] && hand.players[1 - hero].name) || "Opponent"} is thinking\u2026`}
          </span>
        </div>
      </div>
    );
  }

  const applyPreset = (p) => {
    let val;
    if (p[2] != null && p[0] === "All-in") val = maxTo;
    else if (hand.street === "preflop" && p[2] != null) val = Math.min(maxTo, p[2] * E.BB_SIZE);
    else if (p[1] != null) val = targetForFrac(hand, i, p[1]);
    else val = to;
    val = Math.max(minTo, Math.min(maxTo, val));
    setTo(Math.round(val * 10) / 10);
    setActivePreset(p[0]);
  };

  const raiseType = toCall > 0 ? "raise" : "bet";
  const raiseVerb = toCall > 0 ? "Raise" : "Bet";

  return (
    <div className="actionbar">
      {canAggro && (
        <div className="sizing">
          {presets.map((p) => (
            <button key={p[0]} className={"sizechip" + (activePreset === p[0] ? " on" : "")} onClick={() => applyPreset(p)}>{p[0]}</button>
          ))}
          <div className="slider-wrap">
            <input type="range" min={minTo} max={maxTo} step={0.5} value={to}
              onChange={(e) => { setTo(parseFloat(e.target.value)); setActivePreset(null); }} />
            <span className="raise-amt mono">{fmt(to)} bb</span>
          </div>
        </div>
      )}
      <div className="act-row">
        {toCall > 0
          ? <button className="btn fold" onClick={() => onAction({ type: "fold" })}>Fold</button>
          : <button className="btn fold" onClick={() => onAction({ type: "check" })}>Check</button>}
        {toCall > 0 && (
          <button className="btn call" onClick={() => onAction({ type: "call", to: oppBet })}>
            Call<span className="sub">{fmt(Math.min(toCall, me.stack))} bb</span>
          </button>
        )}
        {canAggro && (
          <button className="btn raise" onClick={() => onAction({ type: raiseType, to })}>
            {raiseVerb}<span className="sub">to {fmt(to)} bb</span>
          </button>
        )}
      </div>
      <div className="keyhint"><b>F</b> {toCall > 0 ? "fold" : "check"} · <b>C</b> {toCall > 0 ? "call" : "check"}{canAggro && <>{" · "}<b>R</b> raise{" · "}<b>A</b> all-in</>} · <b>N</b> next</div>
    </div>
  );
}

/* ---------- Action colors + solver mix bar ---------- */
const ACT_COLOR = { raise: "var(--accent)", bet: "var(--accent)", call: "var(--ok)", check: "var(--text-3)", fold: "var(--bad)" };
function MixBar({ mix }) {
  if (!mix || !mix.length) return null;
  return (
    <div className="mixbar">
      {mix.map((m, k) => (
        <div key={k} className="mixseg" style={{ width: (m.freq * 100) + "%", background: ACT_COLOR[m.action] || "var(--line-2)" }}
          title={m.action + " " + Math.round(m.freq * 100) + "%"} />
      ))}
    </div>
  );
}

/* ---------- Study-mode feedback overlay ---------- */
function FeedbackOverlay({ fb, onContinue }) {
  if (!fb) return null;
  const cls = fb.color === "good" ? "fb-good" : fb.color === "ok" ? "fb-ok" : fb.color === "warn" ? "fb-warn" : "fb-bad";
  return (
    <div className="overlay" onClick={onContinue}>
      <div className="overlay-card" onClick={(e) => e.stopPropagation()}>
        <div className="ohead">
          <span className={"fb-badge " + cls}>{ratingIcon(fb.color)} {fb.ratingLabel}</span>
          <span className="mono" style={{ color: "var(--text-3)", fontSize: 12 }}>
            {fb.evLoss > 0 ? `\u2212${fmt(fb.evLoss)} bb EV` : "0 bb lost"}
          </span>
        </div>
        <div className="cmp">
          <div className={fb.correct ? "" : "wrong"}>
            <div className="clab">You played</div>
            <div className="cval">{fb.chosenLabel}</div>
          </div>
          <div className="opt">
            <div className="clab">GTO play</div>
            <div className="cval">{fb.optimalLabel}</div>
          </div>
        </div>
        <div className="solution-banner">
          <span className="sol-ico">{fb.correct ? "✓" : "✦"}</span>
          <span>{fb.correct ? "Best play — you nailed it: " : "Solution — you should: "}<b>{fb.solution}</b></span>
        </div>
        {fb.mixLabel && <MixBar mix={fb.mix} />}
        {fb.mixLabel && <div className="fb-line"><span>{fb.mixSource === "solver" ? "Solver mix" : "GTO mix"}</span><span className="mono">{fb.mixLabel}</span></div>}
        <div className="fb-line"><span>Your equity</span><span className="mono">{fmt(fb.equity)}%</span></div>
        {fb.potOdds > 0 && <div className="fb-line"><span>Pot odds (need)</span><span className="mono">{fmt(fb.potOdds)}%</span></div>}
        <div className="fb-note">{fb.note}</div>
        <button className="next-btn" style={{ width: "100%", marginTop: 16 }} onClick={onContinue}>Continue</button>
      </div>
    </div>
  );
}
function ratingIcon(color) {
  if (color === "good") return "\u2713";
  if (color === "ok") return "\u2248";
  if (color === "warn") return "!";
  return "\u2715";
}

/* ---------- Toast (play mode) ---------- */
function Toast({ fb }) {
  if (!fb) return null;
  const c = fb.color === "good" ? "var(--good)" : fb.color === "ok" ? "var(--ok)" : fb.color === "warn" ? "var(--warn)" : "var(--bad)";
  return (
    <div className="toast">
      <span style={{ color: c }}>{ratingIcon(fb.color)} {fb.ratingLabel}</span>
      {fb.evLoss > 0 && <span className="mono" style={{ color: "var(--text-3)", fontSize: 13 }}>−{fmt(fb.evLoss)} bb</span>}
    </div>
  );
}

window.UI = { Card, Hole, Seat, Board, Pot, ActionBar, FeedbackOverlay, Toast, MixBar, ACT_COLOR, fmt, ratingIcon, targetForFrac };
