import { creditWallet, writeAuditLog } from './db.ts';

export type EventType = 'seasonal' | 'holiday' | 'special' | 'anniversary';
export type EventStatus = 'upcoming' | 'active' | 'ended';

export interface SeasonalEvent {
  id: string;
  name: string;
  description: string;
  type: EventType;
  status: EventStatus;
  icon: string;
  theme: string;
  startDate: Date;
  endDate: Date;
  rewards: {
    cosmetics: string[];
    achievements: string[];
    challenges: string[];
  };
  participantCount: number;
  createdAt: Date;
}

export interface PlayerEventProgress {
  id: string;
  playerId: number;
  eventId: string;
  progress: number;
  tasksCompleted: number;
  rewardsClaimed: boolean;
  participatedAt: Date;
  completedAt?: Date;
}

/**
 * Seasonal Events Manager
 */
export class SeasonalEventsManager {
  private events: Map<string, SeasonalEvent> = new Map();
  private playerProgress: Map<number, PlayerEventProgress[]> = new Map();
  private currentEvent: SeasonalEvent | null = null;

  /**
   * Initialize seasonal events catalog
   */
  async initializeCatalog(): Promise<void> {
    const events: SeasonalEvent[] = [
      // Spring Event
      {
        id: 'spring_2026',
        name: 'Spring Celebration',
        description: 'Welcome to spring with fresh rewards and new cosmetics!',
        type: 'seasonal',
        status: 'upcoming',
        icon: '🌸',
        theme: 'spring',
        startDate: new Date('2026-03-21'),
        endDate: new Date('2026-06-20'),
        rewards: {
          cosmetics: ['spring_avatar_1', 'spring_theme_1', 'spring_animation_1'],
          achievements: ['spring_winner', 'spring_master', 'spring_legend'],
          challenges: ['spring_spin_200', 'spring_win_5000', 'spring_bonus_20'],
        },
        participantCount: 0,
        createdAt: new Date(),
      },

      // Summer Event
      {
        id: 'summer_2026',
        name: 'Summer Blast',
        description: 'Heat up your summer with exclusive tropical cosmetics!',
        type: 'seasonal',
        status: 'upcoming',
        icon: '☀️',
        theme: 'summer',
        startDate: new Date('2026-06-21'),
        endDate: new Date('2026-09-22'),
        rewards: {
          cosmetics: ['summer_avatar_1', 'summer_theme_1', 'summer_animation_1'],
          achievements: ['summer_winner', 'summer_master', 'summer_legend'],
          challenges: ['summer_spin_250', 'summer_win_7500', 'summer_bonus_25'],
        },
        participantCount: 0,
        createdAt: new Date(),
      },

      // Halloween Event
      {
        id: 'halloween_2026',
        name: 'Spooky Halloween',
        description: 'Trick or treat! Unlock spooky cosmetics and exclusive rewards.',
        type: 'holiday',
        status: 'upcoming',
        icon: '🎃',
        theme: 'halloween',
        startDate: new Date('2026-10-01'),
        endDate: new Date('2026-10-31'),
        rewards: {
          cosmetics: ['halloween_avatar_1', 'halloween_theme_1', 'halloween_animation_1'],
          achievements: ['halloween_winner', 'halloween_master', 'halloween_legend'],
          challenges: ['halloween_spin_300', 'halloween_win_10000', 'halloween_bonus_30'],
        },
        participantCount: 0,
        createdAt: new Date(),
      },

      // Christmas Event
      {
        id: 'christmas_2026',
        name: 'Festive Christmas',
        description: 'Celebrate the holidays with festive cosmetics and mega rewards!',
        type: 'holiday',
        status: 'upcoming',
        icon: '🎄',
        theme: 'christmas',
        startDate: new Date('2026-12-01'),
        endDate: new Date('2026-12-31'),
        rewards: {
          cosmetics: ['christmas_avatar_1', 'christmas_theme_1', 'christmas_animation_1'],
          achievements: ['christmas_winner', 'christmas_master', 'christmas_legend'],
          challenges: ['christmas_spin_350', 'christmas_win_15000', 'christmas_bonus_40'],
        },
        participantCount: 0,
        createdAt: new Date(),
      },

      // Anniversary Event
      {
        id: 'anniversary_1st',
        name: '1st Anniversary',
        description: 'Celebrate our first year with special anniversary rewards!',
        type: 'anniversary',
        status: 'upcoming',
        icon: '🎉',
        theme: 'anniversary',
        startDate: new Date('2027-03-23'),
        endDate: new Date('2027-03-30'),
        rewards: {
          cosmetics: ['anniversary_avatar_1', 'anniversary_theme_1', 'anniversary_animation_1'],
          achievements: ['anniversary_winner', 'anniversary_master', 'anniversary_legend'],
          challenges: ['anniversary_spin_400', 'anniversary_win_20000', 'anniversary_bonus_50'],
        },
        participantCount: 0,
        createdAt: new Date(),
      },
    ];

    for (const event of events) {
      this.events.set(event.id, event);
    }

    // Set current event (for demo, use first active event)
    this.updateCurrentEvent();
  }

  /**
   * Update current event based on date
   */
  private updateCurrentEvent(): void {
    const now = new Date();

    for (const event of this.events.values()) {
      if (event.startDate <= now && event.endDate >= now) {
        event.status = 'active';
        this.currentEvent = event;
        return;
      } else if (event.endDate < now) {
        event.status = 'ended';
      }
    }

    this.currentEvent = null;
  }

  /**
   * Get current active event
   */
  getCurrentEvent(): SeasonalEvent | null {
    this.updateCurrentEvent();
    return this.currentEvent;
  }

  /**
   * Get all events
   */
  getAllEvents(): SeasonalEvent[] {
    return Array.from(this.events.values());
  }

  /**
   * Get events by status
   */
  getEventsByStatus(status: EventStatus): SeasonalEvent[] {
    return Array.from(this.events.values()).filter((e) => e.status === status);
  }

  /**
   * Get events by type
   */
  getEventsByType(type: EventType): SeasonalEvent[] {
    return Array.from(this.events.values()).filter((e) => e.type === type);
  }

  /**
   * Participate in event
   */
  async participateInEvent(playerId: number, eventId: string): Promise<{ success: boolean; message: string }> {
    const event = this.events.get(eventId);
    if (!event) {
      return { success: false, message: 'Event not found' };
    }

    if (event.status !== 'active') {
      return { success: false, message: 'Event is not active' };
    }

    // Check if already participating
    const playerProgress = this.playerProgress.get(playerId) || [];
    if (playerProgress.some((p) => p.eventId === eventId)) {
      return { success: false, message: 'Already participating in this event' };
    }

    // Create participation entry
    const progress: PlayerEventProgress = {
      id: `ep_${Date.now()}_${Math.random().toString(36).substring(7)}`,
      playerId,
      eventId,
      progress: 0,
      tasksCompleted: 0,
      rewardsClaimed: false,
      participatedAt: new Date(),
    };

    if (!this.playerProgress.has(playerId)) {
      this.playerProgress.set(playerId, []);
    }
    this.playerProgress.get(playerId)!.push(progress);

    // Increment participant count
    event.participantCount++;

    // Log participation
    await writeAuditLog({
      actorId: playerId,
      actorRole: 'user',
      action: 'event_participated',
      category: 'event',
      details: { eventId, eventName: event.name },
    });

    return { success: true, message: 'Successfully joined event' };
  }

  /**
   * Update event progress
   */
  async updateProgress(playerId: number, eventId: string, increment: number): Promise<void> {
    const playerProgress = this.playerProgress.get(playerId) || [];
    let progress = playerProgress.find((p) => p.eventId === eventId);

    if (!progress) {
      progress = {
        id: `ep_${Date.now()}_${Math.random().toString(36).substring(7)}`,
        playerId,
        eventId,
        progress: 0,
        tasksCompleted: 0,
        rewardsClaimed: false,
        participatedAt: new Date(),
      };

      if (!this.playerProgress.has(playerId)) {
        this.playerProgress.set(playerId, []);
      }
      this.playerProgress.get(playerId)!.push(progress);
    }

    progress.progress += increment;
  }

  /**
   * Complete event task
   */
  async completeTask(playerId: number, eventId: string): Promise<void> {
    const playerProgress = this.playerProgress.get(playerId) || [];
    const progress = playerProgress.find((p) => p.eventId === eventId);

    if (progress) {
      progress.tasksCompleted++;

      if (progress.tasksCompleted >= 3) {
        progress.completedAt = new Date();
      }
    }
  }

  /**
   * Claim event rewards
   */
  async claimRewards(playerId: number, eventId: string): Promise<{ success: boolean; reward: number }> {
    const playerProgress = this.playerProgress.get(playerId) || [];
    const progress = playerProgress.find((p) => p.eventId === eventId);

    if (!progress || progress.rewardsClaimed || !progress.completedAt) {
      return { success: false, reward: 0 };
    }

    const event = this.events.get(eventId);
    if (!event) {
      return { success: false, reward: 0 };
    }

    // Calculate reward based on event type
    let reward = 0;
    switch (event.type) {
      case 'seasonal':
        reward = 1000;
        break;
      case 'holiday':
        reward = 1500;
        break;
      case 'anniversary':
        reward = 2000;
        break;
      case 'special':
        reward = 1200;
        break;
    }

    // Credit reward
    await creditWallet(playerId, 'SC', reward, 'event_reward', `Event Reward: ${event.name}`, String(playerId));

    progress.rewardsClaimed = true;

    return { success: true, reward };
  }

  /**
   * Get player event progress
   */
  async getPlayerEventProgress(playerId: number, eventId: string): Promise<PlayerEventProgress | null> {
    const playerProgress = this.playerProgress.get(playerId) || [];
    return playerProgress.find((p) => p.eventId === eventId) || null;
  }

  /**
   * Get all player event progress
   */
  async getPlayerAllEventProgress(playerId: number): Promise<PlayerEventProgress[]> {
    return this.playerProgress.get(playerId) || [];
  }

  /**
   * Get event leaderboard
   */
  async getEventLeaderboard(eventId: string, limit: number = 100): Promise<Array<{
    rank: number;
    playerId: number;
    progress: number;
    tasksCompleted: number;
  }>> {
    const leaderboard: Array<{ playerId: number; progress: number; tasksCompleted: number }> = [];

    for (const [playerId, progresses] of this.playerProgress.entries()) {
      const eventProgress = progresses.find((p) => p.eventId === eventId);
      if (eventProgress) {
        leaderboard.push({
          playerId,
          progress: eventProgress.progress,
          tasksCompleted: eventProgress.tasksCompleted,
        });
      }
    }

    // Sort by tasks completed, then progress
    leaderboard.sort((a, b) => {
      if (b.tasksCompleted !== a.tasksCompleted) {
        return b.tasksCompleted - a.tasksCompleted;
      }
      return b.progress - a.progress;
    });

    return leaderboard.slice(0, limit).map((entry, index) => ({
      rank: index + 1,
      ...entry,
    }));
  }

  /**
   * Get event stats
   */
  async getEventStats(eventId: string): Promise<{
    totalParticipants: number;
    completedCount: number;
    averageProgress: number;
  }> {
    const event = this.events.get(eventId);
    if (!event) {
      return { totalParticipants: 0, completedCount: 0, averageProgress: 0 };
    }

    let completedCount = 0;
    let totalProgress = 0;
    let progressCount = 0;

    for (const progresses of this.playerProgress.values()) {
      const eventProgress = progresses.find((p) => p.eventId === eventId);
      if (eventProgress) {
        totalProgress += eventProgress.progress;
        progressCount++;

        if (eventProgress.completedAt) {
          completedCount++;
        }
      }
    }

    return {
      totalParticipants: event.participantCount,
      completedCount,
      averageProgress: progressCount > 0 ? totalProgress / progressCount : 0,
    };
  }
}

export const seasonalEventsManager = new SeasonalEventsManager();
