"use client";

import { useMemo, useState } from "react";
import type { CardId } from "@/lib/poker/cards";
import { Palette } from "./components/Palette";
import { Felt } from "./components/Felt";
import { Results } from "./components/Results";
import { useEquity, PHASE_ORDER, type Phase } from "./useEquity";

const ITERATIONS = 100_000;
const MIN_PLAYERS = 2;
const MAX_PLAYERS = 10;
const SLOT_ORDER = ["hole-0", "hole-1", "board-0", "board-1", "board-2", "board-3", "board-4"];

const SLOT_HINT: Record<string, string> = {
  "hole-0": "1ª carta in mano",
  "hole-1": "2ª carta in mano",
  "board-0": "1ª carta del flop",
  "board-1": "2ª carta del flop",
  "board-2": "3ª carta del flop",
  "board-3": "il turn (4ª carta)",
  "board-4": "il river (5ª carta)",
};

function slotValue(hole: (CardId | null)[], board: (CardId | null)[], slot: string): CardId | null {
  const [g, i] = slot.split("-");
  return g === "hole" ? hole[+i] : board[+i];
}

function firstEmpty(hole: (CardId | null)[], board: (CardId | null)[]): string | null {
  for (const slot of SLOT_ORDER) {
    if (slotValue(hole, board, slot) === null) return slot;
  }
  return null;
}

// The board must stay a gap-free prefix (you can't have a river without a turn),
// so the next placeable community card is always the first empty index.
function firstEmptyBoardIndex(board: (CardId | null)[]): number {
  for (let i = 0; i < 5; i++) if (board[i] === null) return i;
  return 5;
}

export default function PokerCalculator() {
  const [players, setPlayers] = useState(6);
  const [hole, setHole] = useState<(CardId | null)[]>([null, null]);
  const [board, setBoard] = useState<(CardId | null)[]>([null, null, null, null, null]);
  const [active, setActive] = useState<string | null>("hole-0");

  const used = useMemo(() => {
    const s = new Set<CardId>();
    for (const c of hole) if (c !== null) s.add(c);
    for (const c of board) if (c !== null) s.add(c);
    return s;
  }, [hole, board]);

  // Engine inputs must be contiguous prefixes.
  const holeCards = hole[0] !== null && hole[1] !== null ? [hole[0], hole[1]] : [];
  const boardCards: CardId[] = [];
  for (const c of board) {
    if (c === null) break;
    boardCards.push(c);
  }

  const phases = useEquity({
    hole: holeCards,
    board: boardCards,
    opponents: players - 1,
    iterations: ITERATIONS,
  });

  const current: Phase | null = useMemo(() => {
    let cur: Phase | null = null;
    for (const p of PHASE_ORDER) if (phases[p]) cur = p;
    return cur;
  }, [phases]);

  // --- interactions -------------------------------------------------------
  function placeCard(card: CardId) {
    const target = active ?? firstEmpty(hole, board);
    if (!target) return;
    const [g, i] = target.split("-");
    let idx = +i;
    const h = [...hole];
    const b = [...board];
    if (g === "hole") {
      h[idx] = card;
    } else {
      // Never write behind a board gap: land on the contiguous frontier.
      if (b[idx] === null) idx = firstEmptyBoardIndex(b);
      if (idx > 4) return;
      b[idx] = card;
    }
    setHole(h);
    setBoard(b);
    setActive(firstEmpty(h, b));
  }

  function removeCard(card: CardId) {
    const h = [...hole];
    const b = [...board];
    let cleared: string | null = active;
    for (let i = 0; i < 2; i++) if (h[i] === card) { h[i] = null; cleared = `hole-${i}`; }
    for (let i = 0; i < 5; i++) {
      if (b[i] === card) {
        for (let k = i; k < 5; k++) b[k] = null; // can't keep later streets
        cleared = `board-${i}`;
        break;
      }
    }
    setHole(h);
    setBoard(b);
    setActive(cleared);
  }

  function onPick(card: CardId) {
    if (used.has(card)) removeCard(card);
    else placeCard(card);
  }

  function onSlot(slot: string) {
    const [g, i] = slot.split("-");
    const idx = +i;
    const filled = slotValue(hole, board, slot) !== null;

    if (filled) {
      if (g === "hole") {
        const h = [...hole];
        h[idx] = null;
        setHole(h);
      } else {
        const b = [...board];
        for (let k = idx; k < 5; k++) b[k] = null; // later streets can't survive
        setBoard(b);
      }
      setActive(slot);
      return;
    }

    // Tapping an empty board slot beyond the frontier snaps to the next real one.
    if (g === "board") {
      setActive(`board-${firstEmptyBoardIndex(board)}`);
    } else {
      setActive(slot);
    }
  }

  function reset() {
    setHole([null, null]);
    setBoard([null, null, null, null, null]);
    setActive("hole-0");
  }

  const ready = holeCards.length === 2;

  return (
    <main className="mx-auto flex w-full max-w-md flex-col gap-4 px-3 py-4">
      <header className="flex items-center justify-between gap-3">
        <div>
          <h1 className="text-lg font-extrabold tracking-tight">
            Poker <span className="text-emerald-400">Odds</span>
          </h1>
          <p className="text-[11px] text-white/45">Texas Hold&apos;em · probabilità di vittoria</p>
        </div>
        <button
          type="button"
          onClick={reset}
          className="rounded-full border border-white/15 bg-white/5 px-3 py-1.5 text-xs font-semibold text-white/80 active:scale-95"
        >
          ↺ Nuova mano
        </button>
      </header>

      {/* Players selector */}
      <div className="flex items-center justify-between rounded-2xl border border-white/10 bg-white/[0.04] px-4 py-3">
        <div>
          <div className="text-sm font-semibold">Giocatori al tavolo</div>
          <div className="text-[11px] text-white/45">{players - 1} avversari</div>
        </div>
        <div className="flex items-center gap-3">
          <Stepper
            value={players}
            min={MIN_PLAYERS}
            max={MAX_PLAYERS}
            onChange={setPlayers}
          />
        </div>
      </div>

      {/* 52-card palette */}
      <section>
        <div className="mb-2 flex items-center justify-between">
          <h2 className="text-xs font-semibold uppercase tracking-widest text-white/55">Mazzo</h2>
          <span className="text-[11px] text-white/45">
            {active ? <>Scegli <span className="text-emerald-300">{SLOT_HINT[active]}</span></> : "Tavolo completo"}
          </span>
        </div>
        <Palette used={used} onPick={onPick} />
      </section>

      {/* Table */}
      <Felt hole={hole} board={board} activeSlot={active} onSlot={onSlot} />

      {/* Results */}
      <Results phases={phases} current={current} ready={ready} iterations={ITERATIONS} />

      <footer className="pb-2 text-center text-[10px] text-white/30">
        Le percentuali assumono carte avversarie casuali.
      </footer>
    </main>
  );
}

function Stepper({
  value,
  min,
  max,
  onChange,
}: {
  value: number;
  min: number;
  max: number;
  onChange: (v: number) => void;
}) {
  const btn =
    "flex h-9 w-9 items-center justify-center rounded-full bg-emerald-500/90 text-lg font-bold text-black disabled:opacity-30 active:scale-90";
  return (
    <div className="flex items-center gap-3">
      <button type="button" className={btn} onClick={() => onChange(Math.max(min, value - 1))} disabled={value <= min} aria-label="Meno giocatori">−</button>
      <span className="w-6 text-center text-2xl font-extrabold tabular-nums">{value}</span>
      <button type="button" className={btn} onClick={() => onChange(Math.min(max, value + 1))} disabled={value >= max} aria-label="Più giocatori">+</button>
    </div>
  );
}
