import Link from "next/link";
import { BetTicketStatus } from "@prisma/client";
import { ReceiptText, TicketCheck, Trophy } from "lucide-react";
import { localizeCompetitionName, localizeEventName, localizeSelectionName, localizeSportName, localizeTeamName } from "@/lib/sports-localization";
import { prisma } from "@/server/db";
import { requirePageUser } from "@/server/security/page-auth";
import { cn, formatMoney, formatOdds } from "@/lib/utils";

export const dynamic = "force-dynamic";

type BetsFilter = "all" | "open" | "settled";

export default async function BetsPage({ searchParams }: { searchParams: Promise<{ filter?: string }> }) {
  const { user } = await requirePageUser();
  const params = await searchParams;
  const filter = parseFilter(params.filter);
  const tickets = await prisma.betTicket.findMany({
    where: { userId: user.id, ...(filter === "open" ? { status: BetTicketStatus.OPEN } : filter === "settled" ? { status: { not: BetTicketStatus.OPEN } } : {}) },
    include: { selections: true },
    orderBy: { placedAt: "desc" },
    take: 50
  });
  const counts = await prisma.betTicket.groupBy({
    by: ["status"],
    where: { userId: user.id },
    _count: { _all: true }
  });
  const allCount = counts.reduce((total, item) => total + item._count._all, 0);
  const openCount = counts.find((item) => item.status === BetTicketStatus.OPEN)?._count._all ?? 0;
  const settledCount = allCount - openCount;

  return (
    <div className="space-y-4">
      <section className="overflow-hidden rounded-lg border border-white/10 bg-[#101521] p-3 shadow-panel sm:p-4">
        <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
          <div className="flex items-center gap-2.5">
            <span className="grid h-10 w-10 place-items-center rounded-lg bg-felt/10 text-felt">
              <TicketCheck className="h-4 w-4" />
            </span>
            <div>
              <h1 className="text-xl font-extrabold text-white">Mes Paris</h1>
              <p className="mt-0.5 text-xs leading-5 text-slate-400">Tickets, cotes, mises et gains estimés.</p>
            </div>
          </div>
          <div className="grid grid-cols-3 gap-2">
            <FilterLink href="/bets" active={filter === "all"} label="Tous" count={allCount} />
            <FilterLink href="/bets?filter=open" active={filter === "open"} label="En cours" count={openCount} />
            <FilterLink href="/bets?filter=settled" active={filter === "settled"} label="Terminés" count={settledCount} />
          </div>
        </div>
      </section>

      {tickets.length ? (
        <div className="grid gap-2.5">
          {tickets.map((ticket) => {
            const isCombo = ticket.selections.length > 1;
            return (
              <article key={ticket.id} className="overflow-hidden rounded-lg border border-white/10 bg-[#202832] shadow-panel">
                <div className="flex items-center justify-between gap-3 border-b border-white/[0.04] px-3 py-2.5">
                  <div className="flex min-w-0 items-center gap-2">
                    <span className="shrink-0 text-sm font-extrabold text-felt">
                      ZIRA<span className="text-white">BET</span>
                    </span>
                    <span className="rounded-md bg-white/[0.06] px-2 py-0.5 text-[10px] font-extrabold uppercase text-slate-400">{isCombo ? "Combiné" : "Simple"}</span>
                  </div>
                  <span className="shrink-0 text-[11px] font-semibold text-slate-400">{formatDateTime(ticket.placedAt)}</span>
                </div>

                <div className="flex items-center justify-between gap-3 px-3 py-2">
                  <StatusBadge status={ticket.status} />
                  <span className="truncate font-mono text-[11px] font-semibold text-slate-500">#{formatTicketId(ticket.id)}</span>
                </div>

                <div className="space-y-2 px-3 pb-2.5">
                  {ticket.selections.map((selection, index) => (
                    <div key={selection.id} className="space-y-2">
                      <div className="rounded-lg bg-[#28313d] px-2.5 py-2.5">
                        <div className="min-w-0">
                          <div className="flex min-w-0 items-center gap-1.5 text-[11px] font-semibold text-slate-400">
                            <Trophy className="h-3 w-3 shrink-0 text-slate-500" />
                            <span className="shrink-0">{sportFromSnapshot(selection.snapshot)}</span>
                            <span className="text-slate-600">›</span>
                            <span className="truncate">{competitionFromSnapshot(selection.snapshot)}</span>
                            <span className="ml-auto shrink-0 text-slate-500">{startTimeFromSnapshot(selection.snapshot)}</span>
                          </div>
                          <h2 className="mt-1 truncate text-[13px] font-bold text-white">
                            {localizeEventName(selection.eventName)}
                          </h2>
                        </div>
                        <div className="mt-2 flex items-end justify-between gap-3">
                          <div className="min-w-0">
                            <div className="truncate text-[10px] font-bold uppercase tracking-[0.08em] text-slate-500">{selection.marketName}</div>
                            <div className="mt-0.5 truncate text-[13px] font-bold text-white">{ticketSelectionName(selection)}</div>
                          </div>
                          <div className="flex shrink-0 items-center gap-2">
                            <OddsMark />
                            <span className="text-sm font-extrabold text-felt">{formatOdds(selection.odds.toString())}</span>
                          </div>
                        </div>
                      </div>
                      {isCombo && index < ticket.selections.length - 1 ? <div className="border-t border-dashed border-slate-600/70" /> : null}
                    </div>
                  ))}
                </div>

                <div className="space-y-1.5 border-t border-white/[0.04] px-3 py-2.5">
                  <TicketLine label={isCombo ? "Combiné" : "Cote"} value={formatOdds(ticket.totalOdds.toString())} />
                  <TicketLine label="Mise" value={formatMoney(ticket.stake.toString(), ticket.currency)} />
                  <TicketLine label="Gain estimé" value={formatMoney(ticket.potentialPayout.toString(), ticket.currency)} highlight />
                </div>
              </article>
            );
          })}
        </div>
      ) : (
        <div className="surface grid min-h-44 place-items-center rounded-lg p-6 text-center">
          <div>
            <ReceiptText className="mx-auto mb-3 h-8 w-8 text-slate-500" />
            <h2 className="font-extrabold text-white">Aucun ticket</h2>
            <p className="mt-2 max-w-sm text-sm leading-6 text-slate-400">
              {filter === "open" ? "Vous n'avez aucun pari en cours." : filter === "settled" ? "Vous n'avez pas encore de pari terminé." : "Vos tickets apparaîtront ici dès que vous placez un pari sportif."}
            </p>
          </div>
        </div>
      )}
    </div>
  );
}

function FilterLink({ href, active, label, count }: { href: string; active: boolean; label: string; count: number }) {
  return (
    <Link
      href={href}
      className={cn(
        "grid h-10 place-items-center rounded-lg border px-3 text-center transition",
        active ? "border-felt bg-felt/10 text-felt" : "border-white/10 bg-white/[0.04] text-slate-300 hover:bg-white/[0.07]"
      )}
    >
      <span className="text-xs font-extrabold">{label}</span>
      <span className="text-[11px] font-bold opacity-70">{count}</span>
    </Link>
  );
}

function TicketLine({ label, value, highlight = false }: { label: string; value: string; highlight?: boolean }) {
  return (
    <div className="flex items-center justify-between gap-3">
      <span className="text-xs font-bold text-slate-400">{label}</span>
      <span className={cn("text-sm font-extrabold", highlight ? "text-felt" : "text-white")}>{value}</span>
    </div>
  );
}

function StatusBadge({ status }: { status: BetTicketStatus }) {
  const label = ticketStatusLabel(status);
  const tone =
    status === BetTicketStatus.OPEN
      ? "border-felt/25 bg-felt/15 text-felt"
      : status === BetTicketStatus.WON || status === BetTicketStatus.PARTIALLY_WON
        ? "border-gold/25 bg-gold/10 text-gold"
        : status === BetTicketStatus.LOST
          ? "border-ember/25 bg-ember/10 text-ember"
          : "border-white/10 bg-white/[0.05] text-slate-300";

  return <span className={cn("rounded-md border px-2.5 py-0.5 text-[10px] font-extrabold uppercase", tone)}>{label}</span>;
}

function parseFilter(value?: string): BetsFilter {
  return value === "open" || value === "settled" ? value : "all";
}

function ticketStatusLabel(status: BetTicketStatus) {
  const labels: Record<BetTicketStatus, string> = {
    OPEN: "En cours",
    WON: "Gagné",
    LOST: "Perdu",
    VOID: "Annulé",
    CASHED_OUT: "Clôturé",
    PARTIALLY_WON: "Partiel",
    CANCELLED: "Annulé"
  };
  return labels[status] ?? status;
}

function sportFromSnapshot(snapshot: unknown) {
  if (snapshot && typeof snapshot === "object" && "sport" in snapshot && typeof snapshot.sport === "string") {
    return localizeSportName(snapshot.sport);
  }
  return "Sport";
}

function competitionFromSnapshot(snapshot: unknown) {
  if (snapshot && typeof snapshot === "object" && "competition" in snapshot && typeof snapshot.competition === "string") {
    return localizeCompetitionName(snapshot.competition);
  }
  return "Compétition";
}

function startTimeFromSnapshot(snapshot: unknown) {
  if (snapshot && typeof snapshot === "object" && "startsAt" in snapshot && typeof snapshot.startsAt === "string") {
    return formatShortDateTime(new Date(snapshot.startsAt));
  }
  return "Date n/d";
}

function ticketSelectionName(selection: { eventName: string; marketName: string; selectionName: string }) {
  if (!isWinnerMarketName(selection.marketName)) return localizeSelectionName(selection.selectionName);
  const raw = selection.selectionName.trim().toLowerCase();
  const teams = splitEventName(selection.eventName);

  if ((raw === "1" || raw === "home") && teams.home) return localizeTeamName(teams.home);
  if (raw === "x" || raw === "draw" || raw.includes("nul")) return "Match nul";
  if ((raw === "2" || raw === "away") && teams.away) return localizeTeamName(teams.away);
  return localizeSelectionName(selection.selectionName);
}

function isWinnerMarketName(marketName: string) {
  const value = marketName.toLowerCase().replaceAll(" ", "");
  return value.includes("1x2") || value.includes("matchwinner") || value.includes("vainqueur");
}

function splitEventName(eventName: string) {
  const [home, away] = eventName.split(/\s+(?:vs|v\.?|contre)\s+|\s+-\s+/i);
  return { home: home?.trim(), away: away?.trim() };
}

function OddsMark() {
  return (
    <span className="grid h-5 w-5 place-items-center rounded-full border border-felt/35 bg-felt/10 text-felt shadow-[0_0_12px_rgba(16,224,189,.14)]" aria-hidden="true">
      <svg viewBox="0 0 20 20" className="h-3.5 w-3.5" fill="none">
        <path d="M4 12.4 7.5 9l2.4 2.2L15.6 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        <path d="M13 5h2.6v2.6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        <circle cx="5" cy="15" r="1.2" fill="currentColor" opacity=".75" />
      </svg>
    </span>
  );
}

function formatTicketId(id: string) {
  return id.replaceAll("-", "").slice(0, 12);
}

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

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