import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';

import '../../../../core/errors/failures.dart';
import '../../domain/entities/kyc_level_entity.dart';
import '../../domain/entities/kyc_application_entity.dart';
import '../../domain/repositories/kyc_repository.dart';
import '../datasources/kyc_remote_datasource.dart';
import '../models/kyc_application_model.dart';

@Injectable(as: KycRepository)
class KycRepositoryImpl implements KycRepository {
  final KycRemoteDataSource _remoteDataSource;

  KycRepositoryImpl(this._remoteDataSource);

  @override
  Future<Either<Failure, List<KycLevelEntity>>> getKycLevels() async {
    print('🔵 KYC_REPO: Getting KYC levels');

    try {
      final levels = await _remoteDataSource.getKycLevels();
      print('🟢 KYC_REPO: Successfully got ${levels.length} KYC levels');
      return Right(levels);
    } on DioException catch (e) {
      print('🔴 KYC_REPO: Dio error getting KYC levels: ${e.message}');
      if (e.response?.statusCode == 401) {
        return Left(UnauthorizedFailure('Authentication required'));
      } else if (e.response?.statusCode == 404) {
        return Left(NotFoundFailure('KYC levels not found'));
      } else {
        return Left(ServerFailure(e.message ?? 'Failed to get KYC levels'));
      }
    } catch (e) {
      print('🔴 KYC_REPO: Unexpected error getting KYC levels: $e');
      return Left(ServerFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, KycLevelEntity>> getKycLevelById(
      String levelId) async {
    print('🔵 KYC_REPO: Getting KYC level by ID: $levelId');

    try {
      final level = await _remoteDataSource.getKycLevelById(levelId);
      print('🟢 KYC_REPO: Successfully got KYC level');
      return Right(level);
    } on DioException catch (e) {
      print('🔴 KYC_REPO: Dio error getting KYC level: ${e.message}');
      if (e.response?.statusCode == 401) {
        return Left(UnauthorizedFailure('Authentication required'));
      } else if (e.response?.statusCode == 404) {
        return Left(NotFoundFailure('KYC level not found'));
      } else {
        return Left(ServerFailure(e.message ?? 'Failed to get KYC level'));
      }
    } catch (e) {
      print('🔴 KYC_REPO: Unexpected error getting KYC level: $e');
      return Left(ServerFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, List<KycApplicationEntity>>>
      getKycApplications() async {
    print('🔵 KYC_REPO: Getting KYC applications');

    try {
      final applications = await _remoteDataSource.getKycApplications();
      print(
          '🟢 KYC_REPO: Successfully got ${applications.length} KYC applications');
      return Right(applications);
    } on DioException catch (e) {
      print('🔴 KYC_REPO: Dio error getting KYC applications: ${e.message}');
      if (e.response?.statusCode == 401) {
        return Left(UnauthorizedFailure('Authentication required'));
      } else if (e.response?.statusCode == 404) {
        return Left(NotFoundFailure('No KYC applications found'));
      } else {
        return Left(
            ServerFailure(e.message ?? 'Failed to get KYC applications'));
      }
    } catch (e) {
      print('🔴 KYC_REPO: Unexpected error getting KYC applications: $e');
      return Left(ServerFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, KycApplicationEntity>> getKycApplicationById(
      String applicationId) async {
    print('🔵 KYC_REPO: Getting KYC application by ID: $applicationId');

    try {
      final application =
          await _remoteDataSource.getKycApplicationById(applicationId);
      print('🟢 KYC_REPO: Successfully got KYC application');
      return Right(application);
    } on DioException catch (e) {
      print('🔴 KYC_REPO: Dio error getting KYC application: ${e.message}');
      if (e.response?.statusCode == 401) {
        return Left(UnauthorizedFailure('Authentication required'));
      } else if (e.response?.statusCode == 404) {
        return Left(NotFoundFailure('KYC application not found'));
      } else {
        return Left(
            ServerFailure(e.message ?? 'Failed to get KYC application'));
      }
    } catch (e) {
      print('🔴 KYC_REPO: Unexpected error getting KYC application: $e');
      return Left(ServerFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, KycApplicationEntity>> submitKycApplication({
    required String levelId,
    required Map<String, dynamic> fields,
  }) async {
    print('🔵 KYC_REPO: Submitting KYC application for level: $levelId');

    try {
      final application = await _remoteDataSource.submitKycApplication(
        levelId: levelId,
        fields: fields,
      );
      print('🟢 KYC_REPO: Successfully submitted KYC application');
      return Right(application);
    } on DioException catch (e) {
      print('🔴 KYC_REPO: Dio error submitting KYC application: ${e.message}');
      if (e.response?.statusCode == 401) {
        return Left(UnauthorizedFailure('Authentication required'));
      } else if (e.response?.statusCode == 400) {
        return Left(ValidationFailure(
            e.response?.data['message'] ?? 'Invalid application data'));
      } else if (e.response?.statusCode == 404) {
        return Left(NotFoundFailure('KYC level not found'));
      } else {
        return Left(
            ServerFailure(e.message ?? 'Failed to submit KYC application'));
      }
    } catch (e) {
      print('🔴 KYC_REPO: Unexpected error submitting KYC application: $e');
      return Left(ServerFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, KycApplicationEntity>> updateKycApplication({
    required String applicationId,
    required Map<String, dynamic> fields,
  }) async {
    print('🔵 KYC_REPO: Updating KYC application: $applicationId');

    try {
      final application = await _remoteDataSource.updateKycApplication(
        applicationId: applicationId,
        fields: fields,
      );
      print('🟢 KYC_REPO: Successfully updated KYC application');
      return Right(application);
    } on DioException catch (e) {
      print('🔴 KYC_REPO: Dio error updating KYC application: ${e.message}');
      if (e.response?.statusCode == 401) {
        return Left(UnauthorizedFailure('Authentication required'));
      } else if (e.response?.statusCode == 400) {
        return Left(ValidationFailure(
            e.response?.data['message'] ?? 'Invalid application data'));
      } else if (e.response?.statusCode == 404) {
        return Left(NotFoundFailure('KYC application not found'));
      } else {
        return Left(
            ServerFailure(e.message ?? 'Failed to update KYC application'));
      }
    } catch (e) {
      print('🔴 KYC_REPO: Unexpected error updating KYC application: $e');
      return Left(ServerFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, String>> uploadKycDocument({
    required String filePath,
    required String fieldId,
    String? applicationId,
  }) async {
    print('🔵 KYC_REPO: Uploading KYC document for field: $fieldId');

    try {
      final fileUrl = await _remoteDataSource.uploadKycDocument(
        filePath: filePath,
        fieldId: fieldId,
        applicationId: applicationId,
      );
      print('🟢 KYC_REPO: Successfully uploaded KYC document');
      return Right(fileUrl);
    } on DioException catch (e) {
      print('🔴 KYC_REPO: Dio error uploading KYC document: ${e.message}');
      if (e.response?.statusCode == 401) {
        return Left(UnauthorizedFailure('Authentication required'));
      } else if (e.response?.statusCode == 400) {
        return Left(ValidationFailure('Invalid file or file too large'));
      } else {
        return Left(ServerFailure(e.message ?? 'Failed to upload document'));
      }
    } catch (e) {
      print('🔴 KYC_REPO: Unexpected error uploading KYC document: $e');
      return Left(ServerFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, KycStatusEntity>> getKycStatus() async {
    print('🔵 KYC_REPO: Getting KYC status');

    try {
      final statusData = await _remoteDataSource.getKycStatus();

      final status = KycStatusEntity(
        isKycRequired: statusData['isKycRequired'] ?? false,
        isKycCompleted: statusData['isKycCompleted'] ?? false,
        currentLevel: statusData['currentLevel'] as String?,
        levelNumber: statusData['levelNumber'] as int?,
        availableFeatures: statusData['availableFeatures'] != null
            ? List<String>.from(statusData['availableFeatures'])
            : null,
        activeApplication: statusData['activeApplication'] != null
            ? KycApplicationModel.fromJson(statusData['activeApplication'])
            : null,
      );

      print('🟢 KYC_REPO: Successfully got KYC status');
      return Right(status);
    } on DioException catch (e) {
      print('🔴 KYC_REPO: Dio error getting KYC status: ${e.message}');
      if (e.response?.statusCode == 401) {
        return Left(UnauthorizedFailure('Authentication required'));
      } else {
        return Left(ServerFailure(e.message ?? 'Failed to get KYC status'));
      }
    } catch (e) {
      print('🔴 KYC_REPO: Unexpected error getting KYC status: $e');
      return Left(ServerFailure(e.toString()));
    }
  }
}
