import 'package:injectable/injectable.dart';
import 'package:superport/data/models/equipment_history_dto.dart';
import 'package:superport/data/repositories/equipment_history_repository.dart';

@lazySingleton
class EquipmentHistoryUseCase {
  final EquipmentHistoryRepository _repository;
  
  EquipmentHistoryUseCase(this._repository);
  
  // 재고 이력 조회
  Future<EquipmentHistoryListResponse> getEquipmentHistories({
    int? page,
    int? pageSize,
    int? equipmentsId,
    int? warehousesId,
    int? companiesId,
    String? transactionType,
    String? startDate,
    String? endDate,
  }) async {
    return await _repository.getEquipmentHistories(
      page: page,
      pageSize: pageSize,
      equipmentsId: equipmentsId,
      warehousesId: warehousesId,
      companiesId: companiesId,
      transactionType: transactionType,
      startDate: startDate,
      endDate: endDate,
    );
  }
  
  // 특정 이력 상세 조회
  Future<EquipmentHistoryDto> getEquipmentHistoryById(int id) async {
    return await _repository.getEquipmentHistoryById(id);
  }
  
  // 장비별 이력 조회
  Future<List<EquipmentHistoryDto>> getEquipmentHistoriesByEquipmentId(
    int equipmentId,
  ) async {
    return await _repository.getEquipmentHistoriesByEquipmentId(equipmentId);
  }
  
  // 창고별 이력 조회
  Future<List<EquipmentHistoryDto>> getEquipmentHistoriesByWarehouseId(
    int warehouseId,
  ) async {
    return await _repository.getEquipmentHistoriesByWarehouseId(warehouseId);
  }
  
  // 장비별 재고 현황 계산 (백엔드 기반)
  Future<int> getCurrentStock(int equipmentId, {int? warehouseId}) async {
    final histories = await getEquipmentHistoriesByEquipmentId(equipmentId);
    
    int totalStock = 0;
    for (final history in histories) {
      if (warehouseId != null && history.warehousesId != warehouseId) continue;
      
      if (history.transactionType == TransactionType.input) {
        totalStock += history.quantity;
      } else if (history.transactionType == TransactionType.output) {
        totalStock -= history.quantity;
      }
    }
    
    return totalStock;
  }
  
  // 입고 처리 (백엔드 스키마 기반)
  Future<EquipmentHistoryDto> createStockIn({
    required int equipmentsId,
    required int warehousesId,
    required int quantity,
    DateTime? transactedAt,
    String? remark,
  }) async {
    // 비즈니스 규칙 검증
    if (quantity <= 0) {
      throw Exception('입고 수량은 0보다 커야 합니다.');
    }
    
    final request = EquipmentHistoryRequestDto(
      equipmentsId: equipmentsId,
      warehousesId: warehousesId,
      transactionType: TransactionType.input,
      quantity: quantity,
      transactedAt: transactedAt ?? DateTime.now(),
      remark: remark,
    );
    
    return await _repository.createEquipmentHistory(request);
  }
  
  // 출고 처리 (백엔드 스키마 기반)
  Future<EquipmentHistoryDto> createStockOut({
    required int equipmentsId,
    required int warehousesId,
    required int quantity,
    DateTime? transactedAt,
    String? remark,
  }) async {
    // 비즈니스 규칙 검증
    if (quantity <= 0) {
      throw Exception('출고 수량은 0보다 커야 합니다.');
    }
    
    // 재고 확인
    final currentStock = await getCurrentStock(equipmentsId, warehouseId: warehousesId);
    if (currentStock < quantity) {
      throw Exception('재고가 부족합니다. (현재 재고: $currentStock개)');
    }
    
    final request = EquipmentHistoryRequestDto(
      equipmentsId: equipmentsId,
      warehousesId: warehousesId,
      transactionType: TransactionType.output,
      quantity: quantity,
      transactedAt: transactedAt ?? DateTime.now(),
      remark: remark,
    );
    
    return await _repository.createEquipmentHistory(request);
  }
  
  // 이력 수정
  Future<EquipmentHistoryDto> updateEquipmentHistory(
    int id,
    EquipmentHistoryUpdateRequestDto request,
  ) async {
    // 수정 권한 검증 (필요시 추가)
    // 이미 완료된 트랜잭션은 수정 불가 등의 규칙
    
    return await _repository.updateEquipmentHistory(id, request);
  }
  
  // 이력 삭제
  Future<void> deleteEquipmentHistory(int id) async {
    // 삭제 권한 검증 (필요시 추가)
    // 감사 추적을 위해 실제로는 soft delete 고려
    
    await _repository.deleteEquipmentHistory(id);
  }
  
  // 재고 이동 (창고 간 이동)
  Future<void> transferStock({
    required int equipmentsId,
    required int quantity,
    required int fromWarehouseId,
    required int toWarehouseId,
    String? remark,
  }) async {
    // 1. 출고 처리 (from warehouse)
    await createStockOut(
      equipmentsId: equipmentsId,
      warehousesId: fromWarehouseId,
      quantity: quantity,
      remark: remark ?? '창고 이동: $fromWarehouseId → $toWarehouseId',
    );
    
    // 2. 입고 처리 (to warehouse)
    await createStockIn(
      equipmentsId: equipmentsId,
      warehousesId: toWarehouseId,
      quantity: quantity,
      remark: remark ?? '창고 이동: $fromWarehouseId → $toWarehouseId',
    );
  }
  
  // 재고 조정 (실사 후 조정)
  Future<EquipmentHistoryDto> adjustInventory({
    required int equipmentsId,
    required int actualQuantity,
    required int warehousesId,
    String? remark,
  }) async {
    // 현재 재고 확인
    final currentStock = await getCurrentStock(equipmentsId, warehouseId: warehousesId);
    final difference = actualQuantity - currentStock;
    
    if (difference == 0) {
      throw Exception('재고 조정이 필요하지 않습니다.');
    }
    
    if (difference > 0) {
      // 재고 증가 - 입고 처리
      return await createStockIn(
        equipmentsId: equipmentsId,
        warehousesId: warehousesId,
        quantity: difference,
        remark: remark ?? '재고 조정: +$difference개',
      );
    } else {
      // 재고 감소 - 출고 처리
      return await createStockOut(
        equipmentsId: equipmentsId,
        warehousesId: warehousesId,
        quantity: -difference,
        remark: remark ?? '재고 조정: $difference개',
      );
    }
  }
  
  // 재고 부족 장비 확인 (단순화)
  Future<List<int>> checkLowStockEquipments({
    int minimumStock = 10,
    int? warehouseId,
    List<int>? equipmentIds,
  }) async {
    final lowStockEquipments = <int>[];
    
    // 특정 장비 ID 목록이 제공된 경우, 해당 장비들만 확인
    if (equipmentIds != null) {
      for (final equipmentId in equipmentIds) {
        final currentStock = await getCurrentStock(equipmentId, warehouseId: warehouseId);
        if (currentStock < minimumStock) {
          lowStockEquipments.add(equipmentId);
        }
      }
    }
    
    return lowStockEquipments;
  }
  
  // 이력 생성 (범용)
  Future<EquipmentHistoryDto> createEquipmentHistory(
    EquipmentHistoryRequestDto request,
  ) async {
    // 비즈니스 규칙 검증
    if (request.quantity <= 0) {
      throw Exception('수량은 0보다 커야 합니다.');
    }
    
    // 출고인 경우 재고 확인
    if (request.transactionType == TransactionType.output) {
      final currentStock = await getCurrentStock(
        request.equipmentsId, 
        warehouseId: request.warehousesId,
      );
      if (currentStock < request.quantity) {
        throw Exception('재고가 부족합니다. (현재 재고: $currentStock개)');
      }
    }
    
    return await _repository.createEquipmentHistory(request);
  }
}