"use client";

import Image from "next/image";
import Link from "next/link";
import type { ReactNode } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import {
  ArrowLeft,
  BarChart3,
  Check,
  ChevronDown,
  Copy,
  Dice5,
  Gauge,
  Infinity,
  Loader2,
  RefreshCw,
  Rocket,
  Settings,
  Sparkles,
  Star,
  X
} from "lucide-react";
import { miniGames } from "@/lib/casino-games";
import { formatAmountInput, formatAmountInputFixed, parseAmountInput } from "@/lib/amount-input";
import { notifyWalletUpdated } from "@/lib/client-events";
import { cn } from "@/lib/utils";
import { CasinoStakeInput } from "@/components/casino/casino-stake-input";
import { GameDetailsPanel } from "@/components/casino/game-details-panel";
import { StakeLimitNote } from "@/components/casino/stake-limit-note";

type DiceRound = {
  id: string;
  currency: string;
  stake: string;
  payout: string;
  profit: string;
  multiplier: string;
  chance: string;
  target: string;
  direction: "over" | "under";
  result: string;
  nonce: number;
  status: "WON" | "LOST" | "VOID";
  serverSeedHash: string;
  createdAt: string;
};

type DiceState = {
  config: {
    minStake: string;
    maxStake: string;
    maxPayout: string;
    minChance: number;
    maxChance: number;
    houseEdgeBps: number;
  };
  currency: string;
  seedPair: {
    id: string;
    clientSeed: string;
    serverSeedHash: string;
    nonce: number;
  };
  stats: {
    stake: string;
    profit: string;
    wins: number;
    losses: number;
  };
  recentRounds: DiceRound[];
};

type Mode = "manual" | "auto" | "advanced";
type Direction = "over" | "under";

const DEFAULT_STATE: DiceState = {
  config: {
    minStake: "0.01",
    maxStake: "10000",
    maxPayout: "100000",
    minChance: 1,
    maxChance: 98,
    houseEdgeBps: 100
  },
  currency: "EUR",
  seedPair: {
    id: "",
    clientSeed: "",
    serverSeedHash: "",
    nonce: 0
  },
  stats: {
    stake: "0",
    profit: "0",
    wins: 0,
    losses: 0
  },
  recentRounds: []
};

export function DiceGame() {
  const [state, setState] = useState<DiceState>(DEFAULT_STATE);
  const [loading, setLoading] = useState(true);
  const [guest, setGuest] = useState(false);
  const [message, setMessage] = useState("");
  const [mode, setMode] = useState<Mode>("manual");
  const [direction, setDirection] = useState<Direction>("over");
  const [chance, setChance] = useState(49.5);
  const [stake, setStake] = useState("0");
  const [betCount, setBetCount] = useState("0");
  const [lastRound, setLastRound] = useState<DiceRound | null>(null);
  const [displayRoll, setDisplayRoll] = useState(50.5);
  const [rolling, setRolling] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [statsOpen, setStatsOpen] = useState(false);
  const [fairnessOpen, setFairnessOpen] = useState(false);
  const [turbo, setTurbo] = useState(false);
  const [maxBet, setMaxBet] = useState(false);
  const [silent, setSilent] = useState(false);
  const [clientSeedInput, setClientSeedInput] = useState("");
  const [revealedSeed, setRevealedSeed] = useState<null | { serverSeed: string; clientSeed: string; nonce: number; serverSeedHash: string }>(null);
  const [verifyInput, setVerifyInput] = useState({ serverSeed: "", clientSeed: "", nonce: "" });
  const [verifyResult, setVerifyResult] = useState<null | { serverSeedHash: string; result: string }>(null);
  const [strategy, setStrategy] = useState("Martingale");
  const [strategyOpen, setStrategyOpen] = useState(false);
  const autoStopRef = useRef(false);

  const target = useMemo(() => round4(direction === "over" ? 100 - chance : chance), [chance, direction]);
  const multiplier = useMemo(() => round4((100 - state.config.houseEdgeBps / 100) / chance), [chance, state.config.houseEdgeBps]);
  const potentialProfit = useMemo(() => {
    const amount = parseAmountInput(stake);
    return amount > 0 ? amount * multiplier - amount : 0;
  }, [multiplier, stake]);
  const recentRolls = state.recentRounds.slice(0, 8);
  const otherGames = miniGames.filter((game) => game.slug !== "dice");

  useEffect(() => {
    void loadState();
  }, []);

  useEffect(() => {
    if (!rolling) return;
    const id = window.setInterval(() => setDisplayRoll(Number((Math.random() * 100).toFixed(2))), 52);
    return () => window.clearInterval(id);
  }, [rolling]);

  async function loadState() {
    try {
      const response = await fetch("/api/casino/dice/state", { cache: "no-store" });
      const payload = await response.json();
      if (!response.ok || !payload.ok) {
        const unauthenticated = response.status === 401 || payload.error?.code === "UNAUTHORIZED";
        setGuest(unauthenticated);
        setMessage(unauthenticated ? "Connecte-toi pour jouer à Dice." : payload.error?.message ?? "Dice indisponible.");
        return;
      }
      setState(payload.data);
      setClientSeedInput(payload.data.seedPair.clientSeed);
      setDisplayRoll(Number(payload.data.recentRounds[0]?.result ?? 50.5));
      setLastRound(payload.data.recentRounds[0] ?? null);
    } catch {
      setMessage("Impossible de charger Dice pour le moment.");
    } finally {
      setLoading(false);
    }
  }

  async function placeRound() {
    if (guest) {
      window.location.href = "/login";
      return null;
    }

    const amount = parseAmountInput(stake);
    if (amount <= 0) {
      setMessage("Saisis une mise valide.");
      return null;
    }

    setMessage("");
    setRolling(true);
    const startedAt = Date.now();

    try {
      const response = await fetch("/api/casino/dice/play", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          currency: state.currency,
          stake: amount,
          chance,
          direction,
          clientRequestId: crypto.randomUUID()
        })
      });
      const payload = await response.json();
      const elapsed = Date.now() - startedAt;
      if (elapsed < 420 && !turbo) {
        await wait(420 - elapsed);
      }

      if (!response.ok || !payload.ok) {
        setMessage(payload.error?.message ?? "Pari refusé.");
        return null;
      }

      const round: DiceRound = payload.data.round;
      setLastRound(round);
      setDisplayRoll(Number(round.result));
      setState((current) => ({
        ...current,
        seedPair: { ...current.seedPair, nonce: current.seedPair.nonce + 1 },
        stats: {
          stake: String(Number(current.stats.stake) + Number(round.stake)),
          profit: String(Number(current.stats.profit) + Number(round.profit)),
          wins: current.stats.wins + (round.status === "WON" ? 1 : 0),
          losses: current.stats.losses + (round.status === "LOST" ? 1 : 0)
        },
        recentRounds: [round, ...current.recentRounds].slice(0, 25)
      }));
      notifyWalletUpdated();
      if (!silent) {
        setMessage(round.status === "WON" ? `Gain ${formatMoney(round.payout, round.currency)}` : "Perdu, prochain roll.");
      }
      return round;
    } catch {
      setMessage("Erreur réseau pendant le pari.");
      return null;
    } finally {
      setRolling(false);
    }
  }

  async function startAuto() {
    autoStopRef.current = false;
    const limit = Number(betCount);
    let played = 0;
    setMessage("");

    while (!autoStopRef.current && (limit <= 0 || played < limit)) {
      const round = await placeRound();
      if (!round) break;
      played += 1;
      await wait(turbo ? 120 : 520);
    }
  }

  function stopAuto() {
    autoStopRef.current = true;
  }

  async function rotateSeeds() {
    setMessage("");
    try {
      const response = await fetch("/api/casino/dice/seeds/rotate", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ clientSeed: clientSeedInput })
      });
      const payload = await response.json();
      if (!response.ok || !payload.ok) {
        setMessage(payload.error?.message ?? "Rotation impossible.");
        return;
      }

      setRevealedSeed(payload.data.previous);
      setState((current) => ({
        ...current,
        seedPair: payload.data.current
      }));
      setClientSeedInput(payload.data.current.clientSeed);
      setMessage("Nouvelle paire de seeds active.");
    } catch {
      setMessage("Rotation des seeds indisponible.");
    }
  }

  async function verifySeed() {
    try {
      const response = await fetch("/api/casino/dice/verify", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(verifyInput)
      });
      const payload = await response.json();
      if (!response.ok || !payload.ok) {
        setMessage(payload.error?.message ?? "Vérification impossible.");
        return;
      }
      setVerifyResult(payload.data);
    } catch {
      setMessage("Vérification indisponible.");
    }
  }

  function changeTarget(nextTarget: number) {
    const boundedTarget = Math.min(99, Math.max(1, nextTarget));
    const nextChance = direction === "over" ? 100 - boundedTarget : boundedTarget;
    setChance(Number(Math.min(state.config.maxChance, Math.max(state.config.minChance, nextChance)).toFixed(4)));
  }

  function halveStake() {
    setStake(formatInputAmount(parseAmountInput(stake) / 2));
  }

  function doubleStake() {
    setStake(formatInputAmount(parseAmountInput(stake) * 2));
  }

  if (loading) {
    return (
      <section className="grid min-h-[360px] place-items-center rounded-lg border border-white/10 bg-[#111720]">
        <Loader2 className="h-7 w-7 animate-spin text-felt" />
      </section>
    );
  }

  return (
    <div className="space-y-3.5">
      <div className="flex items-center gap-2">
        <Link href="/casino" className="grid h-9 w-9 place-items-center rounded-lg border border-white/10 bg-white/[0.04] text-slate-200">
          <ArrowLeft className="h-4 w-4" />
        </Link>
        <div className="flex h-9 items-center gap-2 rounded-lg bg-white/[0.055] px-3 text-sm font-black text-felt">
          <Dice5 className="h-4 w-4" />
          Dice
        </div>
      </div>

      <section className="overflow-hidden rounded-lg border border-white/10 bg-[#0e1219] shadow-panel">
        <div className="relative border-b border-white/10 bg-[#11161f] px-3 pb-4 pt-3 sm:px-4">
          <div className="mb-3 flex items-center gap-1.5 overflow-x-auto pb-1 scrollbar-thin">
            {recentRolls.length ? (
              recentRolls.map((round) => (
                <button
                  key={round.id}
                  className={cn(
                    "h-7 shrink-0 rounded-full px-2.5 text-[11px] font-black",
                    round.status === "WON" ? "bg-felt/[0.12] text-felt" : "bg-ember/[0.12] text-ember"
                  )}
                  onClick={() => {
                    setLastRound(round);
                    setDisplayRoll(Number(round.result));
                  }}
                >
                  {Number(round.result).toFixed(2)}
                </button>
              ))
            ) : (
              <span className="h-7 rounded-full bg-white/[0.04] px-2.5 pt-1.5 text-[11px] font-bold text-slate-500">Aucun roll</span>
            )}
          </div>

          <div className="relative mx-auto max-w-[820px] rounded-lg border border-white/10 bg-black/35 px-3 py-5">
            <DiceTrack
              direction={direction}
              target={target}
              roll={displayRoll}
              rolling={rolling}
              won={lastRound?.status === "WON"}
              onTargetChange={changeTarget}
            />
          </div>

          <div className="mt-4 grid grid-cols-3 gap-2">
            <NumberTile label="Multiplicateur" value={multiplier.toFixed(4)} suffix="x" />
            <button
              onClick={() => setDirection((current) => (current === "over" ? "under" : "over"))}
              className="rounded-lg bg-white/[0.055] p-2.5 text-left transition hover:bg-white/[0.075]"
            >
              <span className="block text-[11px] font-bold text-slate-300">{direction === "over" ? "Lancer au dessus" : "Lancer au dessous"}</span>
              <span className="mt-1 flex items-center justify-between text-sm font-semibold text-white">
                {target.toFixed(2)}
                <RefreshCw className="h-4 w-4 text-slate-300" />
              </span>
            </button>
            <NumberTile label="Chance" value={chance.toFixed(4)} suffix="%" />
          </div>
        </div>

        <div className="border-b border-white/10 p-3 sm:p-4">
          <button
            onClick={mode === "manual" ? placeRound : startAuto}
            disabled={rolling}
            className="grid h-11 w-full place-items-center rounded-lg bg-gradient-to-r from-felt to-emerald-300 text-sm font-black text-ink-950 shadow-[0_16px_36px_rgba(15,191,143,.22)] transition active:scale-[.99] disabled:opacity-60"
          >
            {rolling ? <Loader2 className="h-4 w-4 animate-spin" /> : mode === "manual" ? "Pari" : "Démarrer le pari automatique"}
          </button>
          <StakeLimitNote min={state.config.minStake} max={state.config.maxStake} currency={state.currency} />

          {mode !== "manual" ? (
            <button onClick={stopAuto} className="mt-2 h-9 w-full rounded-lg border border-white/10 bg-white/[0.035] text-xs font-bold text-slate-200">
              Stop
            </button>
          ) : null}

          {message ? <p className="mt-2 rounded-lg border border-white/10 bg-white/[0.035] px-3 py-2 text-xs font-bold text-slate-300">{message}</p> : null}

          <div className="mt-3 space-y-3">
            <CasinoStakeInput value={stake} currency={state.currency} onChange={setStake} onHalf={halveStake} onDouble={doubleStake} />

            <div>
              <div className="mb-1.5 flex items-center justify-between text-[12px] font-bold text-slate-200">
                <span>Profit</span>
                <span className="text-slate-500">{formatAmountInputFixed(potentialProfit)} {state.currency}</span>
              </div>
              <div className="flex h-10 items-center gap-2 rounded-lg border border-white/10 bg-black/20 px-3 text-sm font-semibold text-white">
                <span className="grid h-5 w-5 place-items-center rounded-full bg-felt text-[12px] font-black text-ink-950">€</span>
                {formatInputAmount(Math.max(0, potentialProfit))}
              </div>
            </div>

            {mode !== "manual" ? (
              <AutoPanel
                mode={mode}
                betCount={betCount}
                setBetCount={setBetCount}
                strategy={strategy}
                setStrategy={setStrategy}
                strategyOpen={strategyOpen}
                setStrategyOpen={setStrategyOpen}
              />
            ) : null}

            <div className="grid grid-cols-3 gap-1.5 rounded-lg bg-white/[0.055] p-1.5">
              {modes.map((item) => (
                <button
                  key={item.value}
                  onClick={() => setMode(item.value)}
                  className={cn(
                    "h-9 rounded-md text-xs font-black transition",
                    mode === item.value ? "bg-[#373d4b] text-white" : "text-slate-400 hover:text-white"
                  )}
                >
                  {item.label}
                </button>
              ))}
            </div>
          </div>
        </div>

        <div className="relative flex h-12 items-center justify-between px-3 sm:px-4">
          <div className="flex items-center gap-2">
            <IconButton active={settingsOpen} label="Paramètres" onClick={() => setSettingsOpen((value) => !value)} icon={<Settings className="h-4 w-4" />} />
            <IconButton active={statsOpen} label="Stats" onClick={() => setStatsOpen(true)} icon={<BarChart3 className="h-4 w-4" />} />
            <IconButton label="Favori" onClick={() => setMessage("Dice ajouté à tes favoris.")} icon={<Star className="h-4 w-4" />} />
          </div>
          <button onClick={() => setFairnessOpen((value) => !value)} className="flex items-center gap-1.5 text-xs font-black text-slate-400 underline decoration-slate-600 underline-offset-4">
            Équité
            <Check className="h-3.5 w-3.5 text-felt" />
          </button>

          {settingsOpen ? (
            <SettingsPopover
              turbo={turbo}
              maxBet={maxBet}
              silent={silent}
              onTurbo={setTurbo}
              onMaxBet={(value) => {
                setMaxBet(value);
                if (value) setStake(state.config.maxStake);
              }}
              onSilent={setSilent}
            />
          ) : null}
        </div>
      </section>

      {fairnessOpen ? (
        <FairnessPanel
          state={state}
          revealedSeed={revealedSeed}
          clientSeedInput={clientSeedInput}
          verifyInput={verifyInput}
          verifyResult={verifyResult}
          setClientSeedInput={setClientSeedInput}
          setVerifyInput={setVerifyInput}
          onRotate={rotateSeeds}
          onVerify={verifySeed}
          onClose={() => setFairnessOpen(false)}
        />
      ) : null}

      <GameDetailsPanel kind="dice" rounds={state.recentRounds} currency={state.currency} />

      <section className="space-y-2.5">
        <div className="flex items-center gap-2">
          <span className="grid h-7 w-7 place-items-center rounded-lg bg-felt text-ink-950">
            <Sparkles className="h-4 w-4" />
          </span>
          <h2 className="text-lg font-black text-white">Plus de ZiraBet Games</h2>
        </div>
        <div className="-mx-1 flex gap-2 overflow-x-auto px-1 pb-1 scrollbar-thin">
          {otherGames.slice(0, 5).map((game) => (
            <Link key={game.slug} href={`/casino/games/${game.slug}`} className="relative aspect-[150/205] w-[112px] shrink-0 overflow-hidden rounded-lg border border-white/10 bg-[#151a22] sm:w-[138px]">
              <Image src={game.image} alt="" fill sizes="140px" className="object-cover" />
              <div className="absolute inset-0 bg-gradient-to-t from-black/82 via-transparent to-transparent" />
              <div className="absolute inset-x-0 bottom-0 p-2">
                <p className="text-sm font-black uppercase leading-none text-white">{game.title}</p>
              </div>
            </Link>
          ))}
        </div>
      </section>

      {statsOpen ? <StatsModal state={state} onClose={() => setStatsOpen(false)} /> : null}
    </div>
  );
}

function DiceTrack({
  direction,
  target,
  roll,
  rolling,
  won,
  onTargetChange
}: {
  direction: Direction;
  target: number;
  roll: number;
  rolling: boolean;
  won: boolean;
  onTargetChange: (target: number) => void;
}) {
  const resultLeft = Math.min(100, Math.max(0, roll));
  const targetLeft = Math.min(99, Math.max(1, target));
  const gradient =
    direction === "over"
      ? `linear-gradient(to right, #ff4051 0%, #ff4051 ${targetLeft}%, #0fbf8f ${targetLeft}%, #0fbf8f 100%)`
      : `linear-gradient(to right, #0fbf8f 0%, #0fbf8f ${targetLeft}%, #ff4051 ${targetLeft}%, #ff4051 100%)`;

  return (
    <div className="pb-8 pt-11">
      <div className="relative h-10 rounded-lg bg-[#252b3a] p-2">
        <div className="absolute -top-10 z-10 -translate-x-1/2 rounded-md border-2 bg-[#161b26] px-2 py-1 text-[11px] font-black text-white shadow-panel transition-all" style={{ left: `${rolling ? targetLeft : resultLeft}%`, borderColor: rolling ? "#0fbf8f" : won ? "#0fbf8f" : "#ff4051" }}>
          {roll.toFixed(2)}
        </div>
        <div className="relative h-full rounded-md bg-black/55">
          <div className="absolute inset-x-2 top-1/2 h-2 -translate-y-1/2 rounded-full" style={{ background: gradient }} />
          <div className="absolute top-1/2 h-8 w-4 -translate-x-1/2 -translate-y-1/2 rounded-full bg-felt shadow-[0_0_22px_rgba(15,191,143,.46)]" style={{ left: `${targetLeft}%` }} />
          <input
            type="range"
            min={1}
            max={99}
            step={0.01}
            value={target}
            onChange={(event) => onTargetChange(Number(event.target.value))}
            className="absolute inset-0 h-full w-full cursor-pointer opacity-0"
            aria-label="Seuil Dice"
          />
        </div>
        <div className="absolute left-0 right-0 top-full grid grid-cols-5 px-2 pt-3 text-center text-xs font-black text-slate-300">
          {[0, 25, 50, 75, 100].map((tick) => (
            <span key={tick}>{tick}</span>
          ))}
        </div>
      </div>
    </div>
  );
}

function NumberTile({ label, value, suffix }: { label: string; value: string; suffix: string }) {
  return (
    <div className="rounded-lg bg-white/[0.055] p-2.5">
      <span className="block text-[11px] font-bold text-slate-300">{label}</span>
      <span className="mt-1 flex items-center justify-between text-sm font-semibold text-white">
        {value}
        <span className="text-slate-300">{suffix}</span>
      </span>
    </div>
  );
}

function AutoPanel({
  mode,
  betCount,
  setBetCount,
  strategy,
  setStrategy,
  strategyOpen,
  setStrategyOpen
}: {
  mode: Mode;
  betCount: string;
  setBetCount: (value: string) => void;
  strategy: string;
  setStrategy: (value: string) => void;
  strategyOpen: boolean;
  setStrategyOpen: (value: boolean) => void;
}) {
  return (
    <div className="space-y-3">
      <div>
        <div className="mb-1.5 text-[12px] font-bold text-slate-200">Nombre de paris</div>
        <div className="flex h-10 overflow-hidden rounded-lg bg-[#202631]">
          <input
            value={betCount}
            onChange={(event) => setBetCount(event.target.value)}
            inputMode="numeric"
            className="min-w-0 flex-1 border-0 bg-transparent px-3 text-sm font-semibold text-white placeholder:text-slate-500 focus:ring-0"
            placeholder="0"
          />
          <button onClick={() => setBetCount("0")} className="grid w-14 place-items-center border-l border-white/10 text-white">
            <Infinity className="h-4 w-4" />
          </button>
        </div>
      </div>

      {mode === "advanced" ? (
        <>
          <div>
            <div className="mb-1.5 flex items-center justify-between text-[12px] font-bold text-slate-200">
              <span>Stratégie</span>
              <button className="text-felt">Créer une stratégie</button>
            </div>
            <button onClick={() => setStrategyOpen(!strategyOpen)} className="flex h-10 w-full items-center justify-between rounded-lg border border-felt/60 bg-white/[0.045] px-3 text-sm font-semibold text-white">
              {strategy}
              <ChevronDown className={cn("h-4 w-4 transition", strategyOpen && "rotate-180")} />
            </button>
            {strategyOpen ? (
              <div className="mt-1 overflow-hidden rounded-lg border border-white/10 bg-[#202631]">
                {["Martingale", "Delayed Martingale", "Paroli", "D'Alembert"].map((item) => (
                  <button
                    key={item}
                    onClick={() => {
                      setStrategy(item);
                      setStrategyOpen(false);
                    }}
                    className={cn("block h-10 w-full px-3 text-left text-xs font-bold", item === strategy ? "text-felt" : "text-slate-200")}
                  >
                    {item}
                  </button>
                ))}
              </div>
            ) : null}
          </div>
          <div className="grid grid-cols-3 gap-2">
            {[1, 2, 3].map((item) => (
              <div key={item} className="grid h-10 place-items-center rounded-lg bg-white/[0.055] text-sm font-semibold text-white">{item}</div>
            ))}
          </div>
        </>
      ) : (
        <div className="grid grid-cols-2 gap-2 rounded-lg border border-white/10 bg-black/20 p-3 text-xs text-slate-400">
          <span>Sur victoire</span>
          <span>En cas de perte</span>
          <span className="font-bold text-white">-</span>
          <span className="font-bold text-white">-</span>
          <span>Arrêt sur profit</span>
          <span>Arrêt en cas de perte</span>
          <span className="font-bold text-white">0.00</span>
          <span className="font-bold text-white">0.00</span>
        </div>
      )}
    </div>
  );
}

function SettingsPopover({
  turbo,
  maxBet,
  silent,
  onTurbo,
  onMaxBet,
  onSilent
}: {
  turbo: boolean;
  maxBet: boolean;
  silent: boolean;
  onTurbo: (value: boolean) => void;
  onMaxBet: (value: boolean) => void;
  onSilent: (value: boolean) => void;
}) {
  return (
    <div className="absolute bottom-11 left-3 z-20 w-[210px] overflow-hidden rounded-lg border border-white/10 bg-[#202631] shadow-panel">
      <ToggleRow icon={<Gauge className="h-4 w-4" />} label="Mode Turbo" checked={turbo} onChange={onTurbo} />
      <ToggleRow icon={<Rocket className="h-4 w-4" />} label="Pari maximum" checked={maxBet} onChange={onMaxBet} />
      <ToggleRow icon={<X className="h-4 w-4" />} label="Silencieux" checked={silent} onChange={onSilent} />
    </div>
  );
}

function ToggleRow({ icon, label, checked, onChange }: { icon: ReactNode; label: string; checked: boolean; onChange: (value: boolean) => void }) {
  return (
    <button onClick={() => onChange(!checked)} className="flex h-12 w-full items-center justify-between border-b border-white/10 px-3 text-xs font-bold text-white last:border-b-0">
      <span className="flex items-center gap-2">
        {icon}
        {label}
      </span>
      <span className={cn("relative h-6 w-11 rounded-full transition", checked ? "bg-felt" : "bg-black")}>
        <span className={cn("absolute top-1 h-4 w-4 rounded-full bg-white transition", checked ? "left-6" : "left-1")} />
      </span>
    </button>
  );
}

function FairnessPanel({
  state,
  revealedSeed,
  clientSeedInput,
  verifyInput,
  verifyResult,
  setClientSeedInput,
  setVerifyInput,
  onRotate,
  onVerify,
  onClose
}: {
  state: DiceState;
  revealedSeed: null | { serverSeed: string; clientSeed: string; nonce: number; serverSeedHash: string };
  clientSeedInput: string;
  verifyInput: { serverSeed: string; clientSeed: string; nonce: string };
  verifyResult: null | { serverSeedHash: string; result: string };
  setClientSeedInput: (value: string) => void;
  setVerifyInput: (value: { serverSeed: string; clientSeed: string; nonce: string }) => void;
  onRotate: () => void;
  onVerify: () => void;
  onClose: () => void;
}) {
  const [tab, setTab] = useState<"seeds" | "verify">("seeds");

  return (
    <section
      className="fixed inset-x-0 top-0 bottom-[calc(4.65rem+env(safe-area-inset-bottom))] z-[49] flex flex-col overflow-hidden border-b border-white/10 bg-[#0d1017] text-white shadow-panel"
      aria-label="Équité Dice"
    >
      <header className="flex h-[72px] shrink-0 items-center justify-between border-b border-white/10 px-4">
        <div className="flex min-w-0 items-center gap-2">
          <h2 className="truncate text-[22px] font-extrabold text-white">Équité</h2>
          <span className="rounded-md bg-felt px-2 py-1 text-[11px] font-black text-ink-950">Dice</span>
          <ChevronDown className="h-4 w-4 text-slate-300" />
        </div>
        <button onClick={onClose} className="grid h-9 w-9 place-items-center rounded-full text-slate-300 hover:bg-white/[0.07] hover:text-white" aria-label="Fermer l'équité">
          <X className="h-5 w-5" />
        </button>
      </header>

      <div className="min-h-0 flex-1 overflow-y-auto px-4 py-4 scrollbar-thin">
        <div className="mx-auto h-1 w-9 rounded-full bg-slate-600" />
        <div className="mx-auto w-full max-w-[720px]">
          <div className="mt-4 grid grid-cols-2 border-b border-white/10 text-sm font-black">
            <button onClick={() => setTab("seeds")} className={cn("h-10 border-b-2", tab === "seeds" ? "border-felt text-felt" : "border-transparent text-white")}>Seeds</button>
            <button onClick={() => setTab("verify")} className={cn("h-10 border-b-2", tab === "verify" ? "border-felt text-felt" : "border-transparent text-white")}>Vérifier</button>
          </div>

          {tab === "seeds" ? (
            <div className="mt-4 space-y-3">
              <ReadOnlyField label="Seed de client actif" value={state.seedPair.clientSeed} />
              <ReadOnlyField label="Seed de serveur actif (haché)" value={state.seedPair.serverSeedHash} />
              <ReadOnlyField label="Total des paris effectués avec la paire" value={String(state.seedPair.nonce)} />
              <h3 className="pt-2 text-lg font-black text-white">Faire pivoter la paire de seed</h3>
              <label className="block">
                <span className="text-xs font-bold text-slate-200">Nouvelle seed de client</span>
                <div className="mt-1.5 flex gap-2">
                  <input
                    value={clientSeedInput}
                    onChange={(event) => setClientSeedInput(event.target.value)}
                    className="h-10 min-w-0 flex-1 rounded-lg border-0 bg-white/[0.055] px-3 text-sm font-semibold text-white placeholder:text-slate-500 focus:ring-1 focus:ring-felt"
                  />
                  <button onClick={onRotate} className="h-10 rounded-lg bg-felt px-4 text-xs font-black text-ink-950">Changer</button>
                </div>
              </label>
              {revealedSeed ? (
                <div className="rounded-lg border border-felt/20 bg-felt/[0.08] p-3">
                  <div className="text-xs font-black text-felt">Seed précédente révélée</div>
                  <div className="mt-2 space-y-2">
                    <ReadOnlyField label="Server seed" value={revealedSeed.serverSeed} compact />
                    <ReadOnlyField label="Client seed" value={revealedSeed.clientSeed} compact />
                  </div>
                </div>
              ) : null}
            </div>
          ) : (
            <div className="mt-4 space-y-3">
              <VerifyInput label="Jeu" value="Dice" readOnly />
              <VerifyInput label="Seed de client" value={verifyInput.clientSeed} onChange={(clientSeed) => setVerifyInput({ ...verifyInput, clientSeed })} />
              <VerifyInput label="Seed de serveur" value={verifyInput.serverSeed} onChange={(serverSeed) => setVerifyInput({ ...verifyInput, serverSeed })} />
              <VerifyInput label="Nonce" value={verifyInput.nonce} onChange={(nonce) => setVerifyInput({ ...verifyInput, nonce })} />
              <button onClick={onVerify} className="h-10 w-full rounded-lg bg-felt text-xs font-black text-ink-950">Vérifier le roll</button>
              {verifyResult ? (
                <div className="rounded-lg border border-white/10 bg-black/20 p-3 text-xs text-slate-300">
                  <div>Résultat : <span className="font-black text-felt">{verifyResult.result}</span></div>
                  <div className="mt-1 truncate">Hash : {verifyResult.serverSeedHash}</div>
                </div>
              ) : null}
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

function ReadOnlyField({ label, value, compact = false }: { label: string; value: string; compact?: boolean }) {
  return (
    <label className="block">
      <span className="text-xs font-bold text-slate-200">{label}</span>
      <div className={cn("mt-1.5 flex items-center gap-2 rounded-lg border border-white/10 bg-black/20 px-3", compact ? "h-9" : "h-11")}>
        <span className="min-w-0 flex-1 truncate text-sm font-semibold text-slate-400">{value}</span>
        <button onClick={() => void navigator.clipboard?.writeText(value)} className="text-slate-200" aria-label="Copier">
          <Copy className="h-4 w-4" />
        </button>
      </div>
    </label>
  );
}

function VerifyInput({ label, value, onChange, readOnly }: { label: string; value: string; onChange?: (value: string) => void; readOnly?: boolean }) {
  return (
    <label className="block">
      <span className="text-xs font-bold text-slate-200">{label}</span>
      <input
        value={value}
        onChange={(event) => onChange?.(event.target.value)}
        readOnly={readOnly}
        className="mt-1.5 h-10 w-full rounded-lg border-0 bg-white/[0.055] px-3 text-sm font-semibold text-white placeholder:text-slate-500 focus:ring-1 focus:ring-felt"
      />
    </label>
  );
}

function StatsModal({ state, onClose }: { state: DiceState; onClose: () => void }) {
  return (
    <div className="fixed inset-0 z-[95] flex items-start justify-center overflow-y-auto bg-black/70 px-4 py-12 backdrop-blur" onClick={onClose}>
      <div className="w-full max-w-[330px] rounded-lg border border-white/10 bg-[#151a22] p-3 shadow-panel" onClick={(event) => event.stopPropagation()}>
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2 text-sm font-black text-white">
            <BarChart3 className="h-4 w-4" />
            Live Stats
          </div>
          <button onClick={onClose} className="text-slate-300">
            <X className="h-5 w-5" />
          </button>
        </div>
        <div className="mt-3 rounded-lg bg-white/[0.055] p-3">
          <div className="grid grid-cols-2 gap-3 text-sm">
            <Stat label="Profit" value={formatMoney(state.stats.profit, state.currency)} positive={Number(state.stats.profit) >= 0} />
            <Stat label="Gains" value={String(state.stats.wins)} positive />
            <Stat label="Misé" value={formatMoney(state.stats.stake, state.currency)} />
            <Stat label="Pertes" value={String(state.stats.losses)} negative />
          </div>
        </div>
        <div className="mt-3 space-y-1.5">
          {state.recentRounds.slice(0, 6).map((round) => (
            <div key={round.id} className="flex h-9 items-center justify-between rounded-lg bg-black/20 px-2.5 text-xs font-bold">
              <span className={round.status === "WON" ? "text-felt" : "text-ember"}>{Number(round.result).toFixed(2)}</span>
              <span className="text-slate-400">{Number(round.multiplier).toFixed(2)}x</span>
              <span className="text-white">{formatMoney(round.profit, round.currency)}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function Stat({ label, value, positive, negative }: { label: string; value: string; positive?: boolean; negative?: boolean }) {
  return (
    <div>
      <div className="text-xs font-bold text-slate-500">{label}</div>
      <div className={cn("mt-1 text-sm font-black", positive ? "text-felt" : negative ? "text-ember" : "text-white")}>{value}</div>
    </div>
  );
}

function IconButton({ icon, label, active, onClick }: { icon: ReactNode; label: string; active?: boolean; onClick: () => void }) {
  return (
    <button onClick={onClick} className={cn("grid h-8 w-8 place-items-center rounded-lg text-slate-200 transition hover:bg-white/[0.06]", active && "text-felt")} aria-label={label}>
      {icon}
    </button>
  );
}

const modes: Array<{ value: Mode; label: string }> = [
  { value: "manual", label: "Manuel" },
  { value: "auto", label: "Auto" },
  { value: "advanced", label: "Avancé" }
];

function round4(value: number) {
  return Number(value.toFixed(4));
}

function wait(ms: number) {
  return new Promise((resolve) => window.setTimeout(resolve, ms));
}

function formatInputAmount(value: number) {
  return formatAmountInput(value);
}

function formatMoney(value: string | number, currency: string) {
  return new Intl.NumberFormat("fr-FR", { style: "currency", currency }).format(Number(value));
}
