// File: crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs
// Module: hyperswitch_connectors
// Public functions: 2
// Public structs: 32

use api_models::webhooks::IncomingWebhookEvent;
use cards::CardNumber;
use common_enums::enums;
use common_utils::{
    pii::{self, SecretSerdeValue},
    request::Method,
    types::MinorUnit,
};
use error_stack::ResultExt;
use hyperswitch_domain_models::{
    payment_method_data::{
        BankRedirectData, BankTransferData, Card as CardData, CryptoData, GiftCardData,
        PayLaterData, PaymentMethodData, VoucherData, WalletData,
    },
    router_data::{ConnectorAuthType, RouterData},
    router_flow_types::refunds::{Execute, RSync},
    router_request_types::{
        CompleteAuthorizeData, PaymentsAuthorizeData, PaymentsPreProcessingData, ResponseId,
    },
    router_response_types::{PaymentsResponseData, RedirectForm, RefundsResponseData},
    types::{PaymentsPreProcessingRouterData, RefundsRouterData},
};
use hyperswitch_interfaces::errors;
use masking::Secret;
use serde::{Deserialize, Serialize};
use url::Url;

use crate::{
    types::{
        PaymentsPreprocessingResponseRouterData, RefundsResponseRouterData, ResponseRouterData,
    },
    utils::{
        self, to_connector_meta, PaymentsAuthorizeRequestData,
        PaymentsCompleteAuthorizeRequestData, PaymentsPreProcessingRequestData, RouterData as _,
    },
};

type Error = error_stack::Report<errors::ConnectorError>;

trait Shift4AuthorizePreprocessingCommon {
    fn is_automatic_capture(&self) -> Result<bool, Error>;
    fn get_router_return_url(&self) -> Option<String>;
    fn get_email_optional(&self) -> Option<pii::Email>;
    fn get_complete_authorize_url(&self) -> Option<String>;
    fn get_currency_required(&self) -> Result<enums::Currency, Error>;
    fn get_metadata(&self) -> Result<Option<serde_json::Value>, Error>;
    fn get_payment_method_data_required(&self) -> Result<PaymentMethodData, Error>;
}

pub struct Shift4RouterData<T> {
    pub amount: MinorUnit,
    pub router_data: T,
}

impl<T> TryFrom<(MinorUnit, T)> for Shift4RouterData<T> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from((amount, item): (MinorUnit, T)) -> Result<Self, Self::Error> {
        Ok(Self {
            amount,
            router_data: item,
        })
    }
}

impl Shift4AuthorizePreprocessingCommon for PaymentsAuthorizeData {
    fn get_email_optional(&self) -> Option<pii::Email> {
        self.email.clone()
    }

    fn get_complete_authorize_url(&self) -> Option<String> {
        self.complete_authorize_url.clone()
    }

    fn get_currency_required(
        &self,
    ) -> Result<enums::Currency, error_stack::Report<errors::ConnectorError>> {
        Ok(self.currency)
    }
    fn get_payment_method_data_required(
        &self,
    ) -> Result<PaymentMethodData, error_stack::Report<errors::ConnectorError>> {
        Ok(self.payment_method_data.clone())
    }

    fn is_automatic_capture(&self) -> Result<bool, Error> {
        self.is_auto_capture()
    }

    fn get_router_return_url(&self) -> Option<String> {
        self.router_return_url.clone()
    }

    fn get_metadata(
        &self,
    ) -> Result<Option<serde_json::Value>, error_stack::Report<errors::ConnectorError>> {
        Ok(self.metadata.clone())
    }
}

impl Shift4AuthorizePreprocessingCommon for PaymentsPreProcessingData {
    fn get_email_optional(&self) -> Option<pii::Email> {
        self.email.clone()
    }

    fn get_complete_authorize_url(&self) -> Option<String> {
        self.complete_authorize_url.clone()
    }

    fn get_currency_required(&self) -> Result<enums::Currency, Error> {
        self.get_currency()
    }
    fn get_payment_method_data_required(&self) -> Result<PaymentMethodData, Error> {
        self.payment_method_data.clone().ok_or(
            errors::ConnectorError::MissingRequiredField {
                field_name: "payment_method_data",
            }
            .into(),
        )
    }
    fn is_automatic_capture(&self) -> Result<bool, Error> {
        self.is_auto_capture()
    }

    fn get_router_return_url(&self) -> Option<String> {
        self.router_return_url.clone()
    }
    fn get_metadata(
        &self,
    ) -> Result<Option<serde_json::Value>, error_stack::Report<errors::ConnectorError>> {
        Ok(None)
    }
}
#[derive(Debug, Serialize)]
pub struct Shift4PaymentsRequest {
    amount: MinorUnit,
    currency: enums::Currency,
    captured: bool,
    metadata: Option<serde_json::Value>,
    #[serde(flatten)]
    payment_method: Shift4PaymentMethod,
}

#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum Shift4PaymentMethod {
    CardsNon3DSRequest(Box<CardsNon3DSRequest>),
    BankRedirectRequest(Box<BankRedirectRequest>),
    Cards3DSRequest(Box<Cards3DSRequest>),
    VoucherRequest(Box<VoucherRequest>),
    WalletRequest(Box<WalletRequest>),
    PayLaterRequest(Box<PayLaterRequest>),
    CryptoRequest(Box<CryptoRequest>),
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WalletRequest {
    flow: Flow,
    payment_method: PaymentMethod,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PayLaterRequest {
    flow: Flow,
    payment_method: PaymentMethod,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CryptoRequest {
    flow: Flow,
    payment_method: PaymentMethod,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct VoucherRequest {
    flow: Flow,
    payment_method: PaymentMethod,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BankRedirectRequest {
    payment_method: PaymentMethod,
    flow: Flow,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Cards3DSRequest {
    #[serde(rename = "card[number]")]
    pub card_number: CardNumber,
    #[serde(rename = "card[expMonth]")]
    pub card_exp_month: Secret<String>,
    #[serde(rename = "card[expYear]")]
    pub card_exp_year: Secret<String>,
    return_url: String,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CardsNon3DSRequest {
    card: CardPayment,
    description: Option<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Flow {
    pub return_url: String,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum PaymentMethodType {
    Eps,
    Giropay,
    Ideal,
    Sofort,
    Boleto,
    Trustly,
    Alipay,
    Wechatpay,
    Blik,
    KlarnaDebitRisk,
    Bitpay,
    Paysera,
    Skrill,
}

#[derive(Debug, Serialize)]
pub struct PaymentMethod {
    #[serde(rename = "type")]
    method_type: PaymentMethodType,
    billing: Billing,
}

#[derive(Debug, Serialize)]
pub struct Billing {
    name: Option<Secret<String>>,
    email: Option<pii::Email>,
    address: Option<Address>,
    #[serde(skip_serializing_if = "Option::is_none")]
    vat: Option<Secret<String>>,
}

#[derive(Debug, Serialize)]
pub struct Address {
    line1: Option<Secret<String>>,
    line2: Option<Secret<String>>,
    zip: Option<Secret<String>>,
    state: Option<Secret<String>>,
    city: Option<String>,
    country: Option<api_models::enums::CountryAlpha2>,
}

#[derive(Default, Debug, Serialize, Eq, PartialEq)]
pub struct DeviceData;

#[derive(Default, Debug, Serialize, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Card {
    pub number: CardNumber,
    pub exp_month: Secret<String>,
    pub exp_year: Secret<String>,
    pub cardholder_name: Secret<String>,
}

#[derive(Debug, Serialize, Eq, PartialEq)]
#[serde(untagged)]
pub enum CardPayment {
    RawCard(Box<Card>),
    CardToken(Secret<String>),
}

impl<T, Req> TryFrom<&Shift4RouterData<&RouterData<T, Req, PaymentsResponseData>>>
    for Shift4PaymentsRequest
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(
        item: &Shift4RouterData<&RouterData<T, Req, PaymentsResponseData>>,
    ) -> Result<Self, Self::Error> {
        let submit_for_settlement = item.router_data.request.is_automatic_capture()?;
        let amount = item.amount.to_owned();
        let currency = item.router_data.request.get_currency_required()?;
        let metadata = item.router_data.request.get_metadata()?;
        let payment_method = Shift4PaymentMethod::try_from(item.router_data)?;
        Ok(Self {
            amount,
            currency,
            captured: submit_for_settlement,
            metadata,
            payment_method,
        })
    }
}

impl TryFrom<&PayLaterData> for PaymentMethodType {
    type Error = Error;
    fn try_from(value: &PayLaterData) -> Result<Self, Self::Error> {
        match value {
            PayLaterData::KlarnaRedirect { .. } => Ok(Self::KlarnaDebitRisk),
            PayLaterData::AffirmRedirect { .. }
            | PayLaterData::AfterpayClearpayRedirect { .. }
            | PayLaterData::PayBrightRedirect { .. }
            | PayLaterData::WalleyRedirect { .. }
            | PayLaterData::AlmaRedirect { .. }
            | PayLaterData::AtomeRedirect { .. }
            | PayLaterData::FlexitiRedirect { .. }
            | PayLaterData::KlarnaSdk { .. }
            | PayLaterData::BreadpayRedirect { .. } => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Shift4"),
            )
            .into()),
        }
    }
}

impl<T, Req> TryFrom<(&RouterData<T, Req, PaymentsResponseData>, &PayLaterData)>
    for Shift4PaymentMethod
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(
        (item, pay_later_data): (&RouterData<T, Req, PaymentsResponseData>, &PayLaterData),
    ) -> Result<Self, Self::Error> {
        let flow = Flow::try_from(item.request.get_router_return_url())?;
        let method_type = PaymentMethodType::try_from(pay_later_data)?;
        let billing = Billing::try_from(item)?;
        let payment_method = PaymentMethod {
            method_type,
            billing,
        };
        Ok(Self::BankRedirectRequest(Box::new(BankRedirectRequest {
            payment_method,
            flow,
        })))
    }
}

impl<T, Req> TryFrom<&RouterData<T, Req, PaymentsResponseData>> for Shift4PaymentMethod
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(item: &RouterData<T, Req, PaymentsResponseData>) -> Result<Self, Self::Error> {
        match item.request.get_payment_method_data_required()? {
            PaymentMethodData::Card(ref ccard) => Self::try_from((item, ccard)),
            PaymentMethodData::BankRedirect(ref redirect) => Self::try_from((item, redirect)),
            PaymentMethodData::Wallet(ref wallet_data) => Self::try_from((item, wallet_data)),
            PaymentMethodData::BankTransfer(ref bank_transfer_data) => {
                Self::try_from(bank_transfer_data.as_ref())
            }
            PaymentMethodData::Voucher(ref voucher_data) => Self::try_from((item, voucher_data)),
            PaymentMethodData::GiftCard(ref giftcard_data) => {
                Self::try_from(giftcard_data.as_ref())
            }
            PaymentMethodData::PayLater(ref pay_later_data) => {
                Self::try_from((item, pay_later_data))
            }
            PaymentMethodData::Crypto(ref crypto_data) => Self::try_from((item, crypto_data)),
            PaymentMethodData::CardRedirect(_)
            | PaymentMethodData::BankDebit(_)
            | PaymentMethodData::MandatePayment
            | PaymentMethodData::Reward
            | PaymentMethodData::RealTimePayment(_)
            | PaymentMethodData::MobilePayment(_)
            | PaymentMethodData::Upi(_)
            | PaymentMethodData::OpenBanking(_)
            | PaymentMethodData::CardToken(_)
            | PaymentMethodData::NetworkToken(_)
            | PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
                Err(errors::ConnectorError::NotImplemented(
                    utils::get_unimplemented_payment_method_error_message("Shift4"),
                )
                .into())
            }
        }
    }
}

impl TryFrom<&WalletData> for PaymentMethodType {
    type Error = Error;
    fn try_from(value: &WalletData) -> Result<Self, Self::Error> {
        match value {
            WalletData::AliPayRedirect { .. } => Ok(Self::Alipay),
            WalletData::WeChatPayRedirect { .. } => Ok(Self::Wechatpay),
            WalletData::Paysera(_) => Ok(Self::Paysera),
            WalletData::Skrill(_) => Ok(Self::Skrill),
            WalletData::AliPayQr(_)
            | WalletData::AmazonPay(_)
            | WalletData::AliPayHkRedirect(_)
            | WalletData::AmazonPayRedirect(_)
            | WalletData::MomoRedirect(_)
            | WalletData::KakaoPayRedirect(_)
            | WalletData::GoPayRedirect(_)
            | WalletData::GcashRedirect(_)
            | WalletData::ApplePay(_)
            | WalletData::ApplePayRedirect(_)
            | WalletData::ApplePayThirdPartySdk(_)
            | WalletData::DanaRedirect {}
            | WalletData::GooglePayRedirect(_)
            | WalletData::GooglePayThirdPartySdk(_)
            | WalletData::GooglePay(_)
            | WalletData::BluecodeRedirect {}
            | WalletData::PaypalRedirect(_)
            | WalletData::MbWayRedirect(_)
            | WalletData::MobilePayRedirect(_)
            | WalletData::PaypalSdk(_)
            | WalletData::Paze(_)
            | WalletData::SamsungPay(_)
            | WalletData::TwintRedirect {}
            | WalletData::VippsRedirect {}
            | WalletData::TouchNGoRedirect(_)
            | WalletData::WeChatPayQr(_)
            | WalletData::CashappQr(_)
            | WalletData::SwishQr(_)
            | WalletData::Mifinity(_)
            | WalletData::RevolutPay(_) => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Shift4"),
            )
            .into()),
        }
    }
}

impl<T, Req> TryFrom<(&RouterData<T, Req, PaymentsResponseData>, &WalletData)>
    for Shift4PaymentMethod
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(
        (item, wallet_data): (&RouterData<T, Req, PaymentsResponseData>, &WalletData),
    ) -> Result<Self, Self::Error> {
        let flow = Flow::try_from(item.request.get_router_return_url())?;
        let method_type = PaymentMethodType::try_from(wallet_data)?;
        let billing = Billing::try_from(item)?;
        let payment_method = PaymentMethod {
            method_type,
            billing,
        };
        Ok(Self::WalletRequest(Box::new(WalletRequest {
            payment_method,
            flow,
        })))
    }
}
impl TryFrom<&BankTransferData> for Shift4PaymentMethod {
    type Error = Error;
    fn try_from(bank_transfer_data: &BankTransferData) -> Result<Self, Self::Error> {
        match bank_transfer_data {
            BankTransferData::MultibancoBankTransfer { .. }
            | BankTransferData::AchBankTransfer { .. }
            | BankTransferData::SepaBankTransfer { .. }
            | BankTransferData::BacsBankTransfer { .. }
            | BankTransferData::PermataBankTransfer { .. }
            | BankTransferData::BcaBankTransfer { .. }
            | BankTransferData::BniVaBankTransfer { .. }
            | BankTransferData::BriVaBankTransfer { .. }
            | BankTransferData::CimbVaBankTransfer { .. }
            | BankTransferData::DanamonVaBankTransfer { .. }
            | BankTransferData::MandiriVaBankTransfer { .. }
            | BankTransferData::Pix { .. }
            | BankTransferData::Pse {}
            | BankTransferData::InstantBankTransfer {}
            | BankTransferData::InstantBankTransferFinland { .. }
            | BankTransferData::InstantBankTransferPoland { .. }
            | BankTransferData::IndonesianBankTransfer { .. }
            | BankTransferData::LocalBankTransfer { .. } => {
                Err(errors::ConnectorError::NotImplemented(
                    utils::get_unimplemented_payment_method_error_message("Shift4"),
                )
                .into())
            }
        }
    }
}

impl TryFrom<&VoucherData> for PaymentMethodType {
    type Error = Error;
    fn try_from(value: &VoucherData) -> Result<Self, Self::Error> {
        match value {
            VoucherData::Boleto { .. } => Ok(Self::Boleto),
            VoucherData::Alfamart { .. }
            | VoucherData::Indomaret { .. }
            | VoucherData::Efecty
            | VoucherData::PagoEfectivo
            | VoucherData::RedCompra
            | VoucherData::Oxxo
            | VoucherData::RedPagos
            | VoucherData::SevenEleven { .. }
            | VoucherData::Lawson { .. }
            | VoucherData::MiniStop { .. }
            | VoucherData::FamilyMart { .. }
            | VoucherData::Seicomart { .. }
            | VoucherData::PayEasy { .. } => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Shift4"),
            )
            .into()),
        }
    }
}

impl<T, Req> TryFrom<(&RouterData<T, Req, PaymentsResponseData>, &VoucherData)>
    for Shift4PaymentMethod
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(
        (item, voucher_data): (&RouterData<T, Req, PaymentsResponseData>, &VoucherData),
    ) -> Result<Self, Self::Error> {
        let mut billing = Billing::try_from(item)?;
        match voucher_data {
            VoucherData::Boleto(boleto_data) => {
                billing.vat = boleto_data.social_security_number.clone();
            }
            _ => {
                billing.vat = None;
            }
        };

        let method_type = PaymentMethodType::try_from(voucher_data)?;

        let payment_method_details = PaymentMethod {
            method_type,
            billing,
        };
        let flow = Flow::try_from(item.request.get_router_return_url())?;
        Ok(Self::VoucherRequest(Box::new(VoucherRequest {
            payment_method: payment_method_details,
            flow,
        })))
    }
}

impl TryFrom<&GiftCardData> for Shift4PaymentMethod {
    type Error = Error;
    fn try_from(gift_card_data: &GiftCardData) -> Result<Self, Self::Error> {
        match gift_card_data {
            GiftCardData::Givex(_)
            | GiftCardData::PaySafeCard {}
            | GiftCardData::BhnCardNetwork(_) => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Shift4"),
            )
            .into()),
        }
    }
}

impl<T, Req> TryFrom<(&RouterData<T, Req, PaymentsResponseData>, &CardData)> for Shift4PaymentMethod
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(
        (item, card): (&RouterData<T, Req, PaymentsResponseData>, &CardData),
    ) -> Result<Self, Self::Error> {
        let card_object = Card {
            number: card.card_number.clone(),
            exp_month: card.card_exp_month.clone(),
            exp_year: card.card_exp_year.clone(),
            cardholder_name: item
                .get_optional_billing_full_name()
                .unwrap_or(Secret::new("".to_string())),
        };
        if item.is_three_ds() {
            Ok(Self::Cards3DSRequest(Box::new(Cards3DSRequest {
                card_number: card_object.number,
                card_exp_month: card_object.exp_month,
                card_exp_year: card_object.exp_year,
                return_url: item
                    .request
                    .get_complete_authorize_url()
                    .clone()
                    .ok_or_else(|| errors::ConnectorError::RequestEncodingFailed)?,
            })))
        } else {
            Ok(Self::CardsNon3DSRequest(Box::new(CardsNon3DSRequest {
                card: CardPayment::RawCard(Box::new(card_object)),
                description: item.description.clone(),
            })))
        }
    }
}

impl<T, Req> TryFrom<(&RouterData<T, Req, PaymentsResponseData>, &BankRedirectData)>
    for Shift4PaymentMethod
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(
        (item, redirect_data): (&RouterData<T, Req, PaymentsResponseData>, &BankRedirectData),
    ) -> Result<Self, Self::Error> {
        let flow = Flow::try_from(item.request.get_router_return_url())?;
        let method_type = PaymentMethodType::try_from(redirect_data)?;
        let billing = Billing::try_from(item)?;
        let payment_method = PaymentMethod {
            method_type,
            billing,
        };
        Ok(Self::BankRedirectRequest(Box::new(BankRedirectRequest {
            payment_method,
            flow,
        })))
    }
}

impl TryFrom<&CryptoData> for PaymentMethodType {
    type Error = Error;

    fn try_from(_value: &CryptoData) -> Result<Self, Self::Error> {
        Ok(Self::Bitpay)
    }
}

impl<T, Req> TryFrom<(&RouterData<T, Req, PaymentsResponseData>, &CryptoData)>
    for Shift4PaymentMethod
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(
        (item, redirect_data): (&RouterData<T, Req, PaymentsResponseData>, &CryptoData),
    ) -> Result<Self, Self::Error> {
        let flow = Flow::try_from(item.request.get_router_return_url())?;
        let method_type = PaymentMethodType::try_from(redirect_data)?;
        let billing = Billing::try_from(item)?;
        let payment_method = PaymentMethod {
            method_type,
            billing,
        };
        Ok(Self::CryptoRequest(Box::new(CryptoRequest {
            payment_method,
            flow,
        })))
    }
}

impl<T> TryFrom<&Shift4RouterData<&RouterData<T, CompleteAuthorizeData, PaymentsResponseData>>>
    for Shift4PaymentsRequest
{
    type Error = Error;
    fn try_from(
        item: &Shift4RouterData<&RouterData<T, CompleteAuthorizeData, PaymentsResponseData>>,
    ) -> Result<Self, Self::Error> {
        match &item.router_data.request.payment_method_data {
            Some(PaymentMethodData::Card(_)) => {
                let card_token: Shift4CardToken =
                    to_connector_meta(item.router_data.request.connector_meta.clone())?;
                let metadata = item.router_data.request.metadata.clone();
                Ok(Self {
                    amount: item.amount.to_owned(),
                    currency: item.router_data.request.currency,
                    metadata,
                    payment_method: Shift4PaymentMethod::CardsNon3DSRequest(Box::new(
                        CardsNon3DSRequest {
                            card: CardPayment::CardToken(card_token.id),
                            description: item.router_data.description.clone(),
                        },
                    )),
                    captured: item.router_data.request.is_auto_capture()?,
                })
            }
            Some(PaymentMethodData::Wallet(_))
            | Some(PaymentMethodData::GiftCard(_))
            | Some(PaymentMethodData::CardRedirect(_))
            | Some(PaymentMethodData::PayLater(_))
            | Some(PaymentMethodData::BankDebit(_))
            | Some(PaymentMethodData::BankRedirect(_))
            | Some(PaymentMethodData::BankTransfer(_))
            | Some(PaymentMethodData::Crypto(_))
            | Some(PaymentMethodData::MandatePayment)
            | Some(PaymentMethodData::Voucher(_))
            | Some(PaymentMethodData::Reward)
            | Some(PaymentMethodData::RealTimePayment(_))
            | Some(PaymentMethodData::MobilePayment(_))
            | Some(PaymentMethodData::Upi(_))
            | Some(PaymentMethodData::OpenBanking(_))
            | Some(PaymentMethodData::CardToken(_))
            | Some(PaymentMethodData::NetworkToken(_))
            | Some(PaymentMethodData::CardDetailsForNetworkTransactionId(_))
            | None => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Shift4"),
            )
            .into()),
        }
    }
}

impl TryFrom<&BankRedirectData> for PaymentMethodType {
    type Error = Error;
    fn try_from(value: &BankRedirectData) -> Result<Self, Self::Error> {
        match value {
            BankRedirectData::Eps { .. } => Ok(Self::Eps),
            BankRedirectData::Giropay { .. } => Ok(Self::Giropay),
            BankRedirectData::Ideal { .. } => Ok(Self::Ideal),
            BankRedirectData::Sofort { .. } => Ok(Self::Sofort),
            BankRedirectData::Trustly { .. } => Ok(Self::Trustly),
            BankRedirectData::Blik { .. } => Ok(Self::Blik),
            BankRedirectData::BancontactCard { .. }
            | BankRedirectData::Eft { .. }
            | BankRedirectData::Przelewy24 { .. }
            | BankRedirectData::Bizum {}
            | BankRedirectData::Interac { .. }
            | BankRedirectData::OnlineBankingCzechRepublic { .. }
            | BankRedirectData::OnlineBankingFinland { .. }
            | BankRedirectData::OnlineBankingPoland { .. }
            | BankRedirectData::OnlineBankingSlovakia { .. }
            | BankRedirectData::OpenBankingUk { .. }
            | BankRedirectData::OnlineBankingFpx { .. }
            | BankRedirectData::OnlineBankingThailand { .. }
            | BankRedirectData::LocalBankRedirect {} => {
                Err(errors::ConnectorError::NotImplemented(
                    utils::get_unimplemented_payment_method_error_message("Shift4"),
                )
                .into())
            }
        }
    }
}

impl TryFrom<Option<String>> for Flow {
    type Error = Error;
    fn try_from(router_return_url: Option<String>) -> Result<Self, Self::Error> {
        Ok(Self {
            return_url: router_return_url.ok_or(errors::ConnectorError::RequestEncodingFailed)?,
        })
    }
}

impl<T, Req> TryFrom<&RouterData<T, Req, PaymentsResponseData>> for Billing
where
    Req: Shift4AuthorizePreprocessingCommon,
{
    type Error = Error;
    fn try_from(item: &RouterData<T, Req, PaymentsResponseData>) -> Result<Self, Self::Error> {
        let billing_details = item.get_optional_billing();
        let address_details_model = billing_details.as_ref().and_then(|b| b.address.as_ref());
        let address = get_address_details(address_details_model);

        Ok(Self {
            name: item.get_optional_billing_full_name(),
            email: item.request.get_email_optional(),
            address,
            vat: None,
        })
    }
}

fn get_address_details(
    address_details: Option<&hyperswitch_domain_models::address::AddressDetails>,
) -> Option<Address> {
    address_details.map(|address| Address {
        line1: address.line1.clone(),
        line2: address.line1.clone(),
        zip: address.zip.clone(),
        state: address.state.clone(),
        city: address.city.clone(),
        country: address.country,
    })
}

// Auth Struct
pub struct Shift4AuthType {
    pub(super) api_key: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for Shift4AuthType {
    type Error = Error;
    fn try_from(item: &ConnectorAuthType) -> Result<Self, Self::Error> {
        if let ConnectorAuthType::HeaderKey { api_key } = item {
            Ok(Self {
                api_key: api_key.to_owned(),
            })
        } else {
            Err(errors::ConnectorError::FailedToObtainAuthType)?
        }
    }
}
// PaymentsResponse
#[derive(Debug, Clone, Default, Serialize, Deserialize, Eq, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Shift4PaymentStatus {
    Successful,
    Failed,
    #[default]
    Pending,
}

fn get_status(
    captured: bool,
    next_action: Option<&NextAction>,
    payment_status: Shift4PaymentStatus,
) -> enums::AttemptStatus {
    match payment_status {
        Shift4PaymentStatus::Successful => {
            if captured {
                enums::AttemptStatus::Charged
            } else {
                enums::AttemptStatus::Authorized
            }
        }
        Shift4PaymentStatus::Failed => enums::AttemptStatus::Failure,
        Shift4PaymentStatus::Pending => match next_action {
            Some(NextAction::Redirect) => enums::AttemptStatus::AuthenticationPending,
            Some(NextAction::Wait) | Some(NextAction::None) | None => enums::AttemptStatus::Pending,
        },
    }
}

#[derive(Debug, Deserialize)]
pub struct Shift4WebhookObjectEventType {
    #[serde(rename = "type")]
    pub event_type: Shift4WebhookEvent,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Shift4WebhookEvent {
    ChargeSucceeded,
    ChargeFailed,
    ChargeUpdated,
    ChargeCaptured,
    ChargeRefunded,
    #[serde(other)]
    Unknown,
}

#[derive(Debug, Deserialize)]
pub struct Shift4WebhookObjectData {
    pub id: String,
    pub refunds: Option<Vec<RefundIdObject>>,
}

#[derive(Debug, Deserialize)]
pub struct RefundIdObject {
    pub id: String,
}

#[derive(Debug, Deserialize)]
pub struct Shift4WebhookObjectId {
    #[serde(rename = "type")]
    pub event_type: Shift4WebhookEvent,
    pub data: Shift4WebhookObjectData,
}

#[derive(Debug, Deserialize)]
pub struct Shift4WebhookObjectResource {
    pub data: serde_json::Value,
}

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct Shift4NonThreeDsResponse {
    pub id: String,
    pub currency: String,
    pub amount: u32,
    pub status: Shift4PaymentStatus,
    pub captured: bool,
    pub refunded: bool,
    pub flow: Option<FlowResponse>,
}

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct Shift4ThreeDsResponse {
    pub enrolled: bool,
    pub version: Option<String>,
    #[serde(rename = "redirectUrl")]
    pub redirect_url: Option<Url>,
    pub token: Token,
}

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct Token {
    pub id: Secret<String>,
    pub created: i64,
    #[serde(rename = "objectType")]
    pub object_type: String,
    pub first6: String,
    pub last4: String,
    pub fingerprint: Secret<String>,
    pub brand: String,
    #[serde(rename = "type")]
    pub token_type: String,
    pub country: String,
    pub used: bool,
    #[serde(rename = "threeDSecureInfo")]
    pub three_d_secure_info: ThreeDSecureInfo,
}

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct ThreeDSecureInfo {
    pub amount: MinorUnit,
    pub currency: String,
    pub enrolled: bool,
    #[serde(rename = "liabilityShift")]
    pub liability_shift: Option<String>,
    pub version: String,
    #[serde(rename = "authenticationFlow")]
    pub authentication_flow: Option<SecretSerdeValue>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FlowResponse {
    pub next_action: Option<NextAction>,
    pub redirect: Option<Redirect>,
    pub return_url: Option<Url>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Redirect {
    pub redirect_url: Option<Url>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum NextAction {
    Redirect,
    Wait,
    None,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Shift4CardToken {
    pub id: Secret<String>,
}

impl TryFrom<PaymentsPreprocessingResponseRouterData<Shift4ThreeDsResponse>>
    for PaymentsPreProcessingRouterData
{
    type Error = Error;
    fn try_from(
        item: PaymentsPreprocessingResponseRouterData<Shift4ThreeDsResponse>,
    ) -> Result<Self, Self::Error> {
        let redirection_data = item
            .response
            .redirect_url
            .map(|url| RedirectForm::from((url, Method::Get)));
        Ok(Self {
            status: if redirection_data.is_some() {
                enums::AttemptStatus::AuthenticationPending
            } else {
                enums::AttemptStatus::Pending
            },
            request: PaymentsPreProcessingData {
                enrolled_for_3ds: item.response.enrolled,
                ..item.data.request
            },
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::NoResponseId,
                redirection_data: Box::new(redirection_data),
                mandate_reference: Box::new(None),
                connector_metadata: Some(
                    serde_json::to_value(Shift4CardToken {
                        id: item.response.token.id,
                    })
                    .change_context(errors::ConnectorError::ResponseDeserializationFailed)?,
                ),
                network_txn_id: None,
                connector_response_reference_id: None,
                incremental_authorization_allowed: None,
                charges: None,
            }),
            ..item.data
        })
    }
}

impl<T, F> TryFrom<ResponseRouterData<F, Shift4NonThreeDsResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<F, Shift4NonThreeDsResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        let connector_id = ResponseId::ConnectorTransactionId(item.response.id.clone());
        Ok(Self {
            status: get_status(
                item.response.captured,
                item.response
                    .flow
                    .as_ref()
                    .and_then(|flow| flow.next_action.as_ref()),
                item.response.status,
            ),
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: connector_id,
                redirection_data: Box::new(
                    item.response
                        .flow
                        .and_then(|flow| flow.redirect)
                        .and_then(|redirect| redirect.redirect_url)
                        .map(|url| RedirectForm::from((url, Method::Get))),
                ),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: Some(item.response.id),
                incremental_authorization_allowed: None,
                charges: None,
            }),
            ..item.data
        })
    }
}

// REFUND :
// Type definition for RefundRequest
#[derive(Default, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Shift4RefundRequest {
    charge_id: String,
    amount: MinorUnit,
}

impl<F> TryFrom<&Shift4RouterData<&RefundsRouterData<F>>> for Shift4RefundRequest {
    type Error = Error;
    fn try_from(item: &Shift4RouterData<&RefundsRouterData<F>>) -> Result<Self, Self::Error> {
        Ok(Self {
            charge_id: item.router_data.request.connector_transaction_id.clone(),
            amount: item.amount.to_owned(),
        })
    }
}

impl From<Shift4RefundStatus> for enums::RefundStatus {
    fn from(item: Shift4RefundStatus) -> Self {
        match item {
            Shift4RefundStatus::Successful => Self::Success,
            Shift4RefundStatus::Failed => Self::Failure,
            Shift4RefundStatus::Processing => Self::Pending,
        }
    }
}

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct RefundResponse {
    pub id: String,
    pub amount: i64,
    pub currency: String,
    pub charge: String,
    pub status: Shift4RefundStatus,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize, Eq, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Shift4RefundStatus {
    Successful,
    Processing,
    #[default]
    Failed,
}

impl TryFrom<RefundsResponseRouterData<Execute, RefundResponse>> for RefundsRouterData<Execute> {
    type Error = Error;
    fn try_from(
        item: RefundsResponseRouterData<Execute, RefundResponse>,


// Trait: AuthInfo
// File: crates/router/src/services/authentication.rs
// Module: router

pub trait AuthInfo


// Struct: MerchantDetails
// File: crates/hyperswitch_domain_models/src/router_request_types/unified_authentication_service.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct MerchantDetails


// Trait: VaultingDataInterface
// File: crates/hyperswitch_domain_models/src/vault.rs
// Module: hyperswitch_domain_models

pub trait VaultingDataInterface


// Implementation: impl Payouts
// File: crates/diesel_models/src/query/payouts.rs
// Module: diesel_models
// Methods: 5 total (0 public)

impl Payouts


// Implementation: impl FromStr for for AciStatus
// File: crates/hyperswitch_connectors/src/connectors/aci/transformers.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl FromStr for for AciStatus


                }
                PaymentMethodData::Voucher(ref voucher_data) => {
                    AdyenPaymentRequest::try_from((item, voucher_data))
                }
                PaymentMethodData::GiftCard(ref gift_card_data) => {
                    AdyenPaymentRequest::try_from((item, gift_card_data.as_ref()))
                }
                PaymentMethodData::NetworkToken(ref token_data) => {
                    AdyenPaymentRequest::try_from((item, token_data))
                }
                PaymentMethodData::Crypto(_)
                | PaymentMethodData::MandatePayment
                | PaymentMethodData::Reward
                | PaymentMethodData::RealTimePayment(_)
                | PaymentMethodData::MobilePayment(_)
                | PaymentMethodData::Upi(_)
                | PaymentMethodData::OpenBanking(_)
                | PaymentMethodData::CardToken(_)
                | PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
                    Err(errors::ConnectorError::NotImplemented(
                        utils::get_unimplemented_payment_method_error_message("Adyen"),
                    ))?
                }
            },
        }
    }
}

impl TryFrom<&PaymentsPreProcessingRouterData> for AdyenBalanceRequest<'_> {
    type Error = Error;
    fn try_from(item: &PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> {
        let payment_method = match &item.request.payment_method_data {
            Some(PaymentMethodData::GiftCard(gift_card_data)) => match gift_card_data.as_ref() {
                GiftCardData::Givex(gift_card_data) => {
                    let balance_pm = BalancePmData {
                        number: gift_card_data.number.clone(),
                        cvc: gift_card_data.cvc.clone(),
                    };
                    Ok(AdyenPaymentMethod::PaymentMethodBalance(Box::new(
                        balance_pm,
                    )))
                }
                GiftCardData::PaySafeCard {} | GiftCardData::BhnCardNetwork(_) => {
                    Err(errors::ConnectorError::FlowNotSupported {
                        flow: "Balance".to_string(),
                        connector: "adyen".to_string(),
                    })
                }
            },
            _ => Err(errors::ConnectorError::FlowNotSupported {
                flow: "Balance".to_string(),
                connector: "adyen".to_string(),
            }),
        }?;
        let auth_type = AdyenAuthType::try_from(&item.connector_auth_type)?;
        Ok(Self {
            payment_method,
            merchant_account: auth_type.merchant_account,
        })
    }
}

impl TryFrom<&PaymentsGiftCardBalanceCheckRouterData> for AdyenBalanceRequest<'_> {
    type Error = Error;
    fn try_from(item: &PaymentsGiftCardBalanceCheckRouterData) -> Result<Self, Self::Error> {
        let payment_method = match &item.request.payment_method_data {
            PaymentMethodData::GiftCard(gift_card_data) => match gift_card_data.as_ref() {
                GiftCardData::Givex(gift_card_data) => {
                    let balance_pm = BalancePmData {
                        number: gift_card_data.number.clone(),
                        cvc: gift_card_data.cvc.clone(),
                    };
                    Ok(AdyenPaymentMethod::PaymentMethodBalance(Box::new(
                        balance_pm,
                    )))
                }
                GiftCardData::PaySafeCard {} | GiftCardData::BhnCardNetwork(_) => {
                    Err(errors::ConnectorError::FlowNotSupported {
                        flow: "Balance".to_string(),
                        connector: "adyen".to_string(),
                    })
                }
            },
            _ => Err(errors::ConnectorError::FlowNotSupported {
                flow: "Balance".to_string(),
                connector: "adyen".to_string(),
            }),
        }?;

        let auth_type = AdyenAuthType::try_from(&item.connector_auth_type)?;
        Ok(Self {
            payment_method,
            merchant_account: auth_type.merchant_account,
        })
    }
}

impl From<&PaymentsAuthorizeRouterData> for AdyenShopperInteraction {
    fn from(item: &PaymentsAuthorizeRouterData) -> Self {
        match item.request.off_session {
            Some(true) => Self::ContinuedAuthentication,
            _ => match item.request.payment_channel {
                Some(common_enums::PaymentChannel::Ecommerce)
                | None
                | Some(common_enums::PaymentChannel::Other(_)) => Self::Ecommerce,
                Some(common_enums::PaymentChannel::MailOrder)
                | Some(common_enums::PaymentChannel::TelephoneOrder) => Self::Moto,
            },
        }
    }
}
type RecurringDetails = (Option<AdyenRecurringModel>, Option<bool>, Option<String>);

fn get_recurring_processing_model(
    item: &PaymentsAuthorizeRouterData,
) -> Result<RecurringDetails, Error> {
    let shopper_reference = match item.get_connector_customer_id() {
        Ok(connector_customer_id) => Some(connector_customer_id),
        Err(_) => {
            let customer_id = item.get_customer_id()?;
            Some(format!(
                "{}_{}",
                item.merchant_id.get_string_repr(),
                customer_id.get_string_repr()
            ))
        }
    };

    match (item.request.setup_future_usage, item.request.off_session) {
        (Some(storage_enums::FutureUsage::OffSession), _) => {
            let store_payment_method = item.request.is_mandate_payment();
            Ok((
                Some(AdyenRecurringModel::UnscheduledCardOnFile),
                Some(store_payment_method),
                shopper_reference,
            ))
        }
        (_, Some(true)) => Ok((
            Some(AdyenRecurringModel::UnscheduledCardOnFile),
            None,
            shopper_reference,
        )),
        _ => Ok((None, None, None)),
    }
}

fn get_browser_info(item: &PaymentsAuthorizeRouterData) -> Result<Option<AdyenBrowserInfo>, Error> {
    if item.auth_type == storage_enums::AuthenticationType::ThreeDs
        || item.payment_method == storage_enums::PaymentMethod::Card
        || item.payment_method == storage_enums::PaymentMethod::BankRedirect
        || item.request.payment_method_type == Some(storage_enums::PaymentMethodType::GoPay)
        || item.request.payment_method_type == Some(storage_enums::PaymentMethodType::GooglePay)
    {
        let info = item.request.get_browser_info()?;
        Ok(Some(AdyenBrowserInfo {
            accept_header: info.get_accept_header()?,
            language: info.get_language()?,
            screen_height: info.get_screen_height()?,
            screen_width: info.get_screen_width()?,
            color_depth: info.get_color_depth()?,
            user_agent: info.get_user_agent()?,
            time_zone_offset: info.get_time_zone()?,
            java_enabled: info.get_java_enabled()?,
        }))
    } else {
        Ok(None)
    }
}

fn get_additional_data(item: &PaymentsAuthorizeRouterData) -> Option<AdditionalData> {
    let (authorisation_type, manual_capture) = match item.request.capture_method {
        Some(storage_enums::CaptureMethod::Manual) | Some(enums::CaptureMethod::ManualMultiple) => {
            (Some(AuthType::PreAuth), Some("true".to_string()))
        }
        _ => (None, None),
    };
    let riskdata = item.request.metadata.clone().and_then(get_risk_data);

    let execute_three_d = if matches!(item.auth_type, storage_enums::AuthenticationType::ThreeDs) {
        Some("true".to_string())
    } else {
        Some("false".to_string())
    };
    Some(AdditionalData {
        authorisation_type,
        manual_capture,
        execute_three_d,
        network_tx_reference: None,
        recurring_detail_reference: None,
        recurring_shopper_reference: None,
        recurring_processing_model: None,
        riskdata,
        ..AdditionalData::default()
    })
}

fn get_channel_type(pm_type: Option<storage_enums::PaymentMethodType>) -> Option<Channel> {
    pm_type.as_ref().and_then(|pmt| match pmt {
        storage_enums::PaymentMethodType::GoPay | storage_enums::PaymentMethodType::Vipps => {
            Some(Channel::Web)
        }
        _ => None,
    })
}

fn get_amount_data(item: &AdyenRouterData<&PaymentsAuthorizeRouterData>) -> Amount {
    Amount {
        currency: item.router_data.request.currency,
        value: item.amount.to_owned(),
    }
}

pub fn get_address_info(
    address: Option<&hyperswitch_domain_models::address::Address>,
) -> Option<Result<Address, error_stack::Report<errors::ConnectorError>>> {
    address.and_then(|add| {
        add.address.as_ref().map(
            |a| -> Result<Address, error_stack::Report<errors::ConnectorError>> {
                Ok(Address {
                    city: a.get_city()?.to_owned(),
                    country: a.get_country()?.to_owned(),
                    house_number_or_name: a.get_line1()?.to_owned(),
                    postal_code: a.get_zip()?.to_owned(),
                    state_or_province: a.state.clone(),
                    street: a.get_optional_line2().to_owned(),
                })
            },
        )
    })
}

fn get_line_items(item: &AdyenRouterData<&PaymentsAuthorizeRouterData>) -> Vec<LineItem> {
    let order_details = item.router_data.request.order_details.clone();
    match order_details {
        Some(od) => od
            .iter()
            .enumerate()
            .map(|(i, data)| LineItem {
                amount_including_tax: Some(data.amount),
                amount_excluding_tax: Some(data.amount),
                description: Some(data.product_name.clone()),
                id: Some(format!("Items #{i}")),
                tax_amount: None,
                quantity: Some(data.quantity),
            })
            .collect(),
        None => {
            let line_item = LineItem {
                amount_including_tax: Some(item.amount.to_owned()),
                amount_excluding_tax: Some(item.amount.to_owned()),
                description: item.router_data.description.clone(),
                id: Some(String::from("Items #1")),
                tax_amount: None,
                quantity: Some(1),
            };
            vec![line_item]
        }
    }
}

fn get_telephone_number(item: &PaymentsAuthorizeRouterData) -> Option<Secret<String>> {
    let phone = item
        .get_optional_billing()
        .and_then(|billing| billing.phone.as_ref());

    phone.as_ref().and_then(|phone| {
        phone.number.as_ref().and_then(|number| {
            phone
                .country_code
                .as_ref()
                .map(|cc| Secret::new(format!("{}{}", cc, number.peek())))
        })
    })
}

fn get_shopper_name(
    address: Option<&hyperswitch_domain_models::address::Address>,
) -> Option<ShopperName> {
    let billing = address.and_then(|billing| billing.address.as_ref());
    Some(ShopperName {
        first_name: billing.and_then(|a| a.first_name.clone()),
        last_name: billing.and_then(|a| a.last_name.clone()),
    })
}

fn get_country_code(
    address: Option<&hyperswitch_domain_models::address::Address>,
) -> Option<storage_enums::CountryAlpha2> {
    address.and_then(|billing| billing.address.as_ref().and_then(|address| address.country))
}

fn get_social_security_number(voucher_data: &VoucherData) -> Option<Secret<String>> {
    match voucher_data {
        VoucherData::Boleto(boleto_data) => boleto_data.social_security_number.clone(),
        VoucherData::Alfamart { .. }
        | VoucherData::Indomaret { .. }
        | VoucherData::Efecty
        | VoucherData::PagoEfectivo
        | VoucherData::RedCompra
        | VoucherData::Oxxo
        | VoucherData::RedPagos
        | VoucherData::SevenEleven { .. }
        | VoucherData::Lawson { .. }
        | VoucherData::MiniStop { .. }
        | VoucherData::FamilyMart { .. }
        | VoucherData::Seicomart { .. }
        | VoucherData::PayEasy { .. } => None,
    }
}

fn build_shopper_reference(item: &PaymentsAuthorizeRouterData) -> Option<String> {
    match item.get_connector_customer_id() {
        Ok(connector_customer_id) => Some(connector_customer_id),
        Err(_) => match item.get_customer_id() {
            Ok(customer_id) => Some(format!(
                "{}_{}",
                item.merchant_id.get_string_repr(),
                customer_id.get_string_repr()
            )),
            Err(_) => None,
        },
    }
}

impl TryFrom<(&BankDebitData, &PaymentsAuthorizeRouterData)> for AdyenPaymentMethod<'_> {
    type Error = Error;
    fn try_from(
        (bank_debit_data, item): (&BankDebitData, &PaymentsAuthorizeRouterData),
    ) -> Result<Self, Self::Error> {
        match bank_debit_data {
            BankDebitData::AchBankDebit {
                account_number,
                routing_number,
                ..
            } => Ok(AdyenPaymentMethod::AchDirectDebit(Box::new(
                AchDirectDebitData {
                    bank_account_number: account_number.clone(),
                    bank_location_id: routing_number.clone(),
                    owner_name: item.get_billing_full_name()?,
                },
            ))),
            BankDebitData::SepaBankDebit { iban, .. } => Ok(AdyenPaymentMethod::SepaDirectDebit(
                Box::new(SepaDirectDebitData {
                    owner_name: item.get_billing_full_name()?,
                    iban_number: iban.clone(),
                }),
            )),
            BankDebitData::BacsBankDebit {
                account_number,
                sort_code,
                ..
            } => {
                let testing_data = item
                    .request
                    .get_connector_testing_data()
                    .map(AdyenTestingData::try_from)
                    .transpose()?;
                let test_holder_name = testing_data.and_then(|test_data| test_data.holder_name);
                Ok(AdyenPaymentMethod::BacsDirectDebit(Box::new(
                    BacsDirectDebitData {
                        bank_account_number: account_number.clone(),
                        bank_location_id: sort_code.clone(),
                        holder_name: test_holder_name.unwrap_or(item.get_billing_full_name()?),
                    },
                )))
            }

            BankDebitData::BecsBankDebit { .. } => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Adyen"),
            )
            .into()),
        }
    }
}

impl TryFrom<(&VoucherData, &PaymentsAuthorizeRouterData)> for AdyenPaymentMethod<'_> {
    type Error = Error;
    fn try_from(
        (voucher_data, item): (&VoucherData, &PaymentsAuthorizeRouterData),
    ) -> Result<Self, Self::Error> {
        match voucher_data {
            VoucherData::Boleto { .. } => Ok(AdyenPaymentMethod::BoletoBancario),
            VoucherData::Alfamart(_) => Ok(AdyenPaymentMethod::Alfamart(Box::new(
                DokuBankData::try_from(item)?,
            ))),

            VoucherData::Indomaret(_) => Ok(AdyenPaymentMethod::Indomaret(Box::new(
                DokuBankData::try_from(item)?,
            ))),

            VoucherData::Oxxo => Ok(AdyenPaymentMethod::Oxxo),
            VoucherData::SevenEleven(_) => Ok(AdyenPaymentMethod::SevenEleven(Box::new(
                JCSVoucherData::try_from(item)?,
            ))),
            VoucherData::Lawson(_)
            | VoucherData::MiniStop(_)
            | VoucherData::FamilyMart(_)
            | VoucherData::Seicomart(_)
            | VoucherData::PayEasy(_) => Ok(AdyenPaymentMethod::JapaneseConvenienceStores(
                Box::new(JCSVoucherData::try_from(item)?),
            )),
            VoucherData::Efecty
            | VoucherData::PagoEfectivo
            | VoucherData::RedCompra
            | VoucherData::RedPagos => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Adyen"),
            )
            .into()),
        }
    }
}

impl TryFrom<&GiftCardData> for AdyenPaymentMethod<'_> {
    type Error = Error;
    fn try_from(gift_card_data: &GiftCardData) -> Result<Self, Self::Error> {
        match gift_card_data {
            GiftCardData::PaySafeCard {} => Ok(AdyenPaymentMethod::PaySafeCard),
            GiftCardData::Givex(givex_data) => {
                let gift_card_pm = AdyenGiftCardData {
                    brand: GiftCardBrand::Givex,
                    number: givex_data.number.clone(),
                    cvc: givex_data.cvc.clone(),
                };
                Ok(AdyenPaymentMethod::AdyenGiftCard(Box::new(gift_card_pm)))
            }
            GiftCardData::BhnCardNetwork(_) => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Adyen"),
            )
            .into()),
        }
    }
}

fn get_adyen_card_network(card_network: common_enums::CardNetwork) -> Option<CardBrand> {
    match card_network {
        common_enums::CardNetwork::Visa => Some(CardBrand::Visa),
        common_enums::CardNetwork::Mastercard => Some(CardBrand::MC),
        common_enums::CardNetwork::CartesBancaires => Some(CardBrand::Cartebancaire),
        common_enums::CardNetwork::AmericanExpress => Some(CardBrand::Amex),
        common_enums::CardNetwork::JCB => Some(CardBrand::Jcb),
        common_enums::CardNetwork::DinersClub => Some(CardBrand::Diners),
        common_enums::CardNetwork::Discover => Some(CardBrand::Discover),
        common_enums::CardNetwork::UnionPay => Some(CardBrand::Cup),
        common_enums::CardNetwork::RuPay => Some(CardBrand::Rupay),
        common_enums::CardNetwork::Maestro => Some(CardBrand::Maestro),
        common_enums::CardNetwork::Star => Some(CardBrand::Star),
        common_enums::CardNetwork::Accel => Some(CardBrand::Accel),
        common_enums::CardNetwork::Pulse => Some(CardBrand::Pulse),
        common_enums::CardNetwork::Nyce => Some(CardBrand::Nyce),
        common_enums::CardNetwork::Interac => None,
    }
}

impl TryFrom<(&Card, Option<Secret<String>>)> for AdyenPaymentMethod<'_> {
    type Error = Error;
    fn try_from(
        (card, card_holder_name): (&Card, Option<Secret<String>>),
    ) -> Result<Self, Self::Error> {
        let adyen_card = AdyenCard {
            number: card.card_number.clone(),
            expiry_month: card.card_exp_month.clone(),
            expiry_year: card.get_expiry_year_4_digit(),
            cvc: Some(card.card_cvc.clone()),
            holder_name: card_holder_name,
            brand: card.card_network.clone().and_then(get_adyen_card_network),
            network_payment_reference: None,
        };
        Ok(AdyenPaymentMethod::AdyenCard(Box::new(adyen_card)))
    }
}

impl TryFrom<&storage_enums::PaymentMethodType> for PaymentType {
    type Error = Error;
    fn try_from(item: &storage_enums::PaymentMethodType) -> Result<Self, Self::Error> {
        match item {
            storage_enums::PaymentMethodType::Credit
            | storage_enums::PaymentMethodType::Debit
            | storage_enums::PaymentMethodType::Klarna
            | storage_enums::PaymentMethodType::BancontactCard
            | storage_enums::PaymentMethodType::Blik
            | storage_enums::PaymentMethodType::Eps
            | storage_enums::PaymentMethodType::Ideal
            | storage_enums::PaymentMethodType::OnlineBankingCzechRepublic
            | storage_enums::PaymentMethodType::OnlineBankingFinland
            | storage_enums::PaymentMethodType::OnlineBankingPoland
            | storage_enums::PaymentMethodType::OnlineBankingSlovakia
            | storage_enums::PaymentMethodType::Trustly
            | storage_enums::PaymentMethodType::GooglePay
            | storage_enums::PaymentMethodType::AliPay
            | storage_enums::PaymentMethodType::ApplePay
            | storage_enums::PaymentMethodType::AliPayHk
            | storage_enums::PaymentMethodType::MbWay
            | storage_enums::PaymentMethodType::MobilePay
            | storage_enums::PaymentMethodType::WeChatPay
            | storage_enums::PaymentMethodType::SamsungPay
            | storage_enums::PaymentMethodType::Affirm
            | storage_enums::PaymentMethodType::AfterpayClearpay
            | storage_enums::PaymentMethodType::PayBright
            | storage_enums::PaymentMethodType::Walley => Ok(Self::Scheme),
            storage_enums::PaymentMethodType::Sepa => Ok(Self::SepaDirectDebit),
            storage_enums::PaymentMethodType::Bacs => Ok(Self::BacsDirectDebit),
            storage_enums::PaymentMethodType::Ach => Ok(Self::AchDirectDebit),
            storage_enums::PaymentMethodType::Paypal => Ok(Self::Paypal),
            _ => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Adyen"),
            ))?,
        }
    }
}

impl TryFrom<&utils::CardIssuer> for CardBrand {
    type Error = Error;
    fn try_from(card_issuer: &utils::CardIssuer) -> Result<Self, Self::Error> {
        match card_issuer {
            utils::CardIssuer::AmericanExpress => Ok(Self::Amex),
            utils::CardIssuer::Master => Ok(Self::MC),
            utils::CardIssuer::Visa => Ok(Self::Visa),
            utils::CardIssuer::Maestro => Ok(Self::Maestro),
            utils::CardIssuer::Discover => Ok(Self::Discover),
            utils::CardIssuer::DinersClub => Ok(Self::Diners),
            utils::CardIssuer::JCB => Ok(Self::Jcb),
            utils::CardIssuer::CarteBlanche => Ok(Self::Cartebancaire),
            utils::CardIssuer::CartesBancaires => Ok(Self::Cartebancaire),
            utils::CardIssuer::UnionPay => Ok(Self::Cup),
        }
    }
}

impl TryFrom<(&WalletData, &PaymentsAuthorizeRouterData)> for AdyenPaymentMethod<'_> {
    type Error = Error;
    fn try_from(value: (&WalletData, &PaymentsAuthorizeRouterData)) -> Result<Self, Self::Error> {
        let (wallet_data, item) = value;
        match wallet_data {
            WalletData::GooglePay(data) => {
                let gpay_data = AdyenGPay {
                    google_pay_token: Secret::new(
                        data.tokenization_data
                            .get_encrypted_google_pay_token()
                            .change_context(errors::ConnectorError::MissingRequiredField {
                                field_name: "gpay wallet_token",
                            })?
                            .to_owned(),
                    ),
                };
                Ok(AdyenPaymentMethod::Gpay(Box::new(gpay_data)))
            }
            WalletData::ApplePay(data) => {
                if let Some(PaymentMethodToken::ApplePayDecrypt(apple_pay_decrypte)) =
                    item.payment_method_token.clone()
                {
                    let expiry_year_4_digit = apple_pay_decrypte.get_four_digit_expiry_year();
                    let exp_month = apple_pay_decrypte.get_expiry_month().change_context(
                        errors::ConnectorError::InvalidDataFormat {
                            field_name: "expiration_month",
                        },
                    )?;
                    let apple_pay_decrypted_data = AdyenApplePayDecryptData {
                        number: apple_pay_decrypte.application_primary_account_number,
                        expiry_month: exp_month,
                        expiry_year: expiry_year_4_digit,
                        brand: data.payment_method.network.clone(),
                        payment_type: PaymentType::Scheme,
                    };
                    Ok(AdyenPaymentMethod::ApplePayDecrypt(Box::new(
                        apple_pay_decrypted_data,
                    )))
                } else {
                    let apple_pay_encrypted_data = data
                        .payment_data
                        .get_encrypted_apple_pay_payment_data_mandatory()
                        .change_context(errors::ConnectorError::MissingRequiredField {
                            field_name: "Apple pay encrypted data",
                        })?;
                    let apple_pay_data = AdyenApplePay {
                        apple_pay_token: Secret::new(apple_pay_encrypted_data.to_string()),
                    };
                    Ok(AdyenPaymentMethod::ApplePay(Box::new(apple_pay_data)))
                }
            }
            WalletData::PaypalRedirect(_) => Ok(AdyenPaymentMethod::AdyenPaypal),
            WalletData::AliPayRedirect(_) => Ok(AdyenPaymentMethod::AliPay),
            WalletData::AliPayHkRedirect(_) => Ok(AdyenPaymentMethod::AliPayHk),
            WalletData::GoPayRedirect(_) => {
                let go_pay_data = GoPayData {};
                Ok(AdyenPaymentMethod::GoPay(Box::new(go_pay_data)))
            }
            WalletData::KakaoPayRedirect(_) => {
                let kakao_pay_data = KakaoPayData {};
                Ok(AdyenPaymentMethod::Kakaopay(Box::new(kakao_pay_data)))
            }
            WalletData::GcashRedirect(_) => {
                let gcash_data = GcashData {};
                Ok(AdyenPaymentMethod::Gcash(Box::new(gcash_data)))
            }
            WalletData::MomoRedirect(_) => {
                let momo_data = MomoData {};
                Ok(AdyenPaymentMethod::Momo(Box::new(momo_data)))
            }
            WalletData::TouchNGoRedirect(_) => {
                let touch_n_go_data = TouchNGoData {};
                Ok(AdyenPaymentMethod::TouchNGo(Box::new(touch_n_go_data)))
            }
            WalletData::MbWayRedirect(_) => {
                let phone_details = item.get_billing_phone()?;
                let mbway_data = MbwayData {
                    telephone_number: phone_details.get_number_with_country_code()?,
                };
                Ok(AdyenPaymentMethod::Mbway(Box::new(mbway_data)))
            }
            WalletData::MobilePayRedirect(_) => Ok(AdyenPaymentMethod::MobilePay),
            WalletData::WeChatPayRedirect(_) => Ok(AdyenPaymentMethod::WeChatPayWeb),
            WalletData::SamsungPay(samsung_data) => {
                let data = SamsungPayPmData {
                    samsung_pay_token: samsung_data.payment_credential.token_data.data.to_owned(),
                };
                Ok(AdyenPaymentMethod::SamsungPay(Box::new(data)))
            }
            WalletData::Paze(_) => match item.payment_method_token.clone() {
                Some(PaymentMethodToken::PazeDecrypt(paze_decrypted_data)) => {
                    let data = AdyenPazeData {
                        number: paze_decrypted_data.token.payment_token,
                        expiry_month: paze_decrypted_data.token.token_expiration_month,
                        expiry_year: paze_decrypted_data.token.token_expiration_year,
                        cvc: None,
                        holder_name: paze_decrypted_data
                            .billing_address
                            .name
                            .or(item.get_optional_billing_full_name()),
                        brand: Some(paze_decrypted_data.payment_card_network.clone())
                            .and_then(get_adyen_card_network),
                        network_payment_reference: None,
                    };
                    Ok(AdyenPaymentMethod::AdyenPaze(Box::new(data)))
                }
                _ => Err(errors::ConnectorError::NotImplemented(
                    utils::get_unimplemented_payment_method_error_message("Cybersource"),
                )
                .into()),
            },
            WalletData::TwintRedirect { .. } => Ok(AdyenPaymentMethod::Twint),
            WalletData::VippsRedirect { .. } => Ok(AdyenPaymentMethod::Vipps),
            WalletData::DanaRedirect { .. } => Ok(AdyenPaymentMethod::Dana),
            WalletData::SwishQr(_) => Ok(AdyenPaymentMethod::Swish),
            WalletData::AliPayQr(_)
            | WalletData::AmazonPayRedirect(_)
            | WalletData::Paysera(_)
            | WalletData::Skrill(_)
            | WalletData::ApplePayRedirect(_)
            | WalletData::ApplePayThirdPartySdk(_)
            | WalletData::GooglePayRedirect(_)
            | WalletData::GooglePayThirdPartySdk(_)
            | WalletData::BluecodeRedirect {}
            | WalletData::AmazonPay(_)
            | WalletData::PaypalSdk(_)
            | WalletData::WeChatPayQr(_)
            | WalletData::CashappQr(_)
            | WalletData::Mifinity(_)
            | WalletData::RevolutPay(_) => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Adyen"),
            )
            .into()),
        }
    }
}

pub fn check_required_field<'a, T>(
    field: &'a Option<T>,
    message: &'static str,
) -> Result<&'a T, errors::ConnectorError> {
    field
        .as_ref()
        .ok_or(errors::ConnectorError::MissingRequiredField {
            field_name: message,
        })
}

impl
    TryFrom<(
        &PayLaterData,
        &Option<storage_enums::CountryAlpha2>,
        &Option<Email>,
        &Option<String>,
        &Option<ShopperName>,
        &Option<Secret<String>>,
        &Option<Address>,
        &Option<Address>,
    )> for AdyenPaymentMethod<'_>
{
    type Error = Error;
    fn try_from(
        value: (
            &PayLaterData,
            &Option<storage_enums::CountryAlpha2>,
            &Option<Email>,
            &Option<String>,
            &Option<ShopperName>,
            &Option<Secret<String>>,
            &Option<Address>,
            &Option<Address>,
        ),
    ) -> Result<Self, Self::Error> {
        let (
            pay_later_data,
            country_code,
            shopper_email,
            shopper_reference,
            shopper_name,
            telephone_number,
            billing_address,
            delivery_address,
        ) = value;
        match pay_later_data {
            PayLaterData::KlarnaRedirect { .. } => {
                check_required_field(shopper_email, "email")?;
                check_required_field(shopper_reference, "customer_id")?;
                check_required_field(country_code, "billing.country")?;

                Ok(AdyenPaymentMethod::AdyenKlarna)
            }
            PayLaterData::AffirmRedirect { .. } => {
                check_required_field(shopper_email, "email")?;
                check_required_field(shopper_name, "billing.first_name, billing.last_name")?;
                check_required_field(telephone_number, "billing.phone")?;
                check_required_field(billing_address, "billing")?;

                Ok(AdyenPaymentMethod::AdyenAffirm)
            }
            PayLaterData::AfterpayClearpayRedirect { .. } => {
                check_required_field(shopper_email, "email")?;
                check_required_field(shopper_name, "billing.first_name, billing.last_name")?;
                check_required_field(delivery_address, "shipping")?;
                check_required_field(billing_address, "billing")?;

                if let Some(country) = country_code {
                    match country {
                        storage_enums::CountryAlpha2::IT
                        | storage_enums::CountryAlpha2::FR
                        | storage_enums::CountryAlpha2::ES
                        | storage_enums::CountryAlpha2::GB => Ok(AdyenPaymentMethod::ClearPay),
                        _ => Ok(AdyenPaymentMethod::AfterPay),
                    }
                } else {
                    Err(errors::ConnectorError::MissingRequiredField {
                        field_name: "country",
                    })?
                }
            }
            PayLaterData::PayBrightRedirect { .. } => {
                check_required_field(shopper_name, "billing.first_name, billing.last_name")?;
                check_required_field(telephone_number, "billing.phone")?;
                check_required_field(shopper_email, "email")?;
                check_required_field(billing_address, "billing")?;
                check_required_field(delivery_address, "shipping")?;
                check_required_field(country_code, "billing.country")?;
                Ok(AdyenPaymentMethod::PayBright)
            }
            PayLaterData::WalleyRedirect { .. } => {
                //[TODO: Line items specific sub-fields are mandatory]
                check_required_field(telephone_number, "billing.phone")?;
                check_required_field(shopper_email, "email")?;
                Ok(AdyenPaymentMethod::Walley)
            }
            PayLaterData::AlmaRedirect { .. } => {
                check_required_field(telephone_number, "billing.phone")?;
                check_required_field(shopper_email, "email")?;
                check_required_field(billing_address, "billing")?;
                check_required_field(delivery_address, "shipping")?;
                Ok(AdyenPaymentMethod::AlmaPayLater)
            }
            PayLaterData::AtomeRedirect { .. } => {
                check_required_field(shopper_email, "email")?;
                check_required_field(shopper_name, "billing.first_name, billing.last_name")?;
                check_required_field(telephone_number, "billing.phone")?;
                check_required_field(billing_address, "billing")?;
                Ok(AdyenPaymentMethod::Atome)
            }
            PayLaterData::KlarnaSdk { .. }
            | PayLaterData::BreadpayRedirect {}
            | PayLaterData::FlexitiRedirect {} => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Adyen"),
            )
            .into()),
        }
    }
}

impl TryFrom<(&BankRedirectData, &PaymentsAuthorizeRouterData)> for AdyenPaymentMethod<'_> {
    type Error = Error;
    fn try_from(
        (bank_redirect_data, item): (&BankRedirectData, &PaymentsAuthorizeRouterData),
    ) -> Result<Self, Self::Error> {
        match bank_redirect_data {
            BankRedirectData::BancontactCard {
                card_number,
                card_exp_month,
                card_exp_year,
                ..
            } => {
                let testing_data = item
                    .request
                    .get_connector_testing_data()
                    .map(AdyenTestingData::try_from)
                    .transpose()?;
                let test_holder_name = testing_data.and_then(|test_data| test_data.holder_name);
                Ok(AdyenPaymentMethod::BancontactCard(Box::new(AdyenCard {
                    brand: Some(CardBrand::Bcmc),
                    number: card_number
                        .as_ref()
                        .ok_or(errors::ConnectorError::MissingRequiredField {
                            field_name: "bancontact_card.card_number",
                        })?
                        .clone(),
                    expiry_month: card_exp_month
                        .as_ref()
                        .ok_or(errors::ConnectorError::MissingRequiredField {
                            field_name: "bancontact_card.card_exp_month",
                        })?
                        .clone(),
                    expiry_year: card_exp_year
                        .as_ref()
                        .ok_or(errors::ConnectorError::MissingRequiredField {
                            field_name: "bancontact_card.card_exp_year",
                        })?
                        .clone(),
                    holder_name: test_holder_name.or(Some(item.get_billing_full_name()?)),
                    cvc: None,
                    network_payment_reference: None,
                })))
            }
            BankRedirectData::Bizum { .. } => Ok(AdyenPaymentMethod::Bizum),
            BankRedirectData::Blik { blik_code } => {
                Ok(AdyenPaymentMethod::Blik(Box::new(BlikRedirectionData {
                    blik_code: Secret::new(blik_code.clone().ok_or(
                        errors::ConnectorError::MissingRequiredField {
                            field_name: "blik_code",
                        },
                    )?),
                })))
            }
            BankRedirectData::Eps { bank_name, .. } => Ok(AdyenPaymentMethod::Eps(Box::new(
                BankRedirectionWithIssuer {
                    issuer: Some(
                        AdyenTestBankNames::try_from(&bank_name.ok_or(
                            errors::ConnectorError::MissingRequiredField {
                                field_name: "eps.bank_name",
                            },
                        )?)?
                        .0,
                    ),
                },
            ))),
            BankRedirectData::Ideal { .. } => Ok(AdyenPaymentMethod::Ideal),
            BankRedirectData::OnlineBankingCzechRepublic { issuer } => {
                Ok(AdyenPaymentMethod::OnlineBankingCzechRepublic(Box::new(
                    OnlineBankingCzechRepublicData {
                        issuer: OnlineBankingCzechRepublicBanks::try_from(issuer)?,
                    },
                )))
            }
            BankRedirectData::OnlineBankingFinland { .. } => {
                Ok(AdyenPaymentMethod::OnlineBankingFinland)
            }
            BankRedirectData::OnlineBankingPoland { issuer } => Ok(
                AdyenPaymentMethod::OnlineBankingPoland(Box::new(OnlineBankingPolandData {
                    issuer: OnlineBankingPolandBanks::try_from(issuer)?,
                })),
            ),
            BankRedirectData::OnlineBankingSlovakia { issuer } => Ok(
                AdyenPaymentMethod::OnlineBankingSlovakia(Box::new(OnlineBankingSlovakiaData {
                    issuer: OnlineBankingSlovakiaBanks::try_from(issuer)?,
                })),
            ),
            BankRedirectData::OnlineBankingFpx { issuer } => Ok(
                AdyenPaymentMethod::OnlineBankingFpx(Box::new(OnlineBankingFpxData {
                    issuer: OnlineBankingFpxIssuer::try_from(issuer)?,
                })),
            ),
            BankRedirectData::OnlineBankingThailand { issuer } => Ok(
                AdyenPaymentMethod::OnlineBankingThailand(Box::new(OnlineBankingThailandData {
                    issuer: OnlineBankingThailandIssuer::try_from(issuer)?,
                })),
            ),
            BankRedirectData::OpenBankingUk { issuer, .. } => Ok(
                AdyenPaymentMethod::OpenBankingUK(Box::new(OpenBankingUKData {
                    issuer: match issuer {
                        Some(bank_name) => Some(OpenBankingUKIssuer::try_from(bank_name)?),


// Struct: RefundRequest
// File: crates/hyperswitch_connectors/src/connectors/checkout/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RefundRequest


// Function: reopen_calculate_workflow_on_payment_failure
// File: crates/router/src/core/revenue_recovery/types.rs
// Module: router

// Documentation: Reopen calculate workflow when payment fails

pub fn reopen_calculate_workflow_on_payment_failure(
    state: &SessionState,
    process: &storage::ProcessTracker,
    profile: &domain::Profile,
    merchant_context: domain::MerchantContext,
    payment_intent: &PaymentIntent,
    revenue_recovery_payment_data: &storage::revenue_recovery::RevenueRecoveryPaymentData,
    latest_attempt_id: &id_type::GlobalAttemptId,
) -> RecoveryResult<()>


// Function: setup
// File: crates/router_env/src/logger/setup.rs
// Module: router_env

pub fn setup(
    config: &config::Log,
    service_name: &str,
    crates_to_filter: impl AsRef<[&'static str]>,
) -> error_stack::Result<TelemetryGuard, ConfigError>


// Struct: ExchangeRates
// File: crates/currency_conversion/src/types.rs
// Module: currency_conversion
// Implementations: 1

pub struct ExchangeRates


// Function: new
// File: crates/api_models/src/routing.rs
// Module: api_models

pub fn new(
        profile_id: common_utils::id_type::ProfileId,
        euclid_algorithm_id: common_utils::id_type::RoutingId,
        decision_engine_algorithm_id: String,
        is_active_rule: bool,
    ) -> Self


// File: crates/hyperswitch_connectors/src/connectors/ebanx.rs
// Module: hyperswitch_connectors
// Public functions: 1
// Public structs: 1

pub mod transformers;

use api_models::webhooks::{IncomingWebhookEvent, ObjectReferenceId};
#[cfg(feature = "payouts")]
use common_utils::request::RequestContent;
#[cfg(feature = "payouts")]
use common_utils::request::{Method, Request, RequestBuilder};
#[cfg(feature = "payouts")]
use common_utils::types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector};
use common_utils::{errors::CustomResult, ext_traits::BytesExt};
use error_stack::{report, ResultExt};
#[cfg(feature = "payouts")]
use hyperswitch_domain_models::{
    router_data::RouterData,
    router_flow_types::{PoCancel, PoCreate, PoEligibility, PoFulfill, PoQuote, PoRecipient},
    types::{PayoutsData, PayoutsResponseData, PayoutsRouterData},
};
use hyperswitch_domain_models::{
    router_data::{AccessToken, ErrorResponse},
    router_flow_types::{
        AccessTokenAuth, Authorize, Capture, Execute, PSync, PaymentMethodToken, RSync, Session,
        SetupMandate, Void,
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentsResponseData, RefundsResponseData, SupportedPaymentMethods,
    },
};
#[cfg(feature = "payouts")]
use hyperswitch_interfaces::types::{PayoutCancelType, PayoutCreateType, PayoutFulfillType};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    errors::ConnectorError,
    events::connector_api_logs::ConnectorEvent,
    types::Response,
    webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
};
#[cfg(feature = "payouts")]
use masking::Maskable;
#[cfg(feature = "payouts")]
use router_env::{instrument, tracing};
use transformers as ebanx;

#[cfg(feature = "payouts")]
use crate::{constants::headers, types::ResponseRouterData, utils::convert_amount};
#[derive(Clone)]
pub struct Ebanx {
    #[cfg(feature = "payouts")]
    amount_converter: &'static (dyn AmountConvertor<Output = FloatMajorUnit> + Sync),
}

impl Ebanx {
    pub fn new() -> &'static Self {
        &Self {
            #[cfg(feature = "payouts")]
            amount_converter: &FloatMajorUnitForConnector,
        }
    }
}

impl api::Payment for Ebanx {}
impl api::PaymentSession for Ebanx {}
impl api::ConnectorAccessToken for Ebanx {}
impl api::MandateSetup for Ebanx {}
impl api::PaymentAuthorize for Ebanx {}
impl api::PaymentSync for Ebanx {}
impl api::PaymentCapture for Ebanx {}
impl api::PaymentVoid for Ebanx {}
impl api::Refund for Ebanx {}
impl api::RefundExecute for Ebanx {}
impl api::RefundSync for Ebanx {}
impl api::PaymentToken for Ebanx {}

impl api::Payouts for Ebanx {}
#[cfg(feature = "payouts")]
impl api::PayoutCancel for Ebanx {}
#[cfg(feature = "payouts")]
impl api::PayoutCreate for Ebanx {}
#[cfg(feature = "payouts")]
impl api::PayoutEligibility for Ebanx {}
#[cfg(feature = "payouts")]
impl api::PayoutQuote for Ebanx {}
#[cfg(feature = "payouts")]
impl api::PayoutRecipient for Ebanx {}
#[cfg(feature = "payouts")]
impl api::PayoutFulfill for Ebanx {}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Ebanx
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    #[cfg(feature = "payouts")]
    fn build_headers(
        &self,
        _req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        let header = vec![(
            headers::CONTENT_TYPE.to_string(),
            self.common_get_content_type().to_string().into(),
        )];
        Ok(header)
    }
}

impl ConnectorCommon for Ebanx {
    fn id(&self) -> &'static str {
        "ebanx"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Base
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.ebanx.base_url.as_ref()
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, ConnectorError> {
        let response: ebanx::EbanxErrorResponse =
            res.response
                .parse_struct("EbanxErrorResponse")
                .change_context(ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.status_code,
            message: response.code,
            reason: response.message,
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoCreate, PayoutsData, PayoutsResponseData> for Ebanx {
    fn get_url(
        &self,
        _req: &PayoutsRouterData<PoCreate>,
        connectors: &Connectors,
    ) -> CustomResult<String, ConnectorError> {
        Ok(format!("{}ws/payout/create", connectors.ebanx.base_url))
    }

    fn get_headers(
        &self,
        req: &PayoutsRouterData<PoCreate>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_request_body(
        &self,
        req: &PayoutsRouterData<PoCreate>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.source_currency,
        )?;
        let connector_router_data = ebanx::EbanxRouterData::from((amount, req));
        let connector_req = ebanx::EbanxPayoutCreateRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PayoutsRouterData<PoCreate>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&PayoutCreateType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(PayoutCreateType::get_headers(self, req, connectors)?)
            .set_body(PayoutCreateType::get_request_body(self, req, connectors)?)
            .build();

        Ok(Some(request))
    }

    fn handle_response(
        &self,
        data: &PayoutsRouterData<PoCreate>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PayoutsRouterData<PoCreate>, ConnectorError> {
        let response: ebanx::EbanxPayoutResponse = res
            .response
            .parse_struct("EbanxPayoutResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoFulfill, PayoutsData, PayoutsResponseData> for Ebanx {
    fn get_url(
        &self,
        _req: &PayoutsRouterData<PoFulfill>,
        connectors: &Connectors,
    ) -> CustomResult<String, ConnectorError> {
        Ok(format!("{}ws/payout/commit", connectors.ebanx.base_url,))
    }

    fn get_headers(
        &self,
        req: &PayoutsRouterData<PoFulfill>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_request_body(
        &self,
        req: &PayoutsRouterData<PoFulfill>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.source_currency,
        )?;
        let connector_router_data = ebanx::EbanxRouterData::from((amount, req));
        let connector_req = ebanx::EbanxPayoutFulfillRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PayoutsRouterData<PoFulfill>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&PayoutFulfillType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(PayoutFulfillType::get_headers(self, req, connectors)?)
            .set_body(PayoutFulfillType::get_request_body(self, req, connectors)?)
            .build();

        Ok(Some(request))
    }

    #[instrument(skip_all)]
    fn handle_response(
        &self,
        data: &PayoutsRouterData<PoFulfill>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PayoutsRouterData<PoFulfill>, ConnectorError> {
        let response: ebanx::EbanxFulfillResponse = res
            .response
            .parse_struct("EbanxFulfillResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoCancel, PayoutsData, PayoutsResponseData> for Ebanx {
    fn get_url(
        &self,
        _req: &PayoutsRouterData<PoCancel>,
        connectors: &Connectors,
    ) -> CustomResult<String, ConnectorError> {
        Ok(format!("{}ws/payout/cancel", connectors.ebanx.base_url,))
    }

    fn get_headers(
        &self,
        req: &PayoutsRouterData<PoCancel>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        self.build_headers(req, _connectors)
    }

    fn get_request_body(
        &self,
        req: &PayoutsRouterData<PoCancel>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, ConnectorError> {
        let connector_req = ebanx::EbanxPayoutCancelRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PayoutsRouterData<PoCancel>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Put)
            .url(&PayoutCancelType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(PayoutCancelType::get_headers(self, req, connectors)?)
            .set_body(PayoutCancelType::get_request_body(self, req, connectors)?)
            .build();

        Ok(Some(request))
    }

    #[instrument(skip_all)]
    fn handle_response(
        &self,
        data: &PayoutsRouterData<PoCancel>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PayoutsRouterData<PoCancel>, ConnectorError> {
        let response: ebanx::EbanxCancelResponse = res
            .response
            .parse_struct("EbanxCancelResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoQuote, PayoutsData, PayoutsResponseData> for Ebanx {}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoRecipient, PayoutsData, PayoutsResponseData> for Ebanx {}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoEligibility, PayoutsData, PayoutsResponseData> for Ebanx {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Ebanx
{
    // Not Implemented (R)
}

impl ConnectorValidation for Ebanx {
    //TODO: implement functions when support enabled
}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Ebanx {
    //TODO: implement sessions flow
}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Ebanx {}

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData> for Ebanx {}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Ebanx {}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Ebanx {}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Ebanx {}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Ebanx {}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Ebanx {}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Ebanx {}

impl IncomingWebhook for Ebanx {
    fn get_webhook_object_reference_id(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<ObjectReferenceId, ConnectorError> {
        Err(report!(ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<IncomingWebhookEvent, ConnectorError> {
        Err(report!(ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_resource_object(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, ConnectorError> {
        Err(report!(ConnectorError::WebhooksNotImplemented))
    }
}

static EBANX_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Ebanx",
    description: "EBANX payout connector for cross-border disbursements and local currency payouts across Latin America, Africa, and emerging markets",
    connector_type: common_enums::HyperswitchConnectorCategory::PayoutProcessor,
    integration_status: common_enums::ConnectorIntegrationStatus::Sandbox,
};

impl ConnectorSpecifications for Ebanx {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&EBANX_CONNECTOR_INFO)
    }

    fn get_supported_payment_methods(&self) -> Option<&'static SupportedPaymentMethods> {
        None
    }

    fn get_supported_webhook_flows(&self) -> Option<&'static [common_enums::enums::EventClass]> {
        None
    }
}


// Struct: DatatransAuthType
// File: crates/hyperswitch_connectors/src/connectors/datatrans/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DatatransAuthType


// Function: get_email
// File: crates/router/src/types/domain/user.rs
// Module: router

pub fn get_email(&self) -> pii::Email


// Struct: Event
// File: crates/diesel_models/src/events.rs
// Module: diesel_models
// Implementations: 0

pub struct Event


// Struct: SubmitEvidenceRequestData
// File: crates/hyperswitch_domain_models/src/router_request_types.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct SubmitEvidenceRequestData


// File: crates/router/src/types/api/routing.rs
// Module: router
// Public structs: 3

pub use api_models::{
    enums as api_enums,
    routing::{
        ConnectorVolumeSplit, RoutableChoiceKind, RoutableConnectorChoice, RoutingAlgorithmKind,
        RoutingAlgorithmRef, RoutingConfigRequest, RoutingDictionary, RoutingDictionaryRecord,
        StaticRoutingAlgorithm, StraightThroughAlgorithm,
    },
};

use super::types::api as api_oss;

pub struct SessionRoutingChoice {
    pub connector: api_oss::ConnectorData,
    pub payment_method_type: api_enums::PaymentMethodType,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ConnectorVolumeSplitV0 {
    pub connector: RoutableConnectorChoice,
    pub split: u8,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
pub enum RoutingAlgorithmV0 {
    Single(Box<RoutableConnectorChoice>),
    Priority(Vec<RoutableConnectorChoice>),
    VolumeSplit(Vec<ConnectorVolumeSplitV0>),
    Custom { timestamp: i64 },
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct FrmRoutingAlgorithm {
    pub data: String,
    #[serde(rename = "type")]
    pub algorithm_type: String,
}


// Function: update_by_user_email
// File: crates/diesel_models/src/query/user.rs
// Module: diesel_models

pub fn update_by_user_email(
        conn: &PgPooledConn,
        user_email: &pii::Email,
        user_update: UserUpdate,
    ) -> StorageResult<Self>


// Implementation: impl api::PaymentsPreProcessing for for Adyen
// File: crates/hyperswitch_connectors/src/connectors/adyen.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentsPreProcessing for for Adyen


// Struct: DigitalvirgoConsentStatus
// File: crates/hyperswitch_connectors/src/connectors/digitalvirgo/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DigitalvirgoConsentStatus


// Function: construct_mandate_revoke_router_data
// File: crates/router/src/core/mandate/utils.rs
// Module: router

pub fn construct_mandate_revoke_router_data(
    state: &SessionState,
    merchant_connector_account: helpers::MerchantConnectorAccountType,
    merchant_context: &domain::MerchantContext,
    mandate: Mandate,
) -> CustomResult<types::MandateRevokeRouterData, errors::ApiErrorResponse>


// Implementation: impl ConnectorSpecifications for for Fiuu
// File: crates/hyperswitch_connectors/src/connectors/fiuu.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl ConnectorSpecifications for for Fiuu


// Function: payments_redirect_response_with_creds_identifier
// File: crates/router/src/routes/payments.rs
// Module: router

pub fn payments_redirect_response_with_creds_identifier(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    path: web::Path<(
        common_utils::id_type::PaymentId,
        common_utils::id_type::MerchantId,
        String,
        String,
    )


// Implementation: impl api::PaymentToken for for Gigadat
// File: crates/hyperswitch_connectors/src/connectors/gigadat.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentToken for for Gigadat


// Function: update_profile_active_algorithm_ref
// File: crates/router/src/core/routing/helpers.rs
// Module: router

pub fn update_profile_active_algorithm_ref(
    db: &dyn StorageInterface,
    key_manager_state: &KeyManagerState,
    merchant_key_store: &domain::MerchantKeyStore,
    current_business_profile: domain::Profile,
    algorithm_id: routing_types::RoutingAlgorithmRef,
    transaction_type: &storage::enums::TransactionType,
) -> RouterResult<()>


// Struct: Error
// File: crates/hyperswitch_connectors/src/connectors/powertranz/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Error


// Struct: NmiWebhookObject
// File: crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NmiWebhookObject


// Struct: MerchantIdAndProfileIdAuth
// File: crates/router/src/services/authentication.rs
// Module: router
// Implementations: 0

pub struct MerchantIdAndProfileIdAuth


// Function: send_recon_request
// File: crates/router/src/core/recon.rs
// Module: router

pub fn send_recon_request(
    state: SessionState,
    auth_data: authentication::AuthenticationDataWithUser,
) -> RouterResponse<recon_api::ReconStatusResponse>


// Struct: GoPayRedirection
// File: crates/hyperswitch_domain_models/src/payment_method_data.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct GoPayRedirection


// Function: from_transaction_response
// File: crates/hyperswitch_connectors/src/connectors/celero/transformers.rs
// Module: hyperswitch_connectors

pub fn from_transaction_response(response: &CeleroCardResponse, msg: String) -> Self


// Implementation: impl api::PaymentCapture for for Forte
// File: crates/hyperswitch_connectors/src/connectors/forte.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentCapture for for Forte


// Struct: ApplePayCryptogramData
// File: crates/common_types/src/payments.rs
// Module: common_types
// Implementations: 0

// Documentation: This struct represents the cryptogram data for Apple Pay transactions

pub struct ApplePayCryptogramData


// Function: find_by_customer_id_merchant_id
// File: crates/diesel_models/src/query/payment_method.rs
// Module: diesel_models

pub fn find_by_customer_id_merchant_id(
        conn: &PgPooledConn,
        customer_id: &common_utils::id_type::CustomerId,
        merchant_id: &common_utils::id_type::MerchantId,
        limit: Option<i64>,
    ) -> StorageResult<Vec<Self>>


// Struct: UasConfirmationRequestData
// File: crates/hyperswitch_domain_models/src/router_request_types/unified_authentication_service.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct UasConfirmationRequestData


// Struct: DDCResponse
// File: crates/hyperswitch_connectors/src/connectors/worldpay/response.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DDCResponse