"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import { ArrowDownToLine, ArrowUpFromLine, ChevronLeft, ChevronRight, CircleDollarSign, Loader2, ReceiptText } from "lucide-react";

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

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

type TransactionFilter = "all" | "deposit" | "withdrawal" | "bet" | "casino";

export function WalletPanel() {
  const [wallet, setWallet] = useState<WalletResponse | null>(null);
  const [transactions, setTransactions] = useState<WalletTransaction[]>([]);
  const [filter, setFilter] = useState<TransactionFilter>("all");
  const [page, setPage] = useState(0);
  const [message, setMessage] = useState("");
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    Promise.all([fetch("/api/wallet/me"), fetch("/api/wallet/transactions")])
      .then(async ([walletResponse, transactionsResponse]) => {
        const [walletPayload, transactionsPayload] = await Promise.all([walletResponse.json(), transactionsResponse.json()]);
        if (walletPayload.ok) setWallet(walletPayload.data);
        else setMessage(walletPayload.error?.message ?? "Wallet indisponible");
        if (transactionsPayload.ok) setTransactions(transactionsPayload.data.transactions);
      })
      .finally(() => setLoading(false));
  }, []);

  const filteredTransactions = useMemo(
    () => transactions.filter((transaction) => filter === "all" || transaction.type === filter),
    [filter, transactions]
  );
  const pageSize = 3;
  const pageCount = Math.max(1, Math.ceil(filteredTransactions.length / pageSize));
  const safePage = Math.min(page, pageCount - 1);
  const visibleTransactions = filteredTransactions.slice(safePage * pageSize, safePage * pageSize + pageSize);

  function changeFilter(nextFilter: TransactionFilter) {
    setFilter(nextFilter);
    setPage(0);
  }

  if (loading) {
    return (
      <div className="surface grid min-h-40 place-items-center rounded-lg">
        <Loader2 className="h-6 w-6 animate-spin text-felt" />
      </div>
    );
  }

  return (
    <div className="space-y-3">
      <div className="grid gap-3 lg:grid-cols-[minmax(0,1fr)_280px]">
        <section className="surface rounded-lg p-3">
          <div className="mb-3 flex items-center gap-2">
            <CircleDollarSign className="h-4 w-4 text-felt" />
            <h2 className="text-sm font-semibold text-white">Mon wallet EUR</h2>
          </div>
          {wallet ? (
            <div className="grid grid-cols-3 gap-2">
              {wallet.accounts.map((account) => (
                <div key={account.type} className="rounded-lg border border-white/10 bg-white/[0.035] p-2.5">
                  <div className="text-[10px] font-bold uppercase text-slate-500">{accountLabel(account.type)}</div>
                  <div className="mt-1 truncate text-sm font-extrabold text-white">{Number(account.balance).toFixed(2)}</div>
                  <div className="text-[10px] text-slate-500">{wallet.currency}</div>
                </div>
              ))}
            </div>
          ) : (
            <p className="text-sm text-ember">{message}</p>
          )}
        </section>

        <section className="surface rounded-lg p-3">
          <h2 className="text-sm font-semibold text-white">Crypto-only</h2>
          <p className="mt-1 text-xs leading-5 text-slate-400">
            Dépôts convertis en EUR au taux reçu. Retraits validés par finance.
          </p>
          <div className="mt-3 grid grid-cols-2 gap-2 lg:grid-cols-1">
            <Link href="/wallet/deposit" className="flex h-9 items-center justify-center gap-2 rounded-lg bg-felt px-3 text-xs font-extrabold text-ink-950">
              <ArrowDownToLine className="h-3.5 w-3.5" />
              Dépôt
            </Link>
            <Link href="/wallet/withdraw" className="flex h-9 items-center justify-center gap-2 rounded-lg border border-white/10 bg-white/[0.04] px-3 text-xs font-extrabold text-white">
              <ArrowUpFromLine className="h-3.5 w-3.5" />
              Retrait
            </Link>
          </div>
        </section>
      </div>

      <section className="surface rounded-lg p-3">
        <div className="flex items-center justify-between gap-3">
          <div className="flex items-center gap-2">
            <ReceiptText className="h-4 w-4 text-felt" />
            <h2 className="text-sm font-semibold text-white">Transactions</h2>
          </div>
          <span className="text-[11px] font-semibold text-slate-500">{filteredTransactions.length}</span>
        </div>

        <div className="mt-3 grid grid-cols-5 gap-1.5">
          {transactionFilters.map((item) => (
            <button
              key={item.value}
              onClick={() => changeFilter(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">
          {visibleTransactions.length ? (
            visibleTransactions.map((transaction) => (
              <article key={`${transaction.type}-${transaction.id}`} className="flex items-center justify-between gap-3 rounded-lg border border-white/10 bg-white/[0.03] p-2.5">
                <div className="min-w-0">
                  <div className="flex items-center gap-2">
                    <span className={typeTone(transaction.type)}>{typeLabel(transaction.type)}</span>
                    <span className="truncate text-xs font-semibold text-white">{transaction.label}</span>
                  </div>
                  <div className="mt-1 flex items-center gap-2 text-[11px] text-slate-500">
                    <span>{formatDate(transaction.createdAt)}</span>
                    {transaction.meta ? <span className="truncate">{transaction.meta}</span> : null}
                  </div>
                </div>
                <div className="shrink-0 text-right">
                  <div className="text-xs font-extrabold text-white">{formatMoney(transaction.amount, transaction.currency)}</div>
                  <div className={statusTone(transaction.status)}>{statusLabel(transaction.status)}</div>
                </div>
              </article>
            ))
          ) : (
            <div className="rounded-lg border border-white/10 bg-white/[0.03] p-4 text-center text-xs font-semibold text-slate-500">
              Aucune transaction.
            </div>
          )}
        </div>

        {filteredTransactions.length > pageSize ? (
          <div className="mt-3 flex items-center justify-between gap-3">
            <button
              onClick={() => setPage((current) => Math.max(0, current - 1))}
              disabled={safePage === 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">
              {safePage + 1}/{pageCount}
            </span>
            <button
              onClick={() => setPage((current) => Math.min(pageCount - 1, current + 1))}
              disabled={safePage >= pageCount - 1}
              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>
        ) : null}
      </section>
    </div>
  );
}

function accountLabel(type: string) {
  if (type === "AVAILABLE") return "Disponible";
  if (type === "BONUS") return "Bonus";
  if (type === "LOCKED") return "Réservé";
  return type;
}

const transactionFilters: Array<{ value: TransactionFilter; label: string }> = [
  { value: "all", label: "Tous" },
  { value: "deposit", label: "Dépôts" },
  { value: "withdrawal", label: "Retraits" },
  { value: "bet", label: "Paris" },
  { value: "casino", label: "Casino" }
];

function typeLabel(type: WalletTransaction["type"]) {
  if (type === "deposit") return "Dépôt";
  if (type === "withdrawal") return "Retrait";
  if (type === "casino") return "Casino";
  return "Pari";
}

function typeTone(type: WalletTransaction["type"]) {
  if (type === "deposit") return "rounded-md bg-felt/10 px-2 py-0.5 text-[10px] font-bold uppercase text-felt";
  if (type === "withdrawal") return "rounded-md bg-gold/10 px-2 py-0.5 text-[10px] font-bold uppercase text-gold";
  if (type === "casino") return "rounded-md bg-felt/10 px-2 py-0.5 text-[10px] font-bold uppercase text-felt";
  return "rounded-md bg-white/[0.07] px-2 py-0.5 text-[10px] font-bold uppercase text-slate-300";
}

function statusLabel(status: string) {
  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 statusTone(status: string) {
  const positive = ["CREDITED", "BROADCASTED", "WON", "APPROVED"];
  const negative = ["FAILED", "REJECTED", "LOST", "CANCELLED"];
  if (positive.includes(status)) return "mt-1 text-[11px] font-bold text-felt";
  if (negative.includes(status)) return "mt-1 text-[11px] font-bold text-ember";
  return "mt-1 text-[11px] font-bold text-gold";
}

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

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