// File: crates/router/src/core/fraud_check/flows/checkout_flow.rs
// Module: router
// Public functions: 1

use async_trait::async_trait;
use common_utils::{ext_traits::ValueExt, pii::Email};
use error_stack::ResultExt;
use masking::ExposeInterface;

use super::{ConstructFlowSpecificData, FeatureFrm};
use crate::{
    core::{
        errors::{ConnectorErrorExt, RouterResult},
        fraud_check::types::FrmData,
        payments::{self, helpers},
    },
    errors, services,
    types::{
        api::fraud_check::{self as frm_api, FraudCheckConnectorData},
        domain,
        fraud_check::{FraudCheckCheckoutData, FraudCheckResponseData, FrmCheckoutRouterData},
        storage::enums as storage_enums,
        BrowserInformation, ConnectorAuthType, MerchantRecipientData, ResponseId, RouterData,
    },
    SessionState,
};

#[async_trait]
impl ConstructFlowSpecificData<frm_api::Checkout, FraudCheckCheckoutData, FraudCheckResponseData>
    for FrmData
{
    #[cfg(feature = "v2")]
    async fn construct_router_data<'a>(
        &self,
        _state: &SessionState,
        _connector_id: &str,
        _merchant_context: &domain::MerchantContext,
        _customer: &Option<domain::Customer>,
        _merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
        _merchant_recipient_data: Option<MerchantRecipientData>,
        _header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<RouterData<frm_api::Checkout, FraudCheckCheckoutData, FraudCheckResponseData>>
    {
        todo!()
    }

    #[cfg(feature = "v1")]
    async fn construct_router_data<'a>(
        &self,
        state: &SessionState,
        connector_id: &str,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
        merchant_connector_account: &helpers::MerchantConnectorAccountType,
        _merchant_recipient_data: Option<MerchantRecipientData>,
        header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<RouterData<frm_api::Checkout, FraudCheckCheckoutData, FraudCheckResponseData>>
    {
        use crate::connector::utils::PaymentsAttemptData;

        let status = storage_enums::AttemptStatus::Pending;

        let auth_type: ConnectorAuthType = merchant_connector_account
            .get_connector_account_details()
            .parse_value("ConnectorAuthType")
            .change_context(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
                id: "ConnectorAuthType".to_string(),
            })?;

        let browser_info: Option<BrowserInformation> = self.payment_attempt.get_browser_info().ok();
        let customer_id = customer.to_owned().map(|customer| customer.customer_id);

        let router_data = RouterData {
            flow: std::marker::PhantomData,
            merchant_id: merchant_context.get_merchant_account().get_id().clone(),
            customer_id,
            tenant_id: state.tenant.tenant_id.clone(),
            connector: connector_id.to_string(),
            payment_id: self.payment_intent.payment_id.get_string_repr().to_owned(),
            attempt_id: self.payment_attempt.attempt_id.clone(),
            status,
            payment_method: self
                .payment_attempt
                .payment_method
                .ok_or(errors::ApiErrorResponse::PaymentMethodNotFound)?,
            connector_auth_type: auth_type,
            description: None,
            payment_method_status: None,
            address: self.address.clone(),
            auth_type: storage_enums::AuthenticationType::NoThreeDs,
            connector_meta_data: None,
            connector_wallets_details: None,
            amount_captured: None,
            minor_amount_captured: None,
            request: FraudCheckCheckoutData {
                amount: self
                    .payment_attempt
                    .net_amount
                    .get_total_amount()
                    .get_amount_as_i64(),
                order_details: self.order_details.clone(),
                currency: self.payment_attempt.currency,
                browser_info,
                payment_method_data: self
                    .payment_attempt
                    .payment_method_data
                    .as_ref()
                    .map(|pm_data| {
                        pm_data
                            .clone()
                            .parse_value::<api_models::payments::AdditionalPaymentData>(
                                "AdditionalPaymentData",
                            )
                    })
                    .transpose()
                    .unwrap_or_default(),
                email: customer
                    .clone()
                    .and_then(|customer_data| {
                        customer_data
                            .email
                            .map(|email| Email::try_from(email.into_inner().expose()))
                    })
                    .transpose()
                    .change_context(errors::ApiErrorResponse::InvalidDataValue {
                        field_name: "customer.customer_data.email",
                    })?,
                gateway: self.payment_attempt.connector.clone(),
            }, // self.order_details
            response: Ok(FraudCheckResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId("".to_string()),
                connector_metadata: None,
                status: storage_enums::FraudCheckStatus::Pending,
                score: None,
                reason: None,
            }),
            access_token: None,
            session_token: None,
            reference_id: None,
            payment_method_token: None,
            connector_customer: None,
            preprocessing_id: None,
            connector_request_reference_id: uuid::Uuid::new_v4().to_string(),
            test_mode: None,
            recurring_mandate_payment_data: None,
            #[cfg(feature = "payouts")]
            payout_method_data: None,
            #[cfg(feature = "payouts")]
            quote_id: None,
            payment_method_balance: None,
            connector_http_status_code: None,
            external_latency: None,
            connector_api_version: None,
            apple_pay_flow: None,
            frm_metadata: self.frm_metadata.clone(),
            refund_id: None,
            dispute_id: None,
            connector_response: None,
            integrity_check: Ok(()),
            additional_merchant_data: None,
            header_payload,
            connector_mandate_request_reference_id: None,
            authentication_id: None,
            psd2_sca_exemption_type: None,
            raw_connector_response: None,
            is_payment_id_from_merchant: None,
            l2_l3_data: None,
            minor_amount_capturable: None,
        };

        Ok(router_data)
    }
}

#[async_trait]
impl FeatureFrm<frm_api::Checkout, FraudCheckCheckoutData> for FrmCheckoutRouterData {
    async fn decide_frm_flows<'a>(
        mut self,
        state: &SessionState,
        connector: &FraudCheckConnectorData,
        call_connector_action: payments::CallConnectorAction,
        merchant_context: &domain::MerchantContext,
    ) -> RouterResult<Self> {
        decide_frm_flow(
            &mut self,
            state,
            connector,
            call_connector_action,
            merchant_context,
        )
        .await
    }
}

pub async fn decide_frm_flow(
    router_data: &mut FrmCheckoutRouterData,
    state: &SessionState,
    connector: &FraudCheckConnectorData,
    call_connector_action: payments::CallConnectorAction,
    _merchant_context: &domain::MerchantContext,
) -> RouterResult<FrmCheckoutRouterData> {
    let connector_integration: services::BoxedFrmConnectorIntegrationInterface<
        frm_api::Checkout,
        FraudCheckCheckoutData,
        FraudCheckResponseData,
    > = connector.connector.get_connector_integration();
    let resp = services::execute_connector_processing_step(
        state,
        connector_integration,
        router_data,
        call_connector_action,
        None,
        None,
    )
    .await
    .to_payment_failed_response()?;

    Ok(resp)
}


// File: crates/diesel_models/src/query/locker_mock_up.rs
// Module: diesel_models
// Public functions: 3

use diesel::{associations::HasTable, ExpressionMethods};

use super::generics;
use crate::{
    locker_mock_up::{LockerMockUp, LockerMockUpNew},
    schema::locker_mock_up::dsl,
    PgPooledConn, StorageResult,
};

impl LockerMockUpNew {
    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<LockerMockUp> {
        generics::generic_insert(conn, self).await
    }
}

impl LockerMockUp {
    pub async fn find_by_card_id(conn: &PgPooledConn, card_id: &str) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::card_id.eq(card_id.to_owned()),
        )
        .await
    }

    pub async fn delete_by_card_id(conn: &PgPooledConn, card_id: &str) -> StorageResult<Self> {
        generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::card_id.eq(card_id.to_owned()),
        )
        .await
    }
}


// Struct: MessageResponseType
// File: crates/hyperswitch_connectors/src/connectors/redsys/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MessageResponseType


// Implementation: impl api::PaymentAuthorize for for Cryptopay
// File: crates/hyperswitch_connectors/src/connectors/cryptopay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentAuthorize for for Cryptopay


// Implementation: impl GenericLinkData
// File: crates/diesel_models/src/generic_link.rs
// Module: diesel_models
// Methods: 2 total (2 public)

impl GenericLinkData


// Implementation: impl BillingConnectorPaymentsSyncResponseData
// File: crates/router/src/core/webhooks/recovery_incoming.rs
// Module: router
// Methods: 3 total (0 public)

impl BillingConnectorPaymentsSyncResponseData


// Implementation: impl api::PaymentIncrementalAuthorization for for Cybersource
// File: crates/hyperswitch_connectors/src/connectors/cybersource.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentIncrementalAuthorization for for Cybersource


// Struct: FrmFiltersResponse
// File: crates/api_models/src/analytics.rs
// Module: api_models
// Implementations: 1
// Traits: ApiEventMetric

pub struct FrmFiltersResponse


// Function: get_mca_status
// File: crates/router/src/core/payment_methods/cards.rs
// Module: router

pub fn get_mca_status(
    state: &routes::SessionState,
    key_store: &domain::MerchantKeyStore,
    profile_id: Option<id_type::ProfileId>,
    merchant_id: &id_type::MerchantId,
    is_connector_agnostic_mit_enabled: bool,
    connector_mandate_details: Option<&CommonMandateReference>,
    network_transaction_id: Option<&String>,
    merchant_connector_accounts: &domain::MerchantConnectorAccounts,
) -> bool


                *nuvei_transaction_sync_response
            }
        }
    }
}

impl TryFrom<&types::PaymentsAuthorizeSessionTokenRouterData> for NuveiSessionRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &types::PaymentsAuthorizeSessionTokenRouterData,
    ) -> Result<Self, Self::Error> {
        let connector_meta: NuveiAuthType = NuveiAuthType::try_from(&item.connector_auth_type)?;
        let merchant_id = connector_meta.merchant_id;
        let merchant_site_id = connector_meta.merchant_site_id;
        let client_request_id = item.connector_request_reference_id.clone();
        let time_stamp = date_time::DateTime::<date_time::YYYYMMDDHHmmss>::from(date_time::now());
        let merchant_secret = connector_meta.merchant_secret;
        Ok(Self {
            merchant_id: merchant_id.clone(),
            merchant_site_id: merchant_site_id.clone(),
            client_request_id: client_request_id.clone(),
            time_stamp: time_stamp.clone(),
            checksum: Secret::new(encode_payload(&[
                merchant_id.peek(),
                merchant_site_id.peek(),
                &client_request_id,
                &time_stamp.to_string(),
                merchant_secret.peek(),
            ])?),
        })
    }
}

impl<F, T> TryFrom<ResponseRouterData<F, NuveiSessionResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, NuveiSessionResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            status: enums::AttemptStatus::Pending,
            session_token: Some(item.response.session_token.clone().expose()),
            response: Ok(PaymentsResponseData::SessionTokenResponse {
                session_token: item.response.session_token.expose(),
            }),
            ..item.data
        })
    }
}

#[derive(Debug)]
pub struct NuveiCardDetails {
    card: payment_method_data::Card,
    three_d: Option<ThreeD>,
    card_holder_name: Option<Secret<String>>,
    stored_credentials: Option<StoredCredentialMode>,
}

// Define new structs with camelCase serialization
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct GooglePayCamelCase {
    pm_type: Secret<String>,
    description: Secret<String>,
    info: GooglePayInfoCamelCase,
    tokenization_data: GooglePayTokenizationDataCamelCase,
}

#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct GooglePayInfoCamelCase {
    card_network: Secret<String>,
    card_details: Secret<String>,
    assurance_details: Option<GooglePayAssuranceDetailsCamelCase>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ExternalSchemeDetails {
    transaction_id: Secret<String>, // This is sensitive information
    brand: Option<NuveiCardType>,
}
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct GooglePayAssuranceDetailsCamelCase {
    card_holder_authenticated: bool,
    account_verified: bool,
}

#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct GooglePayTokenizationDataCamelCase {
    #[serde(rename = "type")]
    token_type: Secret<String>,
    token: Secret<String>,
}

// Define ApplePay structs with camelCase serialization
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct ApplePayCamelCase {
    payment_data: Secret<String>,
    payment_method: ApplePayPaymentMethodCamelCase,
    transaction_identifier: Secret<String>,
}

#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct ApplePayPaymentMethodCamelCase {
    display_name: Secret<String>,
    network: Secret<String>,
    #[serde(rename = "type")]
    pm_type: Secret<String>,
}

fn get_google_pay_decrypt_data(
    predecrypt_data: &GPayPredecryptData,
    is_rebilling: Option<String>,
    brand: Option<String>,
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>> {
    Ok(NuveiPaymentsRequest {
        is_rebilling,
        payment_option: PaymentOption {
            card: Some(Card {
                brand,
                card_number: Some(predecrypt_data.application_primary_account_number.clone()),
                last4_digits: Some(Secret::new(
                    predecrypt_data
                        .application_primary_account_number
                        .clone()
                        .get_last4(),
                )),
                expiration_month: Some(predecrypt_data.card_exp_month.clone()),
                expiration_year: Some(predecrypt_data.card_exp_year.clone()),
                external_token: Some(ExternalToken {
                    external_token_provider: ExternalTokenProvider::GooglePay,
                    mobile_token: None,
                    cryptogram: predecrypt_data.cryptogram.clone(),
                    eci_provider: predecrypt_data.eci_indicator.clone(),
                }),
                ..Default::default()
            }),
            ..Default::default()
        },
        ..Default::default()
    })
}

fn get_googlepay_info<F, Req>(
    item: &RouterData<F, Req, PaymentsResponseData>,
    gpay_data: &GooglePayWalletData,
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>>
where
    Req: NuveiAuthorizePreprocessingCommon,
{
    let is_rebilling = if item.request.is_customer_initiated_mandate_payment() {
        Some("0".to_string())
    } else {
        None
    };

    if let Ok(PaymentMethodToken::GooglePayDecrypt(ref token)) = item.get_payment_method_token() {
        return get_google_pay_decrypt_data(
            token,
            is_rebilling,
            Some(gpay_data.info.card_network.clone()),
        );
    }

    match &gpay_data.tokenization_data {
        GpayTokenizationData::Decrypted(gpay_predecrypt_data) => get_google_pay_decrypt_data(
            gpay_predecrypt_data,
            is_rebilling,
            Some(gpay_data.info.card_network.clone()),
        ),
        GpayTokenizationData::Encrypted(ref encrypted_data) => Ok(NuveiPaymentsRequest {
            is_rebilling,
            payment_option: PaymentOption {
                card: Some(Card {
                    external_token: Some(ExternalToken {
                        external_token_provider: ExternalTokenProvider::GooglePay,

                        mobile_token: {
                            let (token_type, token) = (
                                encrypted_data.token_type.clone(),
                                encrypted_data.token.clone(),
                            );

                            let google_pay: GooglePayCamelCase = GooglePayCamelCase {
                                pm_type: Secret::new(gpay_data.pm_type.clone()),
                                description: Secret::new(gpay_data.description.clone()),
                                info: GooglePayInfoCamelCase {
                                    card_network: Secret::new(gpay_data.info.card_network.clone()),
                                    card_details: Secret::new(gpay_data.info.card_details.clone()),
                                    assurance_details: gpay_data
                                        .info
                                        .assurance_details
                                        .as_ref()
                                        .map(|details| GooglePayAssuranceDetailsCamelCase {
                                            card_holder_authenticated: details
                                                .card_holder_authenticated,
                                            account_verified: details.account_verified,
                                        }),
                                },
                                tokenization_data: GooglePayTokenizationDataCamelCase {
                                    token_type: token_type.into(),
                                    token: token.into(),
                                },
                            };
                            Some(Secret::new(
                                google_pay.encode_to_string_of_json().change_context(
                                    errors::ConnectorError::RequestEncodingFailed,
                                )?,
                            ))
                        },
                        cryptogram: None,
                        eci_provider: None,
                    }),
                    ..Default::default()
                }),
                ..Default::default()
            },
            ..Default::default()
        }),
    }
}

fn get_apple_pay_decrypt_data(
    apple_pay_predecrypt_data: &ApplePayPredecryptData,
    is_rebilling: Option<String>,
    network: String,
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>> {
    Ok(NuveiPaymentsRequest {
        is_rebilling,
        payment_option: PaymentOption {
            card: Some(Card {
                brand: Some(network),
                card_number: Some(
                    apple_pay_predecrypt_data
                        .application_primary_account_number
                        .clone(),
                ),
                last4_digits: Some(Secret::new(
                    apple_pay_predecrypt_data
                        .application_primary_account_number
                        .get_last4(),
                )),
                expiration_month: Some(
                    apple_pay_predecrypt_data
                        .application_expiration_month
                        .clone(),
                ),
                expiration_year: Some(
                    apple_pay_predecrypt_data
                        .application_expiration_year
                        .clone(),
                ),
                external_token: Some(ExternalToken {
                    external_token_provider: ExternalTokenProvider::ApplePay,
                    mobile_token: None,
                    cryptogram: Some(
                        apple_pay_predecrypt_data
                            .payment_data
                            .online_payment_cryptogram
                            .clone(),
                    ),
                    eci_provider: apple_pay_predecrypt_data.payment_data.eci_indicator.clone(),
                }),
                ..Default::default()
            }),
            ..Default::default()
        },
        ..Default::default()
    })
}
fn get_applepay_info<F, Req>(
    item: &RouterData<F, Req, PaymentsResponseData>,
    apple_pay_data: &ApplePayWalletData,
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>>
where
    Req: NuveiAuthorizePreprocessingCommon,
{
    let is_rebilling = if item.request.is_customer_initiated_mandate_payment() {
        Some("0".to_string())
    } else {
        None
    };
    if let Ok(PaymentMethodToken::ApplePayDecrypt(ref token)) = item.get_payment_method_token() {
        return get_apple_pay_decrypt_data(
            token,
            is_rebilling,
            apple_pay_data.payment_method.network.clone(),
        );
    }
    match apple_pay_data.payment_data {
        ApplePayPaymentData::Decrypted(ref apple_pay_predecrypt_data) => {
            get_apple_pay_decrypt_data(
                apple_pay_predecrypt_data,
                is_rebilling,
                apple_pay_data.payment_method.network.clone(),
            )
        }

        ApplePayPaymentData::Encrypted(ref encrypted_data) => Ok(NuveiPaymentsRequest {
            is_rebilling,
            payment_option: PaymentOption {
                card: Some(Card {
                    external_token: Some(ExternalToken {
                        external_token_provider: ExternalTokenProvider::ApplePay,
                        mobile_token: {
                            let apple_pay: ApplePayCamelCase = ApplePayCamelCase {
                                payment_data: encrypted_data.to_string().into(),
                                payment_method: ApplePayPaymentMethodCamelCase {
                                    display_name: Secret::new(
                                        apple_pay_data.payment_method.display_name.clone(),
                                    ),
                                    network: Secret::new(
                                        apple_pay_data.payment_method.network.clone(),
                                    ),
                                    pm_type: Secret::new(
                                        apple_pay_data.payment_method.pm_type.clone(),
                                    ),
                                },
                                transaction_identifier: Secret::new(
                                    apple_pay_data.transaction_identifier.clone(),
                                ),
                            };

                            Some(Secret::new(
                                apple_pay.encode_to_string_of_json().change_context(
                                    errors::ConnectorError::RequestEncodingFailed,
                                )?,
                            ))
                        },
                        cryptogram: None,
                        eci_provider: None,
                    }),
                    ..Default::default()
                }),
                ..Default::default()
            },
            ..Default::default()
        }),
    }
}

impl TryFrom<enums::BankNames> for NuveiBIC {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(bank: enums::BankNames) -> Result<Self, Self::Error> {
        match bank {
            enums::BankNames::AbnAmro => Ok(Self::Abnamro),
            enums::BankNames::AsnBank => Ok(Self::ASNBank),
            enums::BankNames::Bunq => Ok(Self::Bunq),
            enums::BankNames::Ing => Ok(Self::Ing),
            enums::BankNames::Knab => Ok(Self::Knab),
            enums::BankNames::Rabobank => Ok(Self::Rabobank),
            enums::BankNames::SnsBank => Ok(Self::SNSBank),
            enums::BankNames::TriodosBank => Ok(Self::TriodosBank),
            enums::BankNames::VanLanschot => Ok(Self::VanLanschotBankiers),
            enums::BankNames::Moneyou => Ok(Self::Moneyou),

            enums::BankNames::AmericanExpress
            | enums::BankNames::AffinBank
            | enums::BankNames::AgroBank
            | enums::BankNames::AllianceBank
            | enums::BankNames::AmBank
            | enums::BankNames::BankOfAmerica
            | enums::BankNames::BankOfChina
            | enums::BankNames::BankIslam
            | enums::BankNames::BankMuamalat
            | enums::BankNames::BankRakyat
            | enums::BankNames::BankSimpananNasional
            | enums::BankNames::Barclays
            | enums::BankNames::BlikPSP
            | enums::BankNames::CapitalOne
            | enums::BankNames::Chase
            | enums::BankNames::Citi
            | enums::BankNames::CimbBank
            | enums::BankNames::Discover
            | enums::BankNames::NavyFederalCreditUnion
            | enums::BankNames::PentagonFederalCreditUnion
            | enums::BankNames::SynchronyBank
            | enums::BankNames::WellsFargo
            | enums::BankNames::Handelsbanken
            | enums::BankNames::HongLeongBank
            | enums::BankNames::HsbcBank
            | enums::BankNames::KuwaitFinanceHouse
            | enums::BankNames::Regiobank
            | enums::BankNames::Revolut
            | enums::BankNames::ArzteUndApothekerBank
            | enums::BankNames::AustrianAnadiBankAg
            | enums::BankNames::BankAustria
            | enums::BankNames::Bank99Ag
            | enums::BankNames::BankhausCarlSpangler
            | enums::BankNames::BankhausSchelhammerUndSchatteraAg
            | enums::BankNames::BankMillennium
            | enums::BankNames::BankPEKAOSA
            | enums::BankNames::BawagPskAg
            | enums::BankNames::BksBankAg
            | enums::BankNames::BrullKallmusBankAg
            | enums::BankNames::BtvVierLanderBank
            | enums::BankNames::CapitalBankGraweGruppeAg
            | enums::BankNames::CeskaSporitelna
            | enums::BankNames::Dolomitenbank
            | enums::BankNames::EasybankAg
            | enums::BankNames::EPlatbyVUB
            | enums::BankNames::ErsteBankUndSparkassen
            | enums::BankNames::FrieslandBank
            | enums::BankNames::HypoAlpeadriabankInternationalAg
            | enums::BankNames::HypoNoeLbFurNiederosterreichUWien
            | enums::BankNames::HypoOberosterreichSalzburgSteiermark
            | enums::BankNames::HypoTirolBankAg
            | enums::BankNames::HypoVorarlbergBankAg
            | enums::BankNames::HypoBankBurgenlandAktiengesellschaft
            | enums::BankNames::KomercniBanka
            | enums::BankNames::MBank
            | enums::BankNames::MarchfelderBank
            | enums::BankNames::Maybank
            | enums::BankNames::OberbankAg
            | enums::BankNames::OsterreichischeArzteUndApothekerbank
            | enums::BankNames::OcbcBank
            | enums::BankNames::PayWithING
            | enums::BankNames::PlaceZIPKO
            | enums::BankNames::PlatnoscOnlineKartaPlatnicza
            | enums::BankNames::PosojilnicaBankEGen
            | enums::BankNames::PostovaBanka
            | enums::BankNames::PublicBank
            | enums::BankNames::RaiffeisenBankengruppeOsterreich
            | enums::BankNames::RhbBank
            | enums::BankNames::SchelhammerCapitalBankAg
            | enums::BankNames::StandardCharteredBank
            | enums::BankNames::SchoellerbankAg
            | enums::BankNames::SpardaBankWien
            | enums::BankNames::SporoPay
            | enums::BankNames::SantanderPrzelew24
            | enums::BankNames::TatraPay
            | enums::BankNames::Viamo
            | enums::BankNames::VolksbankGruppe
            | enums::BankNames::VolkskreditbankAg
            | enums::BankNames::VrBankBraunau
            | enums::BankNames::UobBank
            | enums::BankNames::PayWithAliorBank
            | enums::BankNames::BankiSpoldzielcze
            | enums::BankNames::PayWithInteligo
            | enums::BankNames::BNPParibasPoland
            | enums::BankNames::BankNowySA
            | enums::BankNames::CreditAgricole
            | enums::BankNames::PayWithBOS
            | enums::BankNames::PayWithCitiHandlowy
            | enums::BankNames::PayWithPlusBank
            | enums::BankNames::ToyotaBank
            | enums::BankNames::VeloBank
            | enums::BankNames::ETransferPocztowy24
            | enums::BankNames::PlusBank
            | enums::BankNames::EtransferPocztowy24
            | enums::BankNames::BankiSpbdzielcze
            | enums::BankNames::BankNowyBfgSa
            | enums::BankNames::GetinBank
            | enums::BankNames::Blik
            | enums::BankNames::NoblePay
            | enums::BankNames::IdeaBank
            | enums::BankNames::EnveloBank
            | enums::BankNames::NestPrzelew
            | enums::BankNames::MbankMtransfer
            | enums::BankNames::Inteligo
            | enums::BankNames::PbacZIpko
            | enums::BankNames::BnpParibas
            | enums::BankNames::BankPekaoSa
            | enums::BankNames::VolkswagenBank
            | enums::BankNames::AliorBank
            | enums::BankNames::Boz
            | enums::BankNames::BangkokBank
            | enums::BankNames::KrungsriBank
            | enums::BankNames::KrungThaiBank
            | enums::BankNames::TheSiamCommercialBank
            | enums::BankNames::KasikornBank
            | enums::BankNames::OpenBankSuccess
            | enums::BankNames::OpenBankFailure
            | enums::BankNames::OpenBankCancelled
            | enums::BankNames::Aib
            | enums::BankNames::BankOfScotland
            | enums::BankNames::DanskeBank
            | enums::BankNames::FirstDirect
            | enums::BankNames::FirstTrust
            | enums::BankNames::Halifax
            | enums::BankNames::Lloyds
            | enums::BankNames::Monzo
            | enums::BankNames::NatWest
            | enums::BankNames::NationwideBank
            | enums::BankNames::RoyalBankOfScotland
            | enums::BankNames::Starling
            | enums::BankNames::TsbBank
            | enums::BankNames::TescoBank
            | enums::BankNames::Yoursafe
            | enums::BankNames::N26
            | enums::BankNames::NationaleNederlanden
            | enums::BankNames::UlsterBank => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Nuvei"),
            ))?,
        }
    }
}

impl<F, Req>
    ForeignTryFrom<(
        AlternativePaymentMethodType,
        Option<BankRedirectData>,
        &RouterData<F, Req, PaymentsResponseData>,
    )> for NuveiPaymentsRequest
where
    Req: NuveiAuthorizePreprocessingCommon,
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(
        data: (
            AlternativePaymentMethodType,
            Option<BankRedirectData>,
            &RouterData<F, Req, PaymentsResponseData>,
        ),
    ) -> Result<Self, Self::Error> {
        let (payment_method, redirect, item) = data;
        let bank_id = match (&payment_method, redirect) {
            (AlternativePaymentMethodType::Expresscheckout, _) => None,
            (AlternativePaymentMethodType::Giropay, _) => None,
            (AlternativePaymentMethodType::Sofort, _) | (AlternativePaymentMethodType::Eps, _) => {
                let address = item.get_billing_address()?;
                address.get_first_name()?;
                item.request.get_email_required()?;
                item.get_billing_country()?;
                None
            }
            (
                AlternativePaymentMethodType::Ideal,
                Some(BankRedirectData::Ideal { bank_name, .. }),
            ) => {
                let address = item.get_billing_address()?;
                address.get_first_name()?;
                item.request.get_email_required()?;
                item.get_billing_country()?;
                bank_name.map(NuveiBIC::try_from).transpose()?
            }
            _ => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("Nuvei"),
            ))?,
        };
        let billing_address: Option<BillingAddress> =
            item.get_billing().ok().map(|billing| billing.into());
        Ok(Self {
            payment_option: PaymentOption {
                alternative_payment_method: Some(AlternativePaymentMethod {
                    payment_method,
                    bank_id,
                }),
                ..Default::default()
            },
            billing_address,
            ..Default::default()
        })
    }
}

fn get_pay_later_info<F, Req>(
    payment_method_type: AlternativePaymentMethodType,
    item: &RouterData<F, Req, PaymentsResponseData>,
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>>
where
    Req: NuveiAuthorizePreprocessingCommon,
{
    let address = item
        .get_billing()?
        .address
        .as_ref()
        .ok_or_else(missing_field_err("billing.address"))?;
    address.get_first_name()?;
    let payment_method = payment_method_type;
    address.get_country()?; //country is necessary check
    item.request.get_email_required()?;
    Ok(NuveiPaymentsRequest {
        payment_option: PaymentOption {
            alternative_payment_method: Some(AlternativePaymentMethod {
                payment_method,
                ..Default::default()
            }),
            billing_address: item.get_billing().ok().map(|billing| billing.into()),
            ..Default::default()
        },
        ..Default::default()
    })
}

fn get_ntid_card_info<F, Req>(
    router_data: &RouterData<F, Req, PaymentsResponseData>,
    data: CardDetailsForNetworkTransactionId,
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>>
where
    Req: NuveiAuthorizePreprocessingCommon,
{
    let card_type = match data.card_network.clone() {
        Some(card_type) => NuveiCardType::try_from(card_type)?,
        None => NuveiCardType::try_from(&data.get_card_issuer()?)?,
    };

    let external_scheme_details = Some(ExternalSchemeDetails {
        transaction_id: router_data
            .request
            .get_ntid()
            .ok_or_else(missing_field_err("network_transaction_id"))
            .attach_printable("Nuvei unable to find NTID for MIT")?
            .into(),
        brand: Some(card_type),
    });
    let payment_option: PaymentOption = PaymentOption {
        card: Some(Card {
            card_number: Some(data.card_number),
            card_holder_name: data.card_holder_name,
            expiration_month: Some(data.card_exp_month),
            expiration_year: Some(data.card_exp_year),
            ..Default::default() // CVV should be disabled by nuvei
        }),
        redirect_url: None,
        user_payment_option_id: None,
        alternative_payment_method: None,
        billing_address: None,
        shipping_address: None,
    };
    let is_rebilling = if router_data.request.is_customer_initiated_mandate_payment() {
        Some("0".to_string())
    } else {
        None
    };
    Ok(NuveiPaymentsRequest {
        external_scheme_details,
        payment_option,
        is_rebilling,
        ..Default::default()
    })
}
fn get_l2_l3_items(
    l2_l3_data: &Option<L2L3Data>,
    currency: enums::Currency,
) -> Result<Option<Vec<NuveiItem>>, error_stack::Report<errors::ConnectorError>> {
    l2_l3_data.as_ref().map_or(Ok(None), |data| {
        data.order_details
            .as_ref()
            .map_or(Ok(None), |order_details_list| {
                // Map each order to a Result<NuveiItem>
                let results: Vec<Result<NuveiItem, error_stack::Report<errors::ConnectorError>>> =
                    order_details_list
                        .iter()
                        .map(|order| {
                            let discount = order
                                .unit_discount_amount
                                .map(|amount| {
                                    convert_amount(NUVEI_AMOUNT_CONVERTOR, amount, currency)
                                })
                                .transpose()?;
                            let tax = order
                                .total_tax_amount
                                .map(|amount| {
                                    convert_amount(NUVEI_AMOUNT_CONVERTOR, amount, currency)
                                })
                                .transpose()?;
                            Ok(NuveiItem {
                                name: order.product_name.clone(),
                                item_type: order.product_type.clone().into(),
                                price: convert_amount(
                                    NUVEI_AMOUNT_CONVERTOR,
                                    order.amount,
                                    currency,
                                )?,
                                quantity: order.quantity.to_string(),
                                group_id: order.product_id.clone(),
                                discount,
                                discount_rate: None,
                                shipping: None,
                                shipping_tax: None,
                                shipping_tax_rate: None,
                                tax,
                                tax_rate: order.tax_rate.map(|rate| rate.to_string()),
                                image_url: order.product_img_link.clone(),
                                product_url: None,
                            })
                        })
                        .collect();
                let mut items = Vec::with_capacity(results.len());
                for result in results {
                    match result {
                        Ok(item) => items.push(item),
                        Err(err) => return Err(err),
                    }
                }
                Ok(Some(items))
            })
    })
}

fn get_amount_details(
    l2_l3_data: &Option<L2L3Data>,
    currency: enums::Currency,
) -> Result<Option<NuveiAmountDetails>, error_stack::Report<errors::ConnectorError>> {
    l2_l3_data.as_ref().map_or(Ok(None), |data| {
        let total_tax = data
            .order_tax_amount
            .map(|amount| convert_amount(NUVEI_AMOUNT_CONVERTOR, amount, currency))
            .transpose()?;
        let total_shipping = data
            .shipping_cost
            .map(|amount| convert_amount(NUVEI_AMOUNT_CONVERTOR, amount, currency))
            .transpose()?;
        let total_discount = data
            .discount_amount
            .map(|amount| convert_amount(NUVEI_AMOUNT_CONVERTOR, amount, currency))
            .transpose()?;
        let total_handling = data
            .duty_amount
            .map(|amount| convert_amount(NUVEI_AMOUNT_CONVERTOR, amount, currency))
            .transpose()?;
        Ok(Some(NuveiAmountDetails {
            total_tax,
            total_shipping,
            total_handling,
            total_discount,
        }))
    })
}

impl<F, Req> TryFrom<(&RouterData<F, Req, PaymentsResponseData>, String)> for NuveiPaymentsRequest
where
    Req: NuveiAuthorizePreprocessingCommon,
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        data: (&RouterData<F, Req, PaymentsResponseData>, String),
    ) -> Result<Self, Self::Error> {
        let item = data.0;

        let request_data = match item.request.get_payment_method_data_required()?.clone() {
            PaymentMethodData::Card(card) => get_card_info(item, &card),
            PaymentMethodData::MandatePayment => Self::try_from(item),
            PaymentMethodData::CardDetailsForNetworkTransactionId(data) => {
                get_ntid_card_info(item, data)
            }
            PaymentMethodData::Wallet(wallet) => match wallet {
                WalletData::GooglePay(gpay_data) => get_googlepay_info(item, &gpay_data),
                WalletData::ApplePay(apple_pay_data) => get_applepay_info(item, &apple_pay_data),
                WalletData::PaypalRedirect(_) => Self::foreign_try_from((
                    AlternativePaymentMethodType::Expresscheckout,
                    None,
                    item,
                )),
                WalletData::AliPayQr(_)
                | WalletData::AliPayRedirect(_)
                | WalletData::AliPayHkRedirect(_)
                | WalletData::AmazonPay(_)
                | WalletData::AmazonPayRedirect(_)
                | WalletData::Paysera(_)
                | WalletData::Skrill(_)
                | WalletData::BluecodeRedirect {}
                | WalletData::MomoRedirect(_)
                | WalletData::KakaoPayRedirect(_)
                | WalletData::GoPayRedirect(_)
                | WalletData::GcashRedirect(_)
                | WalletData::ApplePayRedirect(_)
                | WalletData::ApplePayThirdPartySdk(_)
                | WalletData::DanaRedirect {}
                | WalletData::GooglePayRedirect(_)
                | WalletData::GooglePayThirdPartySdk(_)
                | WalletData::MbWayRedirect(_)
                | WalletData::MobilePayRedirect(_)
                | WalletData::PaypalSdk(_)
                | WalletData::Paze(_)
                | WalletData::SamsungPay(_)
                | WalletData::TwintRedirect {}
                | WalletData::VippsRedirect {}
                | WalletData::TouchNGoRedirect(_)
                | WalletData::WeChatPayRedirect(_)
                | WalletData::CashappQr(_)
                | WalletData::SwishQr(_)
                | WalletData::WeChatPayQr(_)
                | WalletData::RevolutPay(_)
                | WalletData::Mifinity(_) => Err(errors::ConnectorError::NotImplemented(
                    utils::get_unimplemented_payment_method_error_message("nuvei"),
                )
                .into()),
            },
            PaymentMethodData::BankRedirect(redirect) => match redirect {
                BankRedirectData::Eps { .. } => Self::foreign_try_from((
                    AlternativePaymentMethodType::Eps,
                    Some(redirect),
                    item,
                )),
                BankRedirectData::Giropay { .. } => Self::foreign_try_from((
                    AlternativePaymentMethodType::Giropay,
                    Some(redirect),
                    item,
                )),
                BankRedirectData::Ideal { .. } => Self::foreign_try_from((
                    AlternativePaymentMethodType::Ideal,
                    Some(redirect),
                    item,
                )),
                BankRedirectData::Sofort { .. } => Self::foreign_try_from((
                    AlternativePaymentMethodType::Sofort,
                    Some(redirect),
                    item,
                )),
                BankRedirectData::BancontactCard { .. }
                | BankRedirectData::Bizum {}
                | BankRedirectData::Blik { .. }
                | BankRedirectData::Eft { .. }
                | BankRedirectData::Interac { .. }
                | BankRedirectData::OnlineBankingCzechRepublic { .. }
                | BankRedirectData::OnlineBankingFinland { .. }
                | BankRedirectData::OnlineBankingPoland { .. }
                | BankRedirectData::OnlineBankingSlovakia { .. }
                | BankRedirectData::Przelewy24 { .. }
                | BankRedirectData::Trustly { .. }
                | BankRedirectData::OnlineBankingFpx { .. }
                | BankRedirectData::OnlineBankingThailand { .. }
                | BankRedirectData::OpenBankingUk { .. }
                | BankRedirectData::LocalBankRedirect {} => {
                    Err(errors::ConnectorError::NotImplemented(
                        utils::get_unimplemented_payment_method_error_message("nuvei"),
                    )
                    .into())
                }
            },
            PaymentMethodData::PayLater(pay_later_data) => match pay_later_data {
                PayLaterData::KlarnaRedirect { .. } => {
                    get_pay_later_info(AlternativePaymentMethodType::Klarna, item)
                }
                PayLaterData::AfterpayClearpayRedirect { .. } => {
                    get_pay_later_info(AlternativePaymentMethodType::AfterPay, item)
                }
                PayLaterData::KlarnaSdk { .. }
                | PayLaterData::FlexitiRedirect {}
                | PayLaterData::AffirmRedirect {}
                | PayLaterData::PayBrightRedirect {}
                | PayLaterData::WalleyRedirect {}
                | PayLaterData::AlmaRedirect {}
                | PayLaterData::AtomeRedirect {}
                | PayLaterData::BreadpayRedirect {} => Err(errors::ConnectorError::NotImplemented(
                    utils::get_unimplemented_payment_method_error_message("nuvei"),
                )
                .into()),
            },
            PaymentMethodData::BankDebit(_)
            | PaymentMethodData::BankTransfer(_)
            | PaymentMethodData::Crypto(_)
            | PaymentMethodData::Reward
            | PaymentMethodData::RealTimePayment(_)
            | PaymentMethodData::MobilePayment(_)
            | PaymentMethodData::Upi(_)
            | PaymentMethodData::Voucher(_)
            | PaymentMethodData::CardRedirect(_)
            | PaymentMethodData::GiftCard(_)
            | PaymentMethodData::OpenBanking(_)
            | PaymentMethodData::CardToken(_)
            | PaymentMethodData::NetworkToken(_) => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("nuvei"),
            )
            .into()),
        }?;
        let currency = item.request.get_currency_required()?;
        let request = Self::try_from(NuveiPaymentRequestData {
            amount: convert_amount(
                NUVEI_AMOUNT_CONVERTOR,
                item.request.get_minor_amount_required()?,
                currency,
            )?,
            currency,
            connector_auth_type: item.connector_auth_type.clone(),
            client_request_id: item.connector_request_reference_id.clone(),
            session_token: Secret::new(data.1),
            capture_method: item.request.get_capture_method(),

            ..Default::default()
        })?;
        let return_url = item.request.get_return_url_required()?;

        let amount_details = get_amount_details(&item.l2_l3_data, currency)?;
        let l2_l3_items: Option<Vec<NuveiItem>> = get_l2_l3_items(&item.l2_l3_data, currency)?;
        let address = {
            let mut billing_address = item.get_billing()?.clone();
            item.get_billing_first_name()?;
            billing_address.email = match item.get_billing_email() {
                Ok(email) => Some(email),
                Err(_) => Some(item.request.get_email_required()?),
            };
            item.get_billing_country()?;
            Some(billing_address)
        };

        let shipping_address: Option<ShippingAddress> =
            item.get_optional_shipping().map(|address| address.into());

        let billing_address: Option<BillingAddress> =
            address.clone().map(|ref address| address.into());
        let device_details = if request_data
            .device_details
            .ip_address
            .clone()
            .expose()
            .is_empty()
        {
            DeviceDetails::foreign_try_from(&item.request.get_browser_info())?
        } else {
            request_data.device_details.clone()
        };

        Ok(Self {
            is_rebilling: request_data.is_rebilling,
            user_token_id: item.customer_id.clone(),
            related_transaction_id: request_data.related_transaction_id,
            payment_option: request_data.payment_option,
            billing_address,
            shipping_address,
            device_details,
            url_details: Some(UrlDetails {
                success_url: return_url.clone(),
                failure_url: return_url.clone(),
                pending_url: return_url.clone(),
            }),
            amount_details,
            items: l2_l3_items,
            is_partial_approval: item.request.get_is_partial_approval(),

            ..request
        })
    }
}

fn get_card_info<F, Req>(
    item: &RouterData<F, Req, PaymentsResponseData>,
    card_details: &payment_method_data::Card,
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>>
where
    Req: NuveiAuthorizePreprocessingCommon,
{
    let browser_information = item.request.get_browser_info().clone();
    let related_transaction_id = if item.is_three_ds() {
        item.request.get_related_transaction_id().clone()
    } else {
        None
    };

    let address: Option<&AddressDetails> = item
        .get_optional_billing()
        .and_then(|billing_details| billing_details.address.as_ref());

    if let Some(address) = address {
        // mandatory fields check
        address.get_first_name()?;
        item.request.get_email_required()?;
        item.get_billing_country()?;
    }

    let (is_rebilling, additional_params, user_token_id) =
        match item.request.is_customer_initiated_mandate_payment() {
            true => {
                (
                    Some("0".to_string()), // In case of first installment, rebilling should be 0
                    Some(V2AdditionalParams {
                        rebill_expiry: Some(
                            time::OffsetDateTime::now_utc()
                                .replace_year(time::OffsetDateTime::now_utc().year() + 5)


// Function: validate_payment_method_type_against_payment_method
// File: crates/payment_methods/src/helpers.rs
// Module: payment_methods

pub fn validate_payment_method_type_against_payment_method(
    payment_method: api_enums::PaymentMethod,
    payment_method_type: api_enums::PaymentMethodType,
) -> bool


// Function: generate_token
// File: crates/common_utils/src/tokenization.rs
// Module: common_utils

// Documentation: Generates a new token string  # Returns A randomly generated token string of length `TOKEN_LENGTH`

pub fn generate_token() -> String


// Function: server
// File: crates/router/src/routes/app.rs
// Module: router

pub fn server(state: AppState) -> Scope


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

impl api::PaymentCapture for for Xendit


// Struct: TaxjarPaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TaxjarPaymentsResponse


// Struct: BillingConnectorPaymentDetails
// File: crates/diesel_models/src/types.rs
// Module: diesel_models
// Implementations: 0

pub struct BillingConnectorPaymentDetails


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

pub fn update_window_for_elimination_routing(
    state: &SessionState,
    payment_attempt: &storage::PaymentAttempt,
    profile_id: &id_type::ProfileId,
    dynamic_algo_ref: routing_types::DynamicRoutingAlgorithmRef,
    elimination_routing_configs_params_interpolator: DynamicRoutingConfigParamsInterpolator,
    gsm_error_category: common_enums::ErrorCategory,
) -> RouterResult<()>


// Struct: PayuPaymentsSyncResponse
// File: crates/hyperswitch_connectors/src/connectors/payu/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PayuPaymentsSyncResponse


// Struct: ForteAuthType
// File: crates/hyperswitch_connectors/src/connectors/forte/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ForteAuthType


// File: crates/router/src/core/three_ds_decision_rule/utils.rs
// Module: router
// Public functions: 1

use api_models::three_ds_decision_rule as api_threedsecure;
use common_types::three_ds_decision_rule_engine::ThreeDSDecision;
use euclid::backend::inputs as dsl_inputs;

use crate::{consts::PSD2_COUNTRIES, types::transformers::ForeignFrom};

// function to apply PSD2 validations to the decision
pub fn apply_psd2_validations_during_execute(
    decision: ThreeDSDecision,
    request: &api_models::three_ds_decision_rule::ThreeDsDecisionRuleExecuteRequest,
) -> ThreeDSDecision {
    let issuer_in_psd2 = request
        .issuer
        .as_ref()
        .and_then(|issuer| issuer.country)
        .map(|country| PSD2_COUNTRIES.contains(&country))
        .unwrap_or(false);
    let acquirer_in_psd2 = request
        .acquirer
        .as_ref()
        .and_then(|acquirer| acquirer.country)
        .map(|country| PSD2_COUNTRIES.contains(&country))
        .unwrap_or(false);
    if issuer_in_psd2 && acquirer_in_psd2 {
        // If both issuer and acquirer are in PSD2 region
        match decision {
            // If the decision is to enforce no 3DS, override it to enforce 3DS
            ThreeDSDecision::NoThreeDs => ThreeDSDecision::ChallengeRequested,
            _ => decision,
        }
    } else {
        // If PSD2 doesn't apply, exemptions cannot be applied
        match decision {
            ThreeDSDecision::NoThreeDs => ThreeDSDecision::NoThreeDs,
            // For all other decisions (including exemptions), enforce challenge as exemptions are only valid in PSD2 regions
            _ => ThreeDSDecision::ChallengeRequested,
        }
    }
}

impl ForeignFrom<api_threedsecure::PaymentData> for dsl_inputs::PaymentInput {
    fn foreign_from(request_payment_data: api_threedsecure::PaymentData) -> Self {
        Self {
            amount: request_payment_data.amount,
            currency: request_payment_data.currency,
            authentication_type: None,
            capture_method: None,
            business_country: None,
            billing_country: None,
            business_label: None,
            setup_future_usage: None,
            card_bin: None,
        }
    }
}

impl ForeignFrom<Option<api_threedsecure::PaymentMethodMetaData>>
    for dsl_inputs::PaymentMethodInput
{
    fn foreign_from(
        request_payment_method_metadata: Option<api_threedsecure::PaymentMethodMetaData>,
    ) -> Self {
        Self {
            payment_method: None,
            payment_method_type: None,
            card_network: request_payment_method_metadata.and_then(|pm| pm.card_network),
        }
    }
}

impl ForeignFrom<api_threedsecure::CustomerDeviceData> for dsl_inputs::CustomerDeviceDataInput {
    fn foreign_from(request_customer_device_data: api_threedsecure::CustomerDeviceData) -> Self {
        Self {
            platform: request_customer_device_data.platform,
            device_type: request_customer_device_data.device_type,
            display_size: request_customer_device_data.display_size,
        }
    }
}

impl ForeignFrom<api_threedsecure::IssuerData> for dsl_inputs::IssuerDataInput {
    fn foreign_from(request_issuer_data: api_threedsecure::IssuerData) -> Self {
        Self {
            name: request_issuer_data.name,
            country: request_issuer_data.country,
        }
    }
}

impl ForeignFrom<api_threedsecure::AcquirerData> for dsl_inputs::AcquirerDataInput {
    fn foreign_from(request_acquirer_data: api_threedsecure::AcquirerData) -> Self {
        Self {
            country: request_acquirer_data.country,
            fraud_rate: request_acquirer_data.fraud_rate,
        }
    }
}

impl ForeignFrom<api_threedsecure::ThreeDsDecisionRuleExecuteRequest> for dsl_inputs::BackendInput {
    fn foreign_from(request: api_threedsecure::ThreeDsDecisionRuleExecuteRequest) -> Self {
        Self {
            metadata: None,
            payment: dsl_inputs::PaymentInput::foreign_from(request.payment),
            payment_method: dsl_inputs::PaymentMethodInput::foreign_from(request.payment_method),
            mandate: dsl_inputs::MandateData {
                mandate_acceptance_type: None,
                mandate_type: None,
                payment_type: None,
            },
            acquirer_data: request.acquirer.map(ForeignFrom::foreign_from),
            customer_device_data: request.customer_device.map(ForeignFrom::foreign_from),
            issuer_data: request.issuer.map(ForeignFrom::foreign_from),
        }
    }
}


// Implementation: impl api::ConnectorAccessToken for for Breadpay
// File: crates/hyperswitch_connectors/src/connectors/breadpay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ConnectorAccessToken for for Breadpay


// File: crates/openapi/src/routes/api_keys.rs
// Module: openapi
// Public functions: 10

#[cfg(feature = "v1")]
/// API Key - Create
///
/// Create a new API Key for accessing our APIs from your servers. The plaintext API Key will be
/// displayed only once on creation, so ensure you store it securely.
#[utoipa::path(
    post,
    path = "/api_keys/{merchant_id}",
    params(("merchant_id" = String, Path, description = "The unique identifier for the merchant account")),
    request_body= CreateApiKeyRequest,
    responses(
        (status = 200, description = "API Key created", body = CreateApiKeyResponse),
        (status = 400, description = "Invalid data")
    ),
    tag = "API Key",
    operation_id = "Create an API Key",
    security(("admin_api_key" = []))
)]
pub async fn api_key_create() {}

#[cfg(feature = "v2")]
/// API Key - Create
///
/// Create a new API Key for accessing our APIs from your servers. The plaintext API Key will be
/// displayed only once on creation, so ensure you store it securely.
#[utoipa::path(
    post,
    path = "/v2/api-keys",
    request_body= CreateApiKeyRequest,
    responses(
        (status = 200, description = "API Key created", body = CreateApiKeyResponse),
        (status = 400, description = "Invalid data")
    ),
    tag = "API Key",
    operation_id = "Create an API Key",
    security(("admin_api_key" = []))
)]
pub async fn api_key_create() {}

#[cfg(feature = "v1")]
/// API Key - Retrieve
///
/// Retrieve information about the specified API Key.
#[utoipa::path(
    get,
    path = "/api_keys/{merchant_id}/{key_id}",
    params (
        ("merchant_id" = String, Path, description = "The unique identifier for the merchant account"),
        ("key_id" = String, Path, description = "The unique identifier for the API Key")
    ),
    responses(
        (status = 200, description = "API Key retrieved", body = RetrieveApiKeyResponse),
        (status = 404, description = "API Key not found")
    ),
    tag = "API Key",
    operation_id = "Retrieve an API Key",
    security(("admin_api_key" = []))
)]
pub async fn api_key_retrieve() {}

#[cfg(feature = "v2")]
/// API Key - Retrieve
///
/// Retrieve information about the specified API Key.
#[utoipa::path(
    get,
    path = "/v2/api-keys/{id}",
    params (
        ("id" = String, Path, description = "The unique identifier for the API Key")
    ),
    responses(
        (status = 200, description = "API Key retrieved", body = RetrieveApiKeyResponse),
        (status = 404, description = "API Key not found")
    ),
    tag = "API Key",
    operation_id = "Retrieve an API Key",
    security(("admin_api_key" = []))
)]
pub async fn api_key_retrieve() {}

#[cfg(feature = "v1")]
/// API Key - Update
///
/// Update information for the specified API Key.
#[utoipa::path(
    post,
    path = "/api_keys/{merchant_id}/{key_id}",
    request_body = UpdateApiKeyRequest,
    params (
        ("merchant_id" = String, Path, description = "The unique identifier for the merchant account"),
        ("key_id" = String, Path, description = "The unique identifier for the API Key")
    ),
    responses(
        (status = 200, description = "API Key updated", body = RetrieveApiKeyResponse),
        (status = 404, description = "API Key not found")
    ),
    tag = "API Key",
    operation_id = "Update an API Key",
    security(("admin_api_key" = []))
)]
pub async fn api_key_update() {}

#[cfg(feature = "v2")]
/// API Key - Update
///
/// Update information for the specified API Key.
#[utoipa::path(
    put,
    path = "/v2/api-keys/{id}",
    request_body = UpdateApiKeyRequest,
    params (
        ("id" = String, Path, description = "The unique identifier for the API Key")
    ),
    responses(
        (status = 200, description = "API Key updated", body = RetrieveApiKeyResponse),
        (status = 404, description = "API Key not found")
    ),
    tag = "API Key",
    operation_id = "Update an API Key",
    security(("admin_api_key" = []))
)]
pub async fn api_key_update() {}

#[cfg(feature = "v1")]
/// API Key - Revoke
///
/// Revoke the specified API Key. Once revoked, the API Key can no longer be used for
/// authenticating with our APIs.
#[utoipa::path(
    delete,
    path = "/api_keys/{merchant_id}/{key_id}",
    params (
        ("merchant_id" = String, Path, description = "The unique identifier for the merchant account"),
        ("key_id" = String, Path, description = "The unique identifier for the API Key")
    ),
    responses(
        (status = 200, description = "API Key revoked", body = RevokeApiKeyResponse),
        (status = 404, description = "API Key not found")
    ),
    tag = "API Key",
    operation_id = "Revoke an API Key",
    security(("admin_api_key" = []))
)]
pub async fn api_key_revoke() {}

#[cfg(feature = "v2")]
/// API Key - Revoke
///
/// Revoke the specified API Key. Once revoked, the API Key can no longer be used for
/// authenticating with our APIs.
#[utoipa::path(
    delete,
    path = "/v2/api-keys/{id}",
    params (
        ("id" = String, Path, description = "The unique identifier for the API Key")
    ),
    responses(
        (status = 200, description = "API Key revoked", body = RevokeApiKeyResponse),
        (status = 404, description = "API Key not found")
    ),
    tag = "API Key",
    operation_id = "Revoke an API Key",
    security(("admin_api_key" = []))
)]
pub async fn api_key_revoke() {}

#[cfg(feature = "v1")]
/// API Key - List
///
/// List all the API Keys associated to a merchant account.
#[utoipa::path(
    get,
    path = "/api_keys/{merchant_id}/list",
    params(
        ("merchant_id" = String, Path, description = "The unique identifier for the merchant account"),
        ("limit" = Option<i64>, Query, description = "The maximum number of API Keys to include in the response"),
        ("skip" = Option<i64>, Query, description = "The number of API Keys to skip when retrieving the list of API keys."),
    ),
    responses(
        (status = 200, description = "List of API Keys retrieved successfully", body = Vec<RetrieveApiKeyResponse>),
    ),
    tag = "API Key",
    operation_id = "List all API Keys associated with a merchant account",
    security(("admin_api_key" = []))
)]
pub async fn api_key_list() {}

#[cfg(feature = "v2")]
/// API Key - List
///
/// List all the API Keys associated to a merchant account.
#[utoipa::path(
    get,
    path = "/v2/api-keys/list",
    params(
        ("limit" = Option<i64>, Query, description = "The maximum number of API Keys to include in the response"),
        ("skip" = Option<i64>, Query, description = "The number of API Keys to skip when retrieving the list of API keys."),
    ),
    responses(
        (status = 200, description = "List of API Keys retrieved successfully", body = Vec<RetrieveApiKeyResponse>),
    ),
    tag = "API Key",
    operation_id = "List all API Keys associated with a merchant account",
    security(("admin_api_key" = []))
)]
pub async fn api_key_list() {}


// Struct: ErrorMessage
// File: crates/hyperswitch_connectors/src/connectors/authorizedotnet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ErrorMessage


// File: crates/router/tests/payouts.rs
// Module: router

#![allow(clippy::unwrap_used, clippy::print_stdout)]

mod utils;

#[actix_web::test]
async fn payouts_todo() {
    Box::pin(utils::setup()).await;

    let client = awc::Client::default();
    let mut response;
    let mut response_body;
    let get_endpoints = vec!["retrieve", "accounts"];
    let post_endpoints = vec!["create", "update", "reverse", "cancel"];

    for endpoint in get_endpoints {
        response = client
            .get(format!("http://127.0.0.1:8080/payouts/{endpoint}"))
            .send()
            .await
            .unwrap();
        response_body = response.body().await;
        println!("{endpoint} =:= {response:?} : {response_body:?}");
        assert_eq!(response.status(), awc::http::StatusCode::OK);
    }

    for endpoint in post_endpoints {
        response = client
            .post(format!("http://127.0.0.1:8080/payouts/{endpoint}"))
            .send()
            .await
            .unwrap();
        response_body = response.body().await;
        println!("{endpoint} =:= {response:?} : {response_body:?}");
        assert_eq!(response.status(), awc::http::StatusCode::OK);
    }
}


// File: crates/router/src/db/locker_mock_up.rs
// Module: router
// Public structs: 1

use error_stack::report;
use router_env::{instrument, tracing};

use super::{MockDb, Store};
use crate::{
    connection,
    core::errors::{self, CustomResult},
    types::storage,
};

#[async_trait::async_trait]
pub trait LockerMockUpInterface {
    async fn find_locker_by_card_id(
        &self,
        card_id: &str,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError>;

    async fn insert_locker_mock_up(
        &self,
        new: storage::LockerMockUpNew,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError>;

    async fn delete_locker_mock_up(
        &self,
        card_id: &str,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError>;
}

#[async_trait::async_trait]
impl LockerMockUpInterface for Store {
    #[instrument(skip_all)]
    async fn find_locker_by_card_id(
        &self,
        card_id: &str,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::LockerMockUp::find_by_card_id(&conn, card_id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn insert_locker_mock_up(
        &self,
        new: storage::LockerMockUpNew,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        new.insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn delete_locker_mock_up(
        &self,
        card_id: &str,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::LockerMockUp::delete_by_card_id(&conn, card_id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl LockerMockUpInterface for MockDb {
    async fn find_locker_by_card_id(
        &self,
        card_id: &str,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError> {
        self.lockers
            .lock()
            .await
            .iter()
            .find(|l| l.card_id == card_id)
            .cloned()
            .ok_or(errors::StorageError::MockDbError.into())
    }

    async fn insert_locker_mock_up(
        &self,
        new: storage::LockerMockUpNew,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError> {
        let mut locked_lockers = self.lockers.lock().await;

        if locked_lockers.iter().any(|l| l.card_id == new.card_id) {
            Err(errors::StorageError::MockDbError)?;
        }

        let created_locker = storage::LockerMockUp {
            card_id: new.card_id,
            external_id: new.external_id,
            card_fingerprint: new.card_fingerprint,
            card_global_fingerprint: new.card_global_fingerprint,
            merchant_id: new.merchant_id,
            card_number: new.card_number,
            card_exp_year: new.card_exp_year,
            card_exp_month: new.card_exp_month,
            name_on_card: new.name_on_card,
            nickname: None,
            customer_id: new.customer_id,
            duplicate: None,
            card_cvc: new.card_cvc,
            payment_method_id: new.payment_method_id,
            enc_card_data: new.enc_card_data,
        };

        locked_lockers.push(created_locker.clone());

        Ok(created_locker)
    }

    async fn delete_locker_mock_up(
        &self,
        card_id: &str,
    ) -> CustomResult<storage::LockerMockUp, errors::StorageError> {
        let mut locked_lockers = self.lockers.lock().await;

        let position = locked_lockers
            .iter()
            .position(|l| l.card_id == card_id)
            .ok_or(errors::StorageError::MockDbError)?;

        Ok(locked_lockers.remove(position))
    }
}

#[cfg(test)]
mod tests {
    #[allow(clippy::unwrap_used)]
    mod mockdb_locker_mock_up_interface {
        use common_utils::{generate_customer_id_of_default_length, id_type};

        use crate::{
            db::{locker_mock_up::LockerMockUpInterface, MockDb},
            types::storage,
        };

        pub struct LockerMockUpIds {
            card_id: String,
            external_id: String,
            merchant_id: id_type::MerchantId,
            customer_id: id_type::CustomerId,
        }

        fn create_locker_mock_up_new(locker_ids: LockerMockUpIds) -> storage::LockerMockUpNew {
            storage::LockerMockUpNew {
                card_id: locker_ids.card_id,
                external_id: locker_ids.external_id,
                card_fingerprint: "card_fingerprint".into(),
                card_global_fingerprint: "card_global_fingerprint".into(),
                merchant_id: locker_ids.merchant_id,
                card_number: "1234123412341234".into(),
                card_exp_year: "2023".into(),
                card_exp_month: "06".into(),
                name_on_card: Some("name_on_card".into()),
                card_cvc: Some("123".into()),
                payment_method_id: Some("payment_method_id".into()),
                customer_id: Some(locker_ids.customer_id),
                nickname: Some("card_holder_nickname".into()),
                enc_card_data: Some("enc_card_data".into()),
            }
        }

        #[tokio::test]
        async fn find_locker_by_card_id() {
            #[allow(clippy::expect_used)]
            let mockdb = MockDb::new(&redis_interface::RedisSettings::default())
                .await
                .expect("Failed to create Mock store");

            let created_locker = mockdb
                .insert_locker_mock_up(create_locker_mock_up_new(LockerMockUpIds {
                    card_id: "card_1".into(),
                    external_id: "external_1".into(),
                    merchant_id: id_type::MerchantId::default(),
                    customer_id: generate_customer_id_of_default_length(),
                }))
                .await
                .unwrap();

            let _ = mockdb
                .insert_locker_mock_up(create_locker_mock_up_new(LockerMockUpIds {
                    card_id: "card_2".into(),
                    external_id: "external_1".into(),
                    merchant_id: id_type::MerchantId::default(),
                    customer_id: generate_customer_id_of_default_length(),
                }))
                .await;

            let found_locker = mockdb.find_locker_by_card_id("card_1").await.unwrap();

            assert_eq!(created_locker, found_locker)
        }

        #[tokio::test]
        async fn insert_locker_mock_up() {
            #[allow(clippy::expect_used)]
            let mockdb = MockDb::new(&redis_interface::RedisSettings::default())
                .await
                .expect("Failed to create Mock store");

            let created_locker = mockdb
                .insert_locker_mock_up(create_locker_mock_up_new(LockerMockUpIds {
                    card_id: "card_1".into(),
                    external_id: "external_1".into(),
                    merchant_id: id_type::MerchantId::default(),
                    customer_id: generate_customer_id_of_default_length(),
                }))
                .await
                .unwrap();

            let found_locker = mockdb
                .lockers
                .lock()
                .await
                .iter()
                .find(|l| l.card_id == "card_1")
                .cloned();

            assert!(found_locker.is_some());

            assert_eq!(created_locker, found_locker.unwrap())
        }

        #[tokio::test]
        async fn delete_locker_mock_up() {
            #[allow(clippy::expect_used)]
            let mockdb = MockDb::new(&redis_interface::RedisSettings::default())
                .await
                .expect("Failed to create Mock store");

            let created_locker = mockdb
                .insert_locker_mock_up(create_locker_mock_up_new(LockerMockUpIds {
                    card_id: "card_1".into(),
                    external_id: "external_1".into(),
                    merchant_id: id_type::MerchantId::default(),
                    customer_id: generate_customer_id_of_default_length(),
                }))
                .await
                .unwrap();

            let deleted_locker = mockdb.delete_locker_mock_up("card_1").await.unwrap();

            assert_eq!(created_locker, deleted_locker);

            let exist = mockdb
                .lockers
                .lock()
                .await
                .iter()
                .any(|l| l.card_id == "card_1");

            assert!(!exist)
        }
    }
}


// Struct: RuleMigrationResult
// File: crates/api_models/src/routing.rs
// Module: api_models
// Implementations: 0

pub struct RuleMigrationResult


// Struct: CreateConnectorCustomer
// File: crates/hyperswitch_domain_models/src/router_flow_types/payments.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct CreateConnectorCustomer


// Struct: RefundRequest
// File: crates/api_models/src/refunds.rs
// Module: api_models
// Implementations: 0

pub struct RefundRequest


// Struct: PaymentRoutingInfoInner
// File: crates/hyperswitch_domain_models/src/routing.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct PaymentRoutingInfoInner


// Implementation: impl std::fmt::Debug for for ConnectorEnum
// File: crates/hyperswitch_interfaces/src/connector_integration_interface.rs
// Module: hyperswitch_interfaces
// Methods: 1 total (0 public)

impl std::fmt::Debug for for ConnectorEnum