import { CasinoGameKey, CasinoRoundStatus, Prisma } from "@prisma/client";
import { NextRequest } from "next/server";
import { AppError } from "@/server/errors";
import { fail, ok } from "@/server/http";
import { prisma } from "@/server/db";

export const dynamic = "force-dynamic";

const gameMap = {
  dice: CasinoGameKey.DICE,
  limbo: CasinoGameKey.LIMBO,
  mines: CasinoGameKey.MINES,
  blackjack: CasinoGameKey.BLACKJACK,
  plinko: CasinoGameKey.PLINKO
} as const;

const leaderboardSelect = {
  id: true,
  currency: true,
  stake: true,
  payout: true,
  profit: true,
  multiplier: true,
  chance: true,
  result: true,
  status: true,
  createdAt: true,
  user: {
    select: {
      username: true
    }
  }
} satisfies Prisma.CasinoRoundSelect;

type LeaderboardRound = Prisma.CasinoRoundGetPayload<{ select: typeof leaderboardSelect }>;

export async function GET(request: NextRequest) {
  try {
    const gameParam = request.nextUrl.searchParams.get("game")?.toLowerCase();
    const game = gameParam ? gameMap[gameParam as keyof typeof gameMap] : null;

    if (!game) {
      throw new AppError("Jeu casino invalide.", 422, "INVALID_CASINO_GAME");
    }

    const where = {
      game,
      status: CasinoRoundStatus.WON,
      payout: { gt: 0 }
    } satisfies Prisma.CasinoRoundWhereInput;

    const [best, lucky] = await Promise.all([
      prisma.casinoRound.findMany({
        where,
        orderBy: [{ payout: "desc" }, { createdAt: "desc" }],
        take: 3,
        select: leaderboardSelect
      }),
      prisma.casinoRound.findMany({
        where,
        orderBy: [{ multiplier: "desc" }, { payout: "desc" }, { createdAt: "desc" }],
        take: 3,
        select: leaderboardSelect
      })
    ]);

    return ok({
      best: best.map(serializeRound),
      lucky: lucky.map(serializeRound)
    });
  } catch (error) {
    return fail(error);
  }
}

function serializeRound(round: LeaderboardRound) {
  return {
    id: round.id,
    currency: round.currency,
    stake: round.stake.toString(),
    payout: round.payout.toString(),
    profit: round.profit.toString(),
    multiplier: round.multiplier.toString(),
    chance: round.chance.toString(),
    result: round.result.toString(),
    status: round.status,
    createdAt: round.createdAt.toISOString(),
    playerName: round.user.username
  };
}
