import 'dart:convert';

import 'package:amazon_payfort/amazon_payfort.dart';
import 'package:hmg_patient_app/config/config.dart';
import 'package:hmg_patient_app/core/service/base_service.dart';
import 'package:hmg_patient_app/services/payfort_services/payfort_project_details_resp_model.dart';
import 'package:hmg_patient_app/services/payfort_services/sdk_token_response_model.dart';
import 'package:hmg_patient_app/uitl/utils.dart';
import 'package:http/http.dart';
import 'package:network_info_plus/network_info_plus.dart';

class PayfortService extends BaseService {
  final AmazonPayfort _payfort = AmazonPayfort.instance;

  final NetworkInfo _info = NetworkInfo();

  Future<void> initPayfortSDK() async {
    await AmazonPayfort.initialize(
      PayFortOptions(environment: payFortEnvironment),
    );
  }

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

    PayfortProjectDetailsRespModel payfortProjectDetailsRespModel = PayfortProjectDetailsRespModel();
    await baseAppClient.post(
      getPayFortProjectDetails,
      onSuccess: (response, statusCode) async {
        payfortProjectDetailsRespModel = PayfortProjectDetailsRespModel.fromJson(response.isNotEmpty ? response.first : response);
      },
      onFailure: (String error, int statusCode) {
        Utils.showErrorToast(error);
        return null;
      },
      body: body,
      isAllowAny: true,
    );
    return payfortProjectDetailsRespModel;
  }

  Future<void> addPayfortApplePayResponse(num patientID, {PayFortResult? result}) async {
    Map<String, dynamic> body = {
      "Fort_id": result!.fortId,
      "CommandType": result!.command,
      "Amount": (num.parse(result.amount!) / 100),
      "Payment_Option": result.paymentOption,
      "Customer_IP": result.customerIp,
      "ECI": result.eci,
      "Response_Message": result.responseMessage,
      "Card_Number": result.cardNumber,
      "Status": result.status,
      "Merchant_Ref": result.merchantReference,
      "Pat_Token": result.tokenName,
      "IsRefund": false,
      "RemmeberMe": false,
      // "Reconciliation_Reference": result.reconciliationReference,
      "LanguageID": 1,
      "PatientID": patientID
    };

    await baseAppClient.post(
      addPayFortApplePayResponse,
      onSuccess: (response, statusCode) async {
        // payfortProjectDetailsRespModel = PayfortProjectDetailsRespModel.fromJson(response.isNotEmpty ? response.first : response);
      },
      onFailure: (String error, int statusCode) {
        Utils.showErrorToast(error);
        return null;
      },
      body: body,
      isAllowAny: true,
    );
  }

  Future<SdkTokenResponse?>? generateSdkSignatureFromAPI(SdkTokenRequest request) async {
    var response = await post(
      Uri.parse(payFortEnvironment.paymentApi),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode(request.asRequest()),
    );
    if (response.statusCode == 200) {
      var decodedResponse = jsonDecode(response.body);
      return SdkTokenResponse.fromMap(decodedResponse);
    }
    return null;
  }

  Future<SdkTokenResponse?> _generateSdkResponse({
    String? applePayAccessCode,
    String? merchantIdentifier,
    String? applePayShaType,
    String? applePayShaRequestPhrase,
  }) async {
    try {
      String? deviceId = await _payfort.getDeviceId();

      /// Step 2:  Generate the Signature
      SdkTokenRequest tokenRequest = SdkTokenRequest(
        accessCode: applePayAccessCode!,
        deviceId: deviceId ?? '',
        merchantIdentifier: merchantIdentifier!,
      );

      String? signature = await _payfort.generateSignature(
        shaType: applePayShaType!,
        concatenatedString: tokenRequest.toConcatenatedString(applePayShaRequestPhrase!),
      );

      tokenRequest = tokenRequest.copyWith(signature: signature);

      /// Step 3: Generate the SDK Token
      return await generateSdkSignatureFromAPI(tokenRequest);
    } catch (e) {
      print("Error here: ${e.toString()}");
    }
    return null;
  }

  Future<String> getPayfortSignature(
    String applePayAccessCode,
    String merchantIdentifier,
    String applePayShaRequestPhrase,
  ) async {
    String? deviceId = await _payfort.getDeviceId();
    SdkTokenRequest tokenRequest = SdkTokenRequest(
      accessCode: applePayAccessCode,
      deviceId: deviceId ?? '',
      merchantIdentifier: merchantIdentifier,
    );

    String? signature = await _payfort.generateSignature(
      shaType: "SHA-256",
      concatenatedString: tokenRequest.toConcatenatedString(applePayShaRequestPhrase),
    );

    return signature!;
  }

  Future<void> paymentWithApplePay({
    SucceededCallback? onSucceeded,
    FailedCallback? onFailed,
    String? customerName,
    String? customerEmail,
    String? orderDescription,
    num? orderAmount,
    String? merchantIdentifier,
    String? applePayAccessCode,
    String? applePayShaRequestPhrase,
    String? merchantReference,
    String currency = "SAR",
    String applePayShaType = "SHA-256",
    String countryIsoCode = "SA",
  }) async {
    try {
      SdkTokenResponse? sdkTokenResponse = await _generateSdkResponse(
        applePayAccessCode: applePayAccessCode,
        merchantIdentifier: merchantIdentifier,
        applePayShaType: applePayShaType,
        applePayShaRequestPhrase: applePayShaRequestPhrase,
      );

      if (sdkTokenResponse != null && sdkTokenResponse.sdkToken == null) {
        onFailed!((sdkTokenResponse.responseMessage ?? '') as PayFortFailureResult);
        return;
      }

      /// Step 4: Processing Payment [Don't multiply with 100]
      /// Amount value send always round ex. [100] not [100.00, 100.21]
      FortRequest request = FortRequest(
          command: FortCommand.purchase,
          amount: orderAmount!,
          customerName: customerName!,
          customerEmail: customerEmail!,
          // orderDescription: orderDescription!,
          orderDescription: "Dr. Sulaiman Al Habib Hospital",
          sdkToken: sdkTokenResponse?.sdkToken ?? '',
          merchantReference: merchantReference!,
          currency: currency,
          customerIp: (await _info.getWifiIP() ?? ''),
          language: 'en');

      _payfort.callPayFortForApplePay(
        request: request,
        countryIsoCode: countryIsoCode,
        applePayMerchantId: applePayMerchantId,
        callback: ApplePayResultCallback(
          onSucceeded: onSucceeded!,
          onFailed: onFailed!,
        ),
      );
    } catch (e) {
      onFailed!(e.toString() as PayFortFailureResult);
    }
  }
}
