/// Maintenance 데이터 검증 스크립트
///
/// License → Maintenance 마이그레이션 후 데이터 무결성을 검증합니다.
library;


/// Maintenance 데이터 검증 클래스
class MaintenanceDataValidator {
  /// 전체 검증 실행
  static Future<ValidationReport> validate({
    required List<Map<String, dynamic>> maintenanceData,
    required List<Map<String, dynamic>> equipmentHistoryData,
    Map<String, dynamic>? originalLicenseData,
  }) async {
    print('[Validator] Maintenance 데이터 검증 시작...');
    
    final report = ValidationReport();
    
    // 1. 필수 필드 검증
    _validateRequiredFields(maintenanceData, report);
    
    // 2. 데이터 타입 검증
    _validateDataTypes(maintenanceData, report);
    
    // 3. 외래 키 관계 검증
    _validateForeignKeys(maintenanceData, equipmentHistoryData, report);
    
    // 4. 비즈니스 규칙 검증
    _validateBusinessRules(maintenanceData, report);
    
    // 5. 날짜 일관성 검증
    _validateDateConsistency(maintenanceData, report);
    
    // 6. 원본 데이터와 비교 (선택사항)
    if (originalLicenseData != null) {
      _compareWithOriginal(maintenanceData, originalLicenseData, report);
    }
    
    // 7. 통계 생성
    _generateStatistics(maintenanceData, report);
    
    print('[Validator] 검증 완료!');
    print('[Validator] - 총 레코드: ${report.totalRecords}개');
    print('[Validator] - 오류: ${report.errors.length}개');
    print('[Validator] - 경고: ${report.warnings.length}개');
    
    return report;
  }
  
  /// 필수 필드 검증
  static void _validateRequiredFields(
    List<Map<String, dynamic>> data,
    ValidationReport report,
  ) {
    report.totalRecords = data.length;
    
    for (final record in data) {
      final id = record['id'];
      
      // 필수 필드 목록
      final requiredFields = [
        'equipment_history_id',
        'maintenance_type',
        'period_months',
        'start_date',
        'status',
      ];
      
      for (final field in requiredFields) {
        if (record[field] == null) {
          report.addError(
            'Record #$id: 필수 필드 \'$field\'가 누락되었습니다.',
          );
        }
      }
    }
  }
  
  /// 데이터 타입 검증
  static void _validateDataTypes(
    List<Map<String, dynamic>> data,
    ValidationReport report,
  ) {
    for (final record in data) {
      final id = record['id'];
      
      // ID 필드 검증
      if (record['id'] != null && record['id'] is! int) {
        report.addError('Record #$id: id는 정수여야 합니다.');
      }
      
      if (record['equipment_history_id'] != null && 
          record['equipment_history_id'] is! int) {
        report.addError('Record #$id: equipment_history_id는 정수여야 합니다.');
      }
      
      // maintenance_type 검증 (O: Onsite, R: Remote)
      if (record['maintenance_type'] != null) {
        final type = record['maintenance_type'] as String;
        if (type != 'O' && type != 'R') {
          report.addError(
            'Record #$id: maintenance_type은 \'O\' 또는 \'R\'이어야 합니다. (현재: $type)',
          );
        }
      }
      
      // period_months 검증
      if (record['period_months'] != null) {
        final period = record['period_months'];
        if (period is! int || period <= 0) {
          report.addError(
            'Record #$id: period_months는 양의 정수여야 합니다. (현재: $period)',
          );
        }
      }
      
      // cost 검증
      if (record['cost'] != null) {
        final cost = record['cost'];
        if ((cost is! int && cost is! double) || cost < 0) {
          report.addError(
            'Record #$id: cost는 0 이상의 숫자여야 합니다. (현재: $cost)',
          );
        }
      }
      
      // status 검증
      if (record['status'] != null) {
        final validStatuses = [
          'upcoming',
          'ongoing', 
          'overdue',
          'completed',
          'scheduled',
          'inProgress',
        ];
        final status = record['status'] as String;
        if (!validStatuses.contains(status)) {
          report.addWarning(
            'Record #$id: 알 수 없는 status: $status',
          );
        }
      }
    }
  }
  
  /// 외래 키 관계 검증
  static void _validateForeignKeys(
    List<Map<String, dynamic>> maintenanceData,
    List<Map<String, dynamic>> equipmentHistoryData,
    ValidationReport report,
  ) {
    final historyIds = equipmentHistoryData
        .map((h) => h['id'] as int?)
        .where((id) => id != null)
        .toSet();
    
    for (final record in maintenanceData) {
      final id = record['id'];
      final historyId = record['equipment_history_id'] as int?;
      
      if (historyId != null && !historyIds.contains(historyId)) {
        report.addError(
          'Record #$id: equipment_history_id #$historyId가 존재하지 않습니다.',
        );
        report.foreignKeyIntegrity = false; // FK 무결성 실패
      }
    }
  }
  
  /// 비즈니스 규칙 검증
  static void _validateBusinessRules(
    List<Map<String, dynamic>> data,
    ValidationReport report,
  ) {
    for (final record in data) {
      final id = record['id'];
      
      // 1. 유지보수 기간 검증 (1-60개월)
      final period = record['period_months'] as int?;
      if (period != null) {
        if (period < 1 || period > 60) {
          report.addWarning(
            'Record #$id: 비정상적인 유지보수 기간: $period개월',
          );
          report.businessRulesValid = false; // 비즈니스 규칙 위반
        }
      }
      
      // 2. 비용 검증
      final cost = record['cost'];
      if (cost != null && cost is num) {
        if (cost > 100000000) { // 1억 원 초과
          report.addWarning(
            'Record #$id: 비정상적으로 높은 비용: $cost',
          );
          report.businessRulesValid = false; // 비즈니스 규칙 위반
        }
      }
      
      // 3. 벤더 정보 일관성
      final vendorName = record['vendor_name'] as String?;
      final vendorContact = record['vendor_contact'] as String?;
      if (vendorName != null && vendorName.isNotEmpty) {
        if (vendorContact == null || vendorContact.isEmpty) {
          report.addWarning(
            'Record #$id: 벤더명은 있지만 연락처가 없습니다.',
          );
        }
      }
    }
  }
  
  /// 날짜 일관성 검증
  static void _validateDateConsistency(
    List<Map<String, dynamic>> data,
    ValidationReport report,
  ) {
    for (final record in data) {
      final id = record['id'];
      
      // 날짜 파싱
      final startDate = _parseDate(record['start_date']);
      final endDate = _parseDate(record['end_date']);
      final nextDate = _parseDate(record['next_date']);
      
      // 시작일과 종료일 검증
      if (startDate != null && endDate != null) {
        if (endDate.isBefore(startDate)) {
          report.addError(
            'Record #$id: 종료일이 시작일보다 이전입니다.',
          );
        }
        
        // 기간 검증
        final period = record['period_months'] as int?;
        if (period != null) {
          final expectedEnd = DateTime(
            startDate.year,
            startDate.month + period,
            startDate.day,
          );
          
          // 1개월 이상 차이나면 경고
          final diff = endDate.difference(expectedEnd).inDays.abs();
          if (diff > 30) {
            report.addWarning(
              'Record #$id: 종료일이 예상 날짜와 $diff일 차이납니다.',
            );
          }
        }
      }
      
      // 다음 유지보수 날짜 검증
      if (nextDate != null && endDate != null) {
        if (nextDate.isAfter(endDate)) {
          report.addWarning(
            'Record #$id: 다음 유지보수 날짜가 종료일 이후입니다.',
          );
        }
      }
      
      // 상태와 날짜 일관성
      final status = record['status'] as String?;
      if (status != null && endDate != null) {
        final now = DateTime.now();
        
        if (status == 'overdue' && endDate.isAfter(now)) {
          report.addWarning(
            'Record #$id: 상태는 overdue지만 아직 만료되지 않았습니다.',
          );
        }
        
        if (status == 'upcoming' && endDate.isBefore(now)) {
          report.addWarning(
            'Record #$id: 상태는 upcoming이지만 이미 만료되었습니다.',
          );
        }
      }
    }
  }
  
  /// 원본 데이터와 비교
  static void _compareWithOriginal(
    List<Map<String, dynamic>> maintenanceData,
    Map<String, dynamic> originalData,
    ValidationReport report,
  ) {
    final originalList = originalData['data'] as List<dynamic>?;
    if (originalList == null) return;
    
    // 데이터 개수 비교
    if (maintenanceData.length != originalList.length) {
      report.addWarning(
        '데이터 개수 불일치: 원본 ${originalList.length}개, 변환 ${maintenanceData.length}개',
      );
    }
    
    // ID 매핑 확인
    final maintenanceIds = maintenanceData.map((m) => m['id']).toSet();
    final originalIds = originalList.map((l) => l['id']).toSet();
    
    final missingIds = originalIds.difference(maintenanceIds);
    if (missingIds.isNotEmpty) {
      report.addError(
        '누락된 레코드 ID: ${missingIds.join(', ')}',
      );
    }
    
    final extraIds = maintenanceIds.difference(originalIds);
    if (extraIds.isNotEmpty) {
      report.addWarning(
        '추가된 레코드 ID: ${extraIds.join(', ')}',
      );
    }
  }
  
  /// 통계 생성
  static void _generateStatistics(
    List<Map<String, dynamic>> data,
    ValidationReport report,
  ) {
    // 상태별 통계
    final statusCount = <String, int>{};
    for (final record in data) {
      final status = record['status'] as String? ?? 'unknown';
      statusCount[status] = (statusCount[status] ?? 0) + 1;
    }
    report.statistics['statusCount'] = statusCount;
    
    // 유형별 통계
    final typeCount = <String, int>{};
    for (final record in data) {
      final type = record['maintenance_type'] as String? ?? 'unknown';
      typeCount[type] = (typeCount[type] ?? 0) + 1;
    }
    report.statistics['typeCount'] = typeCount;
    
    // 비용 통계
    double totalCost = 0;
    int recordsWithCost = 0;
    for (final record in data) {
      final cost = record['cost'];
      if (cost != null && cost is num) {
        totalCost += cost.toDouble();
        recordsWithCost++;
      }
    }
    report.statistics['totalCost'] = totalCost;
    report.statistics['averageCost'] = 
        recordsWithCost > 0 ? totalCost / recordsWithCost : 0;
    
    // 기간 통계
    int totalPeriod = 0;
    int recordsWithPeriod = 0;
    for (final record in data) {
      final period = record['period_months'] as int?;
      if (period != null) {
        totalPeriod += period;
        recordsWithPeriod++;
      }
    }
    report.statistics['averagePeriod'] = 
        recordsWithPeriod > 0 ? totalPeriod / recordsWithPeriod : 0;
  }
  
  /// 날짜 파싱 헬퍼
  static DateTime? _parseDate(dynamic date) {
    if (date == null) return null;
    if (date is DateTime) return date;
    if (date is String) return DateTime.tryParse(date);
    return null;
  }
}

/// 검증 보고서
class ValidationReport {
  int totalRecords = 0;
  final List<ValidationError> errors = [];
  final List<ValidationWarning> warnings = [];
  final Map<String, dynamic> statistics = {};
  
  // 추가된 필드들
  bool dataIntegrity = true;
  bool foreignKeyIntegrity = true;
  bool businessRulesValid = true;
  
  void addError(String message) {
    errors.add(ValidationError(
      message: message,
      timestamp: DateTime.now(),
    ));
    // 오류가 있으면 무결성 필드들을 false로 설정
    dataIntegrity = false;
  }
  
  void addWarning(String message) {
    warnings.add(ValidationWarning(
      message: message,
      timestamp: DateTime.now(),
    ));
  }
  
  bool get isValid => errors.isEmpty;
  
  String generateSummary() {
    final buffer = StringBuffer();
    
    buffer.writeln('=== Maintenance 데이터 검증 보고서 ===');
    buffer.writeln('생성 시간: ${DateTime.now()}');
    buffer.writeln('');
    buffer.writeln('## 요약');
    buffer.writeln('- 총 레코드: $totalRecords개');
    buffer.writeln('- 오류: ${errors.length}개');
    buffer.writeln('- 경고: ${warnings.length}개');
    buffer.writeln('- 검증 결과: ${isValid ? "통과 ✓" : "실패 ✗"}');
    buffer.writeln('');
    
    if (statistics.isNotEmpty) {
      buffer.writeln('## 통계');
      statistics.forEach((key, value) {
        buffer.writeln('- $key: $value');
      });
      buffer.writeln('');
    }
    
    if (errors.isNotEmpty) {
      buffer.writeln('## 오류 목록');
      for (final error in errors) {
        buffer.writeln('- ${error.message}');
      }
      buffer.writeln('');
    }
    
    if (warnings.isNotEmpty) {
      buffer.writeln('## 경고 목록');
      for (final warning in warnings) {
        buffer.writeln('- ${warning.message}');
      }
      buffer.writeln('');
    }
    
    return buffer.toString();
  }
}

/// 검증 오류
class ValidationError {
  final String message;
  final DateTime timestamp;
  
  ValidationError({
    required this.message,
    required this.timestamp,
  });
}

/// 검증 경고
class ValidationWarning {
  final String message;
  final DateTime timestamp;
  
  ValidationWarning({
    required this.message,
    required this.timestamp,
  });
}