import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:superport/models/equipment_unified_model.dart';
import 'package:superport/models/company_model.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/services/mock_data_service.dart';
import 'package:superport/services/warehouse_service.dart';
import 'package:superport/services/company_service.dart';
import 'package:superport/utils/constants.dart';
import 'package:superport/core/errors/failures.dart';
import 'package:superport/core/utils/debug_logger.dart';

/// 장비 입고 폼 컨트롤러
///
/// 폼의 전체 상태, 유효성, 저장, 데이터 로딩 등 비즈니스 로직을 담당한다.
class EquipmentInFormController extends ChangeNotifier {
  final MockDataService dataService;
  final EquipmentService _equipmentService = GetIt.instance<EquipmentService>();
  final WarehouseService _warehouseService = GetIt.instance<WarehouseService>();
  final CompanyService _companyService = GetIt.instance<CompanyService>();
  final int? equipmentInId;
  
  bool _isLoading = false;
  String? _error;
  bool _isSaving = false;
  bool _useApi = true; // Feature flag
  
  // Getters
  bool get isLoading => _isLoading;
  String? get error => _error;
  bool get isSaving => _isSaving;

  // 폼 키
  final GlobalKey<FormState> formKey = GlobalKey<FormState>();

  // 입력 상태 변수
  String manufacturer = '';
  String name = '';
  String category = '';
  String subCategory = '';
  String subSubCategory = '';
  String serialNumber = '';
  String barcode = '';
  int quantity = 1;
  DateTime inDate = DateTime.now();
  String equipmentType = EquipmentType.new_;
  bool hasSerialNumber = true;

  // 워런티 관련 상태
  String? warrantyLicense;
  String? warrantyCode; // 워런티 코드(텍스트 입력)
  DateTime warrantyStartDate = DateTime.now();
  DateTime warrantyEndDate = DateTime.now().add(const Duration(days: 365));
  List<String> warrantyLicenses = [];

  // 자동완성 데이터
  List<String> manufacturers = [];
  List<String> equipmentNames = [];
  // 카테고리 자동완성 데이터
  List<String> categories = [];
  List<String> subCategories = [];
  List<String> subSubCategories = [];
  
  // 창고 위치 전체 데이터 (이름-ID 매핑용)
  Map<String, int> warehouseLocationMap = {};

  // 편집 모드 여부
  bool isEditMode = false;

  // 입고지, 파트너사 관련 상태
  String? warehouseLocation;
  String? partnerCompany;
  List<String> warehouseLocations = [];
  List<String> partnerCompanies = [];

  final TextEditingController remarkController = TextEditingController();

  EquipmentInFormController({required this.dataService, this.equipmentInId}) {
    isEditMode = equipmentInId != null;
    _loadManufacturers();
    _loadEquipmentNames();
    _loadCategories();
    _loadSubCategories();
    _loadSubSubCategories();
    _loadWarehouseLocations();
    _loadPartnerCompanies();
    _loadWarrantyLicenses();
    if (isEditMode) {
      _loadEquipmentIn();
    }
  }

  // 제조사 목록 로드
  void _loadManufacturers() {
    manufacturers = dataService.getAllManufacturers();
  }

  // 장비명 목록 로드
  void _loadEquipmentNames() {
    equipmentNames = dataService.getAllEquipmentNames();
  }

  // 카테고리 목록 로드
  void _loadCategories() {
    categories = dataService.getAllCategories();
  }

  // 서브카테고리 목록 로드
  void _loadSubCategories() {
    subCategories = dataService.getAllSubCategories();
  }

  // 서브서브카테고리 목록 로드
  void _loadSubSubCategories() {
    subSubCategories = dataService.getAllSubSubCategories();
  }

  // 입고지 목록 로드
  void _loadWarehouseLocations() async {
    if (_useApi) {
      try {
        DebugLogger.log('입고지 목록 API 로드 시작', tag: 'EQUIPMENT_IN');
        final locations = await _warehouseService.getWarehouseLocations();
        warehouseLocations = locations.map((e) => e.name).toList();
        // 이름-ID 매핑 저장
        warehouseLocationMap = {for (var loc in locations) loc.name: loc.id};
        DebugLogger.log('입고지 목록 로드 성공', tag: 'EQUIPMENT_IN', data: {
          'count': warehouseLocations.length,
          'locations': warehouseLocations,
          'locationMap': warehouseLocationMap,
        });
        notifyListeners();
      } catch (e) {
        DebugLogger.logError('입고지 목록 로드 실패', error: e);
        // 실패 시 Mock 데이터 사용
        final mockLocations = dataService.getAllWarehouseLocations();
        warehouseLocations = mockLocations.map((e) => e.name).toList();
        warehouseLocationMap = {for (var loc in mockLocations) loc.name: loc.id};
        notifyListeners();
      }
    } else {
      final mockLocations = dataService.getAllWarehouseLocations();
      warehouseLocations = mockLocations.map((e) => e.name).toList();
      warehouseLocationMap = {for (var loc in mockLocations) loc.name: loc.id};
    }
  }

  // 파트너사 목록 로드
  void _loadPartnerCompanies() async {
    if (_useApi) {
      try {
        DebugLogger.log('파트너사 목록 API 로드 시작', tag: 'EQUIPMENT_IN');
        final companies = await _companyService.getCompanies();
        partnerCompanies = companies.map((c) => c.name).toList();
        DebugLogger.log('파트너사 목록 로드 성공', tag: 'EQUIPMENT_IN', data: {
          'count': partnerCompanies.length,
          'companies': partnerCompanies,
        });
        notifyListeners();
      } catch (e) {
        DebugLogger.logError('파트너사 목록 로드 실패', error: e);
        // 실패 시 Mock 데이터 사용
        partnerCompanies =
            dataService
                .getAllCompanies()
                .where((c) => c.companyTypes.contains(CompanyType.partner))
                .map((c) => c.name)
                .toList();
        notifyListeners();
      }
    } else {
      partnerCompanies =
          dataService
              .getAllCompanies()
              .where((c) => c.companyTypes.contains(CompanyType.partner))
              .map((c) => c.name)
              .toList();
    }
  }

  // 워런티 라이센스 목록 로드
  void _loadWarrantyLicenses() {
    // 실제로는 API나 서비스에서 불러와야 하지만, 파트너사와 동일한 데이터 사용
    warrantyLicenses = List.from(partnerCompanies);
  }

  // 기존 데이터 로드(수정 모드)
  void _loadEquipmentIn() async {
    if (equipmentInId == null) return;
    
    _isLoading = true;
    _error = null;
    notifyListeners();
    
    try {
      if (_useApi) {
        // API에서 장비 정보 로드
        // 현재는 장비 정보만 가져올 수 있으므로, 일단 Mock 데이터와 병용
        final equipmentIn = dataService.getEquipmentInById(equipmentInId!);
        if (equipmentIn != null && equipmentIn.equipment.id != null) {
          try {
            // API에서 최신 장비 정보 가져오기
            final equipment = await _equipmentService.getEquipment(equipmentIn.equipment.id!);
            manufacturer = equipment.manufacturer;
            name = equipment.name;
            category = equipment.category;
            subCategory = equipment.subCategory;
            subSubCategory = equipment.subSubCategory;
            serialNumber = equipment.serialNumber ?? '';
            barcode = equipment.barcode ?? '';
            quantity = equipment.quantity;
            remarkController.text = equipment.remark ?? '';
            hasSerialNumber = serialNumber.isNotEmpty;
            
            // 워런티 정보
            warrantyLicense = equipment.warrantyLicense;
            warrantyStartDate = equipment.warrantyStartDate ?? DateTime.now();
            warrantyEndDate = equipment.warrantyEndDate ?? DateTime.now().add(const Duration(days: 365));
            
            // 입고 관련 정보는 아직 Mock 데이터 사용
            inDate = equipmentIn.inDate;
            equipmentType = equipmentIn.type;
            warehouseLocation = equipmentIn.warehouseLocation;
            partnerCompany = equipmentIn.partnerCompany;
          } catch (e) {
            // API 실패 시 Mock 데이터 사용
            _loadFromMockData(equipmentIn);
          }
        } else if (equipmentIn != null) {
          _loadFromMockData(equipmentIn);
        }
      } else {
        // Mock 데이터 사용
        final equipmentIn = dataService.getEquipmentInById(equipmentInId!);
        if (equipmentIn != null) {
          _loadFromMockData(equipmentIn);
        }
      }
    } catch (e) {
      _error = 'Failed to load equipment: $e';
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }
  
  void _loadFromMockData(EquipmentIn equipmentIn) {
    manufacturer = equipmentIn.equipment.manufacturer;
    name = equipmentIn.equipment.name;
    category = equipmentIn.equipment.category;
    subCategory = equipmentIn.equipment.subCategory;
    subSubCategory = equipmentIn.equipment.subSubCategory;
    serialNumber = equipmentIn.equipment.serialNumber ?? '';
    barcode = equipmentIn.equipment.barcode ?? '';
    quantity = equipmentIn.equipment.quantity;
    inDate = equipmentIn.inDate;
    hasSerialNumber = serialNumber.isNotEmpty;
    equipmentType = equipmentIn.type;
    warehouseLocation = equipmentIn.warehouseLocation;
    partnerCompany = equipmentIn.partnerCompany;
    remarkController.text = equipmentIn.remark ?? '';

    // 워런티 정보 로드
    warrantyLicense = equipmentIn.partnerCompany;
    warrantyStartDate = equipmentIn.inDate;
    warrantyEndDate = equipmentIn.inDate.add(const Duration(days: 365));
    warrantyCode = null;
  }

  // 워런티 기간 계산
  String getWarrantyPeriodSummary() {
    final difference = warrantyEndDate.difference(warrantyStartDate);
    final days = difference.inDays;

    if (days <= 0) {
      return '유효하지 않은 기간';
    }

    final years = days ~/ 365;
    final remainingDays = days % 365;

    String summary = '';
    if (years > 0) {
      summary += '$years년 ';
    }
    if (remainingDays > 0) {
      summary += '$remainingDays일';
    }

    return summary.trim();
  }

  // 저장 처리
  Future<bool> save() async {
    if (!formKey.currentState!.validate()) {
      return false;
    }
    formKey.currentState!.save();
    
    _isSaving = true;
    _error = null;
    notifyListeners();
    
    try {

    // 입력값이 리스트에 없으면 추가
    if (partnerCompany != null &&
        partnerCompany!.isNotEmpty &&
        !partnerCompanies.contains(partnerCompany)) {
      partnerCompanies.add(partnerCompany!);
    }
    if (warehouseLocation != null &&
        warehouseLocation!.isNotEmpty &&
        !warehouseLocations.contains(warehouseLocation)) {
      warehouseLocations.add(warehouseLocation!);
    }
    if (manufacturer.isNotEmpty && !manufacturers.contains(manufacturer)) {
      manufacturers.add(manufacturer);
    }
    if (name.isNotEmpty && !equipmentNames.contains(name)) {
      equipmentNames.add(name);
    }
    if (category.isNotEmpty && !categories.contains(category)) {
      categories.add(category);
    }
    if (subCategory.isNotEmpty && !subCategories.contains(subCategory)) {
      subCategories.add(subCategory);
    }
    if (subSubCategory.isNotEmpty &&
        !subSubCategories.contains(subSubCategory)) {
      subSubCategories.add(subSubCategory);
    }
    if (warrantyLicense != null &&
        warrantyLicense!.isNotEmpty &&
        !warrantyLicenses.contains(warrantyLicense)) {
      warrantyLicenses.add(warrantyLicense!);
    }

    final equipment = Equipment(
      manufacturer: manufacturer,
      name: name,
      category: category,
      subCategory: subCategory,
      subSubCategory: subSubCategory,
      serialNumber: hasSerialNumber ? serialNumber : null,
      barcode: barcode.isNotEmpty ? barcode : null,
      quantity: quantity,
      remark: remarkController.text.trim(),
      warrantyLicense: warrantyLicense,
      warrantyStartDate: warrantyStartDate,
      warrantyEndDate: warrantyEndDate,
      // 워런티 코드 저장 필요시 여기에 추가
    );
    
    if (_useApi) {
      // API 호출
      if (isEditMode) {
        // 수정 모드 - API로 장비 정보 업데이트
        await _equipmentService.updateEquipment(equipmentInId!, equipment);
      } else {
        // 생성 모드
        try {
          // 1. 먼저 장비 생성
          DebugLogger.log('장비 생성 시작', tag: 'EQUIPMENT_IN', data: {
            'manufacturer': manufacturer,
            'name': name,
            'serialNumber': serialNumber,
          });
          
          final createdEquipment = await _equipmentService.createEquipment(equipment);
          
          DebugLogger.log('장비 생성 성공', tag: 'EQUIPMENT_IN', data: {
            'equipmentId': createdEquipment.id,
          });
          
          // 2. 입고 처리 (warehouse location ID 필요)
          int? warehouseLocationId;
          if (warehouseLocation != null) {
            // 저장된 매핑에서 ID 가져오기
            warehouseLocationId = warehouseLocationMap[warehouseLocation];
            
            if (warehouseLocationId == null) {
              DebugLogger.logError('창고 위치 ID를 찾을 수 없음', error: 'Warehouse: $warehouseLocation');
            }
          }
          
          DebugLogger.log('입고 처리 시작', tag: 'EQUIPMENT_IN', data: {
            'equipmentId': createdEquipment.id,
            'quantity': quantity,
            'warehouseLocationId': warehouseLocationId,
          });
          
          await _equipmentService.equipmentIn(
            equipmentId: createdEquipment.id!,
            quantity: quantity,
            warehouseLocationId: warehouseLocationId,
            notes: remarkController.text.trim(),
          );
          
          DebugLogger.log('입고 처리 성공', tag: 'EQUIPMENT_IN');
          
        } catch (e) {
          DebugLogger.logError('장비 입고 처리 실패', error: e);
          throw e;  // 에러를 상위로 전파하여 적절한 에러 메시지 표시
        }
      }
    } else {
      // Mock 데이터 사용
      if (isEditMode) {
        final equipmentIn = dataService.getEquipmentInById(equipmentInId!);
        if (equipmentIn != null) {
          final updatedEquipmentIn = EquipmentIn(
            id: equipmentIn.id,
            equipment: equipment,
            inDate: inDate,
            status: equipmentIn.status,
            type: equipmentType,
            warehouseLocation: warehouseLocation,
            partnerCompany: partnerCompany,
            remark: remarkController.text.trim(),
          );
          dataService.updateEquipmentIn(updatedEquipmentIn);
        }
      } else {
        final newEquipmentIn = EquipmentIn(
          equipment: equipment,
          inDate: inDate,
          type: equipmentType,
          warehouseLocation: warehouseLocation,
          partnerCompany: partnerCompany,
          remark: remarkController.text.trim(),
        );
        dataService.addEquipmentIn(newEquipmentIn);
      }
    }

    // 저장 후 리스트 재로딩 (중복 방지 및 최신화)
    _loadManufacturers();
    _loadEquipmentNames();
    _loadCategories();
    _loadSubCategories();
    _loadSubSubCategories();
    _loadWarehouseLocations();
    _loadPartnerCompanies();
    _loadWarrantyLicenses();

    return true;
    } on Failure catch (e) {
      _error = e.message;
      notifyListeners();
      return false;
    } catch (e) {
      _error = 'An unexpected error occurred: $e';
      notifyListeners();
      return false;
    } finally {
      _isSaving = false;
      notifyListeners();
    }
  }

  // 에러 처리
  void clearError() {
    _error = null;
    notifyListeners();
  }
  
  // API 사용 여부 토글 (테스트용)
  void toggleApiUsage() {
    _useApi = !_useApi;
    notifyListeners();
  }
  
  @override
  void dispose() {
    remarkController.dispose();
    super.dispose();
  }
}
