import 'package:get_it/get_it.dart';
import 'package:superport/data/models/inventory_history_view_model.dart';
import 'package:superport/data/models/equipment_history_dto.dart';
import 'package:superport/data/models/equipment/equipment_dto.dart';
import 'package:superport/data/repositories/equipment_history_repository.dart';
import 'package:superport/domain/usecases/equipment/get_equipment_detail_usecase.dart';
import 'package:superport/core/constants/app_constants.dart';

/// 재고 이력 관리 화면 전용 서비스
/// 백엔드 여러 API를 조합하여 화면용 데이터 제공
class InventoryHistoryService {
  final EquipmentHistoryRepository _historyRepository;
  final GetEquipmentDetailUseCase _equipmentDetailUseCase;
  
  InventoryHistoryService({
    EquipmentHistoryRepository? historyRepository,
    GetEquipmentDetailUseCase? equipmentDetailUseCase,
  }) : _historyRepository = historyRepository ?? GetIt.instance<EquipmentHistoryRepository>(),
       _equipmentDetailUseCase = equipmentDetailUseCase ?? GetIt.instance<GetEquipmentDetailUseCase>();

  /// 재고 이력 목록 로드 (여러 API 조합)
  Future<InventoryHistoryListResponse> loadInventoryHistories({
    int page = 1,
    int pageSize = AppConstants.historyPageSize,
    String? searchKeyword,
    String? transactionType,
    int? equipmentId,
    int? warehouseId,
    int? companyId,
    DateTime? dateFrom,
    DateTime? dateTo,
  }) async {
    try {
      // 1. Equipment History 기본 데이터 로드
      final historyResponse = await _historyRepository.getEquipmentHistories(
        page: page,
        pageSize: pageSize,
        transactionType: transactionType,
        equipmentsId: equipmentId,
        warehousesId: warehouseId,
        startDate: dateFrom?.toIso8601String(),
        endDate: dateTo?.toIso8601String(),
      );

      // 2. 각 이력에 대해 추가 정보 조합
      final List<InventoryHistoryViewModel> enrichedItems = [];
      
      for (final history in historyResponse.items) {
        try {
          final viewModel = await _enrichHistoryWithDetails(history, searchKeyword);
          if (viewModel != null) {
            enrichedItems.add(viewModel);
          }
        } catch (e) {
          print('[InventoryHistoryService] Failed to enrich history ${history.id}: $e');
          // 에러 발생해도 기본 정보로라도 표시
          final fallbackViewModel = _createFallbackViewModel(history);
          enrichedItems.add(fallbackViewModel);
        }
      }
      
      // 3. 검색 키워드 필터링 (서버 검색 후 추가 로컬 필터링)
      List<InventoryHistoryViewModel> filteredItems = enrichedItems;
      if (searchKeyword != null && searchKeyword.isNotEmpty) {
        filteredItems = _applyLocalSearch(enrichedItems, searchKeyword);
      }

      return InventoryHistoryListResponse(
        items: filteredItems,
        totalCount: historyResponse.totalCount,
        currentPage: historyResponse.currentPage,
        totalPages: historyResponse.totalPages,
        pageSize: historyResponse.pageSize,
      );
    } catch (e) {
      print('[InventoryHistoryService] Error loading inventory histories: $e');
      rethrow;
    }
  }

  /// 특정 장비의 전체 이력 로드 (상세보기용)
  Future<List<InventoryHistoryViewModel>> loadEquipmentHistory(int equipmentId) async {
    try {
      // 해당 장비의 모든 이력을 시간순(최신순)으로 로드
      final historyResponse = await _historyRepository.getEquipmentHistories(
        equipmentsId: equipmentId,
        page: 1,
        pageSize: AppConstants.maxBulkPageSize, // 모든 이력 로드
      );

      final List<InventoryHistoryViewModel> items = [];
      for (final history in historyResponse.items) {
        try {
          final viewModel = await _enrichHistoryWithDetails(history);
          if (viewModel != null) {
            items.add(viewModel);
          }
        } catch (e) {
          print('[InventoryHistoryService] Failed to enrich equipment history ${history.id}: $e');
          final fallbackViewModel = _createFallbackViewModel(history);
          items.add(fallbackViewModel);
        }
      }

      // 시간순 정렬 (최신순)
      items.sort((a, b) => b.changedDate.compareTo(a.changedDate));
      
      return items;
    } catch (e) {
      print('[InventoryHistoryService] Error loading equipment history: $e');
      rethrow;
    }
  }

  /// History 데이터에 추가 정보를 조합하여 ViewModel 생성
  Future<InventoryHistoryViewModel?> _enrichHistoryWithDetails(
    EquipmentHistoryDto history, 
    [String? searchKeyword]
  ) async {
    try {
      // Equipment 상세 정보 로드
      EquipmentDto? equipmentDetail;
      if (history.equipmentsId != null) {
        final equipmentResult = await _equipmentDetailUseCase(history.equipmentsId);
        equipmentResult.fold(
          (failure) {
            print('[InventoryHistoryService] Failed to load equipment ${history.equipmentsId}: ${failure.message}');
          },
          (equipment) {
            equipmentDetail = equipment;
          },
        );
      }

      // 장비명 결정 (Equipment API에서 가져오거나 fallback)
      final String equipmentName = _determineEquipmentName(equipmentDetail, history);
      
      // 시리얼번호 결정
      final String serialNumber = _determineSerialNumber(equipmentDetail, history);
      
      // 위치 결정 (transaction_type에 따라 다르게)
      final String location = _determineLocation(history);

      return InventoryHistoryViewModel(
        historyId: history.id ?? 0,
        equipmentId: history.equipmentsId,
        equipmentName: equipmentName,
        serialNumber: serialNumber,
        location: location,
        changedDate: history.transactedAt,
        remark: history.remark,
        transactionType: history.transactionType,
        quantity: history.quantity,
        originalHistory: history,
      );
    } catch (e) {
      print('[InventoryHistoryService] Error enriching history ${history.id}: $e');
      return null;
    }
  }

  /// 장비명 결정 로직
  String _determineEquipmentName(EquipmentDto? equipment, EquipmentHistoryDto history) {
    if (equipment != null) {
      // Equipment API에서 가져온 정보 우선 사용
      if (equipment.modelName != null && equipment.vendorName != null) {
        return '${equipment.vendorName} ${equipment.modelName}';
      } else if (equipment.modelName != null) {
        return equipment.modelName!;
      }
    }
    
    // Fallback: History의 equipment_serial 사용
    if (history.equipmentSerial != null) {
      return history.equipmentSerial!;
    }
    
    return 'Unknown Equipment';
  }

  /// 시리얼번호 결정 로직
  String _determineSerialNumber(EquipmentDto? equipment, EquipmentHistoryDto history) {
    if (equipment != null) {
      return equipment.serialNumber;
    }
    
    if (history.equipmentSerial != null) {
      return history.equipmentSerial!;
    }
    
    return 'N/A';
  }

  /// 위치 결정 로직 (transaction_type에 따라 다르게)
  String _determineLocation(EquipmentHistoryDto history) {
    switch (history.transactionType) {
      case 'O': // 출고
      case 'R': // 대여
        // 고객사 정보 사용
        if (history.companies.isNotEmpty) {
          final company = history.companies.first;
          return company['name']?.toString() ?? 'Unknown Company';
        }
        return 'Unknown Company';
        
      case 'I': // 입고
      case 'D': // 폐기
        // 창고 정보 사용
        return history.warehouseName ?? 'Unknown Warehouse';
        
      default:
        return 'N/A';
    }
  }

  /// 에러 발생 시 fallback ViewModel 생성
  InventoryHistoryViewModel _createFallbackViewModel(EquipmentHistoryDto history) {
    return InventoryHistoryViewModel(
      historyId: history.id ?? 0,
      equipmentId: history.equipmentsId,
      equipmentName: history.equipmentSerial ?? 'Unknown Equipment',
      serialNumber: history.equipmentSerial ?? 'N/A',
      location: _determineLocation(history),
      changedDate: history.transactedAt,
      remark: history.remark,
      transactionType: history.transactionType,
      quantity: history.quantity,
      originalHistory: history,
    );
  }

  /// 로컬 검색 필터링 적용
  List<InventoryHistoryViewModel> _applyLocalSearch(
    List<InventoryHistoryViewModel> items, 
    String searchKeyword
  ) {
    final keyword = searchKeyword.toLowerCase();
    return items.where((item) {
      return [
        item.equipmentName,
        item.serialNumber,
        item.location,
        item.remark ?? '',
        item.transactionTypeDisplay,
      ].any((field) => field.toLowerCase().contains(keyword));
    }).toList();
  }
}
