/// 测试类型枚举
enum TestType {
  quick,      // 快速测试
  standard,   // 标准测试
  full,       // 完整测试
  mock,       // 模拟考试
  vocabulary, // 词汇专项
  grammar,    // 语法专项
  reading,    // 阅读专项
  listening,  // 听力专项
  speaking,   // 口语专项
  writing,    // 写作专项
}

/// 测试状态枚举
enum TestStatus {
  notStarted, // 未开始
  inProgress, // 进行中
  paused,     // 暂停
  completed,  // 已完成
  expired,    // 已过期
}

/// 题目类型枚举
enum QuestionType {
  multipleChoice,    // 单选题
  multipleSelect,    // 多选题
  fillInBlank,       // 填空题
  reading,           // 阅读理解
  listening,         // 听力理解
  speaking,          // 口语题
  writing,           // 写作题
}

/// 难度等级枚举
enum DifficultyLevel {
  beginner,          // 初级
  elementary,        // 基础
  intermediate,      // 中级
  upperIntermediate, // 中高级
  advanced,          // 高级
  expert,            // 专家级
}

/// 技能类型枚举
enum SkillType {
  vocabulary,   // 词汇
  grammar,      // 语法
  reading,      // 阅读
  listening,    // 听力
  speaking,     // 口语
  writing,      // 写作
}

/// 测试题目模型
class TestQuestion {
  final String id;
  final QuestionType type;
  final SkillType skillType;
  final DifficultyLevel difficulty;
  final String content;
  final List<String> options;
  final List<String> correctAnswers;
  final String? audioUrl;
  final String? imageUrl;
  final String? explanation;
  final int points;
  final int timeLimit; // 秒
  final Map<String, dynamic>? metadata;

  const TestQuestion({
    required this.id,
    required this.type,
    required this.skillType,
    required this.difficulty,
    required this.content,
    this.options = const [],
    this.correctAnswers = const [],
    this.audioUrl,
    this.imageUrl,
    this.explanation,
    this.points = 1,
    this.timeLimit = 60,
    this.metadata,
  });

  factory TestQuestion.fromJson(Map<String, dynamic> json) {
    return TestQuestion(
      id: json['id'] as String,
      type: QuestionType.values.firstWhere(
        (e) => e.name == json['type'],
        orElse: () => QuestionType.multipleChoice,
      ),
      skillType: SkillType.values.firstWhere(
        (e) => e.name == json['skillType'],
        orElse: () => SkillType.vocabulary,
      ),
      difficulty: DifficultyLevel.values.firstWhere(
        (e) => e.name == json['difficulty'],
        orElse: () => DifficultyLevel.intermediate,
      ),
      content: json['content'] as String,
      options: List<String>.from(json['options'] ?? []),
      correctAnswers: List<String>.from(json['correctAnswers'] ?? []),
      audioUrl: json['audioUrl'] as String?,
      imageUrl: json['imageUrl'] as String?,
      explanation: json['explanation'] as String?,
      points: json['points'] as int? ?? 1,
      timeLimit: json['timeLimit'] as int? ?? 60,
      metadata: json['metadata'] as Map<String, dynamic>?,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'type': type.name,
      'skillType': skillType.name,
      'difficulty': difficulty.name,
      'content': content,
      'options': options,
      'correctAnswers': correctAnswers,
      'audioUrl': audioUrl,
      'imageUrl': imageUrl,
      'explanation': explanation,
      'points': points,
      'timeLimit': timeLimit,
      'metadata': metadata,
    };
  }
}

/// 语言技能枚举 (用于UI显示)
enum LanguageSkill {
  listening,      // 听力
  reading,        // 阅读
  speaking,       // 口语
  writing,        // 写作
  vocabulary,     // 词汇
  grammar,        // 语法
  pronunciation,  // 发音
  comprehension,  // 理解
}

/// 用户技能统计模型
class UserSkillStatistics {
  final SkillType skillType;
  final double averageScore;
  final int totalTests;
  final int correctAnswers;
  final int totalQuestions;
  final DifficultyLevel strongestLevel;
  final DifficultyLevel weakestLevel;
  final DateTime lastTestDate;

  const UserSkillStatistics({
    required this.skillType,
    required this.averageScore,
    required this.totalTests,
    required this.correctAnswers,
    required this.totalQuestions,
    required this.strongestLevel,
    required this.weakestLevel,
    required this.lastTestDate,
  });

  factory UserSkillStatistics.fromJson(Map<String, dynamic> json) {
    return UserSkillStatistics(
      skillType: SkillType.values.firstWhere(
        (e) => e.toString().split('.').last == json['skillType'],
      ),
      averageScore: (json['averageScore'] as num).toDouble(),
      totalTests: json['totalTests'] as int,
      correctAnswers: json['correctAnswers'] as int,
      totalQuestions: json['totalQuestions'] as int,
      strongestLevel: DifficultyLevel.values.firstWhere(
        (e) => e.toString().split('.').last == json['strongestLevel'],
      ),
      weakestLevel: DifficultyLevel.values.firstWhere(
        (e) => e.toString().split('.').last == json['weakestLevel'],
      ),
      lastTestDate: DateTime.parse(json['lastTestDate']),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'skillType': skillType.toString().split('.').last,
      'averageScore': averageScore,
      'totalTests': totalTests,
      'correctAnswers': correctAnswers,
      'totalQuestions': totalQuestions,
      'strongestLevel': strongestLevel.toString().split('.').last,
      'weakestLevel': weakestLevel.toString().split('.').last,
      'lastTestDate': lastTestDate.toIso8601String(),
    };
  }

  double get accuracy => totalQuestions > 0 ? correctAnswers / totalQuestions : 0.0;
}

/// 用户答案模型
class UserAnswer {
  final String questionId;
  final List<String> selectedAnswers;
  final String? textAnswer;
  final String? audioUrl;
  final DateTime answeredAt;
  final int timeSpent; // 秒

  const UserAnswer({
    required this.questionId,
    this.selectedAnswers = const [],
    this.textAnswer,
    this.audioUrl,
    required this.answeredAt,
    required this.timeSpent,
  });

  factory UserAnswer.fromJson(Map<String, dynamic> json) {
    return UserAnswer(
      questionId: json['questionId'] as String,
      selectedAnswers: List<String>.from(json['selectedAnswers'] ?? []),
      textAnswer: json['textAnswer'] as String?,
      audioUrl: json['audioUrl'] as String?,
      answeredAt: DateTime.parse(json['answeredAt'] as String),
      timeSpent: json['timeSpent'] as int,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'questionId': questionId,
      'selectedAnswers': selectedAnswers,
      'textAnswer': textAnswer,
      'audioUrl': audioUrl,
      'answeredAt': answeredAt.toIso8601String(),
      'timeSpent': timeSpent,
    };
  }
}

/// 技能得分模型
class SkillScore {
  final SkillType skillType;
  final int score;
  final int maxScore;
  final double percentage;
  final DifficultyLevel level;
  final String feedback;

  const SkillScore({
    required this.skillType,
    required this.score,
    required this.maxScore,
    required this.percentage,
    required this.level,
    required this.feedback,
  });

  factory SkillScore.fromJson(Map<String, dynamic> json) {
    return SkillScore(
      skillType: SkillType.values.firstWhere(
        (e) => e.name == json['skillType'],
        orElse: () => SkillType.vocabulary,
      ),
      score: json['score'] as int,
      maxScore: json['maxScore'] as int,
      percentage: (json['percentage'] as num).toDouble(),
      level: DifficultyLevel.values.firstWhere(
        (e) => e.name == json['level'],
        orElse: () => DifficultyLevel.intermediate,
      ),
      feedback: json['feedback'] as String,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'skillType': skillType.name,
      'score': score,
      'maxScore': maxScore,
      'percentage': percentage,
      'level': level.name,
      'feedback': feedback,
    };
  }
}

/// 测试结果模型
class TestResult {
  final String id;
  final String testId;
  final String userId;
  final TestType testType;
  final int totalScore;
  final int maxScore;
  final double percentage;
  final DifficultyLevel overallLevel;
  final List<SkillScore> skillScores;
  final List<UserAnswer> answers;
  final DateTime startTime;
  final DateTime endTime;
  final int duration; // 秒
  final String feedback;
  final Map<String, dynamic>? recommendations;

  const TestResult({
    required this.id,
    required this.testId,
    required this.userId,
    required this.testType,
    required this.totalScore,
    required this.maxScore,
    required this.percentage,
    required this.overallLevel,
    required this.skillScores,
    required this.answers,
    required this.startTime,
    required this.endTime,
    required this.duration,
    required this.feedback,
    this.recommendations,
  });

  factory TestResult.fromJson(Map<String, dynamic> json) {
    return TestResult(
      id: json['id'] as String,
      testId: json['testId'] as String,
      userId: json['userId'] as String,
      testType: TestType.values.firstWhere(
        (e) => e.name == json['testType'],
        orElse: () => TestType.standard,
      ),
      totalScore: json['totalScore'] as int,
      maxScore: json['maxScore'] as int,
      percentage: (json['percentage'] as num).toDouble(),
      overallLevel: DifficultyLevel.values.firstWhere(
        (e) => e.name == json['overallLevel'],
        orElse: () => DifficultyLevel.intermediate,
      ),
      skillScores: (json['skillScores'] as List<dynamic>)
          .map((e) => SkillScore.fromJson(e as Map<String, dynamic>))
          .toList(),
      answers: (json['answers'] as List<dynamic>)
          .map((e) => UserAnswer.fromJson(e as Map<String, dynamic>))
          .toList(),
      startTime: DateTime.parse(json['startTime'] as String),
      endTime: DateTime.parse(json['endTime'] as String),
      duration: json['duration'] as int,
      feedback: json['feedback'] as String,
      recommendations: json['recommendations'] as Map<String, dynamic>?,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'testId': testId,
      'userId': userId,
      'testType': testType.name,
      'totalScore': totalScore,
      'maxScore': maxScore,
      'percentage': percentage,
      'overallLevel': overallLevel.name,
      'skillScores': skillScores.map((e) => e.toJson()).toList(),
      'answers': answers.map((e) => e.toJson()).toList(),
      'startTime': startTime.toIso8601String(),
      'endTime': endTime.toIso8601String(),
      'duration': duration,
      'feedback': feedback,
      'recommendations': recommendations,
    };
  }
}

/// 测试模板模型
class TestTemplate {
  final String id;
  final String name;
  final String description;
  final TestType type;
  final int duration; // 分钟
  final int totalQuestions;
  final Map<SkillType, int> skillDistribution;
  final Map<DifficultyLevel, int> difficultyDistribution;
  final List<String> questionIds;
  final bool isActive;
  final DateTime createdAt;
  final DateTime updatedAt;

  const TestTemplate({
    required this.id,
    required this.name,
    required this.description,
    required this.type,
    required this.duration,
    required this.totalQuestions,
    required this.skillDistribution,
    required this.difficultyDistribution,
    required this.questionIds,
    this.isActive = true,
    required this.createdAt,
    required this.updatedAt,
  });

  factory TestTemplate.fromJson(Map<String, dynamic> json) {
    return TestTemplate(
      id: json['id'] as String,
      name: json['name'] as String,
      description: json['description'] as String,
      type: TestType.values.firstWhere(
        (e) => e.name == json['type'],
        orElse: () => TestType.standard,
      ),
      duration: json['duration'] as int,
      totalQuestions: json['totalQuestions'] as int,
      skillDistribution: Map<SkillType, int>.fromEntries(
        (json['skillDistribution'] as Map<String, dynamic>).entries.map(
          (e) => MapEntry(
            SkillType.values.firstWhere((skill) => skill.name == e.key),
            e.value as int,
          ),
        ),
      ),
      difficultyDistribution: Map<DifficultyLevel, int>.fromEntries(
        (json['difficultyDistribution'] as Map<String, dynamic>).entries.map(
          (e) => MapEntry(
            DifficultyLevel.values.firstWhere((level) => level.name == e.key),
            e.value as int,
          ),
        ),
      ),
      questionIds: List<String>.from(json['questionIds']),
      isActive: json['isActive'] as bool? ?? true,
      createdAt: DateTime.parse(json['createdAt'] as String),
      updatedAt: DateTime.parse(json['updatedAt'] as String),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'description': description,
      'type': type.name,
      'duration': duration,
      'totalQuestions': totalQuestions,
      'skillDistribution': skillDistribution.map(
        (key, value) => MapEntry(key.name, value),
      ),
      'difficultyDistribution': difficultyDistribution.map(
        (key, value) => MapEntry(key.name, value),
      ),
      'questionIds': questionIds,
      'isActive': isActive,
      'createdAt': createdAt.toIso8601String(),
      'updatedAt': updatedAt.toIso8601String(),
    };
  }
}

/// 测试会话模型
class TestSession {
  final String id;
  final String templateId;
  final String userId;
  final TestStatus status;
  final List<TestQuestion> questions;
  final List<UserAnswer> answers;
  final int currentQuestionIndex;
  final DateTime startTime;
  final DateTime? endTime;
  final int timeRemaining; // 秒
  final Map<String, dynamic>? metadata;

  const TestSession({
    required this.id,
    required this.templateId,
    required this.userId,
    required this.status,
    required this.questions,
    this.answers = const [],
    this.currentQuestionIndex = 0,
    required this.startTime,
    this.endTime,
    required this.timeRemaining,
    this.metadata,
  });

  factory TestSession.fromJson(Map<String, dynamic> json) {
    return TestSession(
      id: json['id'] as String,
      templateId: json['templateId'] as String,
      userId: json['userId'] as String,
      status: TestStatus.values.firstWhere(
        (e) => e.name == json['status'],
        orElse: () => TestStatus.notStarted,
      ),
      questions: (json['questions'] as List<dynamic>)
          .map((e) => TestQuestion.fromJson(e as Map<String, dynamic>))
          .toList(),
      answers: (json['answers'] as List<dynamic>?)
          ?.map((e) => UserAnswer.fromJson(e as Map<String, dynamic>))
          .toList() ?? [],
      currentQuestionIndex: json['currentQuestionIndex'] as int? ?? 0,
      startTime: DateTime.parse(json['startTime'] as String),
      endTime: json['endTime'] != null 
          ? DateTime.parse(json['endTime'] as String) 
          : null,
      timeRemaining: json['timeRemaining'] as int,
      metadata: json['metadata'] as Map<String, dynamic>?,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'templateId': templateId,
      'userId': userId,
      'status': status.name,
      'questions': questions.map((e) => e.toJson()).toList(),
      'answers': answers.map((e) => e.toJson()).toList(),
      'currentQuestionIndex': currentQuestionIndex,
      'startTime': startTime.toIso8601String(),
      'endTime': endTime?.toIso8601String(),
      'timeRemaining': timeRemaining,
      'metadata': metadata,
    };
  }

  TestSession copyWith({
    String? id,
    String? templateId,
    String? userId,
    TestStatus? status,
    List<TestQuestion>? questions,
    List<UserAnswer>? answers,
    int? currentQuestionIndex,
    DateTime? startTime,
    DateTime? endTime,
    int? timeRemaining,
    Map<String, dynamic>? metadata,
  }) {
    return TestSession(
      id: id ?? this.id,
      templateId: templateId ?? this.templateId,
      userId: userId ?? this.userId,
      status: status ?? this.status,
      questions: questions ?? this.questions,
      answers: answers ?? this.answers,
      currentQuestionIndex: currentQuestionIndex ?? this.currentQuestionIndex,
      startTime: startTime ?? this.startTime,
      endTime: endTime ?? this.endTime,
      timeRemaining: timeRemaining ?? this.timeRemaining,
      metadata: metadata ?? this.metadata,
    );
  }
}