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

export type AchievementCategory = 'gameplay' | 'social' | 'spending' | 'milestone' | 'special';
export type AchievementRarity = 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary';

export interface Achievement {
  id: string;
  name: string;
  description: string;
  category: AchievementCategory;
  rarity: AchievementRarity;
  icon: string;
  badge: string;
  unlockCondition: string;
  reward: number; // SC reward
  progressType?: 'counter' | 'threshold';
  progressMax?: number;
  createdAt: Date;
}

export interface PlayerAchievement {
  id: string;
  playerId: number;
  achievementId: string;
  unlockedAt: Date;
  progress?: number;
  completed: boolean;
}

/**
 * Achievement Manager
 */
export class AchievementManager {
  private achievements: Map<string, Achievement> = new Map();
  private playerAchievements: Map<number, PlayerAchievement[]> = new Map();

  /**
   * Initialize achievement catalog
   */
  async initializeCatalog(): Promise<void> {
    const catalog: Achievement[] = [
      // Gameplay Achievements
      {
        id: 'first_win',
        name: 'First Win',
        description: 'Win your first spin',
        category: 'gameplay',
        rarity: 'common',
        icon: '🎰',
        badge: '🏅',
        unlockCondition: 'Win any spin',
        reward: 50,
        createdAt: new Date(),
      },
      {
        id: 'big_winner',
        name: 'Big Winner',
        description: 'Win 1000 SC in a single spin',
        category: 'gameplay',
        rarity: 'rare',
        icon: '💰',
        badge: '🌟',
        unlockCondition: 'Win 1000 SC in one spin',
        reward: 500,
        createdAt: new Date(),
      },
      {
        id: 'jackpot_master',
        name: 'Jackpot Master',
        description: 'Win a progressive jackpot',
        category: 'gameplay',
        rarity: 'legendary',
        icon: '🎯',
        badge: '👑',
        unlockCondition: 'Win a progressive jackpot',
        reward: 2000,
        createdAt: new Date(),
      },
      {
        id: 'spin_addict',
        name: 'Spin Addict',
        description: 'Complete 100 spins',
        category: 'gameplay',
        rarity: 'uncommon',
        icon: '🔄',
        badge: '⚡',
        unlockCondition: 'Complete 100 spins',
        reward: 200,
        progressType: 'counter',
        progressMax: 100,
        createdAt: new Date(),
      },
      {
        id: 'high_roller',
        name: 'High Roller',
        description: 'Wager 50,000 SC total',
        category: 'spending',
        rarity: 'epic',
        icon: '💎',
        badge: '💰',
        unlockCondition: 'Wager 50,000 SC total',
        reward: 1000,
        progressType: 'counter',
        progressMax: 50000,
        createdAt: new Date(),
      },
      {
        id: 'bonus_hunter',
        name: 'Bonus Hunter',
        description: 'Trigger 10 bonus rounds',
        category: 'gameplay',
        rarity: 'uncommon',
        icon: '🎁',
        badge: '🎉',
        unlockCondition: 'Trigger 10 bonus rounds',
        reward: 300,
        progressType: 'counter',
        progressMax: 10,
        createdAt: new Date(),
      },

      // Social Achievements
      {
        id: 'social_butterfly',
        name: 'Social Butterfly',
        description: 'Add 10 friends',
        category: 'social',
        rarity: 'uncommon',
        icon: '👥',
        badge: '🦋',
        unlockCondition: 'Add 10 friends',
        reward: 250,
        progressType: 'counter',
        progressMax: 10,
        createdAt: new Date(),
      },
      {
        id: 'referral_master',
        name: 'Referral Master',
        description: 'Successfully refer 5 friends',
        category: 'social',
        rarity: 'rare',
        icon: '🔗',
        badge: '🌐',
        unlockCondition: 'Successfully refer 5 friends',
        reward: 500,
        progressType: 'counter',
        progressMax: 5,
        createdAt: new Date(),
      },
      {
        id: 'tournament_champion',
        name: 'Tournament Champion',
        description: 'Win a tournament',
        category: 'special',
        rarity: 'epic',
        icon: '🏆',
        badge: '🥇',
        unlockCondition: 'Win a tournament',
        reward: 1500,
        createdAt: new Date(),
      },

      // Milestone Achievements
      {
        id: 'level_5',
        name: 'Level 5',
        description: 'Reach level 5',
        category: 'milestone',
        rarity: 'common',
        icon: '📈',
        badge: '⭐',
        unlockCondition: 'Reach level 5',
        reward: 100,
        createdAt: new Date(),
      },
      {
        id: 'vip_silver',
        name: 'VIP Silver',
        description: 'Reach VIP Silver tier',
        category: 'milestone',
        rarity: 'uncommon',
        icon: '🥈',
        badge: '✨',
        unlockCondition: 'Reach VIP Silver tier',
        reward: 300,
        createdAt: new Date(),
      },
      {
        id: 'vip_gold',
        name: 'VIP Gold',
        description: 'Reach VIP Gold tier',
        category: 'milestone',
        rarity: 'rare',
        icon: '🥇',
        badge: '🌟',
        unlockCondition: 'Reach VIP Gold tier',
        reward: 800,
        createdAt: new Date(),
      },

      // Special Achievements
      {
        id: 'lucky_day',
        name: 'Lucky Day',
        description: 'Win 5 spins in a row',
        category: 'special',
        rarity: 'rare',
        icon: '🍀',
        badge: '✨',
        unlockCondition: 'Win 5 consecutive spins',
        reward: 600,
        createdAt: new Date(),
      },
      {
        id: 'comeback_kid',
        name: 'Comeback Kid',
        description: 'Win after losing 10 spins in a row',
        category: 'special',
        rarity: 'epic',
        icon: '🔥',
        badge: '💪',
        unlockCondition: 'Win after 10 consecutive losses',
        reward: 1200,
        createdAt: new Date(),
      },
    ];

    for (const achievement of catalog) {
      this.achievements.set(achievement.id, achievement);
    }
  }

  /**
   * Unlock achievement
   */
  async unlockAchievement(playerId: number, achievementId: string): Promise<{ success: boolean; reward: number }> {
    const achievement = this.achievements.get(achievementId);
    if (!achievement) {
      return { success: false, reward: 0 };
    }

    // Check if already unlocked
    const playerAchievements = this.playerAchievements.get(playerId) || [];
    if (playerAchievements.some((a) => a.achievementId === achievementId && a.completed)) {
      return { success: false, reward: 0 };
    }

    // Create achievement entry
    const playerAchievement: PlayerAchievement = {
      id: `pa_${Date.now()}_${Math.random().toString(36).substring(7)}`,
      playerId,
      achievementId,
      unlockedAt: new Date(),
      completed: true,
    };

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

    // Credit reward
    await creditWallet(
      playerId,
      'SC',
      achievement.reward,
      'achievement_unlock',
      `Achievement Unlocked: ${achievement.name}`,
      String(playerId)
    );

    // Log achievement
    await writeAuditLog({
      actorId: playerId,
      actorRole: 'user',
      action: 'achievement_unlocked',
      category: 'achievement',
      details: {
        achievementId,
        achievementName: achievement.name,
        reward: achievement.reward,
      },
    });

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

  /**
   * Update achievement progress
   */
  async updateProgress(playerId: number, achievementId: string, progress: number): Promise<void> {
    const achievement = this.achievements.get(achievementId);
    if (!achievement || !achievement.progressMax) return;

    const playerAchievements = this.playerAchievements.get(playerId) || [];
    let playerAchievement = playerAchievements.find((a) => a.achievementId === achievementId);

    if (!playerAchievement) {
      playerAchievement = {
        id: `pa_${Date.now()}_${Math.random().toString(36).substring(7)}`,
        playerId,
        achievementId,
        unlockedAt: new Date(),
        progress: 0,
        completed: false,
      };

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

    playerAchievement.progress = Math.min(progress, achievement.progressMax);

    // Check if completed
    if (playerAchievement.progress >= achievement.progressMax && !playerAchievement.completed) {
      await this.unlockAchievement(playerId, achievementId);
    }
  }

  /**
   * Get player achievements
   */
  async getPlayerAchievements(playerId: number): Promise<PlayerAchievement[]> {
    return this.playerAchievements.get(playerId) || [];
  }

  /**
   * Get unlocked achievements
   */
  async getUnlockedAchievements(playerId: number): Promise<Achievement[]> {
    const playerAchievements = this.playerAchievements.get(playerId) || [];
    const unlockedIds = playerAchievements.filter((a) => a.completed).map((a) => a.achievementId);

    return unlockedIds
      .map((id) => this.achievements.get(id))
      .filter((a) => a !== undefined) as Achievement[];
  }

  /**
   * Get achievement progress
   */
  async getAchievementProgress(playerId: number, achievementId: string): Promise<{ progress: number; max: number } | null> {
    const achievement = this.achievements.get(achievementId);
    if (!achievement) return null;

    const playerAchievements = this.playerAchievements.get(playerId) || [];
    const playerAchievement = playerAchievements.find((a) => a.achievementId === achievementId);

    return {
      progress: playerAchievement?.progress || 0,
      max: achievement.progressMax || 1,
    };
  }

  /**
   * Get achievement details
   */
  getAchievement(achievementId: string): Achievement | undefined {
    return this.achievements.get(achievementId);
  }

  /**
   * Get all achievements
   */
  getAllAchievements(): Achievement[] {
    return Array.from(this.achievements.values());
  }

  /**
   * Get achievements by category
   */
  getAchievementsByCategory(category: AchievementCategory): Achievement[] {
    return Array.from(this.achievements.values()).filter((a) => a.category === category);
  }

  /**
   * Get achievements by rarity
   */
  getAchievementsByRarity(rarity: AchievementRarity): Achievement[] {
    return Array.from(this.achievements.values()).filter((a) => a.rarity === rarity);
  }

  /**
   * Get player stats
   */
  async getPlayerStats(playerId: number): Promise<{
    totalUnlocked: number;
    totalPoints: number;
    categories: Record<AchievementCategory, number>;
  }> {
    const unlockedAchievements = await this.getUnlockedAchievements(playerId);
    const totalPoints = unlockedAchievements.reduce((sum, a) => sum + a.reward, 0);

    const categories: Record<AchievementCategory, number> = {
      gameplay: 0,
      social: 0,
      spending: 0,
      milestone: 0,
      special: 0,
    };

    for (const achievement of unlockedAchievements) {
      categories[achievement.category]++;
    }

    return {
      totalUnlocked: unlockedAchievements.length,
      totalPoints,
      categories,
    };
  }
}

export const achievementManager = new AchievementManager();
