import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:superport/core/constants/api_endpoints.dart';
import 'package:superport/data/models/equipment_history_dto.dart';
import 'package:superport/data/models/stock_status_dto.dart';

abstract class EquipmentHistoryRepository {
  Future<EquipmentHistoryListResponse> getEquipmentHistories({
    int? page,
    int? pageSize,
    int? equipmentsId,
    int? warehousesId,
    int? companiesId,
    String? transactionType,
    String? startDate,
    String? endDate,
  });
  
  Future<EquipmentHistoryDto> getEquipmentHistoryById(int id);
  
  Future<List<EquipmentHistoryDto>> getEquipmentHistoriesByEquipmentId(int equipmentId);
  
  Future<List<EquipmentHistoryDto>> getEquipmentHistoriesByWarehouseId(int warehouseId);
  
  // 재고 현황 조회 (핵심 기능)
  Future<List<StockStatusDto>> getStockStatus();
  
  // InventoryStatusDto 관련 메서드들 제거 (백엔드에 해당 개념 없음)
  
  Future<EquipmentHistoryDto> createEquipmentHistory(
    EquipmentHistoryRequestDto request,
  );
  
  Future<EquipmentHistoryDto> updateEquipmentHistory(
    int id,
    EquipmentHistoryUpdateRequestDto request,
  );
  
  Future<void> deleteEquipmentHistory(int id);
  
  Future<EquipmentHistoryDto> createStockIn({
    required int equipmentsId,
    required int warehousesId,
    required int quantity,
    DateTime? transactedAt,
    String? remark,
  });
  
  Future<EquipmentHistoryDto> createStockOut({
    required int equipmentsId,
    int? warehousesId,  // 출고 시 null (다른 회사로 완전 이관)
    required int quantity,
    List<int>? companyIds,  // 출고 대상 회사 ID 목록
    DateTime? transactedAt,
    String? remark,
  });
}

@LazySingleton(as: EquipmentHistoryRepository)
class EquipmentHistoryRepositoryImpl implements EquipmentHistoryRepository {
  final Dio _dio;
  
  EquipmentHistoryRepositoryImpl(this._dio);
  
  @override
  Future<EquipmentHistoryListResponse> getEquipmentHistories({
    int? page,
    int? pageSize,
    int? equipmentsId,
    int? warehousesId,
    int? companiesId,
    String? transactionType,
    String? startDate,
    String? endDate,
  }) async {
    try {
      final queryParams = <String, dynamic>{};
      
      if (page != null) queryParams['page'] = page;
      if (pageSize != null) queryParams['page_size'] = pageSize;
      if (equipmentsId != null) queryParams['equipments_id'] = equipmentsId;
      if (warehousesId != null) queryParams['warehouses_id'] = warehousesId;
      if (companiesId != null) queryParams['companies_id'] = companiesId;
      if (transactionType != null) queryParams['transaction_type'] = transactionType;
      if (startDate != null) queryParams['start_date'] = startDate;
      if (endDate != null) queryParams['end_date'] = endDate;
      
      final response = await _dio.get(
        ApiEndpoints.equipmentHistory,
        queryParameters: queryParams,
      );
      
      return EquipmentHistoryListResponse.fromJson(response.data);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  @override
  Future<EquipmentHistoryDto> getEquipmentHistoryById(int id) async {
    try {
      final response = await _dio.get('${ApiEndpoints.equipmentHistory}/$id');
      return EquipmentHistoryDto.fromJson(response.data);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  @override
  Future<List<EquipmentHistoryDto>> getEquipmentHistoriesByEquipmentId(
    int equipmentId,
  ) async {
    try {
      final response = await _dio.get(
        '${ApiEndpoints.equipmentHistory}/by-equipment/$equipmentId',
      );
      
      final List<dynamic> data = response.data is List 
          ? response.data 
          : response.data['data'] ?? [];
          
      return data.map((json) => EquipmentHistoryDto.fromJson(json)).toList();
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  @override
  Future<List<EquipmentHistoryDto>> getEquipmentHistoriesByWarehouseId(
    int warehouseId,
  ) async {
    try {
      final response = await _dio.get(
        '${ApiEndpoints.equipmentHistory}/by-warehouse/$warehouseId',
      );
      
      final List<dynamic> data = response.data is List 
          ? response.data 
          : response.data['data'] ?? [];
          
      return data.map((json) => EquipmentHistoryDto.fromJson(json)).toList();
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  @override
  Future<List<StockStatusDto>> getStockStatus() async {
    try {
      print('[EquipmentHistoryRepository] Stock Status API 호출 시작');
      print('[EquipmentHistoryRepository] URL: ${_dio.options.baseUrl}${ApiEndpoints.equipmentHistoryStockStatus}');
      print('[EquipmentHistoryRepository] Headers: ${_dio.options.headers}');
      
      final response = await _dio.get(ApiEndpoints.equipmentHistoryStockStatus);
      
      print('[EquipmentHistoryRepository] API 응답 수신');
      print('[EquipmentHistoryRepository] Status Code: ${response.statusCode}');
      print('[EquipmentHistoryRepository] Response Type: ${response.data.runtimeType}');
      
      final List<dynamic> data = response.data is List 
          ? response.data 
          : response.data['data'] ?? [];
      
      print('[EquipmentHistoryRepository] 파싱된 데이터 개수: ${data.length}');
      
      final result = data.map((json) => StockStatusDto.fromJson(json)).toList();
      print('[EquipmentHistoryRepository] DTO 변환 완료: ${result.length}개 항목');
      
      return result;
    } on DioException catch (e) {
      print('[EquipmentHistoryRepository] DioException 발생');
      print('[EquipmentHistoryRepository] Error Type: ${e.type}');
      print('[EquipmentHistoryRepository] Error Message: ${e.message}');
      print('[EquipmentHistoryRepository] Response Status: ${e.response?.statusCode}');
      throw _handleError(e);
    } catch (e, stackTrace) {
      print('[EquipmentHistoryRepository] 일반 Exception 발생');
      print('[EquipmentHistoryRepository] Error: $e');
      print('[EquipmentHistoryRepository] StackTrace: $stackTrace');
      rethrow;
    }
  }
  
  // InventoryStatusDto 관련 메서드들 제거 (백엔드에 해당 개념 없음)
  
  @override
  Future<EquipmentHistoryDto> createEquipmentHistory(
    EquipmentHistoryRequestDto request,
  ) async {
    try {
      print('[EquipmentHistoryRepository] Creating equipment history');
      print('[EquipmentHistoryRepository] URL: ${_dio.options.baseUrl}${ApiEndpoints.equipmentHistory}');
      print('[EquipmentHistoryRepository] Headers: ${_dio.options.headers}');
      print('[EquipmentHistoryRepository] Request data: ${request.toJson()}');
      
      final response = await _dio.post(
        ApiEndpoints.equipmentHistory,
        data: request.toJson(),
      );
      
      print('[EquipmentHistoryRepository] Response status: ${response.statusCode}');
      print('[EquipmentHistoryRepository] Response data: ${response.data}');
      
      // 응답 데이터 타입 검증
      if (response.data is String) {
        print('[EquipmentHistoryRepository] Error: Received String response instead of JSON');
        throw Exception('서버에서 오류 응답을 받았습니다: ${response.data}');
      }
      
      return EquipmentHistoryDto.fromJson(response.data);
    } on DioException catch (e) {
      print('[EquipmentHistoryRepository] DioException occurred');
      print('[EquipmentHistoryRepository] Request URL: ${e.requestOptions.uri}');
      print('[EquipmentHistoryRepository] Request headers: ${e.requestOptions.headers}');
      throw _handleError(e);
    }
  }
  
  @override
  Future<EquipmentHistoryDto> updateEquipmentHistory(
    int id,
    EquipmentHistoryUpdateRequestDto request,
  ) async {
    try {
      final response = await _dio.put(
        '${ApiEndpoints.equipmentHistory}/$id',
        data: request.toJson(),
      );
      return EquipmentHistoryDto.fromJson(response.data);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  @override
  Future<void> deleteEquipmentHistory(int id) async {
    try {
      await _dio.delete('${ApiEndpoints.equipmentHistory}/$id');
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }
  
  @override
  Future<EquipmentHistoryDto> createStockIn({
    required int equipmentsId,
    required int warehousesId,
    required int quantity,
    DateTime? transactedAt,
    String? remark,
  }) async {
    final request = EquipmentHistoryRequestDto(
      equipmentsId: equipmentsId,
      warehousesId: warehousesId,
      quantity: quantity,
      transactionType: 'I', // 입고
      transactedAt: (transactedAt ?? DateTime.now()).toUtc(),  // UTC로 변환하여 타임존 정보 포함
      remark: remark,
    );
    
    return createEquipmentHistory(request);
  }
  
  @override
  Future<EquipmentHistoryDto> createStockOut({
    required int equipmentsId,
    int? warehousesId,  // 출고 시 null (다른 회사로 완전 이관)
    required int quantity,
    List<int>? companyIds,  // 출고 대상 회사 ID 목록
    DateTime? transactedAt,
    String? remark,
  }) async {
    // 재고 확인 로직 제거 (백엔드에서 처리)
    final request = EquipmentHistoryRequestDto(
      equipmentsId: equipmentsId,
      warehousesId: warehousesId,
      companyIds: companyIds,  // 백엔드 API에 회사 정보 전달
      quantity: quantity,
      transactionType: 'O', // 출고
      transactedAt: (transactedAt ?? DateTime.now()).toUtc(),  // UTC로 변환하여 타임존 정보 포함
      remark: remark,
    );
    
    return createEquipmentHistory(request);
  }
  
  Exception _handleError(DioException e) {
    print('[EquipmentHistoryRepository] _handleError called');
    print('[EquipmentHistoryRepository] Error type: ${e.type}');
    print('[EquipmentHistoryRepository] Error message: ${e.message}');
    
    if (e.response != null) {
      final statusCode = e.response!.statusCode;
      print('[EquipmentHistoryRepository] Response status: $statusCode');
      print('[EquipmentHistoryRepository] Response data type: ${e.response!.data.runtimeType}');
      print('[EquipmentHistoryRepository] Response data: ${e.response!.data}');
      
      // 안전한 메시지 추출
      String message = '오류가 발생했습니다.';
      try {
        final responseData = e.response!.data;
        if (responseData is Map<String, dynamic>) {
          message = responseData['message']?.toString() ?? message;
        } else if (responseData is String) {
          message = responseData;
        } else {
          message = responseData.toString();
        }
      } catch (messageError) {
        print('[EquipmentHistoryRepository] Message extraction error: $messageError');
        message = '응답 처리 중 오류가 발생했습니다.';
      }
      
      switch (statusCode) {
        case 400:
          return Exception('잘못된 요청: $message');
        case 401:
          return Exception('인증이 필요합니다.');
        case 403:
          return Exception('권한이 없습니다.');
        case 404:
          return Exception('재고 이력을 찾을 수 없습니다.');
        case 409:
          return Exception('재고 충돌: $message');
        case 500:
          return Exception('서버 오류가 발생했습니다.');
        default:
          return Exception('오류가 발생했습니다: $message');
      }
    }
    return Exception('네트워크 오류가 발생했습니다: ${e.message}');
  }
}