/**
 * Gamification Engine
 * Achievement system, daily challenges, seasonal events, and battle pass mechanics
 */

export type AchievementRarity = 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary';
export type ChallengeType = 'daily' | 'weekly' | 'monthly' | 'seasonal' | 'special';
export type BattlePassTier = 'free' | 'premium';

export interface Achievement {
  id: string;
  name: string;
  description: string;
  icon: string;
  rarity: AchievementRarity;
  points: number;
  unlockedBy: number; // total players who unlocked
  requirements: AchievementRequirement[];
  rewards: AchievementReward[];
  createdAt: Date;
}

export interface AchievementRequirement {
  type: 'plays' | 'winnings' | 'games_played' | 'streak' | 'referrals' | 'tournaments';
  value: number;
  description: string;
}

export interface AchievementReward {
  type: 'coins' | 'tokens' | 'xp' | 'badge' | 'nft';
  amount: number;
  description: string;
}

export interface PlayerAchievement {
  id: string;
  playerId: number;
  achievementId: string;
  unlockedAt: Date;
  progress: number; // 0-100
  isCompleted: boolean;
  rewardsCollected: boolean;
}

export interface DailyChallenge {
  id: string;
  date: Date;
  title: string;
  description: string;
  type: ChallengeType;
  objective: ChallengeObjective;
  rewards: ChallengeReward[];
  difficulty: 'easy' | 'medium' | 'hard';
  completionRate: number; // percentage
  participantCount: number;
}

export interface ChallengeObjective {
  type: 'plays' | 'winnings' | 'specific_game' | 'streak' | 'multiplier';
  target: number;
  description: string;
}

export interface ChallengeReward {
  type: 'coins' | 'tokens' | 'xp' | 'multiplier';
  amount: number;
  description: string;
}

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

export interface SeasonalEvent {
  id: string;
  name: string;
  description: string;
  theme: string;
  startDate: Date;
  endDate: Date;
  leaderboard: EventLeaderboard;
  prizes: EventPrize[];
  specialGames: string[]; // game IDs
  participantCount: number;
  totalPrizePool: number;
}

export interface EventLeaderboard {
  eventId: string;
  rankings: Array<{
    rank: number;
    playerId: number;
    username: string;
    score: number;
    prize: number;
  }>;
}

export interface EventPrize {
  rank: number; // 1 for 1st place, 2 for 2nd, etc. 0 for participation
  amount: number;
  description: string;
}

export interface BattlePass {
  id: string;
  seasonId: string;
  tier: BattlePassTier;
  totalTiers: number;
  rewards: BattlePassReward[];
  startDate: Date;
  endDate: Date;
  price: number; // for premium tier
}

export interface BattlePassReward {
  tier: number;
  type: 'coins' | 'tokens' | 'xp' | 'cosmetic' | 'nft';
  amount: number;
  description: string;
  isPremiumOnly: boolean;
}

export interface PlayerBattlePass {
  id: string;
  playerId: number;
  battlePassId: string;
  currentTier: number;
  xp: number;
  rewardsClaimed: number[];
  purchased: boolean;
  purchasedAt?: Date;
}

/**
 * Create achievement
 */
export function createAchievement(
  name: string,
  description: string,
  icon: string,
  rarity: AchievementRarity,
  points: number,
  requirements: AchievementRequirement[],
  rewards: AchievementReward[]
): Achievement {
  return {
    id: `achievement_${name.toLowerCase().replace(/\s+/g, '_')}`,
    name,
    description,
    icon,
    rarity,
    points,
    unlockedBy: 0,
    requirements,
    rewards,
    createdAt: new Date(),
  };
}

/**
 * Unlock player achievement
 */
export function unlockAchievement(
  playerId: number,
  achievementId: string
): PlayerAchievement {
  return {
    id: `player_ach_${playerId}_${achievementId}`,
    playerId,
    achievementId,
    unlockedAt: new Date(),
    progress: 100,
    isCompleted: true,
    rewardsCollected: false,
  };
}

/**
 * Update achievement progress
 */
export function updateAchievementProgress(
  playerAch: PlayerAchievement,
  currentValue: number,
  targetValue: number
): void {
  playerAch.progress = Math.min(100, (currentValue / targetValue) * 100);
  playerAch.isCompleted = playerAch.progress >= 100;
}

/**
 * Create daily challenge
 */
export function createDailyChallenge(
  date: Date,
  title: string,
  description: string,
  objective: ChallengeObjective,
  rewards: ChallengeReward[],
  difficulty: 'easy' | 'medium' | 'hard'
): DailyChallenge {
  return {
    id: `challenge_${date.toISOString().split('T')[0]}_${Math.random().toString(36).substr(2, 9)}`,
    date,
    title,
    description,
    type: 'daily',
    objective,
    rewards,
    difficulty,
    completionRate: 0,
    participantCount: 0,
  };
}

/**
 * Track player challenge progress
 */
export function trackChallengeProgress(
  playerChallenge: PlayerChallenge,
  currentProgress: number,
  targetProgress: number
): void {
  playerChallenge.progress = Math.min(100, (currentProgress / targetProgress) * 100);

  if (playerChallenge.progress >= 100) {
    playerChallenge.completed = true;
    playerChallenge.completedAt = new Date();
  }
}

/**
 * Create seasonal event
 */
export function createSeasonalEvent(
  name: string,
  description: string,
  theme: string,
  startDate: Date,
  endDate: Date,
  specialGames: string[],
  prizes: EventPrize[]
): SeasonalEvent {
  const totalPrizePool = prizes.reduce((sum, p) => sum + p.amount, 0);

  return {
    id: `event_${name.toLowerCase().replace(/\s+/g, '_')}_${Date.now()}`,
    name,
    description,
    theme,
    startDate,
    endDate,
    leaderboard: {
      eventId: '',
      rankings: [],
    },
    prizes,
    specialGames,
    participantCount: 0,
    totalPrizePool,
  };
}

/**
 * Update event leaderboard
 */
export function updateEventLeaderboard(
  event: SeasonalEvent,
  playerId: number,
  username: string,
  score: number
): void {
  const existingRanking = event.leaderboard.rankings.find((r) => r.playerId === playerId);

  if (existingRanking) {
    existingRanking.score = Math.max(existingRanking.score, score);
  } else {
    event.leaderboard.rankings.push({
      rank: 0,
      playerId,
      username,
      score,
      prize: 0,
    });
  }

  // Sort and update ranks
  event.leaderboard.rankings.sort((a, b) => b.score - a.score);
  event.leaderboard.rankings.forEach((ranking, index) => {
    ranking.rank = index + 1;

    // Assign prizes based on rank
    const prize = event.prizes.find((p) => p.rank === ranking.rank);
    ranking.prize = prize?.amount || 0;
  });
}

/**
 * Create battle pass
 */
export function createBattlePass(
  seasonId: string,
  tier: BattlePassTier,
  totalTiers: number,
  rewards: BattlePassReward[],
  startDate: Date,
  endDate: Date,
  price: number = 0
): BattlePass {
  return {
    id: `battlepass_${seasonId}`,
    seasonId,
    tier,
    totalTiers,
    rewards,
    startDate,
    endDate,
    price,
  };
}

/**
 * Purchase battle pass
 */
export function purchaseBattlePass(playerBattlePass: PlayerBattlePass): void {
  playerBattlePass.purchased = true;
  playerBattlePass.purchasedAt = new Date();
}

/**
 * Progress battle pass
 */
export function progressBattlePass(
  playerBattlePass: PlayerBattlePass,
  xpGained: number,
  xpPerTier: number = 1000
): void {
  playerBattlePass.xp += xpGained;

  while (playerBattlePass.xp >= xpPerTier && playerBattlePass.currentTier < 100) {
    playerBattlePass.xp -= xpPerTier;
    playerBattlePass.currentTier++;
  }
}

/**
 * Claim battle pass reward
 */
export function claimBattlePassReward(
  playerBattlePass: PlayerBattlePass,
  tier: number
): boolean {
  if (playerBattlePass.currentTier < tier) {
    return false; // Not reached this tier yet
  }

  if (playerBattlePass.rewardsClaimed.includes(tier)) {
    return false; // Already claimed
  }

  playerBattlePass.rewardsClaimed.push(tier);
  return true;
}

/**
 * Predefined achievements
 */
export const PREDEFINED_ACHIEVEMENTS = {
  first_win: createAchievement(
    'First Win',
    'Win your first game',
    '🏆',
    'common',
    10,
    [{ type: 'plays', value: 1, description: 'Win 1 game' }],
    [{ type: 'coins', amount: 100, description: 'Bonus coins' }]
  ),
  big_spender: createAchievement(
    'Big Spender',
    'Deposit $100 or more',
    '💰',
    'rare',
    50,
    [{ type: 'winnings', value: 100, description: 'Deposit $100' }],
    [{ type: 'tokens', amount: 50, description: 'Bonus tokens' }]
  ),
  streak_master: createAchievement(
    'Streak Master',
    'Win 10 games in a row',
    '🔥',
    'epic',
    100,
    [{ type: 'streak', value: 10, description: 'Win 10 consecutive games' }],
    [
      { type: 'coins', amount: 1000, description: 'Bonus coins' },
      { type: 'nft', amount: 1, description: 'Exclusive NFT' },
    ]
  ),
  referral_king: createAchievement(
    'Referral King',
    'Refer 50 players',
    '👑',
    'legendary',
    200,
    [{ type: 'referrals', value: 50, description: 'Refer 50 players' }],
    [
      { type: 'tokens', amount: 500, description: 'Bonus tokens' },
      { type: 'nft', amount: 1, description: 'Legendary NFT' },
    ]
  ),
};

/**
 * Get achievement progression
 */
export interface AchievementProgression {
  totalAchievements: number;
  unlockedAchievements: number;
  totalPoints: number;
  earnedPoints: number;
  completionPercentage: number;
}

export function calculateAchievementProgression(
  playerAchievements: PlayerAchievement[],
  allAchievements: Achievement[]
): AchievementProgression {
  const unlockedCount = playerAchievements.filter((pa) => pa.isCompleted).length;
  const earnedPoints = playerAchievements
    .filter((pa) => pa.isCompleted)
    .reduce((sum, pa) => {
      const achievement = allAchievements.find((a) => a.id === pa.achievementId);
      return sum + (achievement?.points || 0);
    }, 0);

  const totalPoints = allAchievements.reduce((sum, a) => sum + a.points, 0);

  return {
    totalAchievements: allAchievements.length,
    unlockedAchievements: unlockedCount,
    totalPoints,
    earnedPoints,
    completionPercentage: (unlockedCount / allAchievements.length) * 100,
  };
}

/**
 * Leaderboard for achievements
 */
export interface AchievementLeaderboard {
  rank: number;
  playerId: number;
  username: string;
  points: number;
  achievements: number;
  level: number;
}

export function generateAchievementLeaderboard(
  playerProgression: Array<{ playerId: number; username: string; progression: AchievementProgression }>
): AchievementLeaderboard[] {
  return playerProgression
    .map((p) => ({
      rank: 0,
      playerId: p.playerId,
      username: p.username,
      points: p.progression.earnedPoints,
      achievements: p.progression.unlockedAchievements,
      level: Math.floor(p.progression.earnedPoints / 100) + 1,
    }))
    .sort((a, b) => b.points - a.points)
    .map((item, index) => ({ ...item, rank: index + 1 }));
}

/**
 * Season configuration
 */
export interface GameSeason {
  id: string;
  name: string;
  number: number;
  startDate: Date;
  endDate: Date;
  theme: string;
  battlePass: BattlePass;
  events: SeasonalEvent[];
  challenges: DailyChallenge[];
}

export function createGameSeason(
  name: string,
  number: number,
  startDate: Date,
  endDate: Date,
  theme: string
): GameSeason {
  return {
    id: `season_${number}`,
    name,
    number,
    startDate,
    endDate,
    theme,
    battlePass: createBattlePass(`season_${number}`, 'free', 100, [], startDate, endDate),
    events: [],
    challenges: [],
  };
}
