"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import {
  AlertTriangle,
  ArrowDownToLine,
  ArrowUpFromLine,
  CheckCircle2,
  ChevronLeft,
  ChevronRight,
  Copy,
  Loader2,
  RefreshCw,
  ShieldCheck,
  Wallet,
  X
} from "lucide-react";
import { CryptoIcon } from "@/components/crypto-icon";
import { notifyWalletUpdated } from "@/lib/client-events";
import { cn, formatMoney } from "@/lib/utils";

type CryptoAsset = "BTC" | "ETH" | "USDC" | "USDT";
type WalletTab = "overview" | "deposit" | "withdraw";
type TransactionFilter = "all" | "deposit" | "withdrawal" | "bet";

type DepositAsset = {
  asset: CryptoAsset;
  network: "BITCOIN" | "ETHEREUM";
  label: string;
  ticker: string;
  decimals: number;
  requiredConfirmations: number;
  networkLabel: string;
  address?: string;
  rate?: { rate: string; source: string } | null;
};

type WalletResponse = {
  walletId: string;
  currency: string;
  accounts: Array<{ type: string; balance: string }>;
};

type WalletTransaction = {
  id: string;
  type: "deposit" | "withdrawal" | "bet";
  label: string;
  amount: string;
  currency: string;
  status: string;
  createdAt: string;
  meta?: string;
};

type CryptoDeposit = {
  id: string;
  asset: CryptoAsset;
  network: string;
  txHash: string;
  cryptoAmount: string;
  eurAmount: string | null;
  status: string;
  createdAt: string;
};

type CryptoWithdrawal = {
  id: string;
  asset: CryptoAsset;
  network: string;
  destinationAddress: string;
  eurAmount: string;
  feeEur: string;
  totalDebitEur: string;
  cryptoAmount: string;
  eurRate: string;
  status: string;
  txHash?: string | null;
  reviewReason?: string | null;
  reviewedAt?: string | null;
  createdAt: string;
};

type WelcomePromotion = {
  code: string;
  name: string;
  matchPercent: number;
  maxBonusAmount: string;
  wageringMultiplier: string;
  terms: string;
};

type AddressPayload = {
  minDepositEur: string;
  welcomeBonus: WelcomePromotion | null;
  assets: DepositAsset[];
};

const assetOrder: CryptoAsset[] = ["BTC", "ETH", "USDC", "USDT"];
const transactionFilters: Array<{ value: TransactionFilter; label: string }> = [
  { value: "all", label: "Tout" },
  { value: "deposit", label: "Dépôts" },
  { value: "withdrawal", label: "Retraits" },
  { value: "bet", label: "Paris" }
];

export function PaymentFlow({ initialTab = "overview", onClose }: { initialTab?: WalletTab; onClose?: () => void }) {
  const [tab, setTab] = useState<WalletTab>(initialTab);
  const [assets, setAssets] = useState<DepositAsset[]>([]);
  const [wallet, setWallet] = useState<WalletResponse | null>(null);
  const [transactions, setTransactions] = useState<WalletTransaction[]>([]);
  const [deposits, setDeposits] = useState<CryptoDeposit[]>([]);
  const [withdrawals, setWithdrawals] = useState<CryptoWithdrawal[]>([]);
  const [welcomeBonus, setWelcomeBonus] = useState<WelcomePromotion | null>(null);
  const [selectedAsset, setSelectedAsset] = useState<CryptoAsset>("USDC");
  const [amountEur, setAmountEur] = useState(initialTab === "withdraw" ? "20" : "25");
  const [bonusEstimateEur, setBonusEstimateEur] = useState("100");
  const [destinationAddress, setDestinationAddress] = useState("");
  const [transactionFilter, setTransactionFilter] = useState<TransactionFilter>("all");
  const [transactionPage, setTransactionPage] = useState(0);
  const [depositPage, setDepositPage] = useState(0);
  const [withdrawalPage, setWithdrawalPage] = useState(0);
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [cancelingWithdrawalId, setCancelingWithdrawalId] = useState<string | null>(null);
  const [message, setMessage] = useState("");
  const [copied, setCopied] = useState(false);

  const currentAsset = useMemo(
    () => assets.find((asset) => asset.asset === selectedAsset) ?? assets[0],
    [assets, selectedAsset]
  );
  const availableBalance = wallet?.accounts.find((account) => account.type === "AVAILABLE")?.balance ?? "0";
  const bonusBalance = wallet?.accounts.find((account) => account.type === "BONUS")?.balance ?? "0";
  const rate = Number(currentAsset?.rate?.rate ?? 0);
  const withdrawalAmount = Number(amountEur || 0);
  const withdrawalFee = 2;
  const cryptoPreview = rate > 0 && withdrawalAmount > 0 ? withdrawalAmount / rate : 0;
  const totalDebit = withdrawalAmount + withdrawalFee;
  const estimatedDeposit = Number(bonusEstimateEur || 0);
  const estimatedBonus = welcomeBonus ? Math.min((estimatedDeposit * welcomeBonus.matchPercent) / 100, Number(welcomeBonus.maxBonusAmount)) : 0;
  const pageSize = 3;
  const filteredTransactions = useMemo(
    () => transactions.filter((transaction) => transactionFilter === "all" || transaction.type === transactionFilter),
    [transactionFilter, transactions]
  );
  const transactionPageCount = Math.max(1, Math.ceil(filteredTransactions.length / pageSize));
  const safeTransactionPage = Math.min(transactionPage, transactionPageCount - 1);
  const visibleTransactions = filteredTransactions.slice(safeTransactionPage * pageSize, safeTransactionPage * pageSize + pageSize);
  const depositPageCount = Math.max(1, Math.ceil(deposits.length / pageSize));
  const withdrawalPageCount = Math.max(1, Math.ceil(withdrawals.length / pageSize));
  const safeDepositPage = Math.min(depositPage, depositPageCount - 1);
  const safeWithdrawalPage = Math.min(withdrawalPage, withdrawalPageCount - 1);
  const visibleDeposits = deposits.slice(safeDepositPage * pageSize, safeDepositPage * pageSize + pageSize);
  const visibleWithdrawals = withdrawals.slice(safeWithdrawalPage * pageSize, safeWithdrawalPage * pageSize + pageSize);
  const pendingWithdrawal = withdrawals.find((withdrawal) => withdrawal.status === "REQUESTED");
  const messageClass = isErrorMessage(message) ? "text-ember" : "text-felt";

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

  async function load() {
    setLoading(true);
    setMessage("");
    const [addressResponse, walletResponse, transactionsResponse, depositsResponse, withdrawalsResponse] = await Promise.all([
      fetch("/api/crypto/deposit-addresses", { cache: "no-store" }),
      fetch("/api/wallet/me", { cache: "no-store" }),
      fetch("/api/wallet/transactions", { cache: "no-store" }),
      fetch("/api/crypto/deposits", { cache: "no-store" }),
      fetch("/api/crypto/withdrawals", { cache: "no-store" })
    ]);
    const [addressPayload, walletPayload, transactionsPayload, depositsPayload, withdrawalsPayload] = await Promise.all([
      addressResponse.json(),
      walletResponse.json(),
      transactionsResponse.json(),
      depositsResponse.json(),
      withdrawalsResponse.json()
    ]);

    if (!addressPayload.ok) {
      setMessage(addressPayload.error?.message ?? "Configuration crypto indisponible");
      setLoading(false);
      return;
    }

    const data = addressPayload.data as AddressPayload;
    const orderedAssets = data.assets.sort((left, right) => assetOrder.indexOf(left.asset) - assetOrder.indexOf(right.asset));
    setAssets(orderedAssets);
    setWelcomeBonus(data.welcomeBonus);
    setSelectedAsset((current) => (orderedAssets.some((asset) => asset.asset === current) ? current : orderedAssets[0]?.asset ?? "USDC"));
    if (walletPayload.ok) setWallet(walletPayload.data);
    if (transactionsPayload.ok) setTransactions(transactionsPayload.data.transactions);
    if (depositsPayload.ok) setDeposits(depositsPayload.data.deposits);
    if (withdrawalsPayload.ok) setWithdrawals(withdrawalsPayload.data.withdrawals);
    setLoading(false);
  }

  async function copyAddress() {
    if (!currentAsset?.address) return;
    await navigator.clipboard.writeText(currentAsset.address);
    setCopied(true);
    window.setTimeout(() => setCopied(false), 1400);
  }

  async function requestWithdrawal() {
    setSubmitting(true);
    setMessage("");
    const response = await fetch("/api/crypto/withdrawals", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({
        asset: selectedAsset,
        amountEur: Number(amountEur),
        destinationAddress
      })
    });
    const payload = await response.json();
    setSubmitting(false);

    if (!response.ok || !payload.ok) {
      setMessage(payload.error?.message ?? "Retrait impossible");
      return;
    }

    setDestinationAddress("");
    setMessage("Retrait créé. Il est maintenant en attente de validation admin.");
    notifyWalletUpdated();
    await load();
  }

  async function cancelWithdrawal(withdrawalId: string) {
    setCancelingWithdrawalId(withdrawalId);
    setMessage("");
    const response = await fetch(`/api/crypto/withdrawals/${withdrawalId}`, { method: "DELETE" });
    const payload = await response.json();
    setCancelingWithdrawalId(null);

    if (!response.ok || !payload.ok) {
      setMessage(payload.error?.message ?? "Annulation impossible");
      return;
    }

    setMessage("Retrait annulé. Les fonds sont de nouveau disponibles.");
    notifyWalletUpdated();
    await load();
  }

  if (loading) {
    return (
      <div className="mx-auto grid min-h-44 w-full max-w-[680px] place-items-center rounded-lg border border-white/10 bg-[#151b22] shadow-panel">
        <Loader2 className="h-5 w-5 animate-spin text-felt" />
      </div>
    );
  }

  return (
    <div className="mx-auto w-full max-w-[680px] overflow-hidden rounded-lg border border-white/10 bg-[#151b22] shadow-panel">
      <header className="flex items-center justify-between gap-3 px-3.5 py-3">
        <div className="flex items-center gap-2.5">
          <span className="grid h-8 w-8 place-items-center rounded-lg bg-felt text-ink-950">
            <Wallet className="h-4 w-4" />
          </span>
          <h1 className="text-lg font-bold text-white">Mon wallet</h1>
        </div>
        {onClose ? (
          <button onClick={onClose} className="grid h-8 w-8 place-items-center rounded-full bg-white/[0.1] text-slate-200" aria-label="Fermer">
            <X className="h-4 w-4" />
          </button>
        ) : (
          <Link href="/" className="grid h-8 w-8 place-items-center rounded-full bg-white/[0.1] text-slate-200" aria-label="Fermer">
            <X className="h-4 w-4" />
          </Link>
        )}
      </header>

      {pendingWithdrawal ? (
        <div className="px-3.5 pb-3">
          <PendingWithdrawalCard
            withdrawal={pendingWithdrawal}
            canceling={cancelingWithdrawalId === pendingWithdrawal.id}
            onCancel={() => void cancelWithdrawal(pendingWithdrawal.id)}
          />
        </div>
      ) : null}

      <div className="px-3.5 pb-3">
        <div className="grid grid-cols-3 rounded-lg bg-white/[0.08] p-1">
          <TabButton active={tab === "overview"} onClick={() => setTab("overview")} label="Vue d'ensemble" />
          <TabButton active={tab === "deposit"} onClick={() => setTab("deposit")} label="Dépôt" />
          <TabButton active={tab === "withdraw"} onClick={() => setTab("withdraw")} label="Retrait" />
        </div>
      </div>

      <div className="border-t border-white/10 px-3.5 py-3.5">
        {tab === "overview" ? (
          <div className="space-y-3">
            <OverviewStat label="Solde total" value={formatMoney(availableBalance)} />

            <BalanceStrip available={availableBalance} bonus={bonusBalance} />
            <TransactionsPanel
              transactions={visibleTransactions}
              count={filteredTransactions.length}
              filter={transactionFilter}
              onFilter={(nextFilter) => {
                setTransactionFilter(nextFilter);
                setTransactionPage(0);
              }}
              page={safeTransactionPage}
              pageCount={transactionPageCount}
              showPager={filteredTransactions.length > pageSize}
              onPageChange={setTransactionPage}
            />
          </div>
        ) : null}

        {tab === "deposit" ? (
          <div className="space-y-3">
            {welcomeBonus ? (
              <DepositBonusNotice
                welcomeBonus={welcomeBonus}
                estimatedDeposit={estimatedDeposit}
                estimatedBonus={estimatedBonus}
                bonusEstimateEur={bonusEstimateEur}
                onBonusEstimateChange={setBonusEstimateEur}
              />
            ) : null}

            <div>
              <div className="mb-2 text-[11px] font-extrabold uppercase tracking-[0.18em] text-slate-300">Méthode de dépôt</div>
              <div className="rounded-lg border border-felt/55 bg-[#202830] p-2.5">
                <div className="flex items-center justify-between gap-3">
                  <div className="flex items-center gap-2">
                    <CryptoIcon asset="BTC" className="h-5 w-5" />
                    <CryptoIcon asset="ETH" className="h-5 w-5" />
                    <CryptoIcon asset="USDC" className="h-5 w-5" />
                    <span className="text-xs font-bold text-white">Crypto</span>
                  </div>
                  {welcomeBonus ? <span className="rounded-full bg-felt px-2.5 py-1 text-[11px] font-extrabold text-ink-950">+{welcomeBonus.matchPercent}%</span> : null}
                </div>
              </div>
            </div>

            <div className="flex items-start gap-2 rounded-lg bg-felt/10 p-2.5 text-xs font-semibold leading-5 text-emerald-50">
              <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-felt" />
              Minimum dépôt 25€. Les dépôts sont convertis en EUR au taux reçu, puis crédités automatiquement après confirmations.
            </div>

            <div className="grid gap-2 sm:grid-cols-2">
              <Selector label="Crypto" value={selectedAsset} assets={assets} onSelect={setSelectedAsset} />
              <div>
                <div className="mb-2 text-[11px] font-extrabold uppercase tracking-[0.18em] text-slate-300">Réseau</div>
                <div className="flex h-10 items-center justify-between rounded-lg border border-white/10 bg-[#202830] px-3 text-sm font-bold text-white">
                  {currentAsset?.networkLabel ?? "Réseau"}
                  <ShieldCheck className="h-4 w-4 text-felt" />
                </div>
              </div>
            </div>

            <div>
              <div className="mb-2 text-xs font-semibold text-slate-200">Adresse de dépôt</div>
              <div className="flex items-center gap-2 rounded-lg border border-white/10 bg-[#202830] p-2">
                <div className="min-w-0 flex-1 break-all px-2 font-mono text-xs font-semibold leading-5 text-white">{currentAsset?.address}</div>
                <button onClick={() => void copyAddress()} className="grid h-8 w-8 shrink-0 place-items-center rounded-lg bg-white/[0.08] text-slate-100" aria-label="Copier l'adresse">
                  {copied ? <CheckCircle2 className="h-4 w-4 text-felt" /> : <Copy className="h-4 w-4" />}
                </button>
              </div>
            </div>

            <div className="rounded-lg border border-white/10 bg-[#202830] px-3 py-2 text-xs font-semibold text-slate-200">
              Confirmations requises : <span className="font-extrabold text-white">{currentAsset?.requiredConfirmations ?? 1}</span>
            </div>

            <History title="Derniers dépôts">
              {visibleDeposits.length ? (
                visibleDeposits.map((deposit) => (
                  <HistoryRow
                    key={deposit.id}
                    title={`${deposit.asset} crédité`}
                    meta={`${shortHash(deposit.txHash)} · ${formatDate(deposit.createdAt)}`}
                    value={formatMoney(deposit.eurAmount ?? "0")}
                    status={statusLabel(deposit.status)}
                  />
                ))
              ) : (
                <EmptyHistory text="Aucun dépôt crypto pour le moment." />
              )}
              {deposits.length > pageSize ? <Pager page={safeDepositPage} pageCount={depositPageCount} onPageChange={setDepositPage} /> : null}
            </History>
          </div>
        ) : null}

        {tab === "withdraw" ? (
          <div className="space-y-3">
            <div className="grid gap-2 sm:grid-cols-3">
              <Selector label="Crypto" value={selectedAsset} assets={assets} onSelect={setSelectedAsset} />
              <div>
                <div className="mb-2 text-[11px] font-extrabold uppercase tracking-[0.18em] text-slate-300">Réseau</div>
                <div className="flex h-10 items-center justify-between rounded-lg border border-white/10 bg-[#202830] px-3 text-sm font-bold text-white">
                  {currentAsset?.networkLabel ?? "Réseau"}
                  <ShieldCheck className="h-4 w-4 text-felt" />
                </div>
              </div>
              <label className="block">
                <div className="mb-2 text-[11px] font-extrabold uppercase tracking-[0.18em] text-slate-300">Montant EUR</div>
                <input
                  value={amountEur}
                  onChange={(event) => setAmountEur(event.target.value)}
                  inputMode="decimal"
                  className="h-10 w-full rounded-lg border border-white/10 bg-[#202830] px-3 text-sm font-bold text-white"
                />
              </label>
            </div>

            <label className="block">
              <div className="mb-2 text-[11px] font-extrabold uppercase tracking-[0.18em] text-slate-300">Adresse de destination</div>
              <input
                value={destinationAddress}
                onChange={(event) => setDestinationAddress(event.target.value)}
                placeholder="Adresse crypto externe"
                className="h-10 w-full rounded-lg border border-white/10 bg-[#202830] px-3 text-sm font-semibold text-white placeholder:text-slate-500"
              />
            </label>

            <div className="grid grid-cols-3 gap-2">
              <Preview label="Frais" value={formatMoney(withdrawalFee)} />
              <Preview label="Débit" value={formatMoney(totalDebit)} />
              <Preview label={selectedAsset} value={cryptoPreview ? cryptoPreview.toFixed(currentAsset?.decimals === 6 ? 6 : 8) : "-"} />
            </div>

            {message ? (
              <p className={cn("rounded-lg border border-white/10 bg-white/[0.04] px-3 py-2 text-xs font-bold", messageClass)}>{message}</p>
            ) : null}

            <button
              onClick={() => void requestWithdrawal()}
              disabled={submitting}
              className="flex h-10 w-full items-center justify-center gap-2 rounded-lg bg-felt text-sm font-bold text-ink-950 disabled:bg-slate-700 disabled:text-slate-400"
            >
              {submitting ? <Loader2 className="h-4 w-4 animate-spin" /> : <ArrowUpFromLine className="h-4 w-4" />}
              Demander le retrait
            </button>

            <History title="Derniers retraits">
              {visibleWithdrawals.length ? (
                visibleWithdrawals.map((withdrawal) => (
                  <HistoryRow
                    key={withdrawal.id}
                    title={`${withdrawal.asset} vers ${shortHash(withdrawal.destinationAddress)}`}
                    meta={`${networkLabel(withdrawal.network)} · ${formatDate(withdrawal.createdAt)} · débit ${formatMoney(withdrawal.totalDebitEur)}`}
                    value={formatMoney(withdrawal.eurAmount)}
                    status={statusLabel(withdrawal.status, withdrawal.reviewReason)}
                  />
                ))
              ) : (
                <EmptyHistory text="Aucun retrait crypto pour le moment." />
              )}
              {withdrawals.length > pageSize ? <Pager page={safeWithdrawalPage} pageCount={withdrawalPageCount} onPageChange={setWithdrawalPage} /> : null}
            </History>
          </div>
        ) : null}

        {tab !== "withdraw" && message ? <p className={cn("mt-4 text-sm font-semibold", messageClass)}>{message}</p> : null}
      </div>
    </div>
  );
}

function TabButton({ active, label, onClick }: { active: boolean; label: string; onClick: () => void }) {
  return (
    <button
      onClick={onClick}
      className={active ? "h-9 rounded-lg bg-felt px-2 text-xs font-bold text-ink-950 shadow-lg shadow-felt/20" : "h-9 rounded-lg px-2 text-xs font-bold text-slate-300"}
    >
      {label}
    </button>
  );
}

function PendingWithdrawalCard({
  withdrawal,
  canceling,
  onCancel
}: {
  withdrawal: CryptoWithdrawal;
  canceling: boolean;
  onCancel: () => void;
}) {
  return (
    <article className="rounded-lg border border-gold/25 bg-gold/10 p-2.5">
      <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
        <div className="min-w-0">
          <div className="flex flex-wrap items-center gap-2">
            <span className="rounded-md bg-gold/15 px-2 py-0.5 text-[10px] font-bold uppercase text-gold">En attente</span>
            <span className="text-[11px] font-semibold text-slate-400">{formatLongDate(withdrawal.createdAt)}</span>
          </div>
          <div className="mt-1 truncate text-sm font-bold text-white">
            Retrait {withdrawal.asset} · {networkLabel(withdrawal.network)}
          </div>
        </div>
        <div className="flex items-center justify-between gap-3 sm:justify-end">
          <div className="text-right">
            <div className="text-sm font-extrabold text-white">{formatMoney(withdrawal.eurAmount)}</div>
            <div className="text-[10px] font-semibold text-slate-500">Débit {formatMoney(withdrawal.totalDebitEur)}</div>
          </div>
          <button
            type="button"
            onClick={onCancel}
            disabled={canceling}
            className="flex h-8 shrink-0 items-center justify-center gap-1 rounded-lg border border-white/10 bg-white/[0.08] px-2.5 text-[11px] font-bold text-white transition hover:border-ember/30 hover:text-ember disabled:opacity-60"
          >
            {canceling ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : null}
            Annuler le retrait
          </button>
        </div>
      </div>
    </article>
  );
}

function DepositBonusNotice({
  welcomeBonus,
  estimatedDeposit,
  estimatedBonus,
  bonusEstimateEur,
  onBonusEstimateChange
}: {
  welcomeBonus: WelcomePromotion;
  estimatedDeposit: number;
  estimatedBonus: number;
  bonusEstimateEur: string;
  onBonusEstimateChange: (value: string) => void;
}) {
  return (
    <div className="rounded-lg border border-felt/30 bg-felt/10 p-2.5">
      <div className="flex items-start justify-between gap-3">
        <div className="min-w-0">
          <div className="text-[11px] font-bold uppercase text-felt">Bonus premier dépôt actif</div>
          <div className="mt-1 text-xs font-semibold leading-5 text-slate-200">
            {welcomeBonus.matchPercent}% jusqu'à {formatMoney(welcomeBonus.maxBonusAmount)}. Refusable depuis VIP avant votre dépôt.
          </div>
        </div>
        <span className="shrink-0 rounded-full bg-felt px-2.5 py-1 text-[11px] font-extrabold text-ink-950">+{welcomeBonus.matchPercent}%</span>
      </div>
      <div className="mt-2 grid gap-2 sm:grid-cols-[0.8fr_1.2fr] sm:items-end">
        <label className="text-[10px] font-bold uppercase text-slate-400">
          Dépôt estimé
          <input
            value={bonusEstimateEur}
            onChange={(event) => onBonusEstimateChange(event.target.value)}
            inputMode="decimal"
            className="mt-1 h-8 w-full rounded-lg border-white/10 bg-white px-2.5 text-sm font-bold text-ink-950"
          />
        </label>
        <div className="rounded-lg bg-black/15 px-2.5 py-2 text-xs font-semibold text-slate-200">
          Crédit : {formatMoney(estimatedDeposit)} + <span className="font-extrabold text-felt">{formatMoney(estimatedBonus)} bonus</span>
        </div>
      </div>
    </div>
  );
}

function OverviewStat({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-lg bg-white/[0.045] p-2.5">
      <div className="text-[11px] font-semibold text-slate-400">{label}</div>
      <div className="mt-1 truncate text-base font-bold text-white">{value}</div>
    </div>
  );
}

function BalanceStrip({ available, bonus }: { available: string; bonus: string }) {
  return (
    <div className="grid grid-cols-2 gap-2">
      <MiniBalance label="Réel" value={available} />
      <MiniBalance label="Bonus" value={bonus} />
    </div>
  );
}

function MiniBalance({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-lg border border-white/10 bg-white/[0.03] p-2">
      <div className="text-[10px] font-bold uppercase text-slate-500">{label}</div>
      <div className="mt-1 truncate text-xs font-extrabold text-white">{formatMoney(value)}</div>
    </div>
  );
}

function Selector({ label, value, assets, onSelect }: { label: string; value: CryptoAsset; assets: DepositAsset[]; onSelect: (asset: CryptoAsset) => void }) {
  return (
    <label className="block">
      <div className="mb-2 text-[11px] font-extrabold uppercase tracking-[0.18em] text-slate-300">{label}</div>
      <select
        value={value}
        onChange={(event) => onSelect(event.target.value as CryptoAsset)}
        className="h-10 w-full rounded-lg border border-white/10 bg-[#202830] px-3 text-sm font-bold text-white"
      >
        {assets.map((asset) => (
          <option key={asset.asset} value={asset.asset}>
            {asset.ticker}
          </option>
        ))}
      </select>
    </label>
  );
}

function Preview({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-lg border border-white/10 bg-white/[0.035] p-2">
      <div className="text-[10px] font-bold uppercase text-slate-500">{label}</div>
      <div className="mt-1 break-all text-xs font-extrabold text-white">{value}</div>
    </div>
  );
}

function TransactionsPanel({
  transactions,
  count,
  filter,
  onFilter,
  page,
  pageCount,
  showPager,
  onPageChange
}: {
  transactions: WalletTransaction[];
  count: number;
  filter: TransactionFilter;
  onFilter: (filter: TransactionFilter) => void;
  page: number;
  pageCount: number;
  showPager: boolean;
  onPageChange: (page: number) => void;
}) {
  return (
    <section className="rounded-lg border border-white/10 bg-white/[0.025] p-3">
      <div className="flex items-center justify-between gap-3">
        <h2 className="text-sm font-extrabold text-white">Transactions</h2>
        <span className="text-xs font-bold text-slate-500">{count}</span>
      </div>
      <div className="mt-3 grid grid-cols-4 gap-1.5">
        {transactionFilters.map((item) => (
          <button
            key={item.value}
            onClick={() => onFilter(item.value)}
            className={filter === item.value ? "h-8 rounded-lg border border-felt bg-felt/10 px-2 text-[11px] font-bold text-felt" : "h-8 rounded-lg border border-white/10 bg-white/[0.035] px-2 text-[11px] font-bold text-slate-400"}
          >
            {item.label}
          </button>
        ))}
      </div>
      <div className="mt-3 space-y-2">
        {transactions.length ? (
          transactions.map((transaction) => (
            <HistoryRow
              key={`${transaction.type}-${transaction.id}`}
              title={transaction.label}
              meta={`${formatDate(transaction.createdAt)}${transaction.meta ? ` · ${transaction.meta}` : ""}`}
              value={formatMoney(transaction.amount, transaction.currency)}
              status={statusLabel(transaction.status)}
            />
          ))
        ) : (
          <EmptyHistory text="Aucune transaction." />
        )}
      </div>
      {showPager ? <Pager page={page} pageCount={pageCount} onPageChange={onPageChange} /> : null}
    </section>
  );
}

function History({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <section className="rounded-lg border border-white/10 bg-white/[0.025] p-3">
      <h2 className="text-sm font-extrabold text-white">{title}</h2>
      <div className="mt-3 space-y-2">{children}</div>
    </section>
  );
}

function HistoryRow({ title, meta, value, status }: { title: string; meta: string; value: string; status: string }) {
  return (
    <div className="flex items-center justify-between gap-3 rounded-lg bg-white/[0.045] p-2.5">
      <div className="min-w-0">
        <div className="truncate text-xs font-extrabold text-white">{title}</div>
        <div className="mt-1 truncate text-[11px] text-slate-500">{meta}</div>
      </div>
      <div className="shrink-0 text-right">
        <div className="text-xs font-extrabold text-white">{value}</div>
        <div className="mt-1 text-[10px] font-extrabold uppercase text-felt">{status}</div>
      </div>
    </div>
  );
}

function EmptyHistory({ text }: { text: string }) {
  return <div className="rounded-lg bg-white/[0.04] p-3 text-xs font-semibold text-slate-400">{text}</div>;
}

function Pager({ page, pageCount, onPageChange }: { page: number; pageCount: number; onPageChange: (page: number) => void }) {
  return (
    <div className="mt-3 flex items-center justify-between gap-3">
      <button
        type="button"
        onClick={() => onPageChange(Math.max(0, page - 1))}
        disabled={page === 0}
        className="flex h-8 items-center gap-1 rounded-lg bg-white/[0.06] px-2.5 text-xs font-bold text-white disabled:opacity-40"
      >
        <ChevronLeft className="h-3.5 w-3.5" />
        Préc.
      </button>
      <span className="text-[11px] font-semibold text-slate-500">
        {page + 1}/{pageCount}
      </span>
      <button
        type="button"
        onClick={() => onPageChange(Math.min(pageCount - 1, page + 1))}
        disabled={page + 1 >= pageCount}
        className="flex h-8 items-center gap-1 rounded-lg bg-white/[0.06] px-2.5 text-xs font-bold text-white disabled:opacity-40"
      >
        Suiv.
        <ChevronRight className="h-3.5 w-3.5" />
      </button>
    </div>
  );
}

function networkLabel(network: string) {
  const labels: Record<string, string> = {
    BITCOIN: "Bitcoin",
    ETHEREUM: "Ethereum"
  };
  return labels[network] ?? network;
}

function statusLabel(status: string, reason?: string | null) {
  if (status === "REJECTED" && reason?.toLowerCase().includes("annul")) {
    return "Annulé";
  }

  const labels: Record<string, string> = {
    DETECTED: "Détecté",
    CONFIRMING: "En cours",
    CREDITED: "Terminé",
    IGNORED: "Ignoré",
    FAILED: "Échoué",
    REQUESTED: "En attente",
    APPROVED: "Accepté",
    REJECTED: "Refusé",
    BROADCASTED: "Terminé",
    OPEN: "En cours",
    WON: "Gagné",
    LOST: "Perdu",
    VOID: "Annulé",
    CASHED_OUT: "Clôturé",
    PARTIALLY_WON: "Partiel",
    CANCELLED: "Annulé"
  };
  return labels[status] ?? status;
}

function isErrorMessage(message: string) {
  const normalized = message.toLowerCase();
  return (
    normalized.includes("impossible") ||
    normalized.includes("minimum") ||
    normalized.includes("supérieur") ||
    normalized.includes("refus") ||
    normalized.includes("erreur")
  );
}

function shortHash(value: string) {
  if (value.length <= 14) return value;
  return `${value.slice(0, 7)}...${value.slice(-5)}`;
}

function formatDate(value: string) {
  return new Intl.DateTimeFormat("fr-FR", {
    day: "2-digit",
    month: "2-digit",
    hour: "2-digit",
    minute: "2-digit"
  }).format(new Date(value));
}

function formatLongDate(value: string) {
  return new Intl.DateTimeFormat("fr-FR", {
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit"
  }).format(new Date(value));
}
