import 'package:dartz/dartz.dart';
import 'package:superport/core/errors/exceptions.dart';
import 'package:superport/core/errors/failures.dart';
import 'package:superport/data/datasources/remote/equipment_remote_datasource.dart';
import 'package:superport/data/models/equipment/equipment_dto.dart';
import 'package:superport/data/models/equipment/equipment_in_request.dart';
import 'package:superport/data/models/equipment/equipment_out_request.dart';
import 'package:superport/data/models/equipment/equipment_request.dart';
import 'package:superport/domain/repositories/equipment_repository.dart';
import 'package:superport/models/equipment_unified_model.dart';

class EquipmentRepositoryImpl implements EquipmentRepository {
  final EquipmentRemoteDataSource _remoteDataSource;

  EquipmentRepositoryImpl(this._remoteDataSource);

  @override
  Future<Either<Failure, List<EquipmentIn>>> getEquipmentIns({
    int? page,
    int? limit,
    String? search,
    String? sortBy,
    String? sortOrder,
  }) async {
    try {
      final response = await _remoteDataSource.getEquipments(
        page: page ?? 1,
        perPage: limit ?? 20,
        status: 'IN_WAREHOUSE',
        search: search,
      );

      final equipmentIns = response.items.map((dto) => 
        EquipmentIn(
          id: dto.id,
          equipment: Equipment(
            id: dto.id,
            manufacturer: dto.manufacturer,
            equipmentNumber: dto.equipmentNumber ?? '', // 새로운 필드 (required)
            modelName: dto.modelName ?? '', // 새로운 필드 (required)
            category1: 'N/A', // EquipmentListDto에는 category 필드가 없음 (required)
            category2: 'N/A', // EquipmentListDto에는 category 필드가 없음 (required)
            category3: 'N/A', // EquipmentListDto에는 category 필드가 없음 (required)
            serialNumber: dto.serialNumber,
            quantity: 1,
          ),
          inDate: dto.createdAt,
          status: 'I',
          type: '신제품',
          warehouseLocation: dto.warehouseName,
          remark: null,
        )
      ).toList();

      return Right(equipmentIns);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 입고 목록 조회 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, EquipmentIn>> getEquipmentInById(int id) async {
    try {
      final response = await _remoteDataSource.getEquipmentDetail(id);
      
      final equipmentIn = EquipmentIn(
        id: response.id,
        equipment: Equipment(
          id: response.id,
          manufacturer: response.manufacturer,
          equipmentNumber: response.equipmentNumber ?? '', // 새로운 필드 (required)
          modelName: response.modelName ?? '', // 새로운 필드 (required)
          category1: response.category1 ?? '', // 새로운 필드 (required)
          category2: response.category2 ?? '', // 새로운 필드 (required)
          category3: response.category3 ?? '', // 새로운 필드 (required)
          serialNumber: response.serialNumber,
          barcode: response.barcode,
          quantity: 1,
          purchaseDate: response.purchaseDate, // purchaseDate로 변경
          inDate: response.purchaseDate, // 기존 inDate 유지
          remark: response.remark,
        ),
        inDate: response.purchaseDate ?? DateTime.now(),
        status: 'I',
        type: '신제품',
        warehouseLocation: null,
        remark: response.remark,
      );

      return Right(equipmentIn);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 입고 상세 조회 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, EquipmentIn>> createEquipmentIn(EquipmentIn equipmentIn) async {
    try {
      final request = EquipmentInRequest(
        equipmentId: equipmentIn.equipment.id ?? 0,
        quantity: equipmentIn.equipment.quantity,
        warehouseLocationId: 0, // TODO: warehouseLocation string을 ID로 변환 필요
        notes: equipmentIn.remark,
      );

      final response = await _remoteDataSource.equipmentIn(request);

      final newEquipmentIn = EquipmentIn(
        id: response.transactionId,
        equipment: Equipment(
          id: response.equipmentId,
          manufacturer: 'N/A', // 트랜잭션 응답에는 제조사 정보 없음
          equipmentNumber: 'N/A', // name → equipmentNumber (required)
          modelName: 'N/A', // 새로운 필수 필드 (required)
          category1: 'N/A', // category → category1 (required)
          category2: 'N/A', // subCategory → category2 (required)
          category3: 'N/A', // subSubCategory → category3 (required)
          serialNumber: null,
          quantity: response.quantity,
        ),
        inDate: response.transactionDate,
        status: 'I',
        type: '신제품',
        warehouseLocation: null,
        remark: response.message,
      );

      return Right(newEquipmentIn);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 입고 생성 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, EquipmentIn>> updateEquipmentIn(int id, EquipmentIn equipmentIn) async {
    try {
      final request = UpdateEquipmentRequest(
        manufacturer: equipmentIn.equipment.manufacturer,
        modelName: equipmentIn.equipment.name,
        category1: equipmentIn.equipment.category,
        category2: equipmentIn.equipment.subCategory,
        category3: equipmentIn.equipment.subSubCategory,
        serialNumber: equipmentIn.equipment.serialNumber,
        barcode: equipmentIn.equipment.barcode,
        purchaseDate: equipmentIn.inDate,
        remark: equipmentIn.remark,
      );

      final response = await _remoteDataSource.updateEquipment(id, request);

      final updatedEquipmentIn = EquipmentIn(
        id: response.id,
        equipment: Equipment(
          id: response.id,
          manufacturer: response.manufacturer,
          equipmentNumber: response.equipmentNumber ?? '', // name → equipmentNumber (required)
          modelName: response.modelName ?? '', // 새로운 필수 필드 (required)
          category1: response.category1 ?? '', // category → category1 (required)
          category2: response.category2 ?? '', // subCategory → category2 (required)
          category3: response.category3 ?? '', // subSubCategory → category3 (required)
          serialNumber: response.serialNumber,
          barcode: response.barcode,
          quantity: 1,
          purchaseDate: response.purchaseDate, // purchaseDate로 변경
          inDate: response.purchaseDate, // 기존 inDate 유지
          remark: response.remark,
        ),
        inDate: response.purchaseDate ?? DateTime.now(),
        status: 'I',
        type: '신제품',
        warehouseLocation: null,
        remark: response.remark,
      );

      return Right(updatedEquipmentIn);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 입고 수정 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, void>> deleteEquipmentIn(int id) async {
    try {
      await _remoteDataSource.deleteEquipment(id);
      return const Right(null);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 입고 삭제 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, List<EquipmentOut>>> getEquipmentOuts({
    int? page,
    int? limit,
    String? search,
    String? sortBy,
    String? sortOrder,
  }) async {
    try {
      final response = await _remoteDataSource.getEquipments(
        page: page ?? 1,
        perPage: limit ?? 20,
        status: 'SHIPPED',
        search: search,
      );

      final equipmentOuts = response.items.map((dto) => 
        EquipmentOut(
          id: dto.id,
          equipment: Equipment(
            id: dto.id,
            manufacturer: dto.manufacturer,
            equipmentNumber: dto.equipmentNumber ?? '', // name → equipmentNumber (required)
            modelName: dto.modelName ?? '', // 새로운 필수 필드 (required)
            category1: 'N/A', // category → category1 (required)
            category2: 'N/A', // subCategory → category2 (required)
            category3: 'N/A', // subSubCategory → category3 (required)
            serialNumber: dto.serialNumber,
            quantity: 1,
          ),
          outDate: dto.createdAt,
          status: 'O',
          company: dto.companyName,
          remark: null,
        )
      ).toList();

      return Right(equipmentOuts);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 출고 목록 조회 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, EquipmentOut>> getEquipmentOutById(int id) async {
    try {
      final response = await _remoteDataSource.getEquipmentDetail(id);
      
      final equipmentOut = EquipmentOut(
        id: response.id,
        equipment: Equipment(
          id: response.id,
          manufacturer: response.manufacturer,
          equipmentNumber: response.equipmentNumber ?? '', // name → equipmentNumber (required)
          modelName: response.modelName ?? '', // 새로운 필수 필드 (required)
          category1: response.category1 ?? '', // category → category1 (required)
          category2: response.category2 ?? '', // subCategory → category2 (required)
          category3: response.category3 ?? '', // subSubCategory → category3 (required)
          serialNumber: response.serialNumber,
          barcode: response.barcode,
          quantity: 1,
          purchaseDate: response.purchaseDate, // purchaseDate로 변경
          inDate: response.purchaseDate, // 기존 inDate 유지
          remark: response.remark,
        ),
        outDate: DateTime.now(), // TODO: 실제 출고일 정보 필요
        status: 'O',
        company: null,
        remark: response.remark,
      );

      return Right(equipmentOut);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 출고 상세 조회 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, EquipmentOut>> createEquipmentOut(EquipmentOut equipmentOut) async {
    try {
      final request = EquipmentOutRequest(
        equipmentId: equipmentOut.equipment.id ?? 0,
        quantity: equipmentOut.equipment.quantity,
        companyId: 0, // TODO: company string을 ID로 변환 필요
        notes: equipmentOut.remark,
      );

      final response = await _remoteDataSource.equipmentOut(request);

      final newEquipmentOut = EquipmentOut(
        id: response.transactionId,
        equipment: Equipment(
          id: response.equipmentId,
          manufacturer: 'N/A', // 트랜잭션 응답에는 제조사 정보 없음
          equipmentNumber: 'N/A', // name → equipmentNumber (required)
          modelName: 'N/A', // 새로운 필수 필드 (required)
          category1: 'N/A', // category → category1 (required)
          category2: 'N/A', // subCategory → category2 (required)
          category3: 'N/A', // subSubCategory → category3 (required)
          serialNumber: null,
          quantity: response.quantity,
        ),
        outDate: response.transactionDate,
        status: 'O',
        company: null,
        remark: response.message,
      );

      return Right(newEquipmentOut);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 출고 생성 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, EquipmentOut>> updateEquipmentOut(int id, EquipmentOut equipmentOut) async {
    try {
      final request = UpdateEquipmentRequest(
        companyId: 0, // TODO: company string을 ID로 변환 필요
        remark: equipmentOut.remark,
      );

      final response = await _remoteDataSource.updateEquipment(id, request);

      final updatedEquipmentOut = EquipmentOut(
        id: response.id,
        equipment: Equipment(
          id: response.id,
          manufacturer: response.manufacturer,
          equipmentNumber: response.equipmentNumber ?? '', // name → equipmentNumber (required)
          modelName: response.modelName ?? '', // 새로운 필수 필드 (required)
          category1: response.category1 ?? '', // category → category1 (required)
          category2: response.category2 ?? '', // subCategory → category2 (required)
          category3: response.category3 ?? '', // subSubCategory → category3 (required)
          serialNumber: response.serialNumber,
          barcode: response.barcode,
          quantity: 1,
          purchaseDate: response.purchaseDate, // purchaseDate로 변경
          inDate: response.purchaseDate, // 기존 inDate 유지
          remark: response.remark,
        ),
        outDate: DateTime.now(), // TODO: 실제 출고일 정보 필요
        status: 'O',
        company: null,
        remark: response.remark,
      );

      return Right(updatedEquipmentOut);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 출고 수정 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, void>> deleteEquipmentOut(int id) async {
    try {
      await _remoteDataSource.deleteEquipment(id);
      return const Right(null);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 출고 삭제 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, List<EquipmentOut>>> createBatchEquipmentOut(List<EquipmentOut> equipmentOuts) async {
    try {
      final results = <EquipmentOut>[];
      
      for (final equipmentOut in equipmentOuts) {
        final request = EquipmentOutRequest(
          equipmentId: equipmentOut.equipment.id ?? 0,
          quantity: equipmentOut.equipment.quantity,
          companyId: 0, // TODO: company string을 ID로 변환 필요
          notes: equipmentOut.remark,
        );

        final response = await _remoteDataSource.equipmentOut(request);

        results.add(EquipmentOut(
          id: response.transactionId,
          equipment: Equipment(
            id: response.equipmentId,
            manufacturer: 'N/A', // 트랜잭션 응답에는 제조사 정보 없음
            equipmentNumber: 'N/A', // name → equipmentNumber (required)
            modelName: 'N/A', // 새로운 필수 필드 (required)
            category1: 'N/A', // category → category1 (required)
            category2: 'N/A', // subCategory → category2 (required)
            category3: 'N/A', // subSubCategory → category3 (required)
            serialNumber: null,
            quantity: response.quantity,
          ),
          outDate: response.transactionDate,
          status: 'O',
          company: null,
          remark: response.message,
        ));
      }

      return Right(results);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 일괄 출고 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, List<String>>> getManufacturers() async {
    try {
      // TODO: 실제 API 엔드포인트 구현 필요
      return const Right(['삼성', 'LG', 'Apple', 'Dell', 'HP']);
    } catch (e) {
      return Left(ServerFailure(message: '제조사 목록 조회 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, List<String>>> getEquipmentNames() async {
    try {
      // TODO: 실제 API 엔드포인트 구현 필요
      return const Right(['노트북', '모니터', '키보드', '마우스', '프린터']);
    } catch (e) {
      return Left(ServerFailure(message: '장비명 목록 조회 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, List<dynamic>>> getEquipmentHistory(int equipmentId) async {
    try {
      final history = await _remoteDataSource.getEquipmentHistory(equipmentId);
      return Right(history);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 이력 조회 실패: $e'));
    }
  }

  @override
  Future<Either<Failure, List<Equipment>>> searchEquipment({
    String? manufacturer,
    String? name,
    String? category,
    String? serialNumber,
  }) async {
    try {
      final response = await _remoteDataSource.getEquipments(
        search: serialNumber ?? name ?? manufacturer,
        page: 1,
        perPage: 50,
      );

      final equipments = response.items.map<Equipment>((dto) => 
        Equipment(
          id: dto.id,
          manufacturer: dto.manufacturer,
          equipmentNumber: dto.equipmentNumber ?? '', // name → equipmentNumber (required)
          modelName: dto.modelName ?? '', // 새로운 필수 필드 (required)
          category1: 'N/A', // category → category1 (required)
          category2: 'N/A', // subCategory → category2 (required)
          category3: 'N/A', // subSubCategory → category3 (required)
          serialNumber: dto.serialNumber,
          quantity: 1,
        )
      ).toList();

      return Right(equipments);
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message ?? '서버 오류가 발생했습니다'));
    } catch (e) {
      return Left(ServerFailure(message: '장비 검색 실패: $e'));
    }
  }
}