import { db } from "../db.ts";
import { leaderboards } from "../../drizzle/schema.ts";
import { eq, desc, and, gte } from "drizzle-orm";

export type LeaderboardType = "global" | "weekly" | "daily" | "game_specific";

export async function getLeaderboard(type: LeaderboardType, limit: number = 100, gameId?: string) {
  const now = new Date();
  let startDate = new Date();

  if (type === "daily") {
    startDate.setHours(0, 0, 0, 0);
  } else if (type === "weekly") {
    const day = now.getDay();
    startDate.setDate(now.getDate() - day);
    startDate.setHours(0, 0, 0, 0);
  }

  let query = db
    .select()
    .from(leaderboards)
    .where(eq(leaderboards.leaderboardType, type));

  if (type !== "global" && type !== "game_specific") {
    query = query.where(gte(leaderboards.createdAt, startDate));
  }

  if (type === "game_specific" && gameId) {
    query = query.where(eq(leaderboards.gameId, gameId));
  }

  const entries = await query
    .orderBy(desc(leaderboards.score))
    .limit(limit);

  return entries.map((entry, index) => ({
    ...entry,
    rank: index + 1,
  }));
}

export async function addEntry(
  userId: string,
  type: LeaderboardType,
  score: number,
  gameId?: string
) {
  const now = new Date();

  // Check if user already has an entry
  const existing = await db
    .select()
    .from(leaderboards)
    .where(
      and(
        eq(leaderboards.userId, userId),
        eq(leaderboards.leaderboardType, type),
        gameId ? eq(leaderboards.gameId, gameId) : undefined
      )
    )
    .limit(1);

  if (existing.length > 0) {
    // Update if new score is higher
    if (score > existing[0].score) {
      await db
        .update(leaderboards)
        .set({ score, updatedAt: now })
        .where(eq(leaderboards.id, existing[0].id));
    }
    return existing[0];
  }

  // Create new entry
  const result = await db.insert(leaderboards).values({
    userId,
    leaderboardType: type,
    score,
    gameId,
    createdAt: now,
    updatedAt: now,
  });

  return result;
}

export async function getUserRank(userId: string, type: LeaderboardType, gameId?: string) {
  const leaderboard = await getLeaderboard(type, 10000, gameId);
  const entry = leaderboard.find((e) => e.userId === userId);
  return entry?.rank || null;
}

export async function getPrizePool(type: LeaderboardType) {
  const pools: Record<LeaderboardType, number> = {
    global: 10000,
    weekly: 5000,
    daily: 1000,
    game_specific: 500,
  };
  return pools[type];
}

export async function calculatePrize(type: LeaderboardType, rank: number) {
  const pool = await getPrizePool(type);
  const distribution: Record<number, number> = {
    1: 0.4, // 40%
    2: 0.25, // 25%
    3: 0.15, // 15%
    4: 0.1, // 10%
    5: 0.05, // 5%
  };

  const percentage = distribution[rank] || 0;
  return Math.floor(pool * percentage);
}
