import 'dart:convert';
import '../../../core/network/api_client.dart';
import '../../../core/services/storage_service.dart';
import '../models/study_plan_model.dart';
import '../models/vocabulary_book_model.dart';

/// 学习计划服务
class StudyPlanService {
  final ApiClient _apiClient;
  final StorageService _storageService;
  
  static const String _studyPlansKey = 'study_plans';
  static const String _dailyRecordsKey = 'daily_study_records';
  static const String _templatesKey = 'study_plan_templates';

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

  /// 获取用户的所有学习计划
  Future<List<StudyPlan>> getUserStudyPlans() async {
    try {
      final localData = await _storageService.getString(_studyPlansKey);
      if (localData != null) {
        final List<dynamic> jsonList = json.decode(localData);
        return jsonList.map((json) => StudyPlan.fromJson(json)).toList();
      }
      return [];
    } catch (e) {
      throw Exception('获取学习计划失败: $e');
    }
  }

  /// 创建新的学习计划
  Future<StudyPlan> createStudyPlan({
    required String name,
    String? description,
    required StudyPlanType type,
    required DateTime startDate,
    required DateTime endDate,
    required int dailyTarget,
    List<String> vocabularyBookIds = const [],
  }) async {
    try {
      final studyPlan = StudyPlan(
        id: DateTime.now().millisecondsSinceEpoch.toString(),
        name: name,
        description: description,
        userId: 'current_user',
        type: type,
        status: StudyPlanStatus.active,
        startDate: startDate,
        endDate: endDate,
        dailyTarget: dailyTarget,
        vocabularyBookIds: vocabularyBookIds,
        createdAt: DateTime.now(),
        updatedAt: DateTime.now(),
      );

      final existingPlans = await getUserStudyPlans();
      existingPlans.add(studyPlan);
      await _saveStudyPlansToLocal(existingPlans);

      return studyPlan;
    } catch (e) {
      throw Exception('创建学习计划失败: $e');
    }
  }

  /// 更新学习计划
  Future<StudyPlan> updateStudyPlan(StudyPlan studyPlan) async {
    try {
      final existingPlans = await getUserStudyPlans();
      final index = existingPlans.indexWhere((plan) => plan.id == studyPlan.id);
      
      if (index == -1) {
        throw Exception('学习计划不存在');
      }

      final updatedPlan = studyPlan.copyWith(updatedAt: DateTime.now());
      existingPlans[index] = updatedPlan;
      await _saveStudyPlansToLocal(existingPlans);

      return updatedPlan;
    } catch (e) {
      throw Exception('更新学习计划失败: $e');
    }
  }

  /// 删除学习计划
  Future<void> deleteStudyPlan(String planId) async {
    try {
      final existingPlans = await getUserStudyPlans();
      existingPlans.removeWhere((plan) => plan.id == planId);
      await _saveStudyPlansToLocal(existingPlans);
    } catch (e) {
      throw Exception('删除学习计划失败: $e');
    }
  }

  /// 记录每日学习进度
  Future<void> recordDailyProgress({
    required String planId,
    required DateTime date,
    required int wordsLearned,
    required int wordsReviewed,
    required int studyTimeMinutes,
    List<String> vocabularyBookIds = const [],
  }) async {
    try {
      final record = DailyStudyRecord(
        date: DateTime(date.year, date.month, date.day),
        wordsLearned: wordsLearned,
        wordsReviewed: wordsReviewed,
        studyTimeMinutes: studyTimeMinutes,
        vocabularyBookIds: vocabularyBookIds,
      );

      // 获取现有记录
      final allRecords = await _getAllDailyRecords();
      final recordKey = '${planId}_${_formatDateKey(date)}';
      
      // 更新或添加记录
      allRecords[recordKey] = record;
      await _saveDailyRecordsToLocal(allRecords);

      // 更新学习计划的进度
      await _updateStudyPlanProgress(planId);
    } catch (e) {
      throw Exception('记录学习进度失败: $e');
    }
  }

  /// 获取学习计划统计信息
  Future<StudyPlanStats> getStudyPlanStats(String planId) async {
    try {
      final studyPlans = await getUserStudyPlans();
      final studyPlan = studyPlans.where((plan) => plan.id == planId).firstOrNull;
      
      if (studyPlan == null) {
        throw Exception('学习计划不存在');
      }

      final allRecords = await _getAllDailyRecords();
      final planRecords = <DailyStudyRecord>[];
      
      // 获取该计划的所有记录
      for (final entry in allRecords.entries) {
        if (entry.key.startsWith('${planId}_')) {
          planRecords.add(entry.value);
        }
      }

      // 计算统计信息
      final totalDays = studyPlan.endDate.difference(studyPlan.startDate).inDays + 1;
      final studiedDays = planRecords.length;
      final totalWordsLearned = planRecords.fold(0, (sum, record) => sum + record.wordsLearned);
      final totalWordsReviewed = planRecords.fold(0, (sum, record) => sum + record.wordsReviewed);
      
      // 计算连续学习天数
      final currentStreak = _calculateCurrentStreak(planRecords);
      final maxStreak = _calculateMaxStreak(planRecords);
      
      final completionRate = studyPlan.totalWords > 0 
          ? studyPlan.completedWords / studyPlan.totalWords 
          : 0.0;
      
      final averageDailyWords = studiedDays > 0 
          ? totalWordsLearned / studiedDays 
          : 0.0;
      
      final remainingDays = studyPlan.endDate.difference(DateTime.now()).inDays;
      final remainingWords = studyPlan.totalWords - studyPlan.completedWords;
      
      final lastStudyDate = planRecords.isNotEmpty 
          ? planRecords.map((r) => r.date).reduce((a, b) => a.isAfter(b) ? a : b)
          : null;

      return StudyPlanStats(
        planId: planId,
        totalDays: totalDays,
        studiedDays: studiedDays,
        totalWords: studyPlan.totalWords,
        learnedWords: totalWordsLearned,
        reviewedWords: totalWordsReviewed,
        currentStreak: currentStreak,
        maxStreak: maxStreak,
        completionRate: completionRate,
        averageDailyWords: averageDailyWords,
        remainingDays: remainingDays > 0 ? remainingDays : 0,
        remainingWords: remainingWords > 0 ? remainingWords : 0,
        lastStudyDate: lastStudyDate,
        dailyRecords: planRecords,
      );
    } catch (e) {
      throw Exception('获取学习计划统计失败: $e');
    }
  }

  /// 获取今日学习任务
  Future<List<StudyPlan>> getTodayStudyTasks() async {
    try {
      final allPlans = await getUserStudyPlans();
      final today = DateTime.now();
      
      return allPlans.where((plan) {
        return plan.status == StudyPlanStatus.active &&
               plan.startDate.isBefore(today.add(const Duration(days: 1))) &&
               plan.endDate.isAfter(today.subtract(const Duration(days: 1)));
      }).toList();
    } catch (e) {
      throw Exception('获取今日学习任务失败: $e');
    }
  }

  /// 检查今日是否完成目标
  Future<bool> isTodayTargetAchieved(String planId) async {
    try {
      final today = DateTime.now();
      final allRecords = await _getAllDailyRecords();
      final recordKey = '${planId}_${_formatDateKey(today)}';
      
      final todayRecord = allRecords[recordKey];
      if (todayRecord == null) return false;
      
      final studyPlans = await getUserStudyPlans();
      final studyPlan = studyPlans.where((plan) => plan.id == planId).firstOrNull;
      
      if (studyPlan == null) return false;
      
      return todayRecord.wordsLearned >= studyPlan.dailyTarget;
    } catch (e) {
      return false;
    }
  }

  /// 获取学习计划模板
  Future<List<StudyPlanTemplate>> getStudyPlanTemplates() async {
    try {
      // 返回预设的学习计划模板
      return [
        StudyPlanTemplate(
          id: 'daily_basic',
          name: '每日基础学习',
          description: '每天学习20个新单词，适合初学者',
          type: StudyPlanType.daily,
          durationDays: 30,
          dailyTarget: 20,
          difficulty: 1,
          tags: ['基础', '初学者'],
          isPopular: true,
        ),
        StudyPlanTemplate(
          id: 'weekly_intensive',
          name: '周集中学习',
          description: '每周集中学习，每天50个单词',
          type: StudyPlanType.weekly,
          durationDays: 7,
          dailyTarget: 50,
          difficulty: 3,
          tags: ['集中', '高强度'],
        ),
        StudyPlanTemplate(
          id: 'exam_prep_cet4',
          name: 'CET-4考试准备',
          description: '为大学英语四级考试准备的学习计划',
          type: StudyPlanType.examPrep,
          durationDays: 60,
          dailyTarget: 30,
          difficulty: 2,
          tags: ['考试', 'CET-4'],
          isPopular: true,
        ),
        StudyPlanTemplate(
          id: 'exam_prep_cet6',
          name: 'CET-6考试准备',
          description: '为大学英语六级考试准备的学习计划',
          type: StudyPlanType.examPrep,
          durationDays: 90,
          dailyTarget: 40,
          difficulty: 3,
          tags: ['考试', 'CET-6'],
        ),
        StudyPlanTemplate(
          id: 'toefl_prep',
          name: 'TOEFL考试准备',
          description: '为托福考试准备的高强度学习计划',
          type: StudyPlanType.examPrep,
          durationDays: 120,
          dailyTarget: 60,
          difficulty: 4,
          tags: ['考试', 'TOEFL', '出国'],
          isPopular: true,
        ),
      ];
    } catch (e) {
      throw Exception('获取学习计划模板失败: $e');
    }
  }

  /// 从模板创建学习计划
  Future<StudyPlan> createStudyPlanFromTemplate({
    required StudyPlanTemplate template,
    required DateTime startDate,
    List<String> vocabularyBookIds = const [],
  }) async {
    try {
      final endDate = startDate.add(Duration(days: template.durationDays - 1));
      
      return await createStudyPlan(
        name: template.name,
        description: template.description,
        type: template.type,
        startDate: startDate,
        endDate: endDate,
        dailyTarget: template.dailyTarget,
        vocabularyBookIds: vocabularyBookIds,
      );
    } catch (e) {
      throw Exception('从模板创建学习计划失败: $e');
    }
  }

  /// 保存学习计划到本地存储
  Future<void> _saveStudyPlansToLocal(List<StudyPlan> studyPlans) async {
    final jsonList = studyPlans.map((plan) => plan.toJson()).toList();
    await _storageService.setString(_studyPlansKey, json.encode(jsonList));
  }

  /// 保存每日记录到本地存储
  Future<void> _saveDailyRecordsToLocal(Map<String, DailyStudyRecord> records) async {
    final jsonMap = records.map((key, record) => MapEntry(key, record.toJson()));
    await _storageService.setString(_dailyRecordsKey, json.encode(jsonMap));
  }

  /// 获取所有每日记录
  Future<Map<String, DailyStudyRecord>> _getAllDailyRecords() async {
    final localData = await _storageService.getString(_dailyRecordsKey);
    if (localData == null) {
      return {};
    }

    final Map<String, dynamic> jsonMap = json.decode(localData);
    return jsonMap.map((key, value) => MapEntry(key, DailyStudyRecord.fromJson(value)));
  }

  /// 更新学习计划进度
  Future<void> _updateStudyPlanProgress(String planId) async {
    try {
      final studyPlans = await getUserStudyPlans();
      final index = studyPlans.indexWhere((plan) => plan.id == planId);
      
      if (index == -1) return;
      
      final studyPlan = studyPlans[index];
      final allRecords = await _getAllDailyRecords();
      
      // 计算总完成单词数
      int totalCompleted = 0;
      for (final entry in allRecords.entries) {
        if (entry.key.startsWith('${planId}_')) {
          totalCompleted += entry.value.wordsLearned;
        }
      }
      
      // 计算连续学习天数
      final planRecords = <DailyStudyRecord>[];
      for (final entry in allRecords.entries) {
        if (entry.key.startsWith('${planId}_')) {
          planRecords.add(entry.value);
        }
      }
      
      final currentStreak = _calculateCurrentStreak(planRecords);
      final maxStreak = _calculateMaxStreak(planRecords);
      
      final updatedPlan = studyPlan.copyWith(
        completedWords: totalCompleted,
        currentStreak: currentStreak,
        maxStreak: maxStreak > studyPlan.maxStreak ? maxStreak : studyPlan.maxStreak,
        updatedAt: DateTime.now(),
      );
      
      studyPlans[index] = updatedPlan;
      await _saveStudyPlansToLocal(studyPlans);
    } catch (e) {
      // 忽略更新错误
    }
  }

  /// 计算当前连续学习天数
  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;
  }

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