import { getDb } from "../db.ts";

export type BadgeRarity = "common" | "rare" | "epic" | "legendary";

export interface Badge {
  id: string;
  name: string;
  description: string;
  icon: string;
  rarity: BadgeRarity;
  unlockCondition: string;
  points: number;
}

export interface PlayerBadge {
  playerId: number;
  badgeId: string;
  unlockedAt: Date;
}

export interface LoginStreak {
  playerId: number;
  currentStreak: number;
  longestStreak: number;
  lastLoginDate: Date;
  streakBonusMultiplier: number; // 1x-5x based on streak
}

export interface WeeklyChallenge {
  id: string;
  name: string;
  description: string;
  objective: string;
  targetValue: number;
  reward: number;
  icon: string;
  difficulty: "easy" | "medium" | "hard";
  weekStartDate: Date;
  weekEndDate: Date;
}

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

// Badge definitions
export const BADGES: Badge[] = [
  // Common badges
  {
    id: "first_spin",
    name: "First Spin",
    description: "Play your first spin",
    icon: "🎰",
    rarity: "common",
    unlockCondition: "Play 1 game",
    points: 10,
  },
  {
    id: "lucky_day",
    name: "Lucky Day",
    description: "Win 1,000 GC in a single session",
    icon: "🍀",
    rarity: "common",
    unlockCondition: "Win 1,000 GC",
    points: 25,
  },
  {
    id: "streak_7",
    name: "Week Warrior",
    description: "Maintain a 7-day login streak",
    icon: "⚔️",
    rarity: "common",
    unlockCondition: "7-day streak",
    points: 50,
  },

  // Rare badges
  {
    id: "big_winner",
    name: "Big Winner",
    description: "Win 50,000 GC total",
    icon: "🏆",
    rarity: "rare",
    unlockCondition: "Win 50,000 GC",
    points: 100,
  },
  {
    id: "streak_30",
    name: "Legendary Streak",
    description: "Maintain a 30-day login streak",
    icon: "🔥",
    rarity: "rare",
    unlockCondition: "30-day streak",
    points: 150,
  },
  {
    id: "challenge_master",
    name: "Challenge Master",
    description: "Complete 10 weekly challenges",
    icon: "🎯",
    rarity: "rare",
    unlockCondition: "Complete 10 challenges",
    points: 120,
  },

  // Epic badges
  {
    id: "mega_jackpot",
    name: "Mega Jackpot",
    description: "Win 500,000 GC in a single spin",
    icon: "💎",
    rarity: "epic",
    unlockCondition: "Win 500,000 GC",
    points: 250,
  },
  {
    id: "high_roller",
    name: "High Roller",
    description: "Reach VIP Tier 5",
    icon: "👑",
    rarity: "epic",
    unlockCondition: "VIP Tier 5",
    points: 200,
  },
  {
    id: "streak_100",
    name: "Century Club",
    description: "Maintain a 100-day login streak",
    icon: "💯",
    rarity: "epic",
    unlockCondition: "100-day streak",
    points: 300,
  },

  // Legendary badges
  {
    id: "ultimate_legend",
    name: "Ultimate Legend",
    description: "Unlock all badges",
    icon: "⭐",
    rarity: "legendary",
    unlockCondition: "Unlock all badges",
    points: 500,
  },
  {
    id: "million_club",
    name: "Million Club",
    description: "Win 1,000,000 GC total",
    icon: "🌟",
    rarity: "legendary",
    unlockCondition: "Win 1,000,000 GC",
    points: 400,
  },
];

// Weekly challenges (rotate weekly)
export const WEEKLY_CHALLENGES: WeeklyChallenge[] = [
  {
    id: "spin_10",
    name: "Spin Master",
    description: "Complete 10 spins",
    objective: "Complete 10 spins",
    targetValue: 10,
    reward: 500,
    icon: "🎰",
    difficulty: "easy",
    weekStartDate: new Date(),
    weekEndDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
  },
  {
    id: "win_5000",
    name: "Win Big",
    description: "Win 5,000 GC total",
    objective: "Accumulate 5,000 GC in wins",
    targetValue: 5000,
    reward: 1000,
    icon: "💰",
    difficulty: "medium",
    weekStartDate: new Date(),
    weekEndDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
  },
  {
    id: "login_5",
    name: "Dedicated Player",
    description: "Login 5 days this week",
    objective: "Login on 5 different days",
    targetValue: 5,
    reward: 750,
    icon: "📅",
    difficulty: "easy",
    weekStartDate: new Date(),
    weekEndDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
  },
  {
    id: "win_streak_3",
    name: "Lucky Streak",
    description: "Get 3 wins in a row",
    objective: "Win 3 consecutive games",
    targetValue: 3,
    reward: 1500,
    icon: "🍀",
    difficulty: "hard",
    weekStartDate: new Date(),
    weekEndDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
  },
];

// In-memory storage (in production, use database)
const playerStreaks = new Map<number, LoginStreak>();
const playerBadges = new Map<number, Set<string>>();
const playerChallenges = new Map<number, Map<string, PlayerChallenge>>();

export async function getOrCreateStreak(playerId: number): Promise<LoginStreak> {
  if (!playerStreaks.has(playerId)) {
    playerStreaks.set(playerId, {
      playerId,
      currentStreak: 0,
      longestStreak: 0,
      lastLoginDate: new Date(),
      streakBonusMultiplier: 1,
    });
  }
  return playerStreaks.get(playerId)!;
}

export async function updateLoginStreak(playerId: number): Promise<LoginStreak> {
  const streak = await getOrCreateStreak(playerId);
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const lastLogin = new Date(streak.lastLoginDate);
  lastLogin.setHours(0, 0, 0, 0);

  const daysDiff = Math.floor((today.getTime() - lastLogin.getTime()) / (1000 * 60 * 60 * 24));

  if (daysDiff === 0) {
    // Already logged in today
    return streak;
  } else if (daysDiff === 1) {
    // Consecutive day
    streak.currentStreak++;
  } else {
    // Streak broken
    streak.currentStreak = 1;
  }

  // Update longest streak
  if (streak.currentStreak > streak.longestStreak) {
    streak.longestStreak = streak.currentStreak;
  }

  // Calculate bonus multiplier (1x-5x)
  streak.streakBonusMultiplier = Math.min(1 + Math.floor(streak.currentStreak / 10), 5);
  streak.lastLoginDate = today;

  console.log(`[GAMIFICATION] Player ${playerId} streak updated: ${streak.currentStreak} days (${streak.streakBonusMultiplier}x multiplier)`);

  return streak;
}

export async function getPlayerStreak(playerId: number): Promise<LoginStreak> {
  return getOrCreateStreak(playerId);
}

export async function unlockBadge(playerId: number, badgeId: string): Promise<boolean> {
  if (!playerBadges.has(playerId)) {
    playerBadges.set(playerId, new Set());
  }

  const badges = playerBadges.get(playerId)!;
  if (badges.has(badgeId)) {
    return false; // Already unlocked
  }

  badges.add(badgeId);
  console.log(`[GAMIFICATION] Player ${playerId} unlocked badge: ${badgeId}`);
  return true;
}

export async function getPlayerBadges(playerId: number): Promise<Badge[]> {
  const badgeIds = playerBadges.get(playerId) || new Set();
  return BADGES.filter((b) => badgeIds.has(b.id));
}

export async function getAvailableBadges(): Promise<Badge[]> {
  return BADGES;
}

export async function getWeeklyChallenges(): Promise<WeeklyChallenge[]> {
  return WEEKLY_CHALLENGES;
}

export async function getPlayerChallenges(playerId: number): Promise<PlayerChallenge[]> {
  if (!playerChallenges.has(playerId)) {
    playerChallenges.set(playerId, new Map());
    // Initialize all challenges for this player
    for (const challenge of WEEKLY_CHALLENGES) {
      playerChallenges.get(playerId)!.set(challenge.id, {
        playerId,
        challengeId: challenge.id,
        progress: 0,
        completed: false,
        reward: challenge.reward,
      });
    }
  }

  return Array.from(playerChallenges.get(playerId)!.values());
}

export async function updateChallengeProgress(
  playerId: number,
  challengeId: string,
  progressDelta: number
): Promise<PlayerChallenge | null> {
  const challenges = playerChallenges.get(playerId);
  if (!challenges) {
    return null;
  }

  const challenge = challenges.get(challengeId);
  if (!challenge) {
    return null;
  }

  if (!challenge.completed) {
    challenge.progress += progressDelta;

    const challengeDef = WEEKLY_CHALLENGES.find((c) => c.id === challengeId);
    if (challengeDef && challenge.progress >= challengeDef.targetValue) {
      challenge.completed = true;
      challenge.completedAt = new Date();
      console.log(`[GAMIFICATION] Player ${playerId} completed challenge: ${challengeId}`);
    }
  }

  return challenge;
}

export async function completeChallenge(playerId: number, challengeId: string): Promise<number> {
  const challenge = await updateChallengeProgress(playerId, challengeId, 999999);
  return challenge?.reward || 0;
}

export async function getPlayerStats(playerId: number): Promise<{
  totalBadges: number;
  completedChallenges: number;
  currentStreak: number;
  longestStreak: number;
  streakMultiplier: number;
  totalBadgePoints: number;
}> {
  const badges = await getPlayerBadges(playerId);
  const challenges = await getPlayerChallenges(playerId);
  const streak = await getPlayerStreak(playerId);

  const totalBadgePoints = badges.reduce((sum, b) => sum + b.points, 0);
  const completedChallenges = challenges.filter((c) => c.completed).length;

  return {
    totalBadges: badges.length,
    completedChallenges,
    currentStreak: streak.currentStreak,
    longestStreak: streak.longestStreak,
    streakMultiplier: streak.streakBonusMultiplier,
    totalBadgePoints,
  };
}
