import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:superport/data/models/maintenance_stats_dto.dart';
import 'package:superport/data/repositories/maintenance_stats_repository.dart';
import 'package:superport/domain/usecases/get_maintenance_stats_usecase.dart';
import 'package:superport/screens/maintenance/controllers/maintenance_dashboard_controller.dart';

// Mock 클래스 생성
class MockMaintenanceStatsRepository extends Mock implements MaintenanceStatsRepository {}

void main() {
  group('Maintenance Dashboard Integration Tests', () {
    late MockMaintenanceStatsRepository mockRepository;
    late GetMaintenanceStatsUseCase useCase;
    late MaintenanceDashboardController controller;

    setUp(() {
      mockRepository = MockMaintenanceStatsRepository();
      useCase = GetMaintenanceStatsUseCase(repository: mockRepository);
      controller = MaintenanceDashboardController(
        getMaintenanceStatsUseCase: useCase,
      );
    });

    test('should initialize with empty stats', () {
      // Assert
      expect(controller.stats, equals(const MaintenanceStatsDto()));
      expect(controller.isLoading, false);
      expect(controller.errorMessage, null);
    });

    test('should load dashboard stats successfully', () async {
      // Arrange
      const mockStats = MaintenanceStatsDto(
        activeContracts: 10,
        totalContracts: 15,
        expiring60Days: 5,
        expiring30Days: 3,
        expiring7Days: 1,
        expiredContracts: 2,
        warrantyContracts: 8,
        maintenanceContracts: 5,
        inspectionContracts: 2,
        upcomingInspections: 3,
        overdueMaintenances: 1,
        totalRevenueAtRisk: 500000.0,
        completionRate: 0.85,
        updatedAt: null,
      );

      when(mockRepository.getMaintenanceStats())
          .thenAnswer((_) async => mockStats);

      // Act
      await controller.loadDashboardStats();

      // Assert
      expect(controller.stats, equals(mockStats));
      expect(controller.isLoading, false);
      expect(controller.errorMessage, null);
      expect(controller.hasValidData, false); // updatedAt가 null이므로
      
      // 카드 데이터 검증
      final cards = controller.dashboardCards;
      expect(cards.length, 4);
      expect(cards[0].count, 5); // 60일 내
      expect(cards[1].count, 3); // 30일 내
      expect(cards[2].count, 1); // 7일 내
      expect(cards[3].count, 2); // 만료됨
    });

    test('should handle error state properly', () async {
      // Arrange
      when(mockRepository.getMaintenanceStats())
          .thenThrow(Exception('Network error'));

      // Act
      await controller.loadDashboardStats();

      // Assert
      expect(controller.isLoading, false);
      expect(controller.errorMessage, contains('Network error'));
      expect(controller.stats, equals(const MaintenanceStatsDto()));
    });

    test('should calculate risk score correctly', () async {
      // Arrange
      const highRiskStats = MaintenanceStatsDto(
        totalContracts: 10,
        expiring7Days: 3,    // 30% 가중치
        expiring30Days: 2,   // 20% 가중치  
        expiring60Days: 1,   // 10% 가중치
        expiredContracts: 4, // 40% 가중치
      );

      when(mockRepository.getMaintenanceStats())
          .thenAnswer((_) async => highRiskStats);

      // Act
      await controller.loadDashboardStats();

      // Assert
      final riskScore = controller.riskScore;
      expect(riskScore, greaterThan(0.8)); // 높은 위험도
      expect(controller.riskStatus, MaintenanceCardStatus.critical);
    });

    test('should format revenue at risk correctly', () async {
      // Arrange
      const statsWithRevenue = MaintenanceStatsDto(
        totalRevenueAtRisk: 1500000.0, // 150만원
      );

      when(mockRepository.getMaintenanceStats())
          .thenAnswer((_) async => statsWithRevenue);

      // Act
      await controller.loadDashboardStats();

      // Assert
      expect(controller.formattedRevenueAtRisk, '1.5백만원');
    });

    test('should handle refresh correctly', () async {
      // Arrange
      const mockStats = MaintenanceStatsDto(
        activeContracts: 5,
        updatedAt: null,
      );

      when(mockRepository.getMaintenanceStats())
          .thenAnswer((_) async => mockStats);

      // Act
      await controller.refreshDashboardStats();

      // Assert
      expect(controller.isRefreshing, false);
      expect(controller.stats.activeContracts, 5);
      expect(controller.lastUpdated, isNotNull);
    });

    test('should detect when refresh is needed', () {
      // Assert - 초기 상태에서는 새로고침 필요
      expect(controller.needsRefresh, true);
      
      // 업데이트 시뮬레이션
      controller.loadDashboardStats();
      
      // 즉시는 새로고침 불필요 (실제로는 시간이 지나야 true)
      // 이 테스트는 로직의 존재 여부만 확인
      expect(controller.timeSinceLastUpdate, isNotEmpty);
    });

    test('should provide card status correctly', () {
      // 각 카드 상태 테스트
      expect(controller.expiring60DaysCard.title, '60일 내');
      expect(controller.expiring30DaysCard.title, '30일 내');
      expect(controller.expiring7DaysCard.title, '7일 내');
      expect(controller.expiredContractsCard.title, '만료됨');
      
      // 기본 상태에서는 모두 active 상태여야 함
      expect(controller.expiring60DaysCard.status, MaintenanceCardStatus.active);
      expect(controller.expiring30DaysCard.status, MaintenanceCardStatus.active);
      expect(controller.expiring7DaysCard.status, MaintenanceCardStatus.active);
      expect(controller.expiredContractsCard.status, MaintenanceCardStatus.active);
    });
  });

  group('MaintenanceStatsDto Tests', () {
    test('should create dashboard cards correctly', () {
      // Arrange
      const stats = MaintenanceStatsDto(
        expiring60Days: 10,
        expiring30Days: 5,
        expiring7Days: 2,
        expiredContracts: 3,
      );

      // Act
      final cards = stats.dashboardCards;

      // Assert
      expect(cards.length, 4);
      expect(cards[0].count, 10);
      expect(cards[0].status, MaintenanceCardStatus.warning);
      expect(cards[1].count, 5);
      expect(cards[1].status, MaintenanceCardStatus.urgent);
      expect(cards[2].count, 2);
      expect(cards[2].status, MaintenanceCardStatus.critical);
      expect(cards[3].count, 3);
      expect(cards[3].status, MaintenanceCardStatus.expired);
    });

    test('should calculate risk score correctly', () {
      // Arrange
      const lowRiskStats = MaintenanceStatsDto(
        totalContracts: 100,
        expiring60Days: 5,    // 5%
        expiring30Days: 2,    // 2%
        expiring7Days: 0,     // 0%
        expiredContracts: 1,  // 1%
      );

      const highRiskStats = MaintenanceStatsDto(
        totalContracts: 10,
        expiring60Days: 2,    // 20%
        expiring30Days: 3,    // 30%
        expiring7Days: 2,     // 20%
        expiredContracts: 3,  // 30%
      );

      // Act & Assert
      expect(lowRiskStats.riskScore, lessThan(0.3));
      expect(lowRiskStats.riskStatus, MaintenanceCardStatus.active);
      
      expect(highRiskStats.riskScore, greaterThan(0.7));
      expect(highRiskStats.riskStatus, MaintenanceCardStatus.critical);
    });
  });
}