import 'dart:convert';
import 'dart:math';
import '../../../core/network/api_client.dart';
import '../../../core/services/storage_service.dart';
import '../models/learning_stats_model.dart';

/// 学习统计服务
class LearningStatsService {
  final ApiClient _apiClient;
  final StorageService _storageService;
  
  static const String _statsKey = 'learning_stats';
  static const String _achievementsKey = 'achievements';
  static const String _dailyRecordsKey = 'daily_records';

  LearningStatsService({
    required ApiClient apiClient,
    required StorageService storageService,
  }) : _apiClient = apiClient,
       _storageService = storageService;

  /// 获取用户学习统计
  Future<LearningStats> getUserStats() async {
    try {
      // 1. 从后端API获取每日、每周、每月统计数据
      final today = DateTime.now();
      final sevenDaysAgo = today.subtract(const Duration(days: 7));
      final thirtyDaysAgo = today.subtract(const Duration(days: 30));
      
      final startDateStr = thirtyDaysAgo.toIso8601String().split('T')[0];
      final endDateStr = today.toIso8601String().split('T')[0];
      
      print('🔍 开始获取学习统计: startDate=$startDateStr, endDate=$endDateStr');
      print('🔍 请求路径: /vocabulary/study/statistics/history');
      
      // 获取历史统计数据
      final response = await _apiClient.get(
        '/vocabulary/study/statistics/history',
        queryParameters: {
          'startDate': startDateStr,
          'endDate': endDateStr,
        },
      );
      
      print('✅ API响应成功: statusCode=${response.statusCode}');
      
      final List<dynamic> historyData = response.data['data'] ?? [];
      final dailyRecords = historyData.map((item) => DailyStudyRecord.fromJson(item)).toList();
      
      print('📊 获取到 ${dailyRecords.length} 天的学习记录');
      
      // 2. 计算总体统计
      final totalWordsLearned = dailyRecords.fold(0, (sum, record) => sum + record.wordsLearned);
      final totalWordsReviewed = dailyRecords.fold(0, (sum, record) => sum + record.wordsReviewed);
      final totalStudyTimeMinutes = dailyRecords.fold(0, (sum, record) => sum + record.studyTimeMinutes);
      final totalExp = dailyRecords.fold(0, (sum, record) => sum + record.expGained);
      
      // 3. 计算连续学习天数
      final currentStreak = _calculateCurrentStreak(dailyRecords);
      final maxStreak = _calculateMaxStreak(dailyRecords);
      
      // 4. 计算周统计（使用最近7天的记录）
      final weeklyRecords = dailyRecords.where((record) {
        return record.date.isAfter(sevenDaysAgo.subtract(const Duration(days: 1)));
      }).toList();
      final weeklyStats = _calculateWeeklyStats(weeklyRecords);
      
      print('📅 本周学习记录: ${weeklyRecords.length} 天, 学习 ${weeklyStats.wordsLearned} 个单词');
      
      // 5. 计算月统计（使用最近30天的记录）
      final monthlyRecords = dailyRecords;
      
      // 计算本月的周统计记录（用于柱状图）
      final weeklyStatsList = <WeeklyStats>[];
      final firstDayOfMonth = DateTime(today.year, today.month, 1);
      DateTime currentWeekStart = firstDayOfMonth;
      
      while (currentWeekStart.isBefore(today)) {
        final weekEnd = currentWeekStart.add(const Duration(days: 6));
        final weekRecords = dailyRecords.where((record) {
          return record.date.isAfter(currentWeekStart.subtract(const Duration(days: 1))) &&
                 record.date.isBefore(weekEnd.add(const Duration(days: 1)));
        }).toList();
        
        if (weekRecords.isNotEmpty || currentWeekStart.isBefore(today)) {
          weeklyStatsList.add(_calculateWeeklyStats(weekRecords));
        }
        
        currentWeekStart = currentWeekStart.add(const Duration(days: 7));
      }
      
      final monthlyStats = _calculateMonthlyStats(monthlyRecords, weeklyStatsList);
      
      print('📆 本月学习记录: ${monthlyRecords.length} 天, 学习 ${monthlyStats.wordsLearned} 个单词, ${weeklyStatsList.length} 周数据');
      
      // 6. 计算等级和经验值
      final level = calculateLevel(totalExp);
      final nextLevelExp = calculateNextLevelExp(level);
      final currentExp = calculateCurrentLevelExp(totalExp, level);
      
      // 7. 计算平均值
      final studyDays = dailyRecords.length;
      final averageDailyWords = studyDays > 0 ? totalWordsLearned / studyDays : 0.0;
      final averageDailyMinutes = studyDays > 0 ? totalStudyTimeMinutes / studyDays : 0.0;
      
      // 8. 计算准确率
      final totalTests = dailyRecords.fold(0, (sum, record) => sum + record.testsCompleted);
      final averageAccuracy = totalTests > 0
          ? dailyRecords.fold(0.0, (sum, record) => sum + record.accuracyRate) / totalTests
          : 0.0;
      
      final stats = LearningStats(
        userId: 'current_user',
        totalStudyDays: studyDays,
        currentStreak: currentStreak,
        maxStreak: maxStreak,
        totalWordsLearned: totalWordsLearned,
        totalWordsReviewed: totalWordsReviewed,
        totalStudyTimeMinutes: totalStudyTimeMinutes,
        averageDailyWords: averageDailyWords,
        averageDailyMinutes: averageDailyMinutes,
        accuracyRate: averageAccuracy,
        completedBooks: 0,
        currentBooks: 0,
        masteredWords: 0,
        learningWords: 0,
        reviewWords: 0,
        weeklyStats: weeklyStats,
        monthlyStats: monthlyStats,
        level: level,
        currentExp: currentExp,
        nextLevelExp: nextLevelExp,
        lastStudyTime: dailyRecords.isNotEmpty ? dailyRecords.last.date : null,
        createdAt: DateTime.now(),
        updatedAt: DateTime.now(),
        dailyRecords: dailyRecords,
        achievements: [],
        leaderboard: null,
      );
      
      // 保存到本地缓存
      await _saveStatsToLocal(stats);
      
      return stats;
    } catch (e, stackTrace) {
      print('❌ 从API获取学习统计失败: $e');
      print('❌ 错误堆栈: $stackTrace');
      
      // 如果API失败，尝试从本地缓存加载
      final localData = await _storageService.getString(_statsKey);
      if (localData != null) {
        print('💾 从本地缓存加载数据');
        return LearningStats.fromJson(json.decode(localData));
      }
      // 如果本地也没有，返回默认数据
      print('⚠️ 返回默认数据');
      return _createDefaultStats();
    }
  }

  /// 更新学习统计
  Future<LearningStats> updateStats({
    required int wordsLearned,
    required int wordsReviewed,
    required int studyTimeMinutes,
    required double accuracyRate,
    List<String> vocabularyBookIds = const [],
  }) async {
    try {
      final currentStats = await getUserStats();
      final today = DateTime.now();
      
      // 更新每日记录
      await _updateDailyRecord(
        date: today,
        wordsLearned: wordsLearned,
        wordsReviewed: wordsReviewed,
        studyTimeMinutes: studyTimeMinutes,
        accuracyRate: accuracyRate,
        vocabularyBookIds: vocabularyBookIds,
      );
      
      // 计算新的统计数据
      final updatedStats = await _calculateUpdatedStats(currentStats);
      
      // 保存到本地
      await _saveStatsToLocal(updatedStats);
      
      return updatedStats;
    } catch (e) {
      throw Exception('更新学习统计失败: $e');
    }
  }

  /// 获取每日学习记录
  Future<List<DailyStudyRecord>> getDailyRecords({
    DateTime? startDate,
    DateTime? endDate,
  }) async {
    try {
      final localData = await _storageService.getString(_dailyRecordsKey);
      if (localData == null) {
        return [];
      }

      final Map<String, dynamic> recordsMap = json.decode(localData);
      final records = recordsMap.values
          .map((json) => DailyStudyRecord.fromJson(json))
          .toList();

      // 按日期过滤
      if (startDate != null || endDate != null) {
        return records.where((record) {
          if (startDate != null && record.date.isBefore(startDate)) {
            return false;
          }
          if (endDate != null && record.date.isAfter(endDate)) {
            return false;
          }
          return true;
        }).toList();
      }

      return records;
    } catch (e) {
      throw Exception('获取每日记录失败: $e');
    }
  }

  /// 获取周统计
  Future<WeeklyStats> getWeeklyStats([DateTime? weekStart]) async {
    try {
      final startDate = weekStart ?? _getWeekStart(DateTime.now());
      final endDate = startDate.add(const Duration(days: 6));
      
      final dailyRecords = await getDailyRecords(
        startDate: startDate,
        endDate: endDate,
      );

      return _calculateWeeklyStats(dailyRecords);
    } catch (e) {
      throw Exception('获取周统计失败: $e');
    }
  }

  /// 获取月统计
  Future<MonthlyStats> getMonthlyStats([DateTime? month]) async {
    try {
      final targetMonth = month ?? DateTime.now();
      final startDate = DateTime(targetMonth.year, targetMonth.month, 1);
      final endDate = DateTime(targetMonth.year, targetMonth.month + 1, 0);
      
      final dailyRecords = await getDailyRecords(
        startDate: startDate,
        endDate: endDate,
      );

      // 计算周统计
      final weeklyRecords = <WeeklyStats>[];
      DateTime currentWeekStart = startDate;
      
      while (currentWeekStart.isBefore(endDate)) {
        final weekEnd = currentWeekStart.add(const Duration(days: 6));
        final weekRecords = dailyRecords.where((record) {
          return record.date.isAfter(currentWeekStart.subtract(const Duration(days: 1))) &&
                 record.date.isBefore(weekEnd.add(const Duration(days: 1)));
        }).toList();
        
        weeklyRecords.add(_calculateWeeklyStats(weekRecords));
        currentWeekStart = currentWeekStart.add(const Duration(days: 7));
      }

      return _calculateMonthlyStats(dailyRecords, weeklyRecords);
    } catch (e) {
      throw Exception('获取月统计失败: $e');
    }
  }

  /// 获取用户成就
  Future<List<Achievement>> getUserAchievements() async {
    try {
      final localData = await _storageService.getString(_achievementsKey);
      if (localData != null) {
        final List<dynamic> jsonList = json.decode(localData);
        return jsonList.map((json) => Achievement.fromJson(json)).toList();
      }
      
      // 返回默认成就列表
      return _createDefaultAchievements();
    } catch (e) {
      throw Exception('获取成就失败: $e');
    }
  }

  /// 检查并解锁成就
  Future<List<Achievement>> checkAndUnlockAchievements() async {
    try {
      final stats = await getUserStats();
      final achievements = await getUserAchievements();
      final unlockedAchievements = <Achievement>[];

      for (final achievement in achievements) {
        if (!achievement.isUnlocked) {
          final shouldUnlock = _checkAchievementCondition(achievement, stats);
          if (shouldUnlock) {
            final unlockedAchievement = achievement.copyWith(
              isUnlocked: true,
              unlockedAt: DateTime.now(),
            );
            unlockedAchievements.add(unlockedAchievement);
          }
        }
      }

      if (unlockedAchievements.isNotEmpty) {
        // 更新成就列表
        final updatedAchievements = achievements.map((achievement) {
          final unlocked = unlockedAchievements
              .where((a) => a.id == achievement.id)
              .firstOrNull;
          return unlocked ?? achievement;
        }).toList();

        await _saveAchievementsToLocal(updatedAchievements);
      }

      return unlockedAchievements;
    } catch (e) {
      throw Exception('检查成就失败: $e');
    }
  }

  /// 获取排行榜
  Future<Leaderboard> getLeaderboard({
    required LeaderboardType type,
    required LeaderboardPeriod period,
  }) async {
    try {
      // 模拟排行榜数据
      final entries = _generateMockLeaderboardEntries(type);
      
      return Leaderboard(
        type: type,
        period: period,
        entries: entries,
        userRank: Random().nextInt(100) + 1,
        updatedAt: DateTime.now(),
      );
    } catch (e) {
      throw Exception('获取排行榜失败: $e');
    }
  }

  /// 计算用户等级
  int calculateLevel(int totalExp) {
    // 等级计算公式：level = floor(sqrt(totalExp / 100))
    return (sqrt(totalExp / 100)).floor() + 1;
  }

  /// 计算升级所需经验值
  int calculateNextLevelExp(int level) {
    // 下一级所需总经验值：(level^2) * 100
    return level * level * 100;
  }

  /// 计算当前等级经验值
  int calculateCurrentLevelExp(int totalExp, int level) {
    final currentLevelTotalExp = (level - 1) * (level - 1) * 100;
    return totalExp - currentLevelTotalExp;
  }

  /// 更新每日记录
  Future<void> _updateDailyRecord({
    required DateTime date,
    required int wordsLearned,
    required int wordsReviewed,
    required int studyTimeMinutes,
    required double accuracyRate,
    required List<String> vocabularyBookIds,
  }) async {
    final dateKey = _formatDateKey(date);
    final recordsData = await _storageService.getString(_dailyRecordsKey);
    
    Map<String, dynamic> records = {};
    if (recordsData != null) {
      records = json.decode(recordsData);
    }

    // 获取现有记录或创建新记录
    DailyStudyRecord existingRecord;
    if (records.containsKey(dateKey)) {
      existingRecord = DailyStudyRecord.fromJson(records[dateKey]);
    } else {
      existingRecord = DailyStudyRecord(
        date: DateTime(date.year, date.month, date.day),
        wordsLearned: 0,
        wordsReviewed: 0,
        studyTimeMinutes: 0,
        accuracyRate: 0.0,
        testsCompleted: 0,
        expGained: 0,
        vocabularyBookIds: [],
      );
    }

    // 更新记录
    final updatedRecord = DailyStudyRecord(
      date: existingRecord.date,
      wordsLearned: existingRecord.wordsLearned + wordsLearned,
      wordsReviewed: existingRecord.wordsReviewed + wordsReviewed,
      studyTimeMinutes: existingRecord.studyTimeMinutes + studyTimeMinutes,
      accuracyRate: (existingRecord.accuracyRate + accuracyRate) / 2,
      testsCompleted: existingRecord.testsCompleted + 1,
      expGained: existingRecord.expGained + _calculateExpGained(wordsLearned, wordsReviewed, accuracyRate),
      vocabularyBookIds: [...existingRecord.vocabularyBookIds, ...vocabularyBookIds].toSet().toList(),
    );

    records[dateKey] = updatedRecord.toJson();
    await _storageService.setString(_dailyRecordsKey, json.encode(records));
  }

  /// 计算更新后的统计数据
  Future<LearningStats> _calculateUpdatedStats(LearningStats currentStats) async {
    final allRecords = await getDailyRecords();
    
    // 计算总数据
    final totalWordsLearned = allRecords.fold(0, (sum, record) => sum + record.wordsLearned);
    final totalWordsReviewed = allRecords.fold(0, (sum, record) => sum + record.wordsReviewed);
    final totalStudyTimeMinutes = allRecords.fold(0, (sum, record) => sum + record.studyTimeMinutes);
    final totalExp = allRecords.fold(0, (sum, record) => sum + record.expGained);
    
    // 计算连续学习天数
    final currentStreak = _calculateCurrentStreak(allRecords);
    final maxStreak = _calculateMaxStreak(allRecords);
    
    // 计算平均值
    final studyDays = allRecords.length;
    final averageDailyWords = studyDays > 0 ? totalWordsLearned / studyDays : 0.0;
    final averageDailyMinutes = studyDays > 0 ? totalStudyTimeMinutes / studyDays : 0.0;
    
    // 计算准确率
    final totalTests = allRecords.fold(0, (sum, record) => sum + record.testsCompleted);
    final averageAccuracy = totalTests > 0 
        ? allRecords.fold(0.0, (sum, record) => sum + record.accuracyRate) / totalTests
        : 0.0;
    
    // 计算等级
    final level = calculateLevel(totalExp);
    final nextLevelExp = calculateNextLevelExp(level);
    final currentExp = calculateCurrentLevelExp(totalExp, level);
    
    // 获取周月统计
    final weeklyStats = await getWeeklyStats();
    final monthlyStats = await getMonthlyStats();

    return currentStats.copyWith(
      totalStudyDays: studyDays,
      currentStreak: currentStreak,
      maxStreak: maxStreak > currentStats.maxStreak ? maxStreak : currentStats.maxStreak,
      totalWordsLearned: totalWordsLearned,
      totalWordsReviewed: totalWordsReviewed,
      totalStudyTimeMinutes: totalStudyTimeMinutes,
      averageDailyWords: averageDailyWords,
      averageDailyMinutes: averageDailyMinutes,
      accuracyRate: averageAccuracy,
      weeklyStats: weeklyStats,
      monthlyStats: monthlyStats,
      level: level,
      currentExp: currentExp,
      nextLevelExp: nextLevelExp,
      lastStudyTime: DateTime.now(),
      updatedAt: DateTime.now(),
    );
  }

  /// 创建默认统计数据
  LearningStats _createDefaultStats() {
    final now = DateTime.now();
    return LearningStats(
      userId: 'current_user',
      totalStudyDays: 0,
      currentStreak: 0,
      maxStreak: 0,
      totalWordsLearned: 0,
      totalWordsReviewed: 0,
      totalStudyTimeMinutes: 0,
      averageDailyWords: 0.0,
      averageDailyMinutes: 0.0,
      accuracyRate: 0.0,
      completedBooks: 0,
      currentBooks: 0,
      masteredWords: 0,
      learningWords: 0,
      reviewWords: 0,
      weeklyStats: WeeklyStats(
        studyDays: 0,
        wordsLearned: 0,
        wordsReviewed: 0,
        studyTimeMinutes: 0,
        accuracyRate: 0.0,
        dailyRecords: [],
      ),
      monthlyStats: MonthlyStats(
        studyDays: 0,
        wordsLearned: 0,
        wordsReviewed: 0,
        studyTimeMinutes: 0,
        accuracyRate: 0.0,
        completedBooks: 0,
        weeklyRecords: [],
      ),
      level: 1,
      currentExp: 0,
      nextLevelExp: 100,
      lastStudyTime: null,
      createdAt: now,
      updatedAt: now,
      dailyRecords: [],
      achievements: [],
      leaderboard: null,
    );
  }

  /// 创建默认成就列表
  List<Achievement> _createDefaultAchievements() {
    return [
      Achievement(
        id: 'first_word',
        name: '初学者',
        description: '学习第一个单词',
        icon: '🌱',
        type: AchievementType.wordsLearned,
        isUnlocked: false,
        progress: 0,
        target: 1,
        rewardExp: 10,
      ),
      Achievement(
        id: 'hundred_words',
        name: '百词斩',
        description: '累计学习100个单词',
        icon: '💯',
        type: AchievementType.wordsLearned,
        isUnlocked: false,
        progress: 0,
        target: 100,
        rewardExp: 100,
      ),
      Achievement(
        id: 'first_streak',
        name: '坚持不懈',
        description: '连续学习7天',
        icon: '🔥',
        type: AchievementType.streak,
        isUnlocked: false,
        progress: 0,
        target: 7,
        rewardExp: 50,
      ),
      Achievement(
        id: 'month_streak',
        name: '月度达人',
        description: '连续学习30天',
        icon: '🏆',
        type: AchievementType.streak,
        isUnlocked: false,
        progress: 0,
        target: 30,
        rewardExp: 300,
      ),
    ];
  }

  /// 计算周统计
  WeeklyStats _calculateWeeklyStats(List<DailyStudyRecord> dailyRecords) {
    final studyDays = dailyRecords.length;
    final wordsLearned = dailyRecords.fold(0, (sum, record) => sum + record.wordsLearned);
    final wordsReviewed = dailyRecords.fold(0, (sum, record) => sum + record.wordsReviewed);
    final studyTimeMinutes = dailyRecords.fold(0, (sum, record) => sum + record.studyTimeMinutes);
    final totalTests = dailyRecords.fold(0, (sum, record) => sum + record.testsCompleted);
    final accuracyRate = totalTests > 0 
        ? dailyRecords.fold(0.0, (sum, record) => sum + record.accuracyRate) / totalTests
        : 0.0;

    return WeeklyStats(
      studyDays: studyDays,
      wordsLearned: wordsLearned,
      wordsReviewed: wordsReviewed,
      studyTimeMinutes: studyTimeMinutes,
      accuracyRate: accuracyRate,
      dailyRecords: dailyRecords,
    );
  }

  /// 计算月统计
  MonthlyStats _calculateMonthlyStats(
    List<DailyStudyRecord> dailyRecords,
    List<WeeklyStats> weeklyRecords,
  ) {
    final studyDays = dailyRecords.length;
    final wordsLearned = dailyRecords.fold(0, (sum, record) => sum + record.wordsLearned);
    final wordsReviewed = dailyRecords.fold(0, (sum, record) => sum + record.wordsReviewed);
    final studyTimeMinutes = dailyRecords.fold(0, (sum, record) => sum + record.studyTimeMinutes);
    final totalTests = dailyRecords.fold(0, (sum, record) => sum + record.testsCompleted);
    final accuracyRate = totalTests > 0 
        ? dailyRecords.fold(0.0, (sum, record) => sum + record.accuracyRate) / totalTests
        : 0.0;

    return MonthlyStats(
      studyDays: studyDays,
      wordsLearned: wordsLearned,
      wordsReviewed: wordsReviewed,
      studyTimeMinutes: studyTimeMinutes,
      accuracyRate: accuracyRate,
      completedBooks: 0, // TODO: 从实际数据计算
      weeklyRecords: weeklyRecords,
    );
  }

  /// 计算当前连续学习天数
  int _calculateCurrentStreak(List<DailyStudyRecord> records) {
    if (records.isEmpty) return 0;
    
    records.sort((a, b) => b.date.compareTo(a.date));
    
    int streak = 0;
    DateTime currentDate = DateTime.now();
    
    for (final record in records) {
      final daysDiff = currentDate.difference(record.date).inDays;
      
      if (daysDiff == streak) {
        streak++;
      } else {
        break;
      }
    }
    
    return streak;
  }

  /// 计算最大连续学习天数
  int _calculateMaxStreak(List<DailyStudyRecord> records) {
    if (records.isEmpty) return 0;
    
    records.sort((a, b) => a.date.compareTo(b.date));
    
    int maxStreak = 1;
    int currentStreak = 1;
    
    for (int i = 1; i < records.length; i++) {
      final daysDiff = records[i].date.difference(records[i - 1].date).inDays;
      
      if (daysDiff == 1) {
        currentStreak++;
        maxStreak = maxStreak > currentStreak ? maxStreak : currentStreak;
      } else {
        currentStreak = 1;
      }
    }
    
    return maxStreak;
  }

  /// 计算获得的经验值
  int _calculateExpGained(int wordsLearned, int wordsReviewed, double accuracyRate) {
    final baseExp = wordsLearned * 2 + wordsReviewed * 1;
    final accuracyBonus = (accuracyRate * baseExp * 0.5).round();
    return baseExp + accuracyBonus;
  }

  /// 检查成就条件
  bool _checkAchievementCondition(Achievement achievement, LearningStats stats) {
    switch (achievement.type) {
      case AchievementType.wordsLearned:
        return stats.totalWordsLearned >= achievement.target;
      case AchievementType.streak:
        return stats.currentStreak >= achievement.target;
      case AchievementType.studyDays:
        return stats.totalStudyDays >= achievement.target;
      case AchievementType.booksCompleted:
        return stats.completedBooks >= achievement.target;
      case AchievementType.studyTime:
        return stats.totalStudyTimeMinutes >= achievement.target;
      default:
        return false;
    }
  }

  /// 生成模拟排行榜数据
  List<LeaderboardEntry> _generateMockLeaderboardEntries(LeaderboardType type) {
    final random = Random();
    final entries = <LeaderboardEntry>[];
    
    for (int i = 1; i <= 50; i++) {
      entries.add(LeaderboardEntry(
        rank: i,
        userId: 'user_$i',
        username: '用户$i',
        score: random.nextInt(1000) + 100,
        level: random.nextInt(20) + 1,
      ));
    }
    
    return entries;
  }

  /// 获取周开始日期
  DateTime _getWeekStart(DateTime date) {
    final weekday = date.weekday;
    return date.subtract(Duration(days: weekday - 1));
  }

  /// 格式化日期键
  String _formatDateKey(DateTime date) {
    return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
  }

  /// 保存统计数据到本地
  Future<void> _saveStatsToLocal(LearningStats stats) async {
    await _storageService.setString(_statsKey, json.encode(stats.toJson()));
  }

  /// 保存成就到本地
  Future<void> _saveAchievementsToLocal(List<Achievement> achievements) async {
    final jsonList = achievements.map((achievement) => achievement.toJson()).toList();
    await _storageService.setString(_achievementsKey, json.encode(jsonList));
  }
}