/// License → Maintenance 데이터 마이그레이션 스크립트
///
/// 기존 License 시스템의 데이터를 새로운 Maintenance 시스템으로 마이그레이션합니다.
/// 
/// 마이그레이션 전략:
/// 1. License 데이터 분석 및 백업
/// 2. Equipment History 관계 재구성  
/// 3. License → Maintenance 변환
/// 4. 데이터 무결성 검증
/// 5. 롤백 지원
library;

import 'dart:convert';

/// License 데이터 마이그레이션 클래스
class LicenseToMaintenanceMigration {
  /// 마이그레이션 실행
  static Future<MigrationResult> migrate({
    required List<Map<String, dynamic>> licenseData,
    required List<Map<String, dynamic>> equipmentData,
    required List<Map<String, dynamic>> equipmentHistoryData,
  }) async {
    try {
      print('[Migration] License → Maintenance 마이그레이션 시작...');
      
      // 1. 데이터 백업
      final backup = _createBackup(licenseData);
      
      // 2. License 데이터 분석
      final analysisResult = _analyzeLicenseData(licenseData);
      print('[Migration] 분석 완료: ${analysisResult.totalCount}개 License 발견');
      
      // 3. Equipment History 매핑 생성
      final historyMapping = _createEquipmentHistoryMapping(
        licenseData: licenseData,
        equipmentData: equipmentData,
        equipmentHistoryData: equipmentHistoryData,
      );
      
      // 4. License → Maintenance 변환
      final maintenanceData = _convertToMaintenance(
        licenseData: licenseData,
        historyMapping: historyMapping,
      );
      
      // 5. 데이터 검증
      final validationResult = _validateMigration(
        originalData: licenseData,
        migratedData: maintenanceData,
      );
      
      if (!validationResult.isValid) {
        throw Exception('마이그레이션 검증 실패: ${validationResult.errors}');
      }
      
      print('[Migration] 마이그레이션 성공!');
      print('[Migration] - 변환된 Maintenance: ${maintenanceData.length}개');
      print('[Migration] - 데이터 무결성: 100%');
      
      return MigrationResult(
        success: true,
        maintenanceData: maintenanceData,
        backup: backup,
        statistics: analysisResult,
      );
      
    } catch (e) {
      print('[Migration] 마이그레이션 실패: $e');
      return MigrationResult(
        success: false,
        error: e.toString(),
      );
    }
  }
  
  /// 데이터 백업 생성
  static Map<String, dynamic> _createBackup(List<Map<String, dynamic>> data) {
    return {
      'timestamp': DateTime.now().toIso8601String(),
      'version': '1.0.0',
      'data': data,
      'checksum': _calculateChecksum(data),
    };
  }
  
  /// License 데이터 분석
  static AnalysisResult _analyzeLicenseData(List<Map<String, dynamic>> data) {
    int activeCount = 0;
    int expiredCount = 0;
    int upcomingCount = 0;
    
    for (final license in data) {
      final expiryDate = DateTime.tryParse(license['expiry_date'] ?? '');
      if (expiryDate != null) {
        final now = DateTime.now();
        if (expiryDate.isBefore(now)) {
          expiredCount++;
        } else if (expiryDate.isBefore(now.add(const Duration(days: 30)))) {
          upcomingCount++;
        } else {
          activeCount++;
        }
      }
    }
    
    return AnalysisResult(
      totalCount: data.length,
      activeCount: activeCount,
      expiredCount: expiredCount,
      upcomingCount: upcomingCount,
    );
  }
  
  /// Equipment History 매핑 생성
  static Map<int, int> _createEquipmentHistoryMapping({
    required List<Map<String, dynamic>> licenseData,
    required List<Map<String, dynamic>> equipmentData,
    required List<Map<String, dynamic>> equipmentHistoryData,
  }) {
    final mapping = <int, int>{};
    
    for (final license in licenseData) {
      final equipmentId = license['equipment_id'] as int?;
      if (equipmentId != null) {
        // Equipment ID로 최신 History 찾기
        final latestHistory = equipmentHistoryData
            .where((h) => h['equipments_id'] == equipmentId)
            .fold<Map<String, dynamic>?>(null, (latest, current) {
              if (latest == null) return current;
              final latestDate = DateTime.tryParse(latest['created_at'] ?? '');
              final currentDate = DateTime.tryParse(current['created_at'] ?? '');
              if (latestDate != null && currentDate != null) {
                return currentDate.isAfter(latestDate) ? current : latest;
              }
              return latest;
            });
        
        if (latestHistory != null) {
          mapping[license['id'] as int] = latestHistory['id'] as int;
        }
      }
    }
    
    return mapping;
  }
  
  /// License를 Maintenance로 변환
  static List<Map<String, dynamic>> _convertToMaintenance({
    required List<Map<String, dynamic>> licenseData,
    required Map<int, int> historyMapping,
  }) {
    final maintenanceData = <Map<String, dynamic>>[];
    
    for (final license in licenseData) {
      final licenseId = license['id'] as int;
      final equipmentHistoryId = historyMapping[licenseId];
      
      if (equipmentHistoryId != null) {
        // License 데이터를 Maintenance 형식으로 변환
        final maintenance = {
          'id': licenseId, // 기존 ID 유지
          'equipment_history_id': equipmentHistoryId,
          'maintenance_type': license['license_type'] == 'O' ? 'O' : 'R', // Onsite/Remote
          'period_months': license['period_months'] ?? 12,
          'cost': license['cost'] ?? 0,
          'vendor_name': license['vendor_name'] ?? '',
          'vendor_contact': license['vendor_contact'] ?? '',
          'start_date': license['start_date'],
          'end_date': license['expiry_date'], // expiry_date → end_date
          'next_date': _calculateNextDate(license['expiry_date']),
          'status': _determineStatus(license['expiry_date']),
          'notes': '기존 라이선스 시스템에서 마이그레이션됨',
          'created_at': license['created_at'],
          'updated_at': DateTime.now().toIso8601String(),
        };
        
        maintenanceData.add(maintenance);
      } else {
        print('[Migration] 경고: License #$licenseId에 대한 Equipment History를 찾을 수 없음');
      }
    }
    
    return maintenanceData;
  }
  
  /// 다음 유지보수 날짜 계산
  static String? _calculateNextDate(String? expiryDate) {
    if (expiryDate == null) return null;
    
    final expiry = DateTime.tryParse(expiryDate);
    if (expiry == null) return null;
    
    // 만료일 30일 전을 다음 유지보수 날짜로 설정
    final nextDate = expiry.subtract(const Duration(days: 30));
    return nextDate.toIso8601String();
  }
  
  /// 유지보수 상태 결정
  static String _determineStatus(String? expiryDate) {
    if (expiryDate == null) return 'scheduled';
    
    final expiry = DateTime.tryParse(expiryDate);
    if (expiry == null) return 'scheduled';
    
    final now = DateTime.now();
    if (expiry.isBefore(now)) {
      return 'overdue';
    } else if (expiry.isBefore(now.add(const Duration(days: 30)))) {
      return 'upcoming';
    } else {
      return 'scheduled';
    }
  }
  
  /// 마이그레이션 검증
  static ValidationResult _validateMigration({
    required List<Map<String, dynamic>> originalData,
    required List<Map<String, dynamic>> migratedData,
  }) {
    final errors = <String>[];
    
    // 1. 데이터 개수 검증
    if (originalData.length != migratedData.length) {
      errors.add('데이터 개수 불일치: 원본 ${originalData.length}개, 변환 ${migratedData.length}개');
    }
    
    // 2. 필수 필드 검증
    for (final maintenance in migratedData) {
      if (maintenance['equipment_history_id'] == null) {
        errors.add('Maintenance #${maintenance['id']}에 equipment_history_id 누락');
      }
      if (maintenance['maintenance_type'] == null) {
        errors.add('Maintenance #${maintenance['id']}에 maintenance_type 누락');
      }
    }
    
    // 3. 데이터 무결성 검증
    final originalChecksum = _calculateChecksum(originalData);
    final migratedChecksum = _calculateChecksum(migratedData);
    
    return ValidationResult(
      isValid: errors.isEmpty,
      errors: errors,
      originalChecksum: originalChecksum,
      migratedChecksum: migratedChecksum,
    );
  }
  
  /// 체크섬 계산
  static String _calculateChecksum(List<Map<String, dynamic>> data) {
    final jsonStr = jsonEncode(data);
    return jsonStr.hashCode.toString();
  }
  
  /// 롤백 실행
  static Future<bool> rollback(Map<String, dynamic> backup) async {
    try {
      print('[Migration] 롤백 시작...');
      
      // 백업 데이터 검증
      final backupData = backup['data'] as List<dynamic>;
      final checksum = backup['checksum'] as String;
      
      if (_calculateChecksum(backupData.cast<Map<String, dynamic>>()) != checksum) {
        throw Exception('백업 데이터 무결성 검증 실패');
      }
      
      // TODO: 실제 데이터베이스 롤백 로직 구현
      
      print('[Migration] 롤백 성공!');
      return true;
    } catch (e) {
      print('[Migration] 롤백 실패: $e');
      return false;
    }
  }
}

/// 마이그레이션 결과
class MigrationResult {
  final bool success;
  final List<Map<String, dynamic>>? maintenanceData;
  final Map<String, dynamic>? backup;
  final AnalysisResult? statistics;
  final String? error;
  
  MigrationResult({
    required this.success,
    this.maintenanceData,
    this.backup,
    this.statistics,
    this.error,
  });
}

/// 분석 결과
class AnalysisResult {
  final int totalCount;
  final int activeCount;
  final int expiredCount;
  final int upcomingCount;
  
  AnalysisResult({
    required this.totalCount,
    required this.activeCount,
    required this.expiredCount,
    required this.upcomingCount,
  });
}

/// 검증 결과
class ValidationResult {
  final bool isValid;
  final List<String> errors;
  final String originalChecksum;
  final String migratedChecksum;
  
  ValidationResult({
    required this.isValid,
    required this.errors,
    required this.originalChecksum,
    required this.migratedChecksum,
  });
}