/// 테스트 리포트
class TestReport {
  final String reportId;
  final DateTime generatedAt;
  final ReportType type;
  final List<ScreenTestReport> screenReports;
  final TestSummary summary;
  final List<ErrorAnalysis> errorAnalyses;
  final List<PerformanceMetric> performanceMetrics;
  final Map<String, dynamic> metadata;
  
  TestReport({
    required this.reportId,
    required this.generatedAt,
    required this.type,
    required this.screenReports,
    required this.summary,
    required this.errorAnalyses,
    required this.performanceMetrics,
    required this.metadata,
  });
  
  Map<String, dynamic> toJson() => {
    'reportId': reportId,
    'generatedAt': generatedAt.toIso8601String(),
    'type': type.toString(),
    'screenReports': screenReports.map((r) => r.toJson()).toList(),
    'summary': summary.toJson(),
    'errorAnalyses': errorAnalyses.map((e) => e.toJson()).toList(),
    'performanceMetrics': performanceMetrics.map((m) => m.toJson()).toList(),
    'metadata': metadata,
  };
}

/// 리포트 타입
enum ReportType {
  full,
  summary,
  error,
  performance,
  custom,
}

/// 기능 타입
enum FeatureType {
  crud,
  navigation,
  validation,
  authentication,
  dataSync,
  ui,
  performance,
  custom,
  screen,
}

/// 에러 타입
enum ErrorType {
  runtime,
  network,
  validation,
  authentication,
  timeout,
  assertion,
  ui,
  unknown,
}

/// 근본 원인
class RootCause {
  final String category;
  final String description;
  final double confidence;
  final Map<String, dynamic>? evidence;
  
  RootCause({
    required this.category,
    required this.description,
    required this.confidence,
    this.evidence,
  });
  
  Map<String, dynamic> toJson() => {
    'category': category,
    'description': description,
    'confidence': confidence,
    'evidence': evidence,
  };
}

/// 수정 제안
class FixSuggestion {
  final String title;
  final String description;
  final String code;
  final double priority;
  final bool isAutoFixable;
  
  FixSuggestion({
    required this.title,
    required this.description,
    required this.code,
    required this.priority,
    required this.isAutoFixable,
  });
  
  Map<String, dynamic> toJson() => {
    'title': title,
    'description': description,
    'code': code,
    'priority': priority,
    'isAutoFixable': isAutoFixable,
  };
}

/// 화면별 테스트 리포트
class ScreenTestReport {
  final String screenName;
  final TestResult testResult;
  final List<FeatureReport> featureReports;
  final Map<String, dynamic> coverage;
  final List<String> recommendations;
  
  ScreenTestReport({
    required this.screenName,
    required this.testResult,
    required this.featureReports,
    required this.coverage,
    required this.recommendations,
  });
  
  Map<String, dynamic> toJson() => {
    'screenName': screenName,
    'testResult': testResult.toJson(),
    'featureReports': featureReports.map((r) => r.toJson()).toList(),
    'coverage': coverage,
    'recommendations': recommendations,
  };
}

/// 기능별 리포트
class FeatureReport {
  final String featureName;
  final FeatureType featureType;
  final bool success;
  final int totalTests;
  final int passedTests;
  final int failedTests;
  final Duration totalDuration;
  final List<TestCaseReport> testCaseReports;
  
  FeatureReport({
    required this.featureName,
    required this.featureType,
    required this.success,
    required this.totalTests,
    required this.passedTests,
    required this.failedTests,
    required this.totalDuration,
    required this.testCaseReports,
  });
  
  double get successRate => totalTests > 0 ? passedTests / totalTests : 0;
  
  Map<String, dynamic> toJson() => {
    'featureName': featureName,
    'featureType': featureType.toString(),
    'success': success,
    'totalTests': totalTests,
    'passedTests': passedTests,
    'failedTests': failedTests,
    'successRate': successRate,
    'totalDuration': totalDuration.inMilliseconds,
    'testCaseReports': testCaseReports.map((r) => r.toJson()).toList(),
  };
}

/// 테스트 케이스 리포트
class TestCaseReport {
  final String testCaseName;
  final bool success;
  final Duration duration;
  final String? errorMessage;
  final String? stackTrace;
  final List<TestStep> steps;
  final Map<String, dynamic>? additionalInfo;
  
  TestCaseReport({
    required this.testCaseName,
    required this.success,
    required this.duration,
    this.errorMessage,
    this.stackTrace,
    required this.steps,
    this.additionalInfo,
  });
  
  Map<String, dynamic> toJson() => {
    'testCaseName': testCaseName,
    'success': success,
    'duration': duration.inMilliseconds,
    'errorMessage': errorMessage,
    'stackTrace': stackTrace,
    'steps': steps.map((s) => s.toJson()).toList(),
    'additionalInfo': additionalInfo,
  };
}

/// 테스트 단계
class TestStep {
  final String stepName;
  final StepType type;
  final bool success;
  final String? description;
  final Map<String, dynamic>? data;
  final DateTime timestamp;
  
  TestStep({
    required this.stepName,
    required this.type,
    required this.success,
    this.description,
    this.data,
    required this.timestamp,
  });
  
  Map<String, dynamic> toJson() => {
    'stepName': stepName,
    'type': type.toString(),
    'success': success,
    'description': description,
    'data': data,
    'timestamp': timestamp.toIso8601String(),
  };
}

/// 단계 타입
enum StepType {
  setup,
  action,
  verification,
  teardown,
}

/// 테스트 요약
class TestSummary {
  final int totalScreens;
  final int totalFeatures;
  final int totalTestCases;
  final int passedTestCases;
  final int failedTestCases;
  final int skippedTestCases;
  final Duration totalDuration;
  final double overallSuccessRate;
  final DateTime startTime;
  final DateTime endTime;
  
  TestSummary({
    required this.totalScreens,
    required this.totalFeatures,
    required this.totalTestCases,
    required this.passedTestCases,
    required this.failedTestCases,
    required this.skippedTestCases,
    required this.totalDuration,
    required this.overallSuccessRate,
    required this.startTime,
    required this.endTime,
  });
  
  Map<String, dynamic> toJson() => {
    'totalScreens': totalScreens,
    'totalFeatures': totalFeatures,
    'totalTestCases': totalTestCases,
    'passedTestCases': passedTestCases,
    'failedTestCases': failedTestCases,
    'skippedTestCases': skippedTestCases,
    'totalDuration': totalDuration.inMilliseconds,
    'overallSuccessRate': overallSuccessRate,
    'startTime': startTime.toIso8601String(),
    'endTime': endTime.toIso8601String(),
  };
}

/// 에러 분석
class ErrorAnalysis {
  final String errorId;
  final ErrorType errorType;
  final String description;
  final int occurrenceCount;
  final List<String> affectedScreens;
  final List<String> affectedFeatures;
  final RootCause? rootCause;
  final List<FixSuggestion> suggestedFixes;
  final bool wasAutoFixed;
  final Map<String, dynamic> context;
  
  ErrorAnalysis({
    required this.errorId,
    required this.errorType,
    required this.description,
    required this.occurrenceCount,
    required this.affectedScreens,
    required this.affectedFeatures,
    this.rootCause,
    required this.suggestedFixes,
    required this.wasAutoFixed,
    required this.context,
  });
  
  Map<String, dynamic> toJson() => {
    'errorId': errorId,
    'errorType': errorType.toString(),
    'description': description,
    'occurrenceCount': occurrenceCount,
    'affectedScreens': affectedScreens,
    'affectedFeatures': affectedFeatures,
    'rootCause': rootCause?.toJson(),
    'suggestedFixes': suggestedFixes.map((f) => f.toJson()).toList(),
    'wasAutoFixed': wasAutoFixed,
    'context': context,
  };
}

/// 성능 메트릭
class PerformanceMetric {
  final String metricName;
  final MetricType type;
  final num value;
  final String unit;
  final num? baseline;
  final num? threshold;
  final bool isWithinThreshold;
  final Map<String, dynamic>? breakdown;
  
  PerformanceMetric({
    required this.metricName,
    required this.type,
    required this.value,
    required this.unit,
    this.baseline,
    this.threshold,
    required this.isWithinThreshold,
    this.breakdown,
  });
  
  Map<String, dynamic> toJson() => {
    'metricName': metricName,
    'type': type.toString(),
    'value': value,
    'unit': unit,
    'baseline': baseline,
    'threshold': threshold,
    'isWithinThreshold': isWithinThreshold,
    'breakdown': breakdown,
  };
}

/// 메트릭 타입
enum MetricType {
  duration,
  memory,
  apiCalls,
  errorRate,
  throughput,
  custom,
}

/// 리포트 설정
class ReportConfiguration {
  final bool includeSuccessDetails;
  final bool includeErrorDetails;
  final bool includePerformanceMetrics;
  final bool includeScreenshots;
  final bool generateHtml;
  final bool generateJson;
  final bool generatePdf;
  final String outputDirectory;
  final Map<String, dynamic> customSettings;
  
  ReportConfiguration({
    this.includeSuccessDetails = true,
    this.includeErrorDetails = true,
    this.includePerformanceMetrics = true,
    this.includeScreenshots = false,
    this.generateHtml = true,
    this.generateJson = true,
    this.generatePdf = false,
    required this.outputDirectory,
    this.customSettings = const {},
  });
  
  Map<String, dynamic> toJson() => {
    'includeSuccessDetails': includeSuccessDetails,
    'includeErrorDetails': includeErrorDetails,
    'includePerformanceMetrics': includePerformanceMetrics,
    'includeScreenshots': includeScreenshots,
    'generateHtml': generateHtml,
    'generateJson': generateJson,
    'generatePdf': generatePdf,
    'outputDirectory': outputDirectory,
    'customSettings': customSettings,
  };
}

/// 테스트 결과 (간단한 버전)
class TestResult {
  final int totalTests;
  final int passedTests;
  final int failedTests;
  final int skippedTests;
  final List<TestFailure> failures;
  
  TestResult({
    required this.totalTests,
    required this.passedTests,
    required this.failedTests,
    required this.skippedTests,
    required this.failures,
  });
  
  Map<String, dynamic> toJson() => {
    'totalTests': totalTests,
    'passedTests': passedTests,
    'failedTests': failedTests,
    'skippedTests': skippedTests,
    'failures': failures.map((f) => f.toJson()).toList(),
  };
}

/// 테스트 실패
class TestFailure {
  final String feature;
  final String message;
  final String? stackTrace;
  
  TestFailure({
    required this.feature,
    required this.message,
    this.stackTrace,
  });
  
  Map<String, dynamic> toJson() => {
    'feature': feature,
    'message': message,
    'stackTrace': stackTrace,
  };
}

/// 단계별 리포트
class StepReport {
  final String stepName;
  final DateTime timestamp;
  final bool success;
  final String message;
  final Map<String, dynamic> details;
  
  StepReport({
    required this.stepName,
    required this.timestamp,
    required this.success,
    required this.message,
    required this.details,
  });
  
  Map<String, dynamic> toJson() => {
    'stepName': stepName,
    'timestamp': timestamp.toIso8601String(),
    'success': success,
    'message': message,
    'details': details,
  };
}

/// 에러 리포트
class ErrorReport {
  final String errorType;
  final String message;
  final String? stackTrace;
  final DateTime timestamp;
  final Map<String, dynamic> context;
  
  ErrorReport({
    required this.errorType,
    required this.message,
    this.stackTrace,
    required this.timestamp,
    required this.context,
  });
  
  Map<String, dynamic> toJson() => {
    'errorType': errorType,
    'message': message,
    'stackTrace': stackTrace,
    'timestamp': timestamp.toIso8601String(),
    'context': context,
  };
}

/// 자동 수정 리포트
class AutoFixReport {
  final String errorType;
  final String cause;
  final String solution;
  final bool success;
  final Map<String, dynamic> beforeData;
  final Map<String, dynamic> afterData;
  
  AutoFixReport({
    required this.errorType,
    required this.cause,
    required this.solution,
    required this.success,
    required this.beforeData,
    required this.afterData,
  });
  
  Map<String, dynamic> toJson() => {
    'errorType': errorType,
    'cause': cause,
    'solution': solution,
    'success': success,
    'beforeData': beforeData,
    'afterData': afterData,
  };
}

/// API 호출 리포트
class ApiCallReport {
  final String endpoint;
  final String method;
  final int statusCode;
  final Duration duration;
  final Map<String, dynamic>? request;
  final Map<String, dynamic>? response;
  final bool success;
  
  ApiCallReport({
    required this.endpoint,
    required this.method,
    required this.statusCode,
    required this.duration,
    this.request,
    this.response,
    required this.success,
  });
  
  Map<String, dynamic> toJson() => {
    'endpoint': endpoint,
    'method': method,
    'statusCode': statusCode,
    'duration': duration.inMilliseconds,
    'request': request,
    'response': response,
    'success': success,
  };
}

/// 간단한 테스트 리포트 (BasicTestReport으로 이름 변경)
class BasicTestReport {
  final String reportId;
  final String testName;
  final DateTime startTime;
  final DateTime endTime;
  final Duration duration;
  final Map<String, dynamic> environment;
  final TestResult testResult;
  final List<StepReport> steps;
  final List<ErrorReport> errors;
  final List<AutoFixReport> autoFixes;
  final Map<String, FeatureReport> features;
  final Map<String, List<ApiCallReport>> apiCalls;
  final String summary;
  
  BasicTestReport({
    required this.reportId,
    required this.testName,
    required this.startTime,
    required this.endTime,
    required this.duration,
    required this.environment,
    required this.testResult,
    required this.steps,
    required this.errors,
    required this.autoFixes,
    required this.features,
    required this.apiCalls,
    required this.summary,
  });
  
  Map<String, dynamic> toJson() => {
    'reportId': reportId,
    'testName': testName,
    'startTime': startTime.toIso8601String(),
    'endTime': endTime.toIso8601String(),
    'duration': duration.inMilliseconds,
    'environment': environment,
    'testResult': testResult.toJson(),
    'steps': steps.map((s) => s.toJson()).toList(),
    'errors': errors.map((e) => e.toJson()).toList(),
    'autoFixes': autoFixes.map((f) => f.toJson()).toList(),
    'features': features.map((k, v) => MapEntry(k, v.toJson())),
    'apiCalls': apiCalls.map((k, v) => MapEntry(k, v.map((c) => c.toJson()).toList())),
    'summary': summary,
  };
}