import 'package:amazon_payfort/amazon_payfort.dart';
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_check_payment_status_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_project_details_resp_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/sdk_token_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';

abstract class PayfortRepo {
  Future<Either<Failure, GenericApiModel<PayfortProjectDetailsRespModel>>> getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2});

  Future<Either<Failure, GenericApiModel<dynamic>>> applePayRequestInsert({required ApplePayInsertRequest applePayInsertRequest});

  Future<Either<Failure, GenericApiModel<SdkTokenResponse>>> generateSdkSignatureFromAPI({required SdkTokenRequest tokenRequest});

  Future<Either<Failure, GenericApiModel<PayfortCheckPaymentStatusResponseModel>>> checkPaymentStatus({required String transactionID});
}

class PayfortRepoImp implements PayfortRepo {
  final ApiClient apiClient;
  final LoggerService loggerService;

  PayfortRepoImp({required this.loggerService, required this.apiClient});

  @override
  Future<Either<Failure, GenericApiModel<PayfortProjectDetailsRespModel>>> getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2}) async {
    Map<String, dynamic> body = {"Integration_Id": integrationId, "ServID": serviceId, "ProjectID": projectId};

    try {
      GenericApiModel<PayfortProjectDetailsRespModel>? apiResponse;
      Failure? failure;
      await apiClient.post(getPayFortProjectDetails, body: body, onFailure: (error, statusCode, {messageStatus, failureType}) {
        failure = failureType;
      }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
        try {
          final list = response;
          if (list == null || list.isEmpty) {
            throw Exception("payfort list is empty");
          }

          final applePayConfigurationResponse = PayfortProjectDetailsRespModel.fromJson(list[0]);

          apiResponse = GenericApiModel<PayfortProjectDetailsRespModel>(
            messageStatus: messageStatus,
            statusCode: statusCode,
            errorMessage: null,
            data: applePayConfigurationResponse,
          );
        } catch (e) {
          failure = DataParsingFailure(e.toString());
        }
      }, isAllowAny: true);
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel>> applePayRequestInsert({required ApplePayInsertRequest applePayInsertRequest}) async {
    try {
      GenericApiModel<dynamic>? apiResponse;
      Failure? failure;
      await apiClient.post(APPLE_PAY_INSERT_REQUEST, body: applePayInsertRequest.toJson(), onFailure: (error, statusCode, {messageStatus, failureType}) {
        failure = failureType;
      }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
        try {
          apiResponse = GenericApiModel<dynamic>(
            messageStatus: messageStatus,
            statusCode: statusCode,
            errorMessage: null,
            data: response["result"],
          );
        } catch (e) {
          failure = DataParsingFailure(e.toString());
        }
      }, isAllowAny: true);
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel<SdkTokenResponse>>> generateSdkSignatureFromAPI({required SdkTokenRequest tokenRequest}) async {
    try {
      GenericApiModel<SdkTokenResponse>? apiResponse;
      Failure? failure;
      await apiClient.post(ApiConsts.payFortEnvironment.paymentApi, body: tokenRequest.asRequest(), onFailure: (error, statusCode, {messageStatus, failureType}) {
        failure = failureType;
      }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
        try {
          final sdkTokenResponse = SdkTokenResponse.fromMap(response);

          apiResponse = GenericApiModel<SdkTokenResponse>(
            messageStatus: messageStatus,
            statusCode: statusCode,
            errorMessage: null,
            data: sdkTokenResponse,
          );
        } catch (e) {
          failure = DataParsingFailure(e.toString());
        }
      }, isAllowAny: true, isExternal: true);
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, GenericApiModel<PayfortCheckPaymentStatusResponseModel>>> checkPaymentStatus({required String transactionID}) async {
    Map<String, dynamic> body = {"ClientRequestID": transactionID, "IsPharmacy": false};
    try {
      GenericApiModel<PayfortCheckPaymentStatusResponseModel>? apiResponse;
      Failure? failure;
      await apiClient.post(CHECK_PAYMENT_STATUS, body: body, onFailure: (error, statusCode, {messageStatus, failureType}) {
        failure = failureType;
      }, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
        try {
          final paymentStatusResponse = PayfortCheckPaymentStatusResponseModel.fromJson(response);

          apiResponse = GenericApiModel<PayfortCheckPaymentStatusResponseModel>(
            messageStatus: messageStatus,
            statusCode: statusCode,
            errorMessage: null,
            data: paymentStatusResponse,
          );
        } catch (e) {
          failure = DataParsingFailure(e.toString());
        }
      }, isAllowAny: true);
      if (failure != null) return Left(failure!);
      if (apiResponse == null) return Left(ServerFailure("Unknown error"));
      return Right(apiResponse!);
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }
}
