import 'package:injectable/injectable.dart';
import 'package:superport/core/errors/exceptions.dart';
import 'package:superport/core/errors/failures.dart';
import 'package:superport/data/datasources/remote/maintenance_remote_datasource.dart';
import 'package:superport/data/models/maintenance_dto.dart';
import 'package:superport/data/models/maintenance_stats_dto.dart';
import 'package:superport/data/repositories/maintenance_stats_repository.dart';

@LazySingleton(as: MaintenanceStatsRepository)
class MaintenanceStatsRepositoryImpl implements MaintenanceStatsRepository {
  final MaintenanceRemoteDataSource _remoteDataSource;

  MaintenanceStatsRepositoryImpl({
    required MaintenanceRemoteDataSource remoteDataSource,
  }) : _remoteDataSource = remoteDataSource;

  @override
  Future<MaintenanceStatsDto> getMaintenanceStats() async {
    try {
      // 모든 활성 계약 조회 (대용량 데이터를 위해 페이지 크기 증가)
      final allMaintenances = await _getAllActiveMaintenances();
      
      // 통계 계산
      final stats = _calculateStats(allMaintenances);
      
      return stats.copyWith(updatedAt: DateTime.now());
    } on ServerException catch (e) {
      throw ServerFailure(
        message: e.message,
        statusCode: e.statusCode,
      );
    } catch (e) {
      throw ServerFailure(message: '유지보수 통계 조회 중 오류가 발생했습니다');
    }
  }

  @override
  Future<int> getExpiringContractsCount({required int days}) async {
    try {
      final expiringMaintenances = await _remoteDataSource.getExpiringMaintenances(days: days);
      return expiringMaintenances.length;
    } on ServerException catch (e) {
      throw ServerFailure(
        message: e.message,
        statusCode: e.statusCode,
      );
    } catch (e) {
      throw ServerFailure(message: '만료 예정 계약 조회 중 오류가 발생했습니다');
    }
  }

  @override
  Future<Map<String, int>> getContractsByType() async {
    try {
      final allMaintenances = await _getAllActiveMaintenances();
      
      final contractsByType = <String, int>{
        MaintenanceType.visit: 0,
        MaintenanceType.remote: 0,
      };

      for (final maintenance in allMaintenances) {
        final type = maintenance.maintenanceType;
        contractsByType[type] = (contractsByType[type] ?? 0) + 1;
      }

      return contractsByType;
    } on ServerException catch (e) {
      throw ServerFailure(
        message: e.message,
        statusCode: e.statusCode,
      );
    } catch (e) {
      throw ServerFailure(message: '계약 타입별 통계 조회 중 오류가 발생했습니다');
    }
  }

  @override
  Future<int> getExpiredContractsCount() async {
    try {
      // 만료된 계약 조회 (is_expired = true)
      final expiredResponse = await _remoteDataSource.getMaintenances(
        isExpired: true,
        perPage: 1000, // 충분히 큰 값으로 설정
      );
      
      return expiredResponse.totalCount;
    } on ServerException catch (e) {
      throw ServerFailure(
        message: e.message,
        statusCode: e.statusCode,
      );
    } catch (e) {
      throw ServerFailure(message: '만료된 계약 조회 중 오류가 발생했습니다');
    }
  }

  @override
  Future<int> getActiveContractsCount() async {
    try {
      // 활성 계약만 조회 (is_expired = false)
      final activeResponse = await _remoteDataSource.getMaintenances(
        isExpired: false,
        perPage: 1, // 개수만 필요하므로 1개만 조회
      );
      
      return activeResponse.totalCount;
    } on ServerException catch (e) {
      throw ServerFailure(
        message: e.message,
        statusCode: e.statusCode,
      );
    } catch (e) {
      throw ServerFailure(message: '활성 계약 조회 중 오류가 발생했습니다');
    }
  }

  /// 모든 활성 계약을 페이지네이션으로 조회
  Future<List<MaintenanceDto>> _getAllActiveMaintenances() async {
    final allMaintenances = <MaintenanceDto>[];
    int currentPage = 1;
    const int perPage = 100; // 한 번에 많은 데이터 조회로 API 호출 최소화
    
    while (true) {
      final response = await _remoteDataSource.getMaintenances(
        page: currentPage,
        perPage: perPage,
        isExpired: false, // 활성 계약만 조회
      );
      
      allMaintenances.addAll(response.items);
      
      // 마지막 페이지 도달 시 종료
      if (currentPage >= response.totalPages) {
        break;
      }
      
      currentPage++;
    }
    
    return allMaintenances;
  }

  /// 유지보수 데이터를 기반으로 통계 계산
  MaintenanceStatsDto _calculateStats(List<MaintenanceDto> maintenances) {
    final now = DateTime.now();
    
    // 기본 카운터 초기화
    int expiring60Days = 0;
    int expiring30Days = 0;
    int expiring7Days = 0;
    int expiredContracts = 0;
    
    final contractsByType = <String, int>{
      MaintenanceType.visit: 0,
      MaintenanceType.remote: 0,
    };
    
    // 각 유지보수 계약별 통계 계산
    for (final maintenance in maintenances) {
      // 계약 타입별 카운트
      final type = maintenance.maintenanceType;
      contractsByType[type] = (contractsByType[type] ?? 0) + 1;
      
      // 만료 상태 체크
      if (maintenance.isExpired) {
        expiredContracts++;
        continue;
      }
      
      // 만료일까지 남은 일수 계산
      final daysRemaining = maintenance.daysRemaining ?? 0;
      
      if (daysRemaining <= 7) {
        expiring7Days++;
      } else if (daysRemaining <= 30) {
        expiring30Days++;
      } else if (daysRemaining <= 60) {
        expiring60Days++;
      }
    }

    // 총 계약 수 계산
    final totalContracts = maintenances.length + expiredContracts;
    final activeContracts = maintenances.length;
    
    // 위험 수준의 계약들의 매출 위험도 추정 (간단한 계산)
    final totalRevenueAtRisk = (expiring7Days * 500000.0) + 
                               (expiring30Days * 300000.0) + 
                               (expiredContracts * 1000000.0);
    
    // 완료율 계산 (활성 계약 / 전체 계약)
    final completionRate = totalContracts > 0 
        ? (activeContracts / totalContracts) 
        : 1.0;
    
    return MaintenanceStatsDto(
      // 기본 통계
      activeContracts: activeContracts,
      totalContracts: totalContracts,
      
      // 만료 기간별 통계 (사용자 요구사항)
      expiring60Days: expiring60Days,
      expiring30Days: expiring30Days,
      expiring7Days: expiring7Days,
      expiredContracts: expiredContracts,
      
      // 타입별 통계 (V/R 시스템)
      visitContracts: contractsByType[MaintenanceType.visit] ?? 0,
      remoteContracts: contractsByType[MaintenanceType.remote] ?? 0,
      
      // 예정 작업 (방문 계약과 동일하게 처리)
      upcomingVisits: contractsByType[MaintenanceType.visit] ?? 0,
      overdueMaintenances: expiredContracts,
      
      // 추가 메트릭
      totalRevenueAtRisk: totalRevenueAtRisk,
      completionRate: completionRate,
      
      updatedAt: now,
    );
  }
}