// lib/features/gamification/models/gamification_models.dart
// Data models matching TechDocs v2 DB schema for the Contributor Module.

// ---------------------------------------------------------------------------
// Tier enum — matches PRD v3 §4.4 thresholds (based on Lifetime EP)
// ---------------------------------------------------------------------------
enum ContributorTier { BRONZE, SILVER, GOLD, PLATINUM, DIAMOND }

/// Returns the correct tier for a given lifetime EP total.
ContributorTier tierFromEp(int lifetimeEp) {
  if (lifetimeEp >= 5000) return ContributorTier.DIAMOND;
  if (lifetimeEp >= 1500) return ContributorTier.PLATINUM;
  if (lifetimeEp >= 500) return ContributorTier.GOLD;
  if (lifetimeEp >= 100) return ContributorTier.SILVER;
  return ContributorTier.BRONZE;
}

/// Human-readable label for a tier.
String tierLabel(ContributorTier tier) {
  switch (tier) {
    case ContributorTier.BRONZE:
      return 'Bronze';
    case ContributorTier.SILVER:
      return 'Silver';
    case ContributorTier.GOLD:
      return 'Gold';
    case ContributorTier.PLATINUM:
      return 'Platinum';
    case ContributorTier.DIAMOND:
      return 'Diamond';
  }
}

/// EP threshold for next tier (used for progress bar). Returns null at max tier.
int? nextTierThreshold(ContributorTier tier) {
  switch (tier) {
    case ContributorTier.BRONZE:
      return 100;
    case ContributorTier.SILVER:
      return 500;
    case ContributorTier.GOLD:
      return 1500;
    case ContributorTier.PLATINUM:
      return 5000;
    case ContributorTier.DIAMOND:
      return null;
  }
}

/// Lower EP bound for current tier (used for progress bar calculation).
int tierStartEp(ContributorTier tier) {
  switch (tier) {
    case ContributorTier.BRONZE:
      return 0;
    case ContributorTier.SILVER:
      return 100;
    case ContributorTier.GOLD:
      return 500;
    case ContributorTier.PLATINUM:
      return 1500;
    case ContributorTier.DIAMOND:
      return 5000;
  }
}

// ---------------------------------------------------------------------------
// UserGamificationProfile — mirrors the `UserGamificationProfile` DB table
// ---------------------------------------------------------------------------
class UserGamificationProfile {
  final String userId;
  final int lifetimeEp;  // Never resets. Used for tiers + leaderboard.
  final int currentEp;   // Liquid EP accumulated this month.
  final int currentRp;   // Spendable Reward Points.
  final ContributorTier tier;

  const UserGamificationProfile({
    required this.userId,
    required this.lifetimeEp,
    required this.currentEp,
    required this.currentRp,
    required this.tier,
  });

  factory UserGamificationProfile.fromJson(Map<String, dynamic> json) {
    final ep = (json['lifetime_ep'] as int?) ?? 0;
    return UserGamificationProfile(
      userId: json['user_id'] as String? ?? '',
      lifetimeEp: ep,
      currentEp: (json['current_ep'] as int?) ?? 0,
      currentRp: (json['current_rp'] as int?) ?? 0,
      tier: tierFromEp(ep),
    );
  }
}

// ---------------------------------------------------------------------------
// LeaderboardEntry
// ---------------------------------------------------------------------------
class LeaderboardEntry {
  final int rank;
  final String username;
  final String? avatarUrl;
  final int lifetimeEp;
  final ContributorTier tier;
  final int eventsCount;
  final bool isCurrentUser;

  const LeaderboardEntry({
    required this.rank,
    required this.username,
    this.avatarUrl,
    required this.lifetimeEp,
    required this.tier,
    required this.eventsCount,
    this.isCurrentUser = false,
  });

  factory LeaderboardEntry.fromJson(Map<String, dynamic> json) {
    final ep = (json['lifetime_ep'] as int?) ?? 0;
    return LeaderboardEntry(
      rank: (json['rank'] as int?) ?? 0,
      username: json['username'] as String? ?? '',
      avatarUrl: json['avatar_url'] as String?,
      lifetimeEp: ep,
      tier: tierFromEp(ep),
      eventsCount: (json['events_count'] as int?) ?? 0,
      isCurrentUser: (json['is_current_user'] as bool?) ?? false,
    );
  }
}

// ---------------------------------------------------------------------------
// ShopItem — mirrors `RedeemShopItem` table
// ---------------------------------------------------------------------------
class ShopItem {
  final String id;
  final String name;
  final String description;
  final int rpCost;
  final int stockQuantity;
  final String? imageUrl;

  const ShopItem({
    required this.id,
    required this.name,
    required this.description,
    required this.rpCost,
    required this.stockQuantity,
    this.imageUrl,
  });

  factory ShopItem.fromJson(Map<String, dynamic> json) {
    return ShopItem(
      id: json['id'] as String? ?? '',
      name: json['name'] as String? ?? '',
      description: json['description'] as String? ?? '',
      rpCost: (json['rp_cost'] as int?) ?? 0,
      stockQuantity: (json['stock_quantity'] as int?) ?? 0,
      imageUrl: json['image_url'] as String?,
    );
  }
}

// ---------------------------------------------------------------------------
// RedemptionRecord — mirrors `RedemptionHistory` table
// ---------------------------------------------------------------------------
class RedemptionRecord {
  final String id;
  final String itemId;
  final int rpSpent;
  final String voucherCode;
  final DateTime timestamp;

  const RedemptionRecord({
    required this.id,
    required this.itemId,
    required this.rpSpent,
    required this.voucherCode,
    required this.timestamp,
  });

  factory RedemptionRecord.fromJson(Map<String, dynamic> json) {
    return RedemptionRecord(
      id: json['id'] as String? ?? '',
      itemId: json['item_id'] as String? ?? '',
      rpSpent: (json['rp_spent'] as int?) ?? 0,
      voucherCode: json['voucher_code_issued'] as String? ?? '',
      timestamp: DateTime.tryParse(json['timestamp'] as String? ?? '') ?? DateTime.now(),
    );
  }
}

// ---------------------------------------------------------------------------
// AchievementBadge
// ---------------------------------------------------------------------------
class AchievementBadge {
  final String id;
  final String title;
  final String description;
  final String iconName; // maps to an IconData key
  final bool isUnlocked;
  final double progress; // 0.0 – 1.0

  const AchievementBadge({
    required this.id,
    required this.title,
    required this.description,
    required this.iconName,
    required this.isUnlocked,
    required this.progress,
  });
}
