class WritingStats {
  final String userId;
  final int totalTasks;
  final int completedTasks;
  final int totalWords;
  final int totalTimeSpent; // 秒
  final double averageScore;
  final Map<String, int> taskTypeStats;
  final Map<String, int> difficultyStats;
  final List<WritingProgressData> progressData;
  final WritingSkillAnalysis skillAnalysis;
  final DateTime lastUpdated;

  const WritingStats({
    required this.userId,
    required this.totalTasks,
    required this.completedTasks,
    required this.totalWords,
    required this.totalTimeSpent,
    required this.averageScore,
    required this.taskTypeStats,
    required this.difficultyStats,
    required this.progressData,
    required this.skillAnalysis,
    required this.lastUpdated,
  });

  double get completionRate => totalTasks > 0 ? (completedTasks / totalTasks) * 100 : 0;
  
  double get averageWordsPerTask => completedTasks > 0 ? totalWords / completedTasks : 0;
  
  double get averageTimePerTask => completedTasks > 0 ? totalTimeSpent / completedTasks : 0;

  factory WritingStats.fromJson(Map<String, dynamic> json) {
    final userIdVal = json['userId'];
    final totalTasksVal = json['totalTasks'] ?? json['total_submissions'];
    final completedTasksVal = json['completedTasks'] ?? json['completed_submissions'];
    final totalWordsVal = json['totalWords'] ?? json['total_word_count'];
    final totalTimeSpentVal = json['totalTimeSpent'] ?? json['total_time_spent'];
    final averageScoreVal = json['averageScore'] ?? json['average_score'];
    final difficultyStatsVal = json['difficultyStats'] ?? json['difficulty_stats'] ?? {};
    final progressDataVal = json['progressData'] ?? [];
    final skillAnalysisVal = json['skillAnalysis'];
    final lastUpdatedVal = json['lastUpdated'];

    final stats = WritingStats(
      userId: userIdVal?.toString() ?? '',
      totalTasks: _asInt(totalTasksVal),
      completedTasks: _asInt(completedTasksVal),
      totalWords: _asInt(totalWordsVal),
      totalTimeSpent: _asInt(totalTimeSpentVal),
      averageScore: _asDouble(averageScoreVal),
      taskTypeStats: Map<String, int>.from(json['taskTypeStats'] ?? {}),
      difficultyStats: Map<String, int>.from(difficultyStatsVal),
      progressData: (progressDataVal is List)
          ? progressDataVal
              .map((e) => WritingProgressData.fromJson(Map<String, dynamic>.from(e)))
              .toList()
          : <WritingProgressData>[],
      skillAnalysis: skillAnalysisVal is Map<String, dynamic>
          ? WritingSkillAnalysis.fromJson(skillAnalysisVal)
          : WritingSkillAnalysis(
              criteriaScores: {
                'grammar': _normalize01(_asDouble(json['average_grammar_score'])),
                'coherence': _normalize01(_asDouble(json['average_coherence_score'])),
                'vocab': _normalize01(_asDouble(json['average_vocab_score'])),
              },
              errorCounts: {},
              strengths: const [],
              weaknesses: const [],
              recommendations: const [],
              improvementRate: 0.0,
              lastAnalyzed: DateTime.now(),
            ),
      lastUpdated: lastUpdatedVal is String
          ? DateTime.parse(lastUpdatedVal)
          : DateTime.now(),
    );

    return stats;
  }

  Map<String, dynamic> toJson() {
    return {
      'userId': userId,
      'totalTasks': totalTasks,
      'completedTasks': completedTasks,
      'totalWords': totalWords,
      'totalTimeSpent': totalTimeSpent,
      'averageScore': averageScore,
      'taskTypeStats': taskTypeStats,
      'difficultyStats': difficultyStats,
      'progressData': progressData.map((e) => e.toJson()).toList(),
      'skillAnalysis': skillAnalysis.toJson(),
      'lastUpdated': lastUpdated.toIso8601String(),
    };
  }

  WritingStats copyWith({
    String? userId,
    int? totalTasks,
    int? completedTasks,
    int? totalWords,
    int? totalTimeSpent,
    double? averageScore,
    Map<String, int>? taskTypeStats,
    Map<String, int>? difficultyStats,
    List<WritingProgressData>? progressData,
    WritingSkillAnalysis? skillAnalysis,
    DateTime? lastUpdated,
  }) {
    return WritingStats(
      userId: userId ?? this.userId,
      totalTasks: totalTasks ?? this.totalTasks,
      completedTasks: completedTasks ?? this.completedTasks,
      totalWords: totalWords ?? this.totalWords,
      totalTimeSpent: totalTimeSpent ?? this.totalTimeSpent,
      averageScore: averageScore ?? this.averageScore,
      taskTypeStats: taskTypeStats ?? this.taskTypeStats,
      difficultyStats: difficultyStats ?? this.difficultyStats,
      progressData: progressData ?? this.progressData,
      skillAnalysis: skillAnalysis ?? this.skillAnalysis,
      lastUpdated: lastUpdated ?? this.lastUpdated,
    );
  }
}

class WritingProgressData {
  final DateTime date;
  final double score;
  final int wordCount;
  final int timeSpent;
  final String taskType;
  final String difficulty;

  const WritingProgressData({
    required this.date,
    required this.score,
    required this.wordCount,
    required this.timeSpent,
    required this.taskType,
    required this.difficulty,
  });

  factory WritingProgressData.fromJson(Map<String, dynamic> json) {
    return WritingProgressData(
      date: DateTime.parse(json['date'] as String),
      score: (json['score'] as num).toDouble(),
      wordCount: json['wordCount'] as int,
      timeSpent: json['timeSpent'] as int,
      taskType: json['taskType'] as String,
      difficulty: json['difficulty'] as String,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'date': date.toIso8601String(),
      'score': score,
      'wordCount': wordCount,
      'timeSpent': timeSpent,
      'taskType': taskType,
      'difficulty': difficulty,
    };
  }
}

class WritingSkillAnalysis {
  final Map<String, double> criteriaScores;
  final Map<String, int> errorCounts;
  final List<String> strengths;
  final List<String> weaknesses;
  final List<String> recommendations;
  final double improvementRate;
  final DateTime lastAnalyzed;

  const WritingSkillAnalysis({
    required this.criteriaScores,
    required this.errorCounts,
    required this.strengths,
    required this.weaknesses,
    required this.recommendations,
    required this.improvementRate,
    required this.lastAnalyzed,
  });

  factory WritingSkillAnalysis.fromJson(Map<String, dynamic> json) {
    return WritingSkillAnalysis(
      criteriaScores: Map<String, double>.from(
        (json['criteriaScores'] as Map<String, dynamic>).map(
          (k, v) => MapEntry(k, (v as num).toDouble()),
        ),
      ),
      errorCounts: Map<String, int>.from(json['errorCounts'] ?? {}),
      strengths: List<String>.from(json['strengths'] ?? []),
      weaknesses: List<String>.from(json['weaknesses'] ?? []),
      recommendations: List<String>.from(json['recommendations'] ?? []),
      improvementRate: (json['improvementRate'] as num).toDouble(),
      lastAnalyzed: DateTime.parse(json['lastAnalyzed'] as String),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'criteriaScores': criteriaScores,
      'errorCounts': errorCounts,
      'strengths': strengths,
      'weaknesses': weaknesses,
      'recommendations': recommendations,
      'improvementRate': improvementRate,
      'lastAnalyzed': lastAnalyzed.toIso8601String(),
    };
  }
}

int _asInt(dynamic v) {
  if (v == null) return 0;
  if (v is int) return v;
  if (v is num) return v.toInt();
  if (v is String) {
    final parsed = double.tryParse(v);
    return parsed?.toInt() ?? int.tryParse(v) ?? 0;
  }
  return 0;
}

double _asDouble(dynamic v) {
  if (v == null) return 0.0;
  if (v is double) return v;
  if (v is num) return v.toDouble();
  if (v is String) return double.tryParse(v) ?? 0.0;
  return 0.0;
}

double _normalize01(double v) {
  if (v <= 1.0) return v;
  return v / 100.0;
}