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<EquipmentHistoryRepository>();
  
  // 캐시 저장소
  final Map<int, StockStatusDto> _cache = {};
  
  // 상태 관리
  bool _isLoaded = false;
  bool _isLoading = false;
  DateTime? _lastUpdated;
  String? _lastError;
  
  // 설정 상수
  static const int _cacheValidMinutes = 10; // 10분간 캐시 유효

  /// 캐시 로딩 상태
  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<bool> 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<StockStatusDto> 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<bool> 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<String, dynamic> 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');
    });
  }
}
