import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:superport/data/models/equipment/equipment_dto.dart';
import 'package:superport/data/models/company/company_dto.dart';
import 'package:superport/data/models/stock_status_dto.dart';
import 'package:superport/data/repositories/equipment_history_repository.dart';
import 'package:superport/domain/repositories/company_repository.dart';
import 'package:superport/data/repositories/company_repository_impl.dart';
import 'package:superport/data/datasources/remote/company_remote_datasource.dart';
import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/services/equipment_warehouse_cache_service.dart';

class EquipmentOutboundController extends ChangeNotifier {
  final List<EquipmentDto> selectedEquipments;
  late final CompanyRepository _companyRepository;
  late final EquipmentHistoryRepository _equipmentHistoryRepository;
  late final EquipmentWarehouseCacheService _warehouseCacheService;
  
  // Form controllers
  final TextEditingController remarkController = TextEditingController();
  
  // State variables
  bool _isLoading = false;
  bool _isLoadingCompanies = false;
  bool _isLoadingWarehouseInfo = false;
  String? _errorMessage;
  String? _companyError;
  String? _warehouseError;
  
  // Form data
  DateTime _transactionDate = DateTime.now();
  List<CompanyDto> _companies = [];
  CompanyDto? _selectedCompany;
  final Map<int, DateTime> _warrantyDates = {}; // 각 장비의 워런티 날짜 관리
  
  // Getters
  bool get isLoading => _isLoading;
  bool get isLoadingCompanies => _isLoadingCompanies;
  bool get isLoadingWarehouseInfo => _isLoadingWarehouseInfo;
  String? get errorMessage => _errorMessage;
  String? get companyError => _companyError;
  String? get warehouseError => _warehouseError;
  DateTime get transactionDate => _transactionDate;
  List<CompanyDto> get companies => _companies;
  CompanyDto? get selectedCompany => _selectedCompany;
  
  bool get canSubmit => 
      !_isLoading &&
      _selectedCompany != null &&
      selectedEquipments.isNotEmpty;
  
  EquipmentOutboundController({
    required this.selectedEquipments,
  }) {
    // Initialize repositories directly with proper dependencies
    final apiClient = ApiClient();
    final companyRemoteDataSource = CompanyRemoteDataSourceImpl(apiClient);
    _companyRepository = CompanyRepositoryImpl(remoteDataSource: companyRemoteDataSource);
    
    // Initialize EquipmentHistoryRepository with ApiClient's Dio instance  
    // ApiClient has proper auth headers and base URL configuration
    final dio = apiClient.dio; // Use the authenticated Dio instance from ApiClient
    _equipmentHistoryRepository = EquipmentHistoryRepositoryImpl(dio);
    
    // Initialize warehouse cache service
    _warehouseCacheService = EquipmentWarehouseCacheService();
    
    // 각 장비의 현재 워런티 날짜로 초기화
    for (final equipment in selectedEquipments) {
      final id = equipment.id;
      final warrantyDate = equipment.warrantyEndedAt;
      if (id != null && warrantyDate != null) {
        _warrantyDates[id] = warrantyDate;
      }
    }
  }
  
  set transactionDate(DateTime value) {
    _transactionDate = value;
    notifyListeners();
  }
  
  set selectedCompany(CompanyDto? value) {
    _selectedCompany = value;
    notifyListeners();
  }
  
  Future<void> initialize() async {
    // 병렬로 회사 정보와 창고 캐시 로드
    await Future.wait([
      loadCompanies(),
      _loadWarehouseCache(),
    ]);
  }
  
  
  Future<void> loadCompanies() async {
    print('[EquipmentOutboundController] loadCompanies called');
    _isLoadingCompanies = true;
    _companyError = null;
    notifyListeners();
    
    try {
      print('[EquipmentOutboundController] Calling _companyRepository.getCompanies');
      final result = await _companyRepository.getCompanies(
        limit: 1000, // 모든 회사를 가져오기 위해 큰 값 설정
      );
      
      result.fold(
        (failure) {
          print('[EquipmentOutboundController] Company loading failed: ${failure.message}');
          _companyError = failure.message;
        },
        (data) {
          print('[EquipmentOutboundController] Companies loaded successfully: ${data.items.length} companies');
          // Convert Company to CompanyDto - only use required fields
          _companies = data.items
              .map((company) => CompanyDto(
                    id: company.id,
                    name: company.name,
                    contactName: '', // Default value for required field
                    contactPhone: '', // Default value for required field
                    contactEmail: '', // Default value for required field
                    address: company.address.toString(),
                    isCustomer: company.isCustomer,
                  ))
              .where((c) => c.isCustomer == true)
              .toList();
          print('[EquipmentOutboundController] Filtered customer companies: ${_companies.length}');
        },
      );
    } catch (e, stackTrace) {
      print('[EquipmentOutboundController] Exception in loadCompanies: $e');
      print('[EquipmentOutboundController] Stack trace: $stackTrace');
      _companyError = '회사 목록을 불러오는 중 오류가 발생했습니다: $e';
    } finally {
      _isLoadingCompanies = false;
      notifyListeners();
      print('[EquipmentOutboundController] loadCompanies completed');
    }
  }
  
  /// 창고 캐시 로딩
  Future<void> _loadWarehouseCache() async {
    if (_warehouseCacheService.needsRefresh()) {
      _isLoadingWarehouseInfo = true;
      _warehouseError = null;
      notifyListeners();

      try {
        final success = await _warehouseCacheService.loadCache();
        if (!success) {
          _warehouseError = _warehouseCacheService.lastError ?? '창고 정보 로딩 실패';
        }
      } catch (e) {
        _warehouseError = '창고 정보 로딩 중 오류: $e';
      } finally {
        _isLoadingWarehouseInfo = false;
        notifyListeners();
      }
    }
  }

  /// 장비의 현재 창고 정보 조회 (Stock Status 기반)
  /// 
  /// [equipment]: 조회할 장비
  /// 
  /// Returns: 창고명 (Stock Status 우선, Fallback으로 Equipment DTO 사용)
  String getEquipmentCurrentWarehouse(EquipmentDto equipment) {
    // 디버깅: 실제 Equipment DTO 데이터 출력
    print('[EquipmentOutboundController] Equipment ${equipment.id} 창고 정보:');
    print('  - warehousesId: ${equipment.warehousesId}');
    print('  - warehousesName: ${equipment.warehousesName}');
    print('  - serialNumber: ${equipment.serialNumber}');
    
    if (_warehouseError != null) {
      print('[EquipmentOutboundController] Stock Status API 실패, Equipment DTO 사용');
      final fallbackName = equipment.warehousesName ?? '창고 미지정';
      print('  - Fallback 결과: $fallbackName');
      return fallbackName;
    }
    
    // Primary: Stock Status API 기반 정보 사용
    final stockInfo = _warehouseCacheService.getEquipmentStock(equipment.id);
    print('[EquipmentOutboundController] Stock Status API 결과:');
    print('  - stockInfo 존재: ${stockInfo != null}');
    if (stockInfo != null) {
      print('  - stockInfo.warehouseName: ${stockInfo.warehouseName}');
      print('  - stockInfo.warehouseId: ${stockInfo.warehouseId}');
    }
    
    final finalResult = stockInfo?.warehouseName ?? 
           equipment.warehousesName ?? 
           '입출고 이력 없음';
    print('  - 최종 결과: $finalResult');
    
    return finalResult;
  }

  /// 장비의 현재 창고 ID 조회
  int? getEquipmentCurrentWarehouseId(EquipmentDto equipment) {
    // Primary: Stock Status API 기반 정보 사용
    final stockInfo = _warehouseCacheService.getEquipmentStock(equipment.id);
    return stockInfo?.warehouseId ?? equipment.warehousesId;
  }

  /// 장비의 재고 현황 정보 조회
  StockStatusDto? getEquipmentStockStatus(EquipmentDto equipment) {
    return _warehouseCacheService.getEquipmentStock(equipment.id);
  }

  /// 출고 후 창고 캐시 갱신
  Future<void> _refreshWarehouseCache() async {
    print('[EquipmentOutboundController] 출고 완료 후 창고 캐시 갱신 시작...');
    
    try {
      await _warehouseCacheService.refreshCache();
      print('[EquipmentOutboundController] 창고 캐시 갱신 완료');
    } catch (e) {
      print('[EquipmentOutboundController] 창고 캐시 갱신 실패: $e');
      // 갱신 실패해도 출고 프로세스는 성공으로 간주
    }
  }

  Future<bool> processOutbound() async {
    print('[EquipmentOutboundController] processOutbound called');
    print('[EquipmentOutboundController] canSubmit: $canSubmit');
    print('[EquipmentOutboundController] selectedEquipments count: ${selectedEquipments.length}');
    print('[EquipmentOutboundController] selectedCompany: ${_selectedCompany?.name} (ID: ${_selectedCompany?.id})');
    print('[EquipmentOutboundController] API Base URL: ${_equipmentHistoryRepository.toString()}');
    
    if (!canSubmit) {
      print('[EquipmentOutboundController] Cannot submit - validation failed');
      return false;
    }
    
    _isLoading = true;
    _errorMessage = null;
    notifyListeners();
    
    try {
      print('[EquipmentOutboundController] Starting outbound process for ${selectedEquipments.length} equipments');
      
      // Process each selected equipment
      for (int i = 0; i < selectedEquipments.length; i++) {
        final equipment = selectedEquipments[i];
        
        // 개선된 창고 정보 조회 (Stock Status API 우선)
        final currentWarehouseName = getEquipmentCurrentWarehouse(equipment);
        final currentWarehouseId = getEquipmentCurrentWarehouseId(equipment);
        
        print('[EquipmentOutboundController] Processing equipment ${i+1}/${selectedEquipments.length}');
        print('[EquipmentOutboundController] Equipment ID: ${equipment.id}');
        print('[EquipmentOutboundController] Equipment Serial: ${equipment.serialNumber}');
        print('[EquipmentOutboundController] Current Warehouse (Stock Status): $currentWarehouseName (ID: $currentWarehouseId)');
        print('[EquipmentOutboundController] Original Warehouse (DTO): ${equipment.warehousesName} (ID: ${equipment.warehousesId})');
        
        await _equipmentHistoryRepository.createStockOut(
          equipmentsId: equipment.id,
          warehousesId: currentWarehouseId ?? equipment.warehousesId, // 개선된 창고 정보 사용
          companyIds: _selectedCompany?.id != null ? [_selectedCompany!.id!] : null,
          quantity: 1,
          transactedAt: _transactionDate,
          remark: remarkController.text.isNotEmpty ? remarkController.text : null,
        );
        
        print('[EquipmentOutboundController] Successfully processed equipment ${equipment.id}');
      }
      
      print('[EquipmentOutboundController] All equipments processed successfully');
      
      // 출고 완료 후 창고 캐시 갱신 (백그라운드에서 실행)
      unawaited(_refreshWarehouseCache());
      
      return true;
    } catch (e, stackTrace) {
      print('[EquipmentOutboundController] ERROR during outbound process: $e');
      print('[EquipmentOutboundController] Stack trace: $stackTrace');
      _errorMessage = '출고 처리 중 오류가 발생했습니다: $e';
      notifyListeners();
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
      print('[EquipmentOutboundController] processOutbound completed');
    }
  }
  
  String formatDate(DateTime date) {
    return DateFormat('yyyy-MM-dd').format(date);
  }
  
  String formatPrice(int? price) {
    if (price == null) return '-';
    final formatter = NumberFormat('#,###');
    return '₩${formatter.format(price)}';
  }
  
  DateTime? getWarrantyDate(int equipmentId) {
    return _warrantyDates[equipmentId];
  }
  
  void updateWarrantyDate(int equipmentId, DateTime date) {
    _warrantyDates[equipmentId] = date;
    notifyListeners();
  }
  
  @override
  void dispose() {
    remarkController.dispose();
    super.dispose();
  }
}