import { NextRequest } from "next/server";
import { getMiniGame } from "@/lib/casino-games";
import { prisma } from "@/server/db";
import { fail, ok } from "@/server/http";
import { requireUser } from "@/server/security/auth";

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

export const dynamic = "force-dynamic";

export async function GET(request: NextRequest) {
  try {
    const { user } = await requireUser(request);
    const [deposits, withdrawals, tickets, casinoRounds] = await Promise.all([
      prisma.cryptoDeposit.findMany({
        where: { userId: user.id },
        orderBy: { createdAt: "desc" },
        take: 80
      }),
      prisma.cryptoWithdrawal.findMany({
        where: { userId: user.id },
        orderBy: { createdAt: "desc" },
        take: 80
      }),
      prisma.betTicket.findMany({
        where: { userId: user.id },
        orderBy: { placedAt: "desc" },
        take: 80
      }),
      prisma.casinoRound.findMany({
        where: { userId: user.id },
        orderBy: { createdAt: "desc" },
        take: 80
      })
    ]);

    const transactions: WalletTransaction[] = [
      ...deposits.map((deposit) => ({
        id: deposit.id,
        type: "deposit" as const,
        label: `Dépôt ${deposit.asset}`,
        amount: deposit.eurAmount?.toString() ?? "0",
        currency: "EUR",
        status: deposit.status,
        createdAt: deposit.createdAt,
        meta: shortHash(deposit.txHash)
      })),
      ...withdrawals.map((withdrawal) => ({
        id: withdrawal.id,
        type: "withdrawal" as const,
        label: `Retrait ${withdrawal.asset}`,
        amount: withdrawal.eurAmount.toString(),
        currency: "EUR",
        status: withdrawal.status,
        createdAt: withdrawal.createdAt,
        meta: withdrawal.txHash ? shortHash(withdrawal.txHash) : shortHash(withdrawal.destinationAddress)
      })),
      ...tickets.map((ticket) => ({
        id: ticket.id,
        type: "bet" as const,
        label: ticket.status === "OPEN" ? "Pari sportif" : "Ticket réglé",
        amount: ticket.stake.toString(),
        currency: ticket.currency,
        status: ticket.status,
        createdAt: ticket.placedAt,
        meta: `Cote ${Number(ticket.totalOdds.toString()).toFixed(2)}`
      })),
      ...casinoRounds.map((round) => ({
        id: round.id,
        type: "casino" as const,
        label: casinoGameLabel(round.game),
        amount: round.profit.toString(),
        currency: round.currency,
        status: round.status,
        createdAt: round.createdAt,
        meta: casinoGameMeta(round.game, round.result.toString(), round.multiplier.toString())
      }))
    ].sort((left, right) => right.createdAt.getTime() - left.createdAt.getTime());

    return ok({
      transactions: transactions.map((transaction) => ({
        ...transaction,
        createdAt: transaction.createdAt.toISOString()
      }))
    });
  } catch (error) {
    return fail(error);
  }
}

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

function casinoGameLabel(game: string) {
  const slug = game.toLowerCase();
  const knownGame = getMiniGame(slug);
  if (knownGame) return knownGame.title;

  return slug
    .split("_")
    .map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
    .join(" ");
}

function casinoGameMeta(game: string, result: string, multiplier: string) {
  const gameKey = game.toLowerCase();
  const formattedMultiplier = `${Number(multiplier).toFixed(2)}x`;

  if (gameKey === "dice") {
    return `Roll ${Number(result).toFixed(2)} · ${formattedMultiplier}`;
  }

  if (gameKey === "blackjack") {
    return `Main blackjack · ${formattedMultiplier}`;
  }

  if (gameKey === "plinko") {
    return `Case ${Number(result).toFixed(0)} · ${formattedMultiplier}`;
  }

  return `Résultat ${Number(result).toFixed(2)} · ${formattedMultiplier}`;
}
