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(), _equipmentDetailUseCase = equipmentDetailUseCase ?? GetIt.instance(); /// 재고 이력 목록 로드 (여러 API 조합) Future 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 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 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> loadEquipmentHistory(int equipmentId) async { try { // 해당 장비의 모든 이력을 시간순(최신순)으로 로드 final historyResponse = await _historyRepository.getEquipmentHistories( equipmentsId: equipmentId, page: 1, pageSize: AppConstants.maxBulkPageSize, // 모든 이력 로드 ); final List 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 _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 _applyLocalSearch( List 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(); } }