import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:superport/models/equipment_unified_model.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/core/utils/error_handler.dart';
import 'package:superport/core/controllers/base_list_controller.dart';
import 'package:superport/core/utils/equipment_status_converter.dart';
import 'package:superport/data/models/common/pagination_params.dart';
import 'package:superport/core/services/lookups_service.dart';
import 'package:superport/data/models/lookups/lookup_data.dart';
import 'package:superport/utils/constants.dart';
import 'package:superport/data/models/equipment/equipment_dto.dart';
import 'package:superport/domain/usecases/equipment/search_equipment_usecase.dart';
import 'package:superport/services/equipment_history_service.dart';

/// 장비 목록 화면의 상태 및 비즈니스 로직을 담당하는 컨트롤러 (리팩토링 버전)
/// BaseListController를 상속받아 공통 기능을 재사용
class EquipmentListController extends BaseListController<UnifiedEquipment> {
  late final EquipmentService _equipmentService;
  late final LookupsService _lookupsService;
  late final EquipmentHistoryService _historyService;
  
  // 추가 상태 관리
  final Set<String> selectedEquipmentIds = {}; // 'id:status' 형식
  Map<String, dynamic>? cachedDropdownData; // 드롭다운 데이터 캐시
  
  // 필터
  String? _statusFilter;
  String? _categoryFilter;
  int? _companyIdFilter;
  String? _selectedStatusFilter;
  bool _includeInactive = false; // 비활성(Disposed) 포함 여부
  
  // Getters
  List<UnifiedEquipment> get equipments => items;
  String? get statusFilter => _statusFilter;
  String? get categoryFilter => _categoryFilter;
  int? get companyIdFilter => _companyIdFilter;
  String? get selectedStatusFilter => _selectedStatusFilter;
  bool get includeInactive => _includeInactive;
  
  // Setters
  set selectedStatusFilter(String? value) {
    _selectedStatusFilter = value;
    notifyListeners();
  }

  // 비활성 포함 토글
  void toggleIncludeInactive() {
    _includeInactive = !_includeInactive;
    loadData(isRefresh: true);
  }

  EquipmentListController() {
    if (GetIt.instance.isRegistered<EquipmentService>()) {
      _equipmentService = GetIt.instance<EquipmentService>();
    } else {
      throw Exception('EquipmentService not registered in GetIt');
    }
    
    if (GetIt.instance.isRegistered<LookupsService>()) {
      _lookupsService = GetIt.instance<LookupsService>();
    } else {
      throw Exception('LookupsService not registered in GetIt');
    }
    
    _historyService = EquipmentHistoryService();
  }

  @override
  Future<PagedResult<UnifiedEquipment>> fetchData({
    required PaginationParams params,
    Map<String, dynamic>? additionalFilters,
  }) async {
    // API 호출: BaseListController에서 넘겨준 page/perPage를 그대로 전달
    final apiEquipmentDtos = await ErrorHandler.handleApiCall(
      () => _equipmentService.getEquipmentsWithStatus(
        page: params.page,
        perPage: params.perPage,
        status: _statusFilter != null ? 
          EquipmentStatusConverter.clientToServer(_statusFilter) : null,
        search: params.search,
        companyId: _companyIdFilter, // ✅ 활성화: 회사별 필터링 지원
        // includeInactive: _includeInactive, // 비활성화: EquipmentService에서 지원하지 않음
      ),
      onError: (failure) {
        throw failure;
      },
    );
    
    if (apiEquipmentDtos == null) {
      return PagedResult(
        items: [],
        meta: PaginationMeta(
          currentPage: params.page,
          perPage: params.perPage,
          total: 0,
          totalPages: 0,
          hasNext: false,
          hasPrevious: false,
        ),
      );
    }
    
    // DTO를 UnifiedEquipment로 변환
    print('DEBUG [EquipmentListController] Converting ${apiEquipmentDtos.items.length} DTOs to UnifiedEquipment');
    final items = await Future.wait(apiEquipmentDtos.items.map((dto) async {
      // 🔧 [DEBUG] JOIN된 데이터 로깅
      print('DEBUG [EquipmentListController] DTO ID: ${dto.id}, companyName: "${dto.companyName}", warehousesName: "${dto.warehousesName}", warehousesId: ${dto.warehousesId}');
      final equipment = Equipment(
        id: dto.id,
        modelsId: dto.modelsId, // Sprint 3: Model FK 사용
        model: null, // Equipment 생성자에서 ModelDto? 요구, 현재 DTO는 modelName(String) 제공
        equipmentNumber: dto.serialNumber ?? 'Unknown', // 장비번호 (required)
        serialNumber: dto.serialNumber ?? 'Unknown', // 시리얼번호 (required)
        quantity: 1, // 기본 수량
        // ⚡ [FIX] 누락된 구매 정보 필드들 추가
        purchasePrice: dto.purchasePrice.toDouble(), // int → double 변환
        purchaseDate: dto.purchasedAt, // 구매일
        barcode: dto.barcode, // 바코드
        remark: dto.remark, // 비고
        // 보증 정보
        warrantyLicense: dto.warrantyNumber,
        warrantyStartDate: dto.warrantyStartedAt,
        warrantyEndDate: dto.warrantyEndedAt,
      );
      
      // 간단한 Company 정보 생성 (사용하지 않으므로 제거)
      // final company = dto.companyName != null ? ... : null;
      
      // 각 장비의 최신 히스토리를 조회해서 실제 상태 가져오기
      String status = 'I'; // 기본값: 입고 (I)
      DateTime transactionDate = dto.registeredAt ?? DateTime.now();
      
      try {
        final histories = await _historyService.getEquipmentHistoriesByEquipmentId(dto.id);
        if (histories.isNotEmpty) {
          // 최신 히스토리의 transaction_type 사용
          // 히스토리는 최신순으로 정렬되어 있다고 가정
          status = histories.first.transactionType ?? 'I';
          transactionDate = histories.first.transactedAt ?? transactionDate;
          print('DEBUG [EquipmentListController] Equipment ${dto.id} status from history: $status');
        }
      } catch (e) {
        print('DEBUG [EquipmentListController] Failed to get history for equipment ${dto.id}: $e');
        // 히스토리 조회 실패시 기본값 사용
      }
      
      final unifiedEquipment = UnifiedEquipment(
        id: dto.id,
        equipment: equipment,
        date: transactionDate, // 최신 거래 날짜 사용
        status: status, // 실제 equipment_history의 transaction_type 사용
        notes: dto.remark, // EquipmentDto에 remark 필드 존재
        // 🔧 [BUG FIX] 누락된 위치 정보 필드들 추가
        // 백엔드에서 warehouses_name 제공하므로 이를 사용
        currentCompany: dto.companyName,      // API company_name → currentCompany
        warehouseLocation: dto.warehousesName, // API warehouses_name → warehouseLocation
        // currentBranch는 EquipmentListDto에 없으므로 null (백엔드 API 구조 변경으로 지점 개념 제거)
        currentBranch: null,
        // ⚡ [FIX] 백엔드 직접 제공 필드들 추가 - 화면에서 N/A 문제 해결
        companyName: dto.companyName,         // API company_name → UI 회사명 컬럼  
        vendorName: dto.vendorName,           // API vendor_name → UI 제조사 컬럼
        modelName: dto.modelName,             // API model_name → UI 모델명 컬럼
      );
      // 🔧 [DEBUG] 변환된 UnifiedEquipment 로깅
      print('DEBUG [EquipmentListController] UnifiedEquipment ID: ${unifiedEquipment.id}, currentCompany: "${unifiedEquipment.currentCompany}", warehouseLocation: "${unifiedEquipment.warehouseLocation}"');
      return unifiedEquipment;
    }));
    
    // API에서 반환한 실제 메타데이터 사용
    final meta = PaginationMeta(
      currentPage: apiEquipmentDtos.page,
      perPage: apiEquipmentDtos.size,
      total: apiEquipmentDtos.totalElements,
      totalPages: apiEquipmentDtos.totalPages,
      hasNext: !apiEquipmentDtos.last,
      hasPrevious: !apiEquipmentDtos.first,
    );
    
    return PagedResult(items: items, meta: meta);
  }

  @override
  bool filterItem(UnifiedEquipment item, String query) {
    final q = query.toLowerCase();
    return (item.equipment.serialNumber?.toLowerCase().contains(q) ?? false) || // serialNumber 검색
           (item.equipment.modelName.toLowerCase().contains(q)) || // Equipment.modelName getter 사용
           (item.equipment.manufacturer.toLowerCase().contains(q)) || // Equipment.manufacturer getter 사용
           (item.notes?.toLowerCase().contains(q) ?? false) ||
           (item.status.toLowerCase().contains(q));
  }

  /// 장비 선택/선택 해제
  void toggleSelection(UnifiedEquipment equipment) {
    final equipmentKey = '${equipment.equipment.id}:${equipment.status}';
    if (selectedEquipmentIds.contains(equipmentKey)) {
      selectedEquipmentIds.remove(equipmentKey);
    } else {
      selectedEquipmentIds.add(equipmentKey);
    }
    notifyListeners();
  }

  /// 모든 선택 해제
  void clearSelection() {
    selectedEquipmentIds.clear();
    notifyListeners();
  }

  /// 선택된 장비 정보 가져오기
  Map<String, List<UnifiedEquipment>> getSelectedEquipmentsByStatus() {
    final Map<String, List<UnifiedEquipment>> groupedEquipments = {};
    
    for (final equipment in items) {
      final equipmentKey = '${equipment.equipment.id}:${equipment.status}';
      if (selectedEquipmentIds.contains(equipmentKey)) {
        if (!groupedEquipments.containsKey(equipment.status)) {
          groupedEquipments[equipment.status] = [];
        }
        groupedEquipments[equipment.status]!.add(equipment);
      }
    }
    
    return groupedEquipments;
  }

  /// 드롭다운 데이터를 미리 로드하는 메서드
  Future<void> preloadDropdownData() async {
    try {
      final result = await _lookupsService.getEquipmentFormDropdownData();
      result.fold(
        (failure) {
          debugPrint('❌ 드롭다운 데이터 로드 실패: ${failure.message}');
          // 실패해도 빈 데이터로 초기화하여 타입 오류 방지
          cachedDropdownData = {
            'manufacturers': <String>[],
            'equipment_names': <String>[],
            'companies': <Map<String, dynamic>>[],
            'warehouses': <Map<String, dynamic>>[],
            'category1_list': <String>[],
            'category_combinations': <dynamic>[],
          };
        },
        (data) {
          debugPrint('✅ 드롭다운 데이터 로드 성공: ${data.keys}');
          cachedDropdownData = data;
        },
      );
    } catch (e) {
      debugPrint('❌ 드롭다운 데이터 로드 예외: $e');
      // 예외 발생 시에도 빈 데이터로 초기화
      cachedDropdownData = {
        'manufacturers': <String>[],
        'equipment_names': <String>[],
        'companies': <Map<String, dynamic>>[],
        'warehouses': <Map<String, dynamic>>[],
        'category1_list': <String>[],
        'category_combinations': <dynamic>[],
      };
    }
  }

  /// 장비 상세 데이터 로드
  Future<EquipmentDto?> loadEquipmentDetail(int equipmentId) async {
    try {
      // getEquipmentDetail 메서드 사용 (getEquipmentById는 존재하지 않음)
      final equipment = await _equipmentService.getEquipmentDetail(equipmentId);
      return equipment;
    } catch (e) {
      print('Failed to load equipment detail: $e');
      return null;
    }
  }

  /// 필터 설정
  void setFilters({
    String? status,
    String? category,
    int? companyId,
  }) {
    _statusFilter = status;
    _categoryFilter = category;
    _companyIdFilter = companyId;
    loadData(isRefresh: true);
  }

  /// 상태 필터 변경
  void filterByStatus(String? status) {
    _statusFilter = status;
    loadData(isRefresh: true);
  }

  /// 카테고리 필터 변경
  void filterByCategory(String? category) {
    _categoryFilter = category;
    loadData(isRefresh: true);
  }

  /// 회사 필터 변경
  void filterByCompany(int? companyId) {
    _companyIdFilter = companyId;
    loadData(isRefresh: true);
  }

  /// 시리얼번호로 장비 검색
  Future<EquipmentDto?> searchBySerial(String serial) async {
    try {
      final useCase = GetIt.instance<GetEquipmentBySerialUseCase>();
      final result = await useCase(serial);
      
      return result.fold(
        (failure) {
          throw Exception(failure.message);
        },
        (equipment) => equipment,
      );
    } catch (e) {
      debugPrint('시리얼번호 검색 실패: $e');
      rethrow;
    }
  }

  /// 바코드로 장비 검색
  Future<EquipmentDto?> searchByBarcode(String barcode) async {
    try {
      final useCase = GetIt.instance<GetEquipmentByBarcodeUseCase>();
      final result = await useCase(barcode);
      
      return result.fold(
        (failure) {
          throw Exception(failure.message);
        },
        (equipment) => equipment,
      );
    } catch (e) {
      debugPrint('바코드 검색 실패: $e');
      rethrow;
    }
  }

  /// 회사별 장비 목록 조회
  Future<List<EquipmentDto>?> getEquipmentsByCompany(int companyId) async {
    try {
      final useCase = GetIt.instance<GetEquipmentsByCompanyUseCase>();
      final result = await useCase(companyId);
      
      return result.fold(
        (failure) {
          throw Exception(failure.message);
        },
        (equipments) => equipments,
      );
    } catch (e) {
      debugPrint('회사별 장비 조회 실패: $e');
      rethrow;
    }
  }

  /// 필터 초기화
  void clearFilters() {
    _statusFilter = null;
    _categoryFilter = null;
    _companyIdFilter = null;
    search('');
    loadData(isRefresh: true);
  }

  /// 장비 삭제
  Future<void> deleteEquipment(int id, String status) async {
    await ErrorHandler.handleApiCall<void>(
      () => _equipmentService.deleteEquipment(id),
      onError: (failure) {
        throw failure;
      },
    );
    
    // removeItemLocally((e) => e.equipment.id == id && e.status == status);  // 로컬 삭제 대신 서버에서 새로고침
    
    // 선택 목록에서도 제거
    final equipmentKey = '$id:$status';
    selectedEquipmentIds.remove(equipmentKey);
    
    // 삭제 후 리스트 새로고침 (서버에서 데이터 다시 가져오기)
    await refresh();
  }

  /// 선택된 장비 일괄 삭제
  Future<void> deleteSelectedEquipments() async {
    final selectedGroups = getSelectedEquipmentsByStatus();
    
    for (final entry in selectedGroups.entries) {
      for (final equipment in entry.value) {
        if (equipment.equipment.id != null) {
          await deleteEquipment(equipment.equipment.id!, equipment.status);
        }
      }
    }
    
    clearSelection();
  }

  /// 장비 상태 변경
  Future<void> updateEquipmentStatus(int id, String currentStatus, String newStatus, {String? reason}) async {
    try {
      await ErrorHandler.handleApiCall<void>(
        () => _equipmentService.changeEquipmentStatus(
          id, 
          EquipmentStatusConverter.clientToServer(newStatus),
          // reason 파라미터는 EquipmentService에서 지원하지 않음
        ),
        onError: (failure) {
          throw failure;
        },
      );
      
      // 성공 후 데이터 새로고침
      await refresh();
    } catch (e) {
      debugPrint('장비 상태 변경 실패: $e');
      rethrow;
    }
  }

  /// 선택된 장비들을 폐기 처리
  Future<void> disposeSelectedEquipments({String? reason}) async {
    final selectedEquipments = getSelectedEquipments()
        .where((equipment) => equipment.status != 'P') // 영문 코드로 통일
        .toList();
    
    if (selectedEquipments.isEmpty) {
      throw Exception('폐기할 수 있는 장비가 선택되지 않았습니다.');
    }

    List<String> failedEquipments = [];
    
    for (final equipment in selectedEquipments) {
      try {
        await updateEquipmentStatus(
          equipment.equipment.id!,
          equipment.status,
          EquipmentStatus.disposed,
          reason: reason ?? '폐기 처리',
        );
      } catch (e) {
        failedEquipments.add('${equipment.equipment.manufacturer} ${equipment.equipment.serialNumber}'); // name → serialNumber
      }
    }
    
    clearSelection();
    
    if (failedEquipments.isNotEmpty) {
      throw Exception('일부 장비 폐기에 실패했습니다: ${failedEquipments.join(', ')}');
    }
  }

  /// 장비 정보 수정
  Future<void> updateEquipment(int id, UnifiedEquipment equipment) async {
    // Equipment → EquipmentUpdateRequestDto 변환 (실제 필드명으로 매핑)
    final updateRequest = EquipmentUpdateRequestDto(
      companiesId: equipment.equipment.currentCompanyId ?? equipment.equipment.companyId, // companiesId 필드 없음
      modelsId: equipment.equipment.modelsId, // ✓ 있음
      serialNumber: equipment.equipment.serialNumber, // ✓ 있음
      barcode: equipment.equipment.barcode, // ✓ 있음
      purchasedAt: equipment.equipment.purchaseDate, // purchasedAt → purchaseDate
      purchasePrice: equipment.equipment.purchasePrice?.toInt(), // double? → int? 변환
      warrantyNumber: equipment.equipment.warrantyLicense, // warrantyNumber → warrantyLicense
      warrantyStartedAt: equipment.equipment.warrantyStartDate, // warrantyStartedAt → warrantyStartDate
      warrantyEndedAt: equipment.equipment.warrantyEndDate, // warrantyEndedAt → warrantyEndDate
      remark: equipment.notes, // UnifiedEquipment.notes → DTO.remark
    );
    
    await ErrorHandler.handleApiCall<void>(
      () => _equipmentService.updateEquipment(id, updateRequest),
      onError: (failure) {
        throw failure;
      },
    );
    
    updateItemLocally(equipment, (e) => 
      e.equipment.id == equipment.equipment.id && 
      e.status == equipment.status
    );
  }

  /// 상태 필터 변경
  void changeStatusFilter(String? status) {
    _selectedStatusFilter = status;
    _statusFilter = status;
    notifyListeners();
  }

  /// 검색 키워드 업데이트
  void updateSearchKeyword(String keyword) {
    search(keyword); // BaseListController의 search 메서드 사용
  }

  /// 장비 선택 (토글 선택을 위한 별칭)
  void selectEquipment(UnifiedEquipment equipment) {
    toggleSelection(equipment);
  }

  /// 선택된 입고 상태 장비 개수
  int getSelectedInStockCount() {
    return selectedEquipmentIds
        .where((key) => key.endsWith(':I')) // 영문 코드만 체크
        .length;
  }

  /// 선택된 장비들 가져오기
  List<UnifiedEquipment> getSelectedEquipments() {
    return items.where((equipment) {
      final equipmentKey = '${equipment.equipment.id}:${equipment.status}';
      return selectedEquipmentIds.contains(equipmentKey);
    }).toList();
  }

  /// 선택된 장비들 요약 정보
  String getSelectedEquipmentsSummary() {
    final selectedEquipments = getSelectedEquipments();
    if (selectedEquipments.isEmpty) return '선택된 장비가 없습니다';
    
    final Map<String, int> statusCounts = {};
    for (final equipment in selectedEquipments) {
      statusCounts[equipment.status] = (statusCounts[equipment.status] ?? 0) + 1;
    }
    
    final summaryParts = statusCounts.entries
        .map((entry) => '${entry.key}: ${entry.value}개')
        .toList();
    
    return summaryParts.join(', ');
  }

  /// 선택된 장비 총 개수
  int getSelectedEquipmentCount() {
    return selectedEquipmentIds.length;
  }

  /// 특정 상태의 선택된 장비 개수
  int getSelectedEquipmentCountByStatus(String status) {
    // status가 이미 코드(I, O, T 등)일 수도 있고, 상수명(EquipmentStatus.in_ 등)일 수도 있음
    return selectedEquipmentIds
        .where((key) => key.endsWith(':$status'))
        .length;
  }

  /// 캐시된 제조사 목록 조회
  List<LookupItem> getCachedManufacturers() {
    final result = _lookupsService.getManufacturers();
    return result.fold(
      (failure) => [],
      (manufacturers) => manufacturers,
    );
  }

  /// 캐시된 장비명 목록 조회
  List<EquipmentNameItem> getCachedEquipmentNames() {
    final result = _lookupsService.getEquipmentNames();
    return result.fold(
      (failure) => [],
      (equipmentNames) => equipmentNames,
    );
  }

  /// 캐시된 장비 카테고리 조합 목록 조회
  List<CategoryCombinationItem> getCachedEquipmentCategories() {
    final result = _lookupsService.getEquipmentCategories();
    return result.fold(
      (failure) => [],
      (categories) => categories,
    );
  }

  /// 캐시된 장비 상태 목록 조회
  List<StatusItem> getCachedEquipmentStatuses() {
    final result = _lookupsService.getEquipmentStatuses();
    return result.fold(
      (failure) => [],
      (statuses) => statuses,
    );
  }

  /// 드롭다운용 장비 상태 맵 (id → name)
  Map<String, String> getEquipmentStatusDropdownItems() {
    final result = _lookupsService.getEquipmentStatusDropdownItems();
    return result.fold(
      (failure) => {},
      (items) => items,
    );
  }

  /// 특정 상태 ID에 해당하는 StatusItem 조회
  StatusItem? getEquipmentStatusById(String statusId) {
    final result = _lookupsService.getEquipmentStatusById(statusId);
    return result.fold(
      (failure) => null,
      (statusItem) => statusItem,
    );
  }
}
