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

export type ChallengeDifficulty = 'easy' | 'medium' | 'hard' | 'extreme';
export type ChallengeType = 'spin_count' | 'win_amount' | 'wager_amount' | 'bonus_trigger' | 'game_specific';

export interface Challenge {
  id: string;
  name: string;
  description: string;
  type: ChallengeType;
  difficulty: ChallengeDifficulty;
  icon: string;
  objective: number;
  reward: number; // SC reward
  duration: number; // milliseconds
  createdAt: Date;
  expiresAt: Date;
}

export interface PlayerChallenge {
  id: string;
  playerId: number;
  challengeId: string;
  progress: number;
  completed: boolean;
  completedAt?: Date;
  claimedReward: boolean;
}

/**
 * Daily Challenges Manager
 */
export class DailyChallengesManager {
  private challenges: Map<string, Challenge> = new Map();
  private playerChallenges: Map<number, PlayerChallenge[]> = new Map();
  private dailyRotation: Challenge[] = [];

  /**
   * Initialize daily challenges
   */
  async initializeChallenges(): Promise<void> {
    const allChallenges: Challenge[] = [
      // Easy Challenges
      {
        id: 'spin_10',
        name: 'Spin 10 Times',
        description: 'Complete 10 spins',
        type: 'spin_count',
        difficulty: 'easy',
        icon: '🎰',
        objective: 10,
        reward: 50,
        duration: 24 * 60 * 60 * 1000, // 24 hours
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'win_100',
        name: 'Win 100 SC',
        description: 'Win a total of 100 SC',
        type: 'win_amount',
        difficulty: 'easy',
        icon: '💰',
        objective: 100,
        reward: 75,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'wager_500',
        name: 'Wager 500 SC',
        description: 'Wager a total of 500 SC',
        type: 'wager_amount',
        difficulty: 'easy',
        icon: '🎲',
        objective: 500,
        reward: 100,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },

      // Medium Challenges
      {
        id: 'spin_50',
        name: 'Spin 50 Times',
        description: 'Complete 50 spins',
        type: 'spin_count',
        difficulty: 'medium',
        icon: '🎰',
        objective: 50,
        reward: 150,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'win_500',
        name: 'Win 500 SC',
        description: 'Win a total of 500 SC',
        type: 'win_amount',
        difficulty: 'medium',
        icon: '💰',
        objective: 500,
        reward: 250,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'bonus_3',
        name: 'Trigger 3 Bonuses',
        description: 'Trigger 3 bonus rounds',
        type: 'bonus_trigger',
        difficulty: 'medium',
        icon: '🎁',
        objective: 3,
        reward: 200,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'wager_2000',
        name: 'Wager 2000 SC',
        description: 'Wager a total of 2000 SC',
        type: 'wager_amount',
        difficulty: 'medium',
        icon: '🎲',
        objective: 2000,
        reward: 300,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },

      // Hard Challenges
      {
        id: 'spin_100',
        name: 'Spin 100 Times',
        description: 'Complete 100 spins',
        type: 'spin_count',
        difficulty: 'hard',
        icon: '🎰',
        objective: 100,
        reward: 400,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'win_2000',
        name: 'Win 2000 SC',
        description: 'Win a total of 2000 SC',
        type: 'win_amount',
        difficulty: 'hard',
        icon: '💰',
        objective: 2000,
        reward: 600,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'bonus_10',
        name: 'Trigger 10 Bonuses',
        description: 'Trigger 10 bonus rounds',
        type: 'bonus_trigger',
        difficulty: 'hard',
        icon: '🎁',
        objective: 10,
        reward: 500,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },

      // Extreme Challenges
      {
        id: 'spin_200',
        name: 'Spin 200 Times',
        description: 'Complete 200 spins',
        type: 'spin_count',
        difficulty: 'extreme',
        icon: '🎰',
        objective: 200,
        reward: 1000,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'win_5000',
        name: 'Win 5000 SC',
        description: 'Win a total of 5000 SC',
        type: 'win_amount',
        difficulty: 'extreme',
        icon: '💰',
        objective: 5000,
        reward: 1500,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
      {
        id: 'wager_10000',
        name: 'Wager 10000 SC',
        description: 'Wager a total of 10000 SC',
        type: 'wager_amount',
        difficulty: 'extreme',
        icon: '🎲',
        objective: 10000,
        reward: 2000,
        duration: 24 * 60 * 60 * 1000,
        createdAt: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
      },
    ];

    for (const challenge of allChallenges) {
      this.challenges.set(challenge.id, challenge);
    }

    // Initialize daily rotation (3 random challenges per day)
    await this.rotateDailyChallenge();
  }

  /**
   * Rotate daily challenges
   */
  async rotateDailyChallenge(): Promise<void> {
    const allChallenges = Array.from(this.challenges.values());

    // Select 3 random challenges
    this.dailyRotation = [];
    for (let i = 0; i < 3; i++) {
      const randomIndex = Math.floor(Math.random() * allChallenges.length);
      this.dailyRotation.push(allChallenges[randomIndex]);
    }
  }

  /**
   * Get today's challenges
   */
  async getTodaysChallenges(): Promise<Challenge[]> {
    return this.dailyRotation;
  }

  /**
   * Get player's active challenges
   */
  async getPlayerChallenges(playerId: number): Promise<PlayerChallenge[]> {
    const playerChallenges = this.playerChallenges.get(playerId) || [];

    // Filter out expired challenges
    const now = new Date();
    return playerChallenges.filter((pc) => {
      const challenge = this.challenges.get(pc.challengeId);
      return challenge && challenge.expiresAt > now;
    });
  }

  /**
   * Initialize player challenges
   */
  async initializePlayerChallenges(playerId: number): Promise<void> {
    const todaysChallenges = await this.getTodaysChallenges();

    if (!this.playerChallenges.has(playerId)) {
      this.playerChallenges.set(playerId, []);
    }

    for (const challenge of todaysChallenges) {
      const playerChallenges = this.playerChallenges.get(playerId)!;

      // Check if already exists
      if (!playerChallenges.some((pc) => pc.challengeId === challenge.id)) {
        playerChallenges.push({
          id: `pc_${Date.now()}_${Math.random().toString(36).substring(7)}`,
          playerId,
          challengeId: challenge.id,
          progress: 0,
          completed: false,
          claimedReward: false,
        });
      }
    }
  }

  /**
   * Update challenge progress
   */
  async updateProgress(playerId: number, challengeId: string, increment: number): Promise<void> {
    const playerChallenges = this.playerChallenges.get(playerId) || [];
    let playerChallenge = playerChallenges.find((pc) => pc.challengeId === challengeId);

    if (!playerChallenge) {
      playerChallenge = {
        id: `pc_${Date.now()}_${Math.random().toString(36).substring(7)}`,
        playerId,
        challengeId,
        progress: 0,
        completed: false,
        claimedReward: false,
      };

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

    const challenge = this.challenges.get(challengeId);
    if (!challenge) return;

    playerChallenge.progress = Math.min(playerChallenge.progress + increment, challenge.objective);

    // Check if completed
    if (playerChallenge.progress >= challenge.objective && !playerChallenge.completed) {
      playerChallenge.completed = true;
      playerChallenge.completedAt = new Date();

      // Log completion
      await writeAuditLog({
        actorId: playerId,
        actorRole: 'user',
        action: 'challenge_completed',
        category: 'challenge',
        details: {
          challengeId,
          challengeName: challenge.name,
          reward: challenge.reward,
        },
      });
    }
  }

  /**
   * Claim challenge reward
   */
  async claimReward(playerId: number, challengeId: string): Promise<{ success: boolean; reward: number }> {
    const playerChallenges = this.playerChallenges.get(playerId) || [];
    const playerChallenge = playerChallenges.find((pc) => pc.challengeId === challengeId);

    if (!playerChallenge || !playerChallenge.completed || playerChallenge.claimedReward) {
      return { success: false, reward: 0 };
    }

    const challenge = this.challenges.get(challengeId);
    if (!challenge) {
      return { success: false, reward: 0 };
    }

    // Credit reward
    await creditWallet(
      playerId,
      'SC',
      challenge.reward,
      'challenge_reward',
      `Challenge Completed: ${challenge.name}`,
      String(playerId)
    );

    playerChallenge.claimedReward = true;

    return { success: true, reward: challenge.reward };
  }

  /**
   * Get challenge details
   */
  getChallenge(challengeId: string): Challenge | undefined {
    return this.challenges.get(challengeId);
  }

  /**
   * Get all challenges
   */
  getAllChallenges(): Challenge[] {
    return Array.from(this.challenges.values());
  }

  /**
   * Get challenges by difficulty
   */
  getChallengesByDifficulty(difficulty: ChallengeDifficulty): Challenge[] {
    return Array.from(this.challenges.values()).filter((c) => c.difficulty === difficulty);
  }

  /**
   * Get player stats
   */
  async getPlayerStats(playerId: number): Promise<{
    totalCompleted: number;
    totalRewardsClaimed: number;
    activeChallenges: number;
  }> {
    const playerChallenges = await this.getPlayerChallenges(playerId);
    const completed = playerChallenges.filter((pc) => pc.completed).length;
    const claimed = playerChallenges.filter((pc) => pc.claimedReward).length;
    const active = playerChallenges.filter((pc) => !pc.completed).length;

    let totalRewardsClaimed = 0;
    for (const pc of playerChallenges) {
      if (pc.claimedReward) {
        const challenge = this.challenges.get(pc.challengeId);
        if (challenge) {
          totalRewardsClaimed += challenge.reward;
        }
      }
    }

    return {
      totalCompleted: completed,
      totalRewardsClaimed,
      activeChallenges: active,
    };
  }
}

export const dailyChallengesManager = new DailyChallengesManager();
