"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,
  Bomb,
  Check,
  ChevronDown,
  Copy,
  Gauge,
  Gem,
  Infinity,
  Loader2,
  Settings,
  Sparkles,
  Star,
  X
} from "lucide-react";
import { CasinoStakeInput } from "@/components/casino/casino-stake-input";
import { GameDetailsPanel } from "@/components/casino/game-details-panel";
import { StakeLimitNote } from "@/components/casino/stake-limit-note";
import { formatAmountInput, formatAmountInputFixed, parseAmountInput } from "@/lib/amount-input";
import { notifyWalletUpdated } from "@/lib/client-events";
import { miniGames } from "@/lib/casino-games";
import { cn } from "@/lib/utils";

type MinesRound = {
  id: string;
  currency: string;
  stake: string;
  payout: string;
  profit: string;
  multiplier: string;
  chance: string;
  target: string;
  direction: string;
  result: string;
  nonce: number;
  status: "ACTIVE" | "WON" | "LOST" | "VOID";
  serverSeedHash: string;
  createdAt: string;
  tileCount: number;
  mineCount: number;
  revealedTiles: number[];
  mineTiles: number[];
  explodedTile?: number;
  currentMultiplier: string;
  nextMultiplier: string;
  potentialPayout: string;
  canCashout: boolean;
};

type MinesState = {
  config: {
    minStake: string;
    maxStake: string;
    maxPayout: string;
    tileCount: number;
    minMines: number;
    maxMines: number;
    houseEdgeBps: number;
  };
  currency: string;
  seedPair: {
    id: string;
    clientSeed: string;
    serverSeedHash: string;
    nonce: number;
  };
  stats: {
    stake: string;
    profit: string;
    wins: number;
    losses: number;
  };
  activeRound: MinesRound | null;
  recentRounds: MinesRound[];
};

type Mode = "manual" | "auto";
type ResultFlash = {
  tone: "won" | "lost";
  title: "Gagné" | "Perdu";
  amount: string;
};

const DEFAULT_STATE: MinesState = {
  config: {
    minStake: "0.01",
    maxStake: "10000",
    maxPayout: "100000",
    tileCount: 25,
    minMines: 1,
    maxMines: 24,
    houseEdgeBps: 100
  },
  currency: "EUR",
  seedPair: {
    id: "",
    clientSeed: "",
    serverSeedHash: "",
    nonce: 0
  },
  stats: {
    stake: "0",
    profit: "0",
    wins: 0,
    losses: 0
  },
  activeRound: null,
  recentRounds: []
};

const DEFAULT_MINE_OPTIONS = [1, 2, 3, 5, 8, 10, 12, 15, 18, 20, 22, 24];

export function MinesGame() {
  const [state, setState] = useState<MinesState>(DEFAULT_STATE);
  const [loading, setLoading] = useState(true);
  const [guest, setGuest] = useState(false);
  const [message, setMessage] = useState("");
  const [mode, setMode] = useState<Mode>("manual");
  const [stake, setStake] = useState("0");
  const [mineCount, setMineCount] = useState(3);
  const [mineSelectOpen, setMineSelectOpen] = useState(false);
  const [betCount, setBetCount] = useState("0");
  const [lastRound, setLastRound] = useState<MinesRound | null>(null);
  const [starting, setStarting] = useState(false);
  const [revealingTile, setRevealingTile] = useState<number | null>(null);
  const [cashoutLoading, setCashoutLoading] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [statsOpen, setStatsOpen] = useState(false);
  const [fairnessOpen, setFairnessOpen] = useState(false);
  const [autoConfigOpen, setAutoConfigOpen] = useState(false);
  const [turbo, setTurbo] = useState(false);
  const [maxBet, setMaxBet] = useState(false);
  const [silent, setSilent] = useState(false);
  const [resultFlash, setResultFlash] = useState<ResultFlash | null>(null);
  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: "", mines: "3" });
  const [verifyResult, setVerifyResult] = useState<null | { serverSeedHash: string; mineTiles: number[] }>(null);
  const autoStopRef = useRef(false);
  const resultFlashTimeoutRef = useRef<number | null>(null);

  const activeRound = state.activeRound;
  const displayRound = activeRound ?? lastRound;
  const finishedDisplayRound = displayRound && displayRound.status !== "ACTIVE" ? displayRound : null;
  const revealedSafeCount = useMemo(() => {
    if (!displayRound) return 0;
    return displayRound.revealedTiles.filter((tile) => !displayRound.mineTiles.includes(tile)).length;
  }, [displayRound]);
  const currentMultiplier = displayRound ? Number(displayRound.currentMultiplier) : 1;
  const nextMultiplier = activeRound ? Number(activeRound.nextMultiplier) : 1;
  const potentialProfit = activeRound
    ? Math.max(0, Number(activeRound.potentialPayout) - Number(activeRound.stake))
    : calculateFirstPotentialProfit(stake, mineCount);
  const otherGames = miniGames.filter((game) => game.slug !== "mines");

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

  useEffect(() => {
    return () => {
      if (resultFlashTimeoutRef.current !== null) {
        window.clearTimeout(resultFlashTimeoutRef.current);
      }
    };
  }, []);

  async function loadState() {
    try {
      const response = await fetch("/api/casino/mines/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 à Mines." : payload.error?.message ?? "Mines indisponible.");
        return;
      }
      setState(payload.data);
      setClientSeedInput(payload.data.seedPair.clientSeed);
      setMineCount(payload.data.activeRound?.mineCount ?? 3);
      setLastRound(payload.data.activeRound ?? payload.data.recentRounds[0] ?? null);
    } catch {
      setMessage("Impossible de charger Mines pour le moment.");
    } finally {
      setLoading(false);
    }
  }

  async function startRound() {
    if (guest) {
      window.location.href = "/login";
      return null;
    }
    if (activeRound) {
      setMessage("Termine ou encaisse la partie en cours avant d'en lancer une autre.");
      return activeRound;
    }

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

    setMessage("");
    setStarting(true);
    try {
      const response = await fetch("/api/casino/mines/start", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          currency: state.currency,
          stake: amount,
          mines: mineCount,
          clientRequestId: crypto.randomUUID()
        })
      });
      const payload = await response.json();
      if (!response.ok || !payload.ok) {
        setMessage(payload.error?.message ?? "Partie refusée.");
        return null;
      }

      const round: MinesRound = payload.data.round;
      setState((current) => ({
        ...current,
        seedPair: { ...current.seedPair, nonce: current.seedPair.nonce + 1 },
        activeRound: round
      }));
      setLastRound(round);
      notifyWalletUpdated();
      if (!silent) setMessage("Partie lancée. Révèle une case sûre pour augmenter le multiplicateur.");
      return round;
    } catch {
      setMessage("Erreur réseau pendant le lancement.");
      return null;
    } finally {
      setStarting(false);
    }
  }

  async function revealTile(tile: number) {
    if (!activeRound || revealingTile !== null) return;
    if (activeRound.revealedTiles.includes(tile)) return;

    setMessage("");
    setRevealingTile(tile);
    try {
      const response = await fetch("/api/casino/mines/reveal", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ roundId: activeRound.id, tile })
      });
      const payload = await response.json();
      if (!response.ok || !payload.ok) {
        setMessage(payload.error?.message ?? "Case refusée.");
        return null;
      }

      const round: MinesRound = payload.data.round;
      applyRoundUpdate(round);
      if (round.status === "LOST") {
        notifyWalletUpdated();
        if (!silent) setMessage("Mine révélée. La partie est perdue.");
      } else if (round.status === "WON") {
        notifyWalletUpdated();
        if (!silent) setMessage(`Partie encaissée : ${formatMoney(round.payout, round.currency)}.`);
      }
      return round;
    } catch {
      setMessage("Erreur réseau pendant l'ouverture de la case.");
      return null;
    } finally {
      await wait(turbo ? 90 : 240);
      setRevealingTile(null);
    }
  }

  async function cashoutRound() {
    if (!activeRound || !activeRound.canCashout || cashoutLoading) return null;

    setCashoutLoading(true);
    setMessage("");
    try {
      const response = await fetch("/api/casino/mines/cashout", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ roundId: activeRound.id })
      });
      const payload = await response.json();
      if (!response.ok || !payload.ok) {
        setMessage(payload.error?.message ?? "Encaissement refusé.");
        return null;
      }

      const round: MinesRound = payload.data.round;
      applyRoundUpdate(round);
      notifyWalletUpdated();
      if (!silent) setMessage(`Gain encaissé : ${formatMoney(round.payout, round.currency)}.`);
      return round;
    } catch {
      setMessage("Erreur réseau pendant l'encaissement.");
      return null;
    } finally {
      setCashoutLoading(false);
    }
  }

  async function startAuto() {
    autoStopRef.current = false;
    const limit = Number(betCount);
    const roundsToPlay = limit > 0 ? limit : 1;

    for (let played = 0; played < roundsToPlay; played += 1) {
      if (autoStopRef.current) break;
      const started = await startRound();
      if (!started) break;

      await wait(turbo ? 120 : 420);
      const safeAttempt = await revealTileFromRound(started);
      if (!safeAttempt || safeAttempt.status !== "ACTIVE") {
        await wait(turbo ? 160 : 520);
        continue;
      }
      await cashoutSpecificRound(safeAttempt);
      await wait(turbo ? 180 : 620);
    }
  }

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

  async function revealTileFromRound(round: MinesRound) {
    const availableTiles = Array.from({ length: round.tileCount }, (_, index) => index).filter((tile) => !round.revealedTiles.includes(tile));
    const randomTile = availableTiles[Math.floor(Math.random() * availableTiles.length)];
    if (typeof randomTile !== "number") return null;

    setRevealingTile(randomTile);
    try {
      const response = await fetch("/api/casino/mines/reveal", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ roundId: round.id, tile: randomTile })
      });
      const payload = await response.json();
      if (!response.ok || !payload.ok) {
        setMessage(payload.error?.message ?? "Auto stoppé.");
        return null;
      }
      const nextRound: MinesRound = payload.data.round;
      applyRoundUpdate(nextRound);
      return nextRound;
    } finally {
      setRevealingTile(null);
    }
  }

  async function cashoutSpecificRound(round: MinesRound) {
    if (!round.canCashout) return null;
    const response = await fetch("/api/casino/mines/cashout", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ roundId: round.id })
    });
    const payload = await response.json();
    if (!response.ok || !payload.ok) {
      setMessage(payload.error?.message ?? "Auto stoppé.");
      return null;
    }
    const settled: MinesRound = payload.data.round;
    applyRoundUpdate(settled);
    notifyWalletUpdated();
    return settled;
  }

  function applyRoundUpdate(round: MinesRound) {
    showResultFlash(round);
    setLastRound(round);
    setState((current) => {
      if (round.status === "ACTIVE") {
        return { ...current, activeRound: round };
      }
      return {
        ...current,
        activeRound: null,
        stats: {
          stake: String(Number(current.stats.stake) + Number(round.status === "LOST" || round.status === "WON" ? round.stake : 0)),
          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.filter((item) => item.id !== round.id)].slice(0, 25)
      };
    });
  }

  function showResultFlash(round: MinesRound) {
    if (round.status !== "WON" && round.status !== "LOST") return;

    if (resultFlashTimeoutRef.current !== null) {
      window.clearTimeout(resultFlashTimeoutRef.current);
    }

    const netAmount = round.status === "WON"
      ? Math.max(0, Number(round.profit))
      : Math.max(0, Number(round.stake));

    setResultFlash({
      tone: round.status === "WON" ? "won" : "lost",
      title: round.status === "WON" ? "Gagné" : "Perdu",
      amount: `${round.status === "WON" ? "+" : "-"} ${formatMoney(netAmount, round.currency)}`
    });

    resultFlashTimeoutRef.current = window.setTimeout(() => {
      setResultFlash(null);
      resultFlashTimeoutRef.current = null;
    }, 1500);
  }

  async function rotateSeeds() {
    setMessage("");
    try {
      const response = await fetch("/api/casino/mines/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/mines/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 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">
          <Bomb className="h-4 w-4" />
          Mines
        </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">
            {state.recentRounds.slice(0, 8).length ? (
              state.recentRounds.slice(0, 8).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)}
                >
                  {Number(round.multiplier).toFixed(2)}x
                </button>
              ))
            ) : (
              <span className="h-7 rounded-full bg-white/[0.04] px-2.5 pt-1.5 text-[11px] font-bold text-slate-500">Aucune partie</span>
            )}
          </div>

          <div className="relative mx-auto max-w-[820px] rounded-lg border border-white/10 bg-black/35 p-3 sm:p-4">
            <div className="mb-3 grid grid-cols-3 gap-2">
              <MinesMetric label="Mines" value={displayRound ? String(displayRound.mineCount) : String(mineCount)} tone="danger" />
              <MinesMetric label="Révélées" value={String(revealedSafeCount)} tone="safe" />
              <MinesMetric label="Multi" value={`${currentMultiplier.toFixed(2)}x`} tone="accent" />
            </div>

            <MinesBoard
              round={displayRound}
              active={Boolean(activeRound)}
              revealingTile={revealingTile}
              resultFlash={resultFlash}
              onReveal={revealTile}
            />

            <div className="mt-3 flex items-center justify-between rounded-lg border border-white/10 bg-white/[0.035] px-3 py-2 text-xs">
              <span className="font-bold text-slate-400">Prochaine case sûre</span>
              <span className="font-black text-felt">{activeRound ? `${nextMultiplier.toFixed(2)}x` : "1.00x"}</span>
            </div>
          </div>
        </div>

        <div className="border-b border-white/10 p-3 sm:p-4">
          <button
            onClick={activeRound?.canCashout ? cashoutRound : mode === "manual" ? startRound : startAuto}
            disabled={starting || revealingTile !== null || cashoutLoading}
            className={cn(
              "grid h-11 w-full place-items-center rounded-lg text-sm font-black shadow-[0_16px_36px_rgba(15,191,143,.22)] transition active:scale-[.99] disabled:opacity-60",
              activeRound?.canCashout ? "bg-gradient-to-r from-felt to-emerald-300 text-ink-950" : "bg-gradient-to-r from-felt to-emerald-300 text-ink-950"
            )}
          >
            {starting || cashoutLoading ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : activeRound?.canCashout ? (
              `Encaisser ${formatMoney(activeRound.potentialPayout, activeRound.currency)}`
            ) : 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">
            <StakeInput
              currency={state.currency}
              stake={stake}
              potentialProfit={potentialProfit}
              disabled={Boolean(activeRound)}
              onStake={setStake}
              onHalf={halveStake}
              onDouble={doubleStake}
            />

            <div className={cn("grid gap-2", mode === "auto" ? "grid-cols-2" : "grid-cols-1")}>
              <MinesSelect
                value={mineCount}
                disabled={Boolean(activeRound)}
                open={mineSelectOpen}
                onOpen={setMineSelectOpen}
                onChange={(value) => {
                  setMineCount(value);
                  setVerifyInput((current) => ({ ...current, mines: String(value) }));
                }}
              />
              {mode === "auto" ? <BetCountInput value={betCount} onChange={setBetCount} /> : null}
            </div>

            {mode === "auto" ? (
              <button onClick={() => setAutoConfigOpen(true)} className="h-10 w-full rounded-lg border border-white/80 text-xs font-black text-white">
                Configurer automatiquement
              </button>
            ) : null}

            <div className="grid grid-cols-2 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("Mines ajouté à tes favoris.")} icon={<Star className="h-4 w-4" />} />
          </div>
          <button onClick={() => setFairnessOpen(true)} 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 ? (
        <MinesFairnessPanel
          state={state}
          revealedSeed={revealedSeed}
          clientSeedInput={clientSeedInput}
          verifyInput={verifyInput}
          verifyResult={verifyResult}
          setClientSeedInput={setClientSeedInput}
          setVerifyInput={setVerifyInput}
          onRotate={rotateSeeds}
          onVerify={verifySeed}
          onClose={() => setFairnessOpen(false)}
        />
      ) : null}

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

      <MoreGames games={otherGames} />

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

function MinesBoard({
  round,
  active,
  revealingTile,
  resultFlash,
  onReveal
}: {
  round: MinesRound | null;
  active: boolean;
  revealingTile: number | null;
  resultFlash: ResultFlash | null;
  onReveal: (tile: number) => void;
}) {
  const tileCount = round?.tileCount ?? 25;
  const tiles = Array.from({ length: tileCount }, (_, index) => index);

  return (
    <div className="relative">
      <div className="grid grid-cols-5 gap-1.5 sm:gap-2">
        {tiles.map((tile) => {
          const revealed = round?.revealedTiles.includes(tile) ?? false;
          const mineVisible = Boolean(round && round.status !== "ACTIVE" && round.mineTiles.includes(tile));
          const safeVisible = revealed && !mineVisible;
          const exploded = round?.explodedTile === tile;
          const disabled = !active || revealed || revealingTile !== null;

          return (
            <button
              key={tile}
              type="button"
              disabled={disabled}
              onClick={() => onReveal(tile)}
              className={cn(
                "group relative aspect-square overflow-hidden rounded-lg border border-black/30 bg-[#202631] shadow-[inset_0_1px_0_rgba(255,255,255,.05),0_8px_16px_rgba(0,0,0,.2)] transition duration-200",
                active && !revealed && "hover:-translate-y-0.5 hover:border-felt/30 hover:bg-[#242c39]",
                (safeVisible || mineVisible) && "animate-mine-reveal",
                safeVisible && "border-felt/25 bg-felt/[0.08]",
                mineVisible && "border-ember/35 bg-ember/[0.09]",
                exploded && "animate-mine-shake border-ember bg-ember/20 shadow-[0_0_26px_rgba(239,111,60,.25)]",
                revealingTile === tile && "scale-[0.97] border-felt/40"
              )}
              aria-label={`Case ${tile + 1}`}
            >
              <span className="absolute inset-0 rounded-lg bg-gradient-to-b from-white/[0.055] to-black/15" />
              {!safeVisible && !mineVisible ? (
                <span className="absolute inset-[18%] rounded-md bg-black/10 opacity-70 shadow-[inset_0_0_12px_rgba(0,0,0,.45)] transition group-hover:bg-felt/[0.08]" />
              ) : null}
              {safeVisible ? (
                <Image
                  src="/images/casino/assets/mines-gem.png"
                  alt=""
                  fill
                  sizes="80px"
                  className="object-contain p-[16%] drop-shadow-[0_0_16px_rgba(15,191,143,.45)]"
                />
              ) : null}
              {mineVisible ? (
                <Image
                  src="/images/casino/assets/mines-bomb.png"
                  alt=""
                  fill
                  sizes="80px"
                  className={cn("object-contain p-[14%] drop-shadow-[0_0_18px_rgba(239,111,60,.45)]", exploded && "animate-mine-pop")}
                />
              ) : null}
            </button>
          );
        })}
      </div>

      {resultFlash ? <MinesResultFlash flash={resultFlash} /> : null}
    </div>
  );
}

function MinesResultFlash({ flash }: { flash: ResultFlash }) {
  const won = flash.tone === "won";

  return (
    <div className="pointer-events-none absolute inset-0 z-20 grid place-items-center">
      <div
        className={cn(
          "animate-mines-result-toast min-w-[142px] rounded-xl border px-4 py-3 text-center shadow-[0_18px_50px_rgba(0,0,0,.44)] backdrop-blur-md",
          won
            ? "border-felt/35 bg-[#061711]/88 text-felt"
            : "border-ember/40 bg-[#1a0b0a]/88 text-ember"
        )}
      >
        <div className="text-sm font-black leading-none text-white">{flash.title}</div>
        <div className="mt-1.5 text-base font-black leading-none">{flash.amount}</div>
      </div>
    </div>
  );
}

function MinesMetric({ label, value, tone }: { label: string; value: string; tone: "safe" | "danger" | "accent" }) {
  return (
    <div className="rounded-lg border border-white/10 bg-black/20 px-2.5 py-2">
      <div className="text-[10px] font-black uppercase tracking-[0.08em] text-slate-500">{label}</div>
      <div className={cn("mt-1 text-sm font-black", tone === "safe" ? "text-felt" : tone === "danger" ? "text-ember" : "text-white")}>{value}</div>
    </div>
  );
}

function StakeInput({
  currency,
  stake,
  potentialProfit,
  disabled,
  onStake,
  onHalf,
  onDouble
}: {
  currency: string;
  stake: string;
  potentialProfit: number;
  disabled: boolean;
  onStake: (value: string) => void;
  onHalf: () => void;
  onDouble: () => void;
}) {
  return (
    <>
      <CasinoStakeInput value={stake} currency={currency} disabled={disabled} onChange={onStake} onHalf={onHalf} onDouble={onDouble} />

      <div>
        <div className="mb-1.5 flex items-center justify-between text-[12px] font-bold text-slate-200">
          <span>Profit potentiel</span>
          <span className="text-slate-500">{formatAmountInputFixed(potentialProfit)} {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>
    </>
  );
}

function MinesSelect({
  value,
  disabled,
  open,
  onOpen,
  onChange
}: {
  value: number;
  disabled: boolean;
  open: boolean;
  onOpen: (value: boolean) => void;
  onChange: (value: number) => void;
}) {
  return (
    <div className="relative">
      <div className="mb-1.5 text-[12px] font-bold text-slate-200">Mines</div>
      <button
        type="button"
        disabled={disabled}
        onClick={() => onOpen(!open)}
        className="flex h-10 w-full items-center justify-between rounded-lg bg-[#202631] px-3 text-sm font-semibold text-white disabled:text-slate-500"
      >
        {value}
        <ChevronDown className={cn("h-4 w-4 text-slate-300 transition", open && "rotate-180")} />
      </button>
      {open && !disabled ? (
        <div className="absolute left-0 right-0 top-[64px] z-20 grid max-h-[212px] grid-cols-3 gap-1 overflow-y-auto rounded-lg border border-white/10 bg-[#202631] p-1.5 shadow-panel scrollbar-thin">
          {DEFAULT_MINE_OPTIONS.map((option) => (
            <button
              key={option}
              onClick={() => {
                onChange(option);
                onOpen(false);
              }}
              className={cn("h-8 rounded-md text-xs font-black", value === option ? "bg-felt text-ink-950" : "bg-white/[0.04] text-slate-200")}
            >
              {option}
            </button>
          ))}
        </div>
      ) : null}
    </div>
  );
}

function BetCountInput({ value, onChange }: { value: string; onChange: (value: string) => void }) {
  return (
    <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={value}
          onChange={(event) => onChange(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={() => onChange("0")} className="grid w-14 place-items-center border-l border-white/10 text-white">
          <Infinity className="h-4 w-4" />
        </button>
      </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={<Sparkles 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 MinesFairnessPanel({
  state,
  revealedSeed,
  clientSeedInput,
  verifyInput,
  verifyResult,
  setClientSeedInput,
  setVerifyInput,
  onRotate,
  onVerify,
  onClose
}: {
  state: MinesState;
  revealedSeed: null | { serverSeed: string; clientSeed: string; nonce: number; serverSeedHash: string };
  clientSeedInput: string;
  verifyInput: { serverSeed: string; clientSeed: string; nonce: string; mines: string };
  verifyResult: null | { serverSeedHash: string; mineTiles: number[] };
  setClientSeedInput: (value: string) => void;
  setVerifyInput: (value: { serverSeed: string; clientSeed: string; nonce: string; mines: 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é Mines"
    >
      <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">Mines</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 parties effectuées 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="Mines" 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 })} />
              <VerifyInput label="Mines" value={verifyInput.mines} onChange={(mines) => setVerifyInput({ ...verifyInput, mines })} />
              <button onClick={onVerify} className="h-10 w-full rounded-lg bg-felt text-xs font-black text-ink-950">Vérifier la grille</button>
              {verifyResult ? (
                <div className="rounded-lg border border-white/10 bg-black/20 p-3 text-xs text-slate-300">
                  <div>
                    Mines : <span className="font-black text-felt">{verifyResult.mineTiles.map((tile) => tile + 1).join(", ")}</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: MinesState; 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.multiplier).toFixed(2)}x</span>
              <span className="text-slate-400">{round.revealedTiles.length} cases</span>
              <span className="text-white">{formatMoney(round.profit, round.currency)}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function AutoConfigSheet({ onClose }: { onClose: () => void }) {
  return (
    <section className="fixed inset-x-0 bottom-0 z-[90] rounded-t-2xl border-t border-white/10 bg-[#11151c] p-4 pb-[calc(1rem+env(safe-area-inset-bottom))] shadow-panel">
      <div className="mx-auto h-1 w-9 rounded-full bg-slate-600" />
      <div className="mx-auto mt-4 w-full max-w-[520px]">
        <div className="flex items-center justify-between">
          <h2 className="text-lg font-black text-white">Configurer automatiquement</h2>
          <button onClick={onClose} className="grid h-9 w-9 place-items-center rounded-full bg-white/[0.06] text-white">
            <X className="h-5 w-5" />
          </button>
        </div>
        <div className="mt-4 space-y-3">
          <AutoRule title="Sur victoire" />
          <AutoRule title="En cas de perte" />
          <MoneyRule title="Arrêtez sur le profit" />
          <MoneyRule title="Arrêt en cas de perte" />
          <button onClick={onClose} className="h-11 w-full rounded-lg bg-gradient-to-r from-felt to-emerald-300 text-sm font-black text-ink-950">
            Appliquer
          </button>
          <button onClick={onClose} className="block h-9 w-full text-center text-xs font-black text-slate-200 underline underline-offset-4">
            Effacer tout
          </button>
        </div>
      </div>
    </section>
  );
}

function AutoRule({ title }: { title: string }) {
  return (
    <div>
      <div className="mb-1.5 text-[12px] font-bold text-slate-200">{title}</div>
      <div className="grid grid-cols-[auto_1fr_auto] gap-2 rounded-lg bg-[#202631] p-2">
        <span className="grid h-9 place-items-center rounded-md bg-white px-3 text-xs font-black text-ink-950">Réinitialiser</span>
        <span className="grid h-9 place-items-center rounded-md bg-white/[0.05] px-3 text-xs font-bold text-slate-200">Augmenté de</span>
        <span className="grid h-9 min-w-[88px] place-items-center text-sm font-semibold text-slate-500">0,00 %</span>
      </div>
    </div>
  );
}

function MoneyRule({ title }: { title: string }) {
  return (
    <div>
      <div className="mb-1.5 flex items-center justify-between text-[12px] font-bold text-slate-200">
        <span>{title}</span>
        <span className="text-slate-500">0,00000000 EUR</span>
      </div>
      <div className="flex h-11 items-center gap-2 rounded-lg bg-[#202631] 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>
        0,00
      </div>
    </div>
  );
}

function MoreGames({ games }: { games: typeof miniGames }) {
  return (
    <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">
        {games.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>
  );
}

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" }
];

function calculateFirstPotentialProfit(stake: string, mines: number) {
  const amount = parseAmountInput(stake);
  if (amount <= 0) return 0;
  const safe = 25 - mines;
  if (safe <= 0) return 0;
  const firstMultiplier = 0.99 / (safe / 25);
  return amount * firstMultiplier - amount;
}

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));
}
