import { z } from 'zod';
import { publicProcedure, protectedProcedure, router } from "../_core/trpc.ts";
import { TRPCError } from '@trpc/server';
import { getDb } from "../db.ts";

// Seasonal events data
const SEASONAL_EVENTS = {
  halloween_2026: {
    id: 'halloween_2026',
    name: 'Spooky Spin Spectacular',
    description: 'Halloween-themed games with 2x bonus multiplier',
    theme: 'halloween',
    startDate: new Date('2026-10-01'),
    endDate: new Date('2026-10-31'),
    bonusMultiplier: 2.0,
    specialGames: ['haunted-mansion', 'pumpkin-patch', 'ghost-fortune'],
    rewards: [
      {
        id: 'halloween_wins_10',
        name: 'Trick or Treat',
        description: 'Win 10 games during Halloween',
        icon: '🎃',
        requirement: 10,
        bonus: 100,
        currency: 'SC' as const,
      },
      {
        id: 'halloween_wins_25',
        name: 'Spooky Master',
        description: 'Win 25 games during Halloween',
        icon: '👻',
        requirement: 25,
        bonus: 500,
        currency: 'SC' as const,
      },
    ],
  },
  christmas_2026: {
    id: 'christmas_2026',
    name: 'Festive Fortune',
    description: 'Christmas-themed games with 3x bonus multiplier',
    theme: 'christmas',
    startDate: new Date('2026-12-01'),
    endDate: new Date('2026-12-31'),
    bonusMultiplier: 3.0,
    specialGames: ['santa-sleigh', 'christmas-tree', 'gift-bonanza'],
    rewards: [
      {
        id: 'christmas_wins_15',
        name: 'Jolly Winner',
        description: 'Win 15 games during Christmas',
        icon: '🎅',
        requirement: 15,
        bonus: 250,
        currency: 'SC' as const,
      },
      {
        id: 'christmas_wins_50',
        name: 'Holiday Champion',
        description: 'Win 50 games during Christmas',
        icon: '🎄',
        requirement: 50,
        bonus: 1000,
        currency: 'SC' as const,
      },
    ],
  },
  new_year_2027: {
    id: 'new_year_2027',
    name: 'New Year New Luck',
    description: 'Fresh start with 2.5x bonus multiplier',
    theme: 'new_year',
    startDate: new Date('2027-01-01'),
    endDate: new Date('2027-01-31'),
    bonusMultiplier: 2.5,
    specialGames: ['lucky-7', 'fortune-wheel', 'golden-coins'],
    rewards: [
      {
        id: 'new_year_wins_20',
        name: 'Lucky Start',
        description: 'Win 20 games in January',
        icon: '🎆',
        requirement: 20,
        bonus: 300,
        currency: 'SC' as const,
      },
    ],
  },
  summer_2026: {
    id: 'summer_2026',
    name: 'Summer Sizzle',
    description: 'Beach-themed games with 1.5x bonus multiplier',
    theme: 'summer',
    startDate: new Date('2026-06-21'),
    endDate: new Date('2026-09-22'),
    bonusMultiplier: 1.5,
    specialGames: ['beach-party', 'surfing-safari', 'tropical-paradise'],
    rewards: [
      {
        id: 'summer_wins_30',
        name: 'Summer Superstar',
        description: 'Win 30 games during summer',
        icon: '☀️',
        requirement: 30,
        bonus: 600,
        currency: 'SC' as const,
      },
    ],
  },
};

import { SeasonalEventAutomation } from "../services/seasonalEventAutomation.ts";
import { SeasonalGameGenerator } from "../services/seasonalGameGenerator.ts";
import { notifyOwner } from "../_core/notification.ts";

export const seasonalEventsRouter = router({
  // Get all active events
  getActiveEvents: publicProcedure.query(async () => {
    const now = new Date();
    const activeEvents = Object.values(SEASONAL_EVENTS).filter(
      (event) => event.startDate <= now && event.endDate >= now
    );
    return activeEvents;
  }),

  // Get all events
  getAllEvents: publicProcedure.query(async () => {
    return Object.values(SEASONAL_EVENTS);
  }),

  // Get specific event
  getEvent: publicProcedure
    .input(z.object({ eventId: z.string() }))
    .query(async ({ input }) => {
      const event = SEASONAL_EVENTS[input.eventId as keyof typeof SEASONAL_EVENTS];
      if (!event) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'Event not found',
        });
      }
      return event;
    }),

  // Get player progress in an event
  getPlayerProgress: protectedProcedure
    .input(z.object({ eventId: z.string() }))
    .query(async ({ input, ctx }) => {
      const event = SEASONAL_EVENTS[input.eventId as keyof typeof SEASONAL_EVENTS];
      if (!event) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'Event not found',
        });
      }

      // Get player wins during event period
      const db = await getDb();
      if (!db) {
        return {
          eventId: event.id,
          eventName: event.name,
          totalWins: 0,
          totalWinnings: 0,
          earnedRewards: [],
          progress: 0,
          nextReward: event.rewards[0],
        };
      }

      try {
        const result = await db.raw(
          `SELECT COUNT(*) as total_wins, SUM(CAST(amount AS DECIMAL(18,2))) as total_winnings
           FROM transactions 
           WHERE userId = ? AND type = 'game_win' 
           AND createdAt >= ? AND createdAt <= ?`,
          [
            ctx.user.id,
            event.startDate.toISOString(),
            event.endDate.toISOString(),
          ]
        );

        const totalWins = result[0]?.total_wins || 0;
        const totalWinnings = parseFloat(result[0]?.total_winnings || '0');

        // Calculate rewards earned
        const earnedRewards = event.rewards.filter((reward) => totalWins >= reward.requirement);

        // Calculate progress percentage
        const maxRequirement = Math.max(...event.rewards.map((r) => r.requirement), 1);
        const progress = (totalWins / maxRequirement) * 100;

        return {
          eventId: event.id,
          eventName: event.name,
          totalWins,
          totalWinnings,
          earnedRewards,
          progress: Math.min(progress, 100),
          nextReward: event.rewards.find((r) => totalWins < r.requirement),
        };
      } catch (error) {
        console.error('Error getting player progress:', error);
        return {
          eventId: event.id,
          eventName: event.name,
          totalWins: 0,
          totalWinnings: 0,
          earnedRewards: [],
          progress: 0,
          nextReward: event.rewards[0],
        };
      }
    }),

  // Get bonus multiplier for event
  getBonusMultiplier: publicProcedure
    .input(z.object({ eventId: z.string() }))
    .query(async ({ input }) => {
      const event = SEASONAL_EVENTS[input.eventId as keyof typeof SEASONAL_EVENTS];
      if (!event) {
        return 1.0;
      }
      return event.bonusMultiplier;
    }),

  // Claim event reward
  claimReward: protectedProcedure
    .input(
      z.object({
        eventId: z.string(),
        rewardId: z.string(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      const event = SEASONAL_EVENTS[input.eventId as keyof typeof SEASONAL_EVENTS];
      if (!event) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'Event not found',
        });
      }

      const reward = event.rewards.find((r) => r.id === input.rewardId);
      if (!reward) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'Reward not found',
        });
      }

      const db = await getDb();
      if (!db) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Database connection failed',
        });
      }

      try {
        // Check if player qualifies
        const result = await db.raw(
          `SELECT COUNT(*) as total_wins
           FROM transactions 
           WHERE userId = ? AND type = 'game_win' 
           AND createdAt >= ? AND createdAt <= ?`,
          [
            ctx.user.id,
            event.startDate.toISOString(),
            event.endDate.toISOString(),
          ]
        );

        const totalWins = result[0]?.total_wins || 0;
        if (totalWins < reward.requirement) {
          throw new TRPCError({
            code: 'FORBIDDEN',
            message: `You need ${reward.requirement} wins to claim this reward. You have ${totalWins} wins.`,
          });
        }

        // Check if already claimed
        const claimedCheck = await db.raw(
          `SELECT COUNT(*) as count FROM transactions 
           WHERE userId = ? AND referenceType = 'seasonal_reward' 
           AND referenceId = ?`,
          [ctx.user.id, input.rewardId]
        );

        if (claimedCheck[0]?.count > 0) {
          throw new TRPCError({
            code: 'CONFLICT',
            message: 'You have already claimed this reward',
          });
        }

        // Credit reward to wallet
        const wallet = await db.raw(
          `SELECT * FROM wallets WHERE userId = ? AND currency = ?`,
          [ctx.user.id, reward.currency]
        );

        if (!wallet || wallet.length === 0) {
          throw new TRPCError({
            code: 'INTERNAL_SERVER_ERROR',
            message: 'Wallet not found',
          });
        }

        const currentBalance = parseFloat(wallet[0].balance);
        const newBalance = currentBalance + reward.bonus;

        // Update wallet
        await db.raw(
          `UPDATE wallets SET balance = ? WHERE userId = ? AND currency = ?`,
          [newBalance, ctx.user.id, reward.currency]
        );

        // Log transaction
        await db.raw(
          `INSERT INTO transactions (userId, type, currency, amount, balanceBefore, balanceAfter, referenceId, referenceType, description, createdAt)
           VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())`,
          [
            ctx.user.id,
            'promo_credit',
            reward.currency,
            reward.bonus,
            currentBalance,
            newBalance,
            input.rewardId,
            'seasonal_reward',
            `Seasonal event reward: ${reward.name}`,
          ]
        );

        return {
          success: true,
          message: `Claimed ${reward.name}!`,
          bonus: reward.bonus,
          currency: reward.currency,
        };
      } catch (error) {
        if (error instanceof TRPCError) throw error;
        console.error('Error claiming reward:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to claim reward',
        });
      }
    }),
});
