import 'package:get_it/get_it.dart'; import 'package:superport/data/models/stock_status_dto.dart'; import 'package:superport/data/repositories/equipment_history_repository.dart'; /// 장비-창고 매핑 캐시 서비스 /// /// Stock Status API를 활용하여 장비별 현재 창고 정보를 캐싱하고 /// 빠른 조회를 제공하는 싱글톤 서비스입니다. /// /// 주요 기능: /// - 앱 시작 시 전체 장비-창고 매핑 로드 및 캐싱 /// - 출고 처리 후 자동 캐시 갱신 /// - 장비별 현재 창고 정보 빠른 조회 /// - Fallback 전략으로 안정성 보장 class EquipmentWarehouseCacheService { static final EquipmentWarehouseCacheService _instance = EquipmentWarehouseCacheService._internal(); factory EquipmentWarehouseCacheService() => _instance; EquipmentWarehouseCacheService._internal(); // 의존성 주입 late final EquipmentHistoryRepository _repository = GetIt.instance(); // 캐시 저장소 final Map _cache = {}; // 상태 관리 bool _isLoaded = false; bool _isLoading = false; DateTime? _lastUpdated; String? _lastError; // 설정 상수 static const int _cacheValidMinutes = 10; // 10분간 캐시 유효 static const int _maxRetryCount = 3; // 최대 재시도 횟수 /// 캐시 로딩 상태 bool get isLoaded => _isLoaded; bool get isLoading => _isLoading; DateTime? get lastUpdated => _lastUpdated; String? get lastError => _lastError; int get cachedCount => _cache.length; /// 캐시 로드 (앱 시작 시 또는 필요 시 호출) /// /// Returns: /// - true: 로드 성공 /// - false: 로드 실패 (에러는 lastError에서 확인) Future loadCache() async { if (_isLoading) return _isLoaded; // 이미 로딩 중이면 현재 상태 반환 _isLoading = true; _lastError = null; try { print('[EquipmentWarehouseCacheService] 재고 현황 로딩 시작...'); print('[EquipmentWarehouseCacheService] Repository: ${_repository.runtimeType}'); // Stock Status API 호출 final stocks = await _repository.getStockStatus(); print('[EquipmentWarehouseCacheService] API 응답 수신: ${stocks.length}개 항목'); // 캐시 업데이트 _cache.clear(); for (var stock in stocks) { print('[EquipmentWarehouseCacheService] 캐시 추가: 장비${stock.equipmentId} → ${stock.warehouseName}'); _cache[stock.equipmentId] = stock; } // 상태 업데이트 _isLoaded = true; _lastUpdated = DateTime.now(); print('[EquipmentWarehouseCacheService] 재고 현황 로딩 완료: ${_cache.length}개 장비'); print('[EquipmentWarehouseCacheService] 캐시된 장비 ID들: ${_cache.keys.toList()}'); return true; } catch (e, stackTrace) { _lastError = '재고 현황 로딩 실패: $e'; print('[EquipmentWarehouseCacheService] $_lastError'); print('[EquipmentWarehouseCacheService] StackTrace: $stackTrace'); return false; } finally { _isLoading = false; } } /// 장비의 현재 창고 정보 조회 /// /// [equipmentId]: 조회할 장비 ID /// /// Returns: /// - StockStatusDto: 장비의 재고 현황 정보 /// - null: 캐시에 없는 경우 StockStatusDto? getEquipmentStock(int equipmentId) { return _cache[equipmentId]; } /// 장비의 현재 창고명 조회 (간편 메소드) /// /// [equipmentId]: 조회할 장비 ID /// [fallbackName]: 캐시에 없을 때 반환할 기본값 /// /// Returns: 창고명 또는 fallbackName String getWarehouseName(int equipmentId, {String fallbackName = '위치 미확인'}) { return _cache[equipmentId]?.warehouseName ?? fallbackName; } /// 장비의 현재 창고 ID 조회 /// /// [equipmentId]: 조회할 장비 ID /// /// Returns: 창고 ID 또는 null int? getWarehouseId(int equipmentId) { return _cache[equipmentId]?.warehouseId; } /// 장비가 특정 창고에 있는지 확인 /// /// [equipmentId]: 확인할 장비 ID /// [warehouseId]: 확인할 창고 ID /// /// Returns: true if 장비가 해당 창고에 있음 bool isEquipmentInWarehouse(int equipmentId, int warehouseId) { return _cache[equipmentId]?.warehouseId == warehouseId; } /// 특정 창고에 있는 모든 장비 목록 조회 /// /// [warehouseId]: 조회할 창고 ID /// /// Returns: 해당 창고에 있는 장비들의 StockStatusDto 목록 List getEquipmentsByWarehouse(int warehouseId) { return _cache.values .where((stock) => stock.warehouseId == warehouseId) .toList(); } /// 캐시 갱신 필요 여부 확인 /// /// Returns: true if 캐시 갱신이 필요함 bool needsRefresh() { if (!_isLoaded || _lastUpdated == null) return true; final difference = DateTime.now().difference(_lastUpdated!); return difference.inMinutes >= _cacheValidMinutes; } /// 캐시 강제 갱신 /// /// 출고/입고 처리 후 호출하여 최신 재고 상태를 반영합니다. /// /// Returns: true if 갱신 성공 Future refreshCache() async { print('[EquipmentWarehouseCacheService] 강제 캐시 갱신 시작...'); // 강제로 갱신하도록 상태 초기화 _isLoaded = false; _lastUpdated = null; return await loadCache(); } /// 캐시 무효화 (메모리 정리) /// /// 로그아웃 시 또는 메모리 절약이 필요할 때 호출 void invalidateCache() { _cache.clear(); _isLoaded = false; _isLoading = false; _lastUpdated = null; _lastError = null; print('[EquipmentWarehouseCacheService] 캐시 무효화 완료'); } /// 캐시 통계 정보 조회 (디버깅용) /// /// Returns: 캐시 상태 정보 맵 Map getCacheStats() { return { 'isLoaded': _isLoaded, 'isLoading': _isLoading, 'cachedCount': _cache.length, 'lastUpdated': _lastUpdated?.toIso8601String(), 'lastError': _lastError, 'needsRefresh': needsRefresh(), 'cacheValidMinutes': _cacheValidMinutes, }; } /// 개발용: 캐시 상태 출력 void printCacheStats() { final stats = getCacheStats(); print('[EquipmentWarehouseCacheService] Cache Stats:'); stats.forEach((key, value) { print(' $key: $value'); }); } }