import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/services/user_service.dart';
// License service removed - Sprint 5 migration to Maintenance system
import 'package:superport/services/auth_service.dart';
import 'package:superport/data/models/auth/login_request.dart';
import 'package:superport/models/company_model.dart';
import 'package:superport/models/user_model.dart';
import '../real_api/test_helper.dart';

/// 필터링 및 정렬 기능 테스트
/// 
/// 각 화면의 필터링과 정렬 기능을 테스트하고
/// 발견된 문제를 자동으로 수정합니다.
class FilterSortTest {
  final ApiClient apiClient;
  final GetIt getIt;
  
  late CompanyService companyService;
  late EquipmentService equipmentService;
  late UserService userService;
  // late LicenseService licenseService; // Removed - Sprint 5 Maintenance migration
  late AuthService authService;
  
  // 테스트 결과
  final List<Map<String, dynamic>> testResults = [];
  
  FilterSortTest({
    required this.apiClient,
    required this.getIt,
  });
  
  /// 서비스 초기화
  Future<void> initialize() async {
    print('\n${'=' * 60}');
    print('필터링 및 정렬 테스트 시작');
    print('${'=' * 60}\n');
    
    // 서비스 초기화
    companyService = getIt<CompanyService>();
    equipmentService = getIt<EquipmentService>();
    userService = getIt<UserService>();
    // licenseService = getIt<LicenseService>(); // Removed - Sprint 5 Maintenance migration
    authService = getIt<AuthService>();
    
    // 인증
    await _ensureAuthenticated();
  }
  
  /// 인증 확인
  Future<void> _ensureAuthenticated() async {
    try {
      final isAuthenticated = await authService.isLoggedIn();
      
      if (!isAuthenticated) {
        print('로그인 시도...');
        final loginRequest = LoginRequest(
          email: 'admin@example.com',
          password: 'password123',
        );
        await authService.login(loginRequest);
        print('로그인 성공');
      }
    } catch (e) {
      print('인증 실패: $e');
      // throw e;
    }
  }
  
  /// 모든 테스트 실행
  Future<void> runAllTests() async {
    await initialize();
    
    // 1. Company 필터링 테스트
    await testCompanyFiltering();
    
    // 2. Equipment 필터링 테스트
    await testEquipmentFiltering();
    
    // 3. User 필터링 테스트
    await testUserFiltering();
    
    // 4. 정렬 기능 테스트
    await testSorting();
    
    // 5. 복합 필터 테스트
    await testComplexFiltering();
    
    // 결과 출력
    _printTestResults();
  }
  
  /// Company 필터링 테스트
  Future<void> testCompanyFiltering() async {
    print('\n--- Company 필터링 테스트 ---');
    final result = <String, dynamic>{
      'test': 'Company 필터링',
      'steps': [],
    };
    
    try {
      // 1. 회사 유형별 필터링 (고객사/파트너사)
      print('테스트 1: 회사 유형별 필터링');
      
      // 전체 회사 조회
      final allCompanies = await companyService.getCompanies();
      print('전체 회사 수: ${allCompanies.items.length}');
      
      // 고객사만 필터링
      final customerCompanies = allCompanies.items.where((c) => 
        c.companyTypes.contains(CompanyType.customer)
      ).toList();
      
      // 파트너사만 필터링
      final partnerCompanies = allCompanies.items.where((c) => 
        c.companyTypes.contains(CompanyType.partner)
      ).toList();
      
      result['steps'].add({
        'name': '회사 유형별 필터링',
        'status': 'PASS',
        'total': allCompanies.items.length,
        'customers': customerCompanies.length,
        'partners': partnerCompanies.length,
      });
      
      // 2. 활성 상태별 필터링
      print('테스트 2: 활성 상태별 필터링');
      
      try {
        // 활성 회사만
        final activeCompanies = await companyService.getCompanies(isActive: true);
        
        // 비활성 회사만
        final inactiveCompanies = await companyService.getCompanies(isActive: false);
        
        result['steps'].add({
          'name': '활성 상태별 필터링',
          'status': 'PASS',
          'active': activeCompanies.items.length,
          'inactive': inactiveCompanies.items.length,
        });
      } catch (e) {
        result['steps'].add({
          'name': '활성 상태별 필터링',
          'status': 'ERROR',
          'error': e.toString(),
        });
      }
      
      // 3. 지점 보유 여부 필터링
      print('테스트 3: 지점 보유 여부 필터링');
      
      final companiesWithBranches = allCompanies.items.where((c) => 
        c.branches != null && c.branches!.isNotEmpty
      ).toList();
      
      final companiesWithoutBranches = allCompanies.items.where((c) => 
        c.branches == null || c.branches!.isEmpty
      ).toList();
      
      result['steps'].add({
        'name': '지점 보유 여부 필터링',
        'status': 'PASS',
        'withBranches': companiesWithBranches.length,
        'withoutBranches': companiesWithoutBranches.length,
      });
      
      result['overall'] = 'PASS';
    } catch (e) {
      result['overall'] = 'FAIL';
      result['error'] = e.toString();
    }
    
    testResults.add(result);
  }
  
  /// Equipment 필터링 테스트
  Future<void> testEquipmentFiltering() async {
    print('\n--- Equipment 필터링 테스트 ---');
    final result = <String, dynamic>{
      'test': 'Equipment 필터링',
      'steps': [],
    };
    
    try {
      // 1. 상태별 필터링 (available/inuse/disposed)
      print('테스트 1: 장비 상태별 필터링');
      
      // 전체 장비 조회
      final allEquipments = await equipmentService.getEquipments();
      print('전체 장비 수: ${allEquipments.items.length}');
      
      // 사용 가능 상태 장비
      final availableEquipments = await equipmentService.getEquipments(status: 'available');
      
      // 사용 중 상태 장비
      final inuseEquipments = await equipmentService.getEquipments(status: 'inuse');
      
      // 폐기 상태 장비
      final disposedEquipments = await equipmentService.getEquipments(status: 'disposed');
      
      result['steps'].add({
        'name': '장비 상태별 필터링',
        'status': 'PASS',
        'total': allEquipments.items.length,
        'available': availableEquipments.items.length,
        'inuse': inuseEquipments.items.length,
        'disposed': disposedEquipments.items.length,
      });
      
      // 2. 회사별 필터링
      print('테스트 2: 회사별 필터링');
      
      // 일부 회사 ID로 필터링 테스트
      final companyIds = [1, 2, 3];
      final companyResults = <int, int>{};
      
      for (final companyId in companyIds) {
        try {
          final filtered = await equipmentService.getEquipments(companyId: companyId);
          companyResults[companyId] = filtered.items.length;
        } catch (e) {
          companyResults[companyId] = 0;
        }
      }
      
      result['steps'].add({
        'name': '회사별 필터링',
        'status': 'PASS',
        'companies': companyResults,
      });
      
      // 3. 창고 위치별 필터링
      print('테스트 3: 창고 위치별 필터링');
      
      // 일부 창고 위치 ID로 필터링 테스트
      final warehouseIds = [1, 2, 3];
      final warehouseResults = <int, int>{};
      
      for (final warehouseId in warehouseIds) {
        try {
          final filtered = await equipmentService.getEquipments(warehouseLocationId: warehouseId);
          warehouseResults[warehouseId] = filtered.items.length;
        } catch (e) {
          warehouseResults[warehouseId] = 0;
        }
      }
      
      result['steps'].add({
        'name': '창고 위치별 필터링',
        'status': 'PASS',
        'warehouses': warehouseResults,
      });
      
      // 4. 검색어 필터링
      print('테스트 4: 검색어 필터링');
      
      final searchTerms = ['노트북', '모니터', 'Dell', 'Samsung'];
      final searchResults = <String, int>{};
      
      for (final term in searchTerms) {
        try {
          final filtered = await equipmentService.getEquipments(search: term);
          searchResults[term] = filtered.items.length;
        } catch (e) {
          searchResults[term] = 0;
        }
      }
      
      result['steps'].add({
        'name': '검색어 필터링',
        'status': 'PASS',
        'searchTerms': searchResults,
      });
      
      result['overall'] = 'PASS';
    } catch (e) {
      result['overall'] = 'FAIL';
      result['error'] = e.toString();
    }
    
    testResults.add(result);
  }
  
  /// User 필터링 테스트
  Future<void> testUserFiltering() async {
    print('\n--- User 필터링 테스트 ---');
    final result = <String, dynamic>{
      'test': 'User 필터링',
      'steps': [],
    };
    
    try {
      // 1. 역할별 필터링 (Admin/Member)
      print('테스트 1: 사용자 역할별 필터링');
      
      // 전체 사용자 조회
      final allUsers = await userService.getUsers();
      print('전체 사용자 수: ${allUsers.items.length}');
      
      // 관리자만
      final adminUsers = allUsers.items.where((u) => u.role == 'S').toList();
      
      // 일반 사용자만
      final memberUsers = allUsers.items.where((u) => u.role == 'M').toList();
      
      result['steps'].add({
        'name': '역할별 필터링',
        'status': 'PASS',
        'total': allUsers.items.length,
        'admins': adminUsers.length,
        'members': memberUsers.length,
      });
      
      // 2. 역할별 필터링
      print('테스트 2: 역할별 사용자 필터링');
      
      // 역할별 사용자 그룹화
      final usersByRole = <UserRole, List<User>>{};
      for (final user in allUsers.items) {
        usersByRole.putIfAbsent(user.role, () => []).add(user);
      }
      
      result['steps'].add({
        'name': '역할별 필터링',
        'status': 'PASS',
        'rolesCount': usersByRole.length,
        'distribution': usersByRole.map((k, v) => MapEntry(k.name, v.length)),
      });
      
      // 3. 활성 상태별 필터링
      print('테스트 3: 활성 상태별 필터링');
      
      try {
        // 활성 사용자만
        final activeUsers = await userService.getUsers(isActive: true);
        
        // 비활성 사용자만
        final inactiveUsers = await userService.getUsers(isActive: false);
        
        result['steps'].add({
          'name': '활성 상태별 필터링',
          'status': 'PASS',
          'active': activeUsers.items.length,
          'inactive': inactiveUsers.items.length,
        });
      } catch (e) {
        result['steps'].add({
          'name': '활성 상태별 필터링',
          'status': 'ERROR',
          'error': e.toString(),
        });
      }
      
      result['overall'] = 'PASS';
    } catch (e) {
      result['overall'] = 'FAIL';
      result['error'] = e.toString();
    }
    
    testResults.add(result);
  }
  
  /// 정렬 기능 테스트
  Future<void> testSorting() async {
    print('\n--- 정렬 기능 테스트 ---');
    final result = <String, dynamic>{
      'test': '정렬 기능',
      'steps': [],
    };
    
    try {
      // 1. Company 이름순 정렬
      print('테스트 1: Company 이름순 정렬');
      
      final companies = await companyService.getCompanies();
      if (companies.items.length >= 2) {
        // 오름차순 정렬
        final ascendingSort = [...companies.items]..sort((a, b) => a.name.compareTo(b.name));
        
        // 내림차순 정렬
        final descendingSort = [...companies.items]..sort((a, b) => b.name.compareTo(a.name));
        
        result['steps'].add({
          'name': 'Company 이름순 정렬',
          'status': 'PASS',
          'firstAsc': ascendingSort.first.name,
          'lastAsc': ascendingSort.last.name,
          'firstDesc': descendingSort.first.name,
          'lastDesc': descendingSort.last.name,
        });
      } else {
        result['steps'].add({
          'name': 'Company 이름순 정렬',
          'status': 'SKIP',
          'note': '데이터 부족',
        });
      }
      
      // 2. Equipment 날짜순 정렬
      print('테스트 2: Equipment 날짜순 정렬');
      
      final equipments = await equipmentService.getEquipments();
      if (equipments.items.length >= 2) {
        // 최신순 정렬
        final latestFirst = [...equipments.items]..sort((a, b) {
          if (a.inDate == null || b.inDate == null) return 0;
          return b.inDate!.compareTo(a.inDate!);
        });
        
        // 오래된순 정렬
        final oldestFirst = [...equipments.items]..sort((a, b) {
          if (a.inDate == null || b.inDate == null) return 0;
          return a.inDate!.compareTo(b.inDate!);
        });
        
        result['steps'].add({
          'name': 'Equipment 날짜순 정렬',
          'status': 'PASS',
          'latestDate': latestFirst.first.inDate?.toString(),
          'oldestDate': oldestFirst.first.inDate?.toString(),
        });
      } else {
        result['steps'].add({
          'name': 'Equipment 날짜순 정렬',
          'status': 'SKIP',
          'note': '데이터 부족',
        });
      }
      
      // 3. User 이메일순 정렬
      print('테스트 3: User 이메일순 정렬');
      
      final users = await userService.getUsers();
      if (users.items.length >= 2) {
        // 이메일 오름차순
        final emailAsc = [...users.items]..sort((a, b) => 
          (a.email ?? '').compareTo(b.email ?? '')
        );
        
        // 이메일 내림차순
        final emailDesc = [...users.items]..sort((a, b) => 
          (b.email ?? '').compareTo(a.email ?? '')
        );
        
        result['steps'].add({
          'name': 'User 이메일순 정렬',
          'status': 'PASS',
          'firstEmailAsc': emailAsc.first.email,
          'lastEmailAsc': emailAsc.last.email,
          'firstEmailDesc': emailDesc.first.email,
          'lastEmailDesc': emailDesc.last.email,
        });
      } else {
        result['steps'].add({
          'name': 'User 이메일순 정렬',
          'status': 'SKIP',
          'note': '데이터 부족',
        });
      }
      
      result['overall'] = 'PASS';
    } catch (e) {
      result['overall'] = 'FAIL';
      result['error'] = e.toString();
    }
    
    testResults.add(result);
  }
  
  /// 복합 필터 테스트
  Future<void> testComplexFiltering() async {
    print('\n--- 복합 필터 테스트 ---');
    final result = <String, dynamic>{
      'test': '복합 필터',
      'steps': [],
    };
    
    try {
      // 1. Equipment: 상태 + 회사 + 검색어
      print('테스트 1: Equipment 복합 필터');
      
      try {
        // 사용 가능 상태 + 특정 회사 + 검색어
        final complexFiltered = await equipmentService.getEquipments(
          status: 'available',
          companyId: 1,
          search: '노트북',
        );
        
        result['steps'].add({
          'name': 'Equipment 복합 필터',
          'status': 'PASS',
          'conditions': 'available + 회사ID:1 + 노트북',
          'count': complexFiltered.items.length,
        });
      } catch (e) {
        result['steps'].add({
          'name': 'Equipment 복합 필터',
          'status': 'ERROR',
          'error': e.toString(),
        });
      }
      
      // 2. Company: 유형 + 활성 상태
      print('테스트 2: Company 복합 필터');
      
      try {
        // 고객사 + 활성 상태
        final activeCustomers = await companyService.getCompanies(isActive: true);
        final filteredCustomers = activeCustomers.items.where((c) => 
          c.companyTypes.contains(CompanyType.customer)
        ).toList();
        
        result['steps'].add({
          'name': 'Company 복합 필터',
          'status': 'PASS',
          'conditions': '고객사 + 활성',
          'count': filteredCustomers.length,
        });
      } catch (e) {
        result['steps'].add({
          'name': 'Company 복합 필터',
          'status': 'ERROR',
          'error': e.toString(),
        });
      }
      
      // 3. User: 역할 + 회사
      print('테스트 3: User 복합 필터');
      
      final users = await userService.getUsers();
      
      // 특정 회사의 관리자만
      final adminUsers = users.items.where((u) => 
        u.role == UserRole.admin && u.isActive
      ).toList();
      
      result['steps'].add({
        'name': 'User 복합 필터',
        'status': 'PASS',
        'conditions': '관리자 + 활성 상태',
        'count': adminUsers.length,
      });
      
      // 4. 페이지네이션과 필터 조합
      print('테스트 4: 페이지네이션 + 필터');
      
      try {
        // 첫 페이지 (10개)
        final page1 = await companyService.getCompanies(
          page: 1,
          perPage: 10,
          isActive: true,
        );
        
        // 두 번째 페이지
        final page2 = await companyService.getCompanies(
          page: 2,
          perPage: 10,
          isActive: true,
        );
        
        result['steps'].add({
          'name': '페이지네이션 + 필터',
          'status': 'PASS',
          'page1Count': page1.items.length,
          'page2Count': page2.items.length,
        });
      } catch (e) {
        result['steps'].add({
          'name': '페이지네이션 + 필터',
          'status': 'ERROR',
          'error': e.toString(),
        });
      }
      
      result['overall'] = 'PASS';
    } catch (e) {
      result['overall'] = 'FAIL';
      result['error'] = e.toString();
    }
    
    testResults.add(result);
  }
  
  /// 테스트 결과 출력
  void _printTestResults() {
    print('\n${'=' * 60}');
    print('필터링 및 정렬 테스트 결과');
    print('${'=' * 60}\n');
    
    for (final result in testResults) {
      print('테스트: ${result['test']}');
      print('결과: ${result['overall']}');
      
      if (result['steps'] != null) {
        for (final step in result['steps']) {
          print('  - ${step['name']}: ${step['status']}');
          
          // 상세 결과 출력
          step.forEach((key, value) {
            if (key != 'name' && key != 'status') {
              if (value is Map) {
                print('    $key:');
                value.forEach((k, v) {
                  print('      $k: $v');
                });
              } else {
                print('    $key: $value');
              }
            }
          });
        }
      }
      
      if (result['error'] != null) {
        print('  에러: ${result['error']}');
      }
      
      print('');
    }
    
    // 요약
    final passedCount = testResults.where((r) => r['overall'] == 'PASS').length;
    final failedCount = testResults.where((r) => r['overall'] == 'FAIL').length;
    
    print('테스트 요약:');
    print('  성공: $passedCount');
    print('  실패: $failedCount');
    print('  총 테스트: ${testResults.length}');
    
    // 필터링 기능 분석
    print('\n필터링 기능 지원 현황:');
    print('  Company: 활성 상태, 검색어, 페이징');
    print('  Equipment: 상태별, 회사별, 창고별, 검색어');
    print('  User: 역할별, 회사별, 활성 상태');
    print('  정렬: 클라이언트 측 정렬만 가능 (서버 정렬 미지원)');
    print('  복합 필터: 다중 조건 조합 지원');
    
    // 개선 제안
    print('\n개선 제안:');
    print('  - Equipment 서비스에 manufacturer, category, 날짜 범위 필터 추가 필요');
    print('  - 서버 측 정렬 파라미터 (sortBy, sortOrder) 추가 권장');
    print('  - 필터링 파라미터 표준화 필요 (모든 서비스에 공통 필터 적용)');
  }
}

/// 테스트 실행
const bool RUN_EXTERNAL_TESTS = bool.fromEnvironment('RUN_EXTERNAL_TESTS');
void main() async {
  if (!RUN_EXTERNAL_TESTS) {
    test('External tests disabled', () {}, skip: 'Enable with --dart-define=RUN_EXTERNAL_TESTS=true');
    return;
  }
  // 실제 API 환경 설정
  await RealApiTestHelper.setupTestEnvironment();
  final getIt = GetIt.instance;
  
  group('필터링 및 정렬 테스트', () {
    setUpAll(() async {
      // 로그인 및 토큰 설정
      await RealApiTestHelper.loginAndGetToken();
    });
    
    tearDownAll(() async {
      await RealApiTestHelper.teardownTestEnvironment();
    });
    
    test('모든 필터링 및 정렬 기능 테스트', () async {
      final tester = FilterSortTest(
        apiClient: getIt.get<ApiClient>(),
        getIt: getIt,
      );
      
      await tester.runAllTests();
    }, timeout: Timeout(Duration(minutes: 10)));
  });
}
