import { getDb } from "../db.ts";
import { seasonalEvents, eventParticipation, wallets } from "../../drizzle/schema.ts";
import { eq, and, gte, lte } from "drizzle-orm";

export interface SeasonalEvent {
  id: number;
  name: string;
  description: string;
  theme: string; // "halloween", "christmas", "newyear", "summer", etc
  startDate: Date;
  endDate: Date;
  prizePool: number;
  maxParticipants: number;
  icon: string;
  color: string;
  rewards: {
    firstPlace: number;
    secondPlace: number;
    thirdPlace: number;
    participation: number;
  };
}

export interface EventParticipation {
  userId: number;
  eventId: number;
  score: number;
  rank: number;
  joinedAt: Date;
  rewards: number;
}

const SEASONAL_EVENTS: SeasonalEvent[] = [
  {
    id: 1,
    name: "Halloween Spooktacular",
    description: "Spin the reels and collect spooky symbols for extra rewards",
    theme: "halloween",
    startDate: new Date("2026-10-01"),
    endDate: new Date("2026-10-31"),
    prizePool: 50000,
    maxParticipants: 10000,
    icon: "🎃",
    color: "#FF6B35",
    rewards: {
      firstPlace: 5000,
      secondPlace: 2500,
      thirdPlace: 1000,
      participation: 100,
    },
  },
  {
    id: 2,
    name: "Winter Wonderland",
    description: "Join the festive tournament and win holiday-themed cosmetics",
    theme: "christmas",
    startDate: new Date("2026-12-01"),
    endDate: new Date("2026-12-25"),
    prizePool: 75000,
    maxParticipants: 15000,
    icon: "🎄",
    color: "#00A86B",
    rewards: {
      firstPlace: 7500,
      secondPlace: 3750,
      thirdPlace: 1500,
      participation: 150,
    },
  },
  {
    id: 3,
    name: "New Year Bonanza",
    description: "Start the year strong with double rewards and exclusive games",
    theme: "newyear",
    startDate: new Date("2026-01-01"),
    endDate: new Date("2026-01-31"),
    prizePool: 100000,
    maxParticipants: 20000,
    icon: "🎆",
    color: "#FFD700",
    rewards: {
      firstPlace: 10000,
      secondPlace: 5000,
      thirdPlace: 2000,
      participation: 200,
    },
  },
  {
    id: 4,
    name: "Summer Sizzler",
    description: "Beat the heat with tropical-themed games and beach cosmetics",
    theme: "summer",
    startDate: new Date("2026-06-01"),
    endDate: new Date("2026-08-31"),
    prizePool: 60000,
    maxParticipants: 12000,
    icon: "☀️",
    color: "#FF8C00",
    rewards: {
      firstPlace: 6000,
      secondPlace: 3000,
      thirdPlace: 1200,
      participation: 120,
    },
  },
];

export async function getActiveEvents(): Promise<SeasonalEvent[]> {
  const now = new Date();
  return SEASONAL_EVENTS.filter((event) => event.startDate <= now && now <= event.endDate);
}

export async function getUpcomingEvents(): Promise<SeasonalEvent[]> {
  const now = new Date();
  return SEASONAL_EVENTS.filter((event) => event.startDate > now).sort(
    (a, b) => a.startDate.getTime() - b.startDate.getTime()
  );
}

export async function getAllEvents(): Promise<SeasonalEvent[]> {
  return SEASONAL_EVENTS;
}

export async function getEventById(eventId: number): Promise<SeasonalEvent | undefined> {
  return SEASONAL_EVENTS.find((e) => e.id === eventId);
}

export async function joinEvent(userId: number, eventId: number): Promise<boolean> {
  const db = await getDb();
  if (!db) return false;

  const event = await getEventById(eventId);
  if (!event) return false;

  // Check if user already joined
  const existing = await db
    .select()
    .from(eventParticipation)
    .where(and(eq(eventParticipation.userId, userId), eq(eventParticipation.eventId, eventId)))
    .limit(1);

  if (existing.length > 0) return false;

  // Add participation record
  await db.insert(eventParticipation).values({
    userId,
    eventId,
    score: 0,
    rank: 0,
    joinedAt: new Date(),
    rewards: 0,
  });

  return true;
}

export async function updateEventScore(userId: number, eventId: number, scoreIncrease: number): Promise<void> {
  const db = await getDb();
  if (!db) return;

  const participation = await db
    .select()
    .from(eventParticipation)
    .where(and(eq(eventParticipation.userId, userId), eq(eventParticipation.eventId, eventId)))
    .limit(1);

  if (participation.length === 0) return;

  const currentScore = participation[0].score || 0;
  const newScore = currentScore + scoreIncrease;

  await db
    .update(eventParticipation)
    .set({ score: newScore })
    .where(
      and(
        eq(eventParticipation.userId, userId),
        eq(eventParticipation.eventId, eventId)
      )
    );
}

export async function getEventLeaderboard(
  eventId: number,
  limit: number = 100
): Promise<
  Array<{
    userId: number;
    score: number;
    rank: number;
    rewards: number;
  }>
> {
  const db = await getDb();
  if (!db) return [];

  const leaderboard = await db
    .select()
    .from(eventParticipation)
    .where(eq(eventParticipation.eventId, eventId))
    .orderBy((table) => [table.score])
    .limit(limit);

  return leaderboard.map((entry, index) => ({
    userId: entry.userId,
    score: entry.score || 0,
    rank: index + 1,
    rewards: entry.rewards || 0,
  }));
}

export async function getUserEventParticipation(userId: number): Promise<EventParticipation[]> {
  const db = await getDb();
  if (!db) return [];

  const participation = await db
    .select()
    .from(eventParticipation)
    .where(eq(eventParticipation.userId, userId));

  return participation as EventParticipation[];
}

export async function distributeEventRewards(eventId: number): Promise<void> {
  const db = await getDb();
  if (!db) return;

  const event = await getEventById(eventId);
  if (!event) return;

  const leaderboard = await getEventLeaderboard(eventId, 3);

  for (const entry of leaderboard) {
    let reward = 0;

    if (entry.rank === 1) {
      reward = event.rewards.firstPlace;
    } else if (entry.rank === 2) {
      reward = event.rewards.secondPlace;
    } else if (entry.rank === 3) {
      reward = event.rewards.thirdPlace;
    }

    if (reward > 0) {
      // Add reward to user's wallet
      const wallet = await db
        .select()
        .from(wallets)
        .where(eq(wallets.userId, entry.userId))
        .limit(1);

      if (wallet.length > 0) {
        const currentBalance = parseFloat(wallet[0].scBalance || "0");
        const newBalance = currentBalance + reward;

        await db
          .update(wallets)
          .set({ scBalance: newBalance.toString() })
          .where(eq(wallets.userId, entry.userId));
      }

      // Update participation record
      await db
        .update(eventParticipation)
        .set({ rewards: reward })
        .where(
          and(
            eq(eventParticipation.userId, entry.userId),
            eq(eventParticipation.eventId, eventId)
          )
        );
    }
  }
}

export async function getEventStats(eventId: number): Promise<{
  totalParticipants: number;
  totalWagered: number;
  topScore: number;
  averageScore: number;
}> {
  const leaderboard = await getEventLeaderboard(eventId, 10000);

  const totalParticipants = leaderboard.length;
  const totalWagered = leaderboard.reduce((sum, entry) => sum + entry.score, 0);
  const topScore = leaderboard.length > 0 ? leaderboard[0].score : 0;
  const averageScore = totalParticipants > 0 ? totalWagered / totalParticipants : 0;

  return {
    totalParticipants,
    totalWagered,
    topScore,
    averageScore,
  };
}
