// File: crates/router/src/types/api/connector_mapping.rs

use std::str::FromStr;

use error_stack::{report, ResultExt};
use hyperswitch_connectors::connectors::{Paytm, Phonepe};

use crate::{
    configs::settings::Connectors,
    connector,
    core::errors::{self, CustomResult},
    services::connector_integration_interface::ConnectorEnum,
    types::{self, api::enums},
};

/// Routing algorithm will output merchant connector identifier instead of connector name
/// In order to support backwards compatibility for older routing algorithms and merchant accounts
/// the support for connector name is retained
#[derive(Clone, Debug)]
pub struct ConnectorData {
    pub connector: ConnectorEnum,
    pub connector_name: types::Connector,
    pub get_token: GetToken,
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
}

// Normal flow will call the connector and follow the flow specific operations (capture, authorize)
// SessionTokenFromMetadata will avoid calling the connector instead create the session token ( for sdk )
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum GetToken {
    GpayMetadata,
    SamsungPayMetadata,
    AmazonPayMetadata,
    ApplePayMetadata,
    PaypalSdkMetadata,
    PazeMetadata,
    Connector,
}

impl ConnectorData {
    pub fn get_connector_by_name(
        _connectors: &Connectors,
        name: &str,
        connector_type: GetToken,
        connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    ) -> CustomResult<Self, errors::ApiErrorResponse> {
        let connector = Self::convert_connector(name)?;
        let connector_name = enums::Connector::from_str(name)
            .change_context(errors::ConnectorError::InvalidConnectorName)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable_lazy(|| format!("unable to parse connector name {name}"))?;
        Ok(Self {
            connector,
            connector_name,
            get_token: connector_type,
            merchant_connector_id: connector_id,
        })
    }

    #[cfg(feature = "payouts")]
    pub fn get_payout_connector_by_name(
        _connectors: &Connectors,
        name: &str,
        connector_type: GetToken,
        connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    ) -> CustomResult<Self, errors::ApiErrorResponse> {
        let connector = Self::convert_connector(name)?;
        let payout_connector_name = enums::PayoutConnectors::from_str(name)
            .change_context(errors::ConnectorError::InvalidConnectorName)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable_lazy(|| format!("unable to parse payout connector name {name}"))?;
        let connector_name = enums::Connector::from(payout_connector_name);
        Ok(Self {
            connector,
            connector_name,
            get_token: connector_type,
            merchant_connector_id: connector_id,
        })
    }

    pub fn get_external_vault_connector_by_name(
        _connectors: &Connectors,
        connector: String,
        connector_type: GetToken,
        connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    ) -> CustomResult<Self, errors::ApiErrorResponse> {
        let connector_enum = Self::convert_connector(&connector)?;
        let external_vault_connector_name = enums::VaultConnectors::from_str(&connector)
            .change_context(errors::ConnectorError::InvalidConnectorName)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable_lazy(|| {
                format!("unable to parse external vault connector name {connector:?}")
            })?;
        let connector_name = enums::Connector::from(external_vault_connector_name);
        Ok(Self {
            connector: connector_enum,
            connector_name,
            get_token: connector_type,
            merchant_connector_id: connector_id,
        })
    }

    pub fn convert_connector(
        connector_name: &str,
    ) -> CustomResult<ConnectorEnum, errors::ApiErrorResponse> {
        match enums::Connector::from_str(connector_name) {
            Ok(name) => match name {
                enums::Connector::Aci => Ok(ConnectorEnum::Old(Box::new(connector::Aci::new()))),
                enums::Connector::Adyen => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Adyen::new())))
                }
                enums::Connector::Affirm => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Affirm::new())))
                }
                enums::Connector::Adyenplatform => Ok(ConnectorEnum::Old(Box::new(
                    connector::Adyenplatform::new(),
                ))),
                enums::Connector::Airwallex => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Airwallex::new())))
                }
                enums::Connector::Amazonpay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Amazonpay::new())))
                }
                enums::Connector::Archipel => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Archipel::new())))
                }
                enums::Connector::Authipay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Authipay::new())))
                }
                enums::Connector::Authorizedotnet => Ok(ConnectorEnum::Old(Box::new(
                    connector::Authorizedotnet::new(),
                ))),
                enums::Connector::Bambora => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Bambora::new())))
                }
                enums::Connector::Bamboraapac => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Bamboraapac::new())))
                }
                enums::Connector::Bankofamerica => Ok(ConnectorEnum::Old(Box::new(
                    connector::Bankofamerica::new(),
                ))),
                enums::Connector::Barclaycard => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Barclaycard::new())))
                }
                enums::Connector::Billwerk => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Billwerk::new())))
                }
                enums::Connector::Bitpay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Bitpay::new())))
                }
                enums::Connector::Blackhawknetwork => Ok(ConnectorEnum::Old(Box::new(
                    connector::Blackhawknetwork::new(),
                ))),
                enums::Connector::Bluesnap => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Bluesnap::new())))
                }
                enums::Connector::Calida => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Calida::new())))
                }
                enums::Connector::Boku => Ok(ConnectorEnum::Old(Box::new(connector::Boku::new()))),
                enums::Connector::Braintree => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Braintree::new())))
                }
                enums::Connector::Breadpay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Breadpay::new())))
                }
                enums::Connector::Cashtocode => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Cashtocode::new())))
                }
                enums::Connector::Celero => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Celero::new())))
                }
                enums::Connector::Chargebee => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Chargebee::new())))
                }
                enums::Connector::Checkbook => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Checkbook::new())))
                }
                enums::Connector::Checkout => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Checkout::new())))
                }
                enums::Connector::Coinbase => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Coinbase::new())))
                }
                enums::Connector::Coingate => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Coingate::new())))
                }
                enums::Connector::Zift => Ok(ConnectorEnum::Old(Box::new(connector::Zift::new()))),
                enums::Connector::Cryptopay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Cryptopay::new())))
                }
                enums::Connector::CtpMastercard => {
                    Ok(ConnectorEnum::Old(Box::new(&connector::CtpMastercard)))
                }
                enums::Connector::Custombilling => Ok(ConnectorEnum::Old(Box::new(
                    connector::Custombilling::new(),
                ))),
                enums::Connector::CtpVisa => Ok(ConnectorEnum::Old(Box::new(
                    connector::UnifiedAuthenticationService::new(),
                ))),
                enums::Connector::Cybersource => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Cybersource::new())))
                }
                enums::Connector::Datatrans => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Datatrans::new())))
                }
                enums::Connector::Deutschebank => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Deutschebank::new())))
                }
                enums::Connector::Digitalvirgo => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Digitalvirgo::new())))
                }
                enums::Connector::Dlocal => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Dlocal::new())))
                }
                #[cfg(feature = "dummy_connector")]
                enums::Connector::DummyConnector1 => Ok(ConnectorEnum::Old(Box::new(
                    connector::DummyConnector::<1>::new(),
                ))),
                #[cfg(feature = "dummy_connector")]
                enums::Connector::DummyConnector2 => Ok(ConnectorEnum::Old(Box::new(
                    connector::DummyConnector::<2>::new(),
                ))),
                #[cfg(feature = "dummy_connector")]
                enums::Connector::DummyConnector3 => Ok(ConnectorEnum::Old(Box::new(
                    connector::DummyConnector::<3>::new(),
                ))),
                #[cfg(feature = "dummy_connector")]
                enums::Connector::DummyConnector4 => Ok(ConnectorEnum::Old(Box::new(
                    connector::DummyConnector::<4>::new(),
                ))),
                #[cfg(feature = "dummy_connector")]
                enums::Connector::DummyConnector5 => Ok(ConnectorEnum::Old(Box::new(
                    connector::DummyConnector::<5>::new(),
                ))),
                #[cfg(feature = "dummy_connector")]
                enums::Connector::DummyConnector6 => Ok(ConnectorEnum::Old(Box::new(
                    connector::DummyConnector::<6>::new(),
                ))),
                #[cfg(feature = "dummy_connector")]
                enums::Connector::DummyConnector7 => Ok(ConnectorEnum::Old(Box::new(
                    connector::DummyConnector::<7>::new(),
                ))),
                #[cfg(feature = "dummy_connector")]
                enums::Connector::DummyBillingConnector => Ok(ConnectorEnum::Old(Box::new(
                    connector::DummyConnector::<8>::new(),
                ))),
                enums::Connector::Dwolla => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Dwolla::new())))
                }
                enums::Connector::Ebanx => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Ebanx::new())))
                }
                enums::Connector::Elavon => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Elavon::new())))
                }
                enums::Connector::Facilitapay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Facilitapay::new())))
                }
                enums::Connector::Finix => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Finix::new())))
                }
                enums::Connector::Fiserv => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Fiserv::new())))
                }
                enums::Connector::Fiservemea => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Fiservemea::new())))
                }
                enums::Connector::Fiuu => Ok(ConnectorEnum::Old(Box::new(connector::Fiuu::new()))),
                enums::Connector::Flexiti => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Flexiti::new())))
                }
                enums::Connector::Forte => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Forte::new())))
                }
                enums::Connector::Getnet => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Getnet::new())))
                }
                enums::Connector::Gigadat => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Gigadat::new())))
                }
                enums::Connector::Globalpay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Globalpay::new())))
                }
                enums::Connector::Globepay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Globepay::new())))
                }
                enums::Connector::Gocardless => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Gocardless::new())))
                }
                enums::Connector::Hipay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Hipay::new())))
                }
                enums::Connector::Helcim => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Helcim::new())))
                }
                enums::Connector::HyperswitchVault => {
                    Ok(ConnectorEnum::Old(Box::new(&connector::HyperswitchVault)))
                }
                enums::Connector::Iatapay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Iatapay::new())))
                }
                enums::Connector::Inespay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Inespay::new())))
                }
                enums::Connector::Itaubank => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Itaubank::new())))
                }
                enums::Connector::Jpmorgan => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Jpmorgan::new())))
                }
                enums::Connector::Juspaythreedsserver => Ok(ConnectorEnum::Old(Box::new(
                    connector::Juspaythreedsserver::new(),
                ))),
                enums::Connector::Klarna => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Klarna::new())))
                }
                enums::Connector::Loonio => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Loonio::new())))
                }
                enums::Connector::Mollie => {
                    // enums::Connector::Moneris => Ok(ConnectorEnum::Old(Box::new(connector::Moneris))),
                    Ok(ConnectorEnum::Old(Box::new(connector::Mollie::new())))
                }
                enums::Connector::Moneris => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Moneris::new())))
                }
                enums::Connector::Nexixpay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Nexixpay::new())))
                }
                enums::Connector::Nmi => Ok(ConnectorEnum::Old(Box::new(connector::Nmi::new()))),
                enums::Connector::Nomupay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Nomupay::new())))
                }
                enums::Connector::Noon => Ok(ConnectorEnum::Old(Box::new(connector::Noon::new()))),
                enums::Connector::Nordea => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Nordea::new())))
                }
                enums::Connector::Novalnet => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Novalnet::new())))
                }
                enums::Connector::Nuvei => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Nuvei::new())))
                }
                enums::Connector::Opennode => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Opennode::new())))
                }
                enums::Connector::Paybox => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Paybox::new())))
                }
                // "payeezy" => Ok(ConnectorIntegrationEnum::Old(Box::new(&connector::Payeezy)), As psync and rsync are not supported by this connector, it is added as template code for future usage
                // enums::Connector::Payload => {
                //     Ok(ConnectorEnum::Old(Box::new(connector::Paybload::new())))
                // }
                enums::Connector::Payload => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Payload::new())))
                }
                enums::Connector::Payjustnow => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Payjustnow::new())))
                }
                enums::Connector::Payme => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Payme::new())))
                }
                enums::Connector::Payone => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Payone::new())))
                }
                enums::Connector::Payu => Ok(ConnectorEnum::Old(Box::new(connector::Payu::new()))),
                enums::Connector::Peachpayments => Ok(ConnectorEnum::Old(Box::new(
                    hyperswitch_connectors::connectors::Peachpayments::new(),
                ))),
                enums::Connector::Placetopay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Placetopay::new())))
                }
                enums::Connector::Powertranz => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Powertranz::new())))
                }
                enums::Connector::Prophetpay => {
                    Ok(ConnectorEnum::Old(Box::new(&connector::Prophetpay)))
                }
                enums::Connector::Razorpay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Razorpay::new())))
                }
                enums::Connector::Rapyd => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Rapyd::new())))
                }
                enums::Connector::Recurly => {
                    Ok(ConnectorEnum::New(Box::new(connector::Recurly::new())))
                }
                enums::Connector::Redsys => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Redsys::new())))
                }
                enums::Connector::Santander => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Santander::new())))
                }
                enums::Connector::Shift4 => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Shift4::new())))
                }
                enums::Connector::Silverflow => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Silverflow::new())))
                }
                enums::Connector::Square => Ok(ConnectorEnum::Old(Box::new(&connector::Square))),
                enums::Connector::Stax => Ok(ConnectorEnum::Old(Box::new(&connector::Stax))),
                enums::Connector::Stripe => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Stripe::new())))
                }
                enums::Connector::Stripebilling => Ok(ConnectorEnum::Old(Box::new(
                    connector::Stripebilling::new(),
                ))),
                enums::Connector::Wise => Ok(ConnectorEnum::Old(Box::new(connector::Wise::new()))),
                enums::Connector::Worldline => {
                    Ok(ConnectorEnum::Old(Box::new(&connector::Worldline)))
                }
                enums::Connector::Worldpay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Worldpay::new())))
                }
                enums::Connector::Worldpayvantiv => Ok(ConnectorEnum::Old(Box::new(
                    connector::Worldpayvantiv::new(),
                ))),
                enums::Connector::Worldpayxml => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Worldpayxml::new())))
                }
                enums::Connector::Xendit => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Xendit::new())))
                }
                enums::Connector::Mifinity => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Mifinity::new())))
                }
                enums::Connector::Multisafepay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Multisafepay::new())))
                }
                enums::Connector::Netcetera => {
                    Ok(ConnectorEnum::Old(Box::new(&connector::Netcetera)))
                }
                enums::Connector::Nexinets => {
                    Ok(ConnectorEnum::Old(Box::new(&connector::Nexinets)))
                }
                // enums::Connector::Nexixpay => {
                //     Ok(ConnectorEnum::Old(Box::new(&connector::Nexixpay)))
                // }
                enums::Connector::Paypal => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Paypal::new())))
                }
                enums::Connector::Paysafe => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Paysafe::new())))
                }
                enums::Connector::Paystack => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Paystack::new())))
                }
                // enums::Connector::Thunes => Ok(ConnectorEnum::Old(Box::new(connector::Thunes))),
                enums::Connector::Tesouro => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Tesouro::new())))
                }
                enums::Connector::Tokenex => Ok(ConnectorEnum::Old(Box::new(&connector::Tokenex))),
                enums::Connector::Tokenio => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Tokenio::new())))
                }
                enums::Connector::Trustpay => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Trustpay::new())))
                }
                enums::Connector::Trustpayments => Ok(ConnectorEnum::Old(Box::new(
                    connector::Trustpayments::new(),
                ))),
                enums::Connector::Tsys => Ok(ConnectorEnum::Old(Box::new(connector::Tsys::new()))),
                // enums::Connector::UnifiedAuthenticationService => Ok(ConnectorEnum::Old(Box::new(
                //     connector::UnifiedAuthenticationService,
                // ))),
                enums::Connector::Vgs => Ok(ConnectorEnum::Old(Box::new(&connector::Vgs))),
                enums::Connector::Volt => Ok(ConnectorEnum::Old(Box::new(connector::Volt::new()))),
                enums::Connector::Wellsfargo => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Wellsfargo::new())))
                }

                // enums::Connector::Wellsfargopayout => {
                //     Ok(Box::new(connector::Wellsfargopayout::new()))
                // }
                enums::Connector::Zen => Ok(ConnectorEnum::Old(Box::new(&connector::Zen))),
                enums::Connector::Zsl => Ok(ConnectorEnum::Old(Box::new(&connector::Zsl))),
                enums::Connector::Plaid => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Plaid::new())))
                }
                enums::Connector::Signifyd
                | enums::Connector::Riskified
                | enums::Connector::Gpayments
                | enums::Connector::Threedsecureio
                | enums::Connector::Cardinal
                | enums::Connector::Taxjar => {
                    Err(report!(errors::ConnectorError::InvalidConnectorName)
                        .attach_printable(format!("invalid connector name: {connector_name}")))
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                }
                enums::Connector::Phonepe => Ok(ConnectorEnum::Old(Box::new(Phonepe::new()))),
                enums::Connector::Paytm => Ok(ConnectorEnum::Old(Box::new(Paytm::new()))),
            },
            Err(_) => Err(report!(errors::ConnectorError::InvalidConnectorName)
                .attach_printable(format!("invalid connector name: {connector_name}")))
            .change_context(errors::ApiErrorResponse::InternalServerError),
        }
    }
}


// File: crates/router/src/types/api/fraud_check_v2.rs

pub use hyperswitch_domain_models::router_flow_types::fraud_check::{
    Checkout, Fulfillment, RecordReturn, Sale, Transaction,
};
pub use hyperswitch_interfaces::api::fraud_check_v2::{
    FraudCheckCheckoutV2, FraudCheckFulfillmentV2, FraudCheckRecordReturnV2, FraudCheckSaleV2,
    FraudCheckTransactionV2, FraudCheckV2,
};


// File: crates/router/src/types/api/payouts_v2.rs

pub use api_models::payouts::{
    AchBankTransfer, BacsBankTransfer, Bank as BankPayout, CardPayout, PayoutActionRequest,
    PayoutAttemptResponse, PayoutCreateRequest, PayoutCreateResponse, PayoutListConstraints,
    PayoutListFilterConstraints, PayoutListFilters, PayoutListResponse, PayoutMethodData,
    PayoutRequest, PayoutRetrieveBody, PayoutRetrieveRequest, PixBankTransfer, SepaBankTransfer,
    Wallet as WalletPayout,
};
pub use hyperswitch_domain_models::router_flow_types::payouts::{
    PoCancel, PoCreate, PoEligibility, PoFulfill, PoQuote, PoRecipient, PoRecipientAccount, PoSync,
};
pub use hyperswitch_interfaces::api::payouts_v2::{
    PayoutCancelV2, PayoutCreateV2, PayoutEligibilityV2, PayoutFulfillV2, PayoutQuoteV2,
    PayoutRecipientAccountV2, PayoutRecipientV2, PayoutSyncV2,
};

use crate::types::api as api_types;

pub trait PayoutsV2:
    api_types::ConnectorCommon
    + PayoutCancelV2
    + PayoutCreateV2
    + PayoutEligibilityV2
    + PayoutFulfillV2
    + PayoutQuoteV2
    + PayoutRecipientV2
    + PayoutSyncV2
    + PayoutRecipientAccountV2
{
}


// File: crates/router/src/types/api/payment_methods.rs

#[cfg(feature = "v2")]
pub use api_models::payment_methods::{
    CardDetail, CardDetailFromLocker, CardDetailsPaymentMethod, CardNetworkTokenizeRequest,
    CardNetworkTokenizeResponse, CardType, CustomerPaymentMethodResponseItem,
    DeleteTokenizeByTokenRequest, GetTokenizePayloadRequest, GetTokenizePayloadResponse,
    ListCountriesCurrenciesRequest, MigrateCardDetail, NetworkTokenDetailsPaymentMethod,
    NetworkTokenDetailsResponse, NetworkTokenResponse, PaymentMethodCollectLinkRenderRequest,
    PaymentMethodCollectLinkRequest, PaymentMethodCreate, PaymentMethodCreateData,
    PaymentMethodDeleteResponse, PaymentMethodId, PaymentMethodIntentConfirm,
    PaymentMethodIntentCreate, PaymentMethodListData, PaymentMethodListResponseForSession,
    PaymentMethodMigrate, PaymentMethodMigrateResponse, PaymentMethodResponse,
    PaymentMethodResponseData, PaymentMethodUpdate, PaymentMethodUpdateData, PaymentMethodsData,
    ProxyCardDetails, RequestPaymentMethodTypes, TokenDataResponse, TokenDetailsResponse,
    TokenizePayloadEncrypted, TokenizePayloadRequest, TokenizedCardValue1, TokenizedCardValue2,
    TokenizedWalletValue1, TokenizedWalletValue2, TotalPaymentMethodCountResponse,
};
#[cfg(feature = "v1")]
pub use api_models::payment_methods::{
    CardDetail, CardDetailFromLocker, CardDetailsPaymentMethod, CardNetworkTokenizeRequest,
    CardNetworkTokenizeResponse, CustomerPaymentMethod, CustomerPaymentMethodUpdateResponse,
    CustomerPaymentMethodsListResponse, DefaultPaymentMethod, DeleteTokenizeByTokenRequest,
    GetTokenizePayloadRequest, GetTokenizePayloadResponse, ListCountriesCurrenciesRequest,
    MigrateCardDetail, PaymentMethodCollectLinkRenderRequest, PaymentMethodCollectLinkRequest,
    PaymentMethodCreate, PaymentMethodCreateData, PaymentMethodDeleteResponse, PaymentMethodId,
    PaymentMethodListRequest, PaymentMethodListResponse, PaymentMethodMigrate,
    PaymentMethodMigrateResponse, PaymentMethodResponse, PaymentMethodUpdate, PaymentMethodsData,
    TokenizeCardRequest, TokenizeDataRequest, TokenizePayloadEncrypted, TokenizePayloadRequest,
    TokenizePaymentMethodRequest, TokenizedCardValue1, TokenizedCardValue2, TokenizedWalletValue1,
    TokenizedWalletValue2,
};
use error_stack::report;

use crate::core::{
    errors::{self, RouterResult},
    payments::helpers::validate_payment_method_type_against_payment_method,
};
#[cfg(feature = "v2")]
use crate::utils;

pub(crate) trait PaymentMethodCreateExt {
    fn validate(&self) -> RouterResult<()>;
}

// convert self.payment_method_type to payment_method and compare it against self.payment_method
#[cfg(feature = "v1")]
impl PaymentMethodCreateExt for PaymentMethodCreate {
    fn validate(&self) -> RouterResult<()> {
        if let Some(pm) = self.payment_method {
            if let Some(payment_method_type) = self.payment_method_type {
                if !validate_payment_method_type_against_payment_method(pm, payment_method_type) {
                    return Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                        message: "Invalid 'payment_method_type' provided".to_string()
                    })
                    .attach_printable("Invalid payment method type"));
                }
            }
        }
        Ok(())
    }
}

#[cfg(feature = "v2")]
impl PaymentMethodCreateExt for PaymentMethodCreate {
    fn validate(&self) -> RouterResult<()> {
        utils::when(
            !validate_payment_method_type_against_payment_method(
                self.payment_method_type,
                self.payment_method_subtype,
            ),
            || {
                Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid 'payment_method_type' provided".to_string()
                })
                .attach_printable("Invalid payment method type"))
            },
        )?;

        utils::when(
            !Self::validate_payment_method_data_against_payment_method(
                self.payment_method_type,
                self.payment_method_data.clone(),
            ),
            || {
                Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid 'payment_method_data' provided".to_string()
                })
                .attach_printable("Invalid payment method data"))
            },
        )?;
        Ok(())
    }
}

#[cfg(feature = "v2")]
impl PaymentMethodCreateExt for PaymentMethodIntentConfirm {
    fn validate(&self) -> RouterResult<()> {
        utils::when(
            !validate_payment_method_type_against_payment_method(
                self.payment_method_type,
                self.payment_method_subtype,
            ),
            || {
                Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid 'payment_method_type' provided".to_string()
                })
                .attach_printable("Invalid payment method type"))
            },
        )?;

        utils::when(
            !Self::validate_payment_method_data_against_payment_method(
                self.payment_method_type,
                self.payment_method_data.clone(),
            ),
            || {
                Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Invalid 'payment_method_data' provided".to_string()
                })
                .attach_printable("Invalid payment method data"))
            },
        )?;
        Ok(())
    }
}


// File: crates/router/src/types/api/refunds.rs

#[cfg(feature = "v1")]
pub use api_models::refunds::RefundRequest;
pub use api_models::refunds::{
    RefundListRequest, RefundListResponse, RefundResponse, RefundStatus, RefundType,
    RefundUpdateRequest, RefundsRetrieveBody, RefundsRetrieveRequest,
};
#[cfg(feature = "v2")]
pub use api_models::refunds::{RefundMetadataUpdateRequest, RefundsCreateRequest};
pub use hyperswitch_domain_models::router_flow_types::refunds::{Execute, RSync};
pub use hyperswitch_interfaces::api::refunds::{Refund, RefundExecute, RefundSync};

use crate::types::{storage::enums as storage_enums, transformers::ForeignFrom};

impl ForeignFrom<storage_enums::RefundStatus> for RefundStatus {
    fn foreign_from(status: storage_enums::RefundStatus) -> Self {
        match status {
            storage_enums::RefundStatus::Failure
            | storage_enums::RefundStatus::TransactionFailure => Self::Failed,
            storage_enums::RefundStatus::ManualReview => Self::Review,
            storage_enums::RefundStatus::Pending => Self::Pending,
            storage_enums::RefundStatus::Success => Self::Succeeded,
        }
    }
}


// File: crates/router/src/types/api/payouts.rs

pub use api_models::payouts::{
    AchBankTransfer, BacsBankTransfer, Bank as BankPayout, BankRedirect as BankRedirectPayout,
    CardPayout, Passthrough as PassthroughPayout, PaymentMethodTypeInfo, PayoutActionRequest,
    PayoutAttemptResponse, PayoutCreateRequest, PayoutCreateResponse,
    PayoutEnabledPaymentMethodsInfo, PayoutLinkResponse, PayoutListConstraints,
    PayoutListFilterConstraints, PayoutListFilters, PayoutListFiltersV2, PayoutListResponse,
    PayoutMethodData, PayoutMethodDataResponse, PayoutRequest, PayoutRetrieveBody,
    PayoutRetrieveRequest, PixBankTransfer, RequiredFieldsOverrideRequest, SepaBankTransfer,
    Wallet as WalletPayout,
};
pub use hyperswitch_domain_models::router_flow_types::payouts::{
    PoCancel, PoCreate, PoEligibility, PoFulfill, PoQuote, PoRecipient, PoRecipientAccount, PoSync,
};
pub use hyperswitch_interfaces::api::payouts::{
    PayoutCancel, PayoutCreate, PayoutEligibility, PayoutFulfill, PayoutQuote, PayoutRecipient,
    PayoutRecipientAccount, PayoutSync, Payouts,
};

pub use super::payouts_v2::{
    PayoutCancelV2, PayoutCreateV2, PayoutEligibilityV2, PayoutFulfillV2, PayoutQuoteV2,
    PayoutRecipientAccountV2, PayoutRecipientV2, PayoutSyncV2, PayoutsV2,
};


// File: crates/router/src/types/api/refunds_v2.rs

pub use hyperswitch_interfaces::api::refunds_v2::{RefundExecuteV2, RefundSyncV2, RefundV2};


// File: crates/router/src/types/api/fraud_check.rs

use std::str::FromStr;

use api_models::enums;
use common_utils::errors::CustomResult;
use error_stack::ResultExt;
pub use hyperswitch_domain_models::router_flow_types::fraud_check::{
    Checkout, Fulfillment, RecordReturn, Sale, Transaction,
};
pub use hyperswitch_interfaces::api::fraud_check::{
    FraudCheckCheckout, FraudCheckFulfillment, FraudCheckRecordReturn, FraudCheckSale,
    FraudCheckTransaction,
};

pub use super::fraud_check_v2::{
    FraudCheckCheckoutV2, FraudCheckFulfillmentV2, FraudCheckRecordReturnV2, FraudCheckSaleV2,
    FraudCheckTransactionV2, FraudCheckV2,
};
use super::{ConnectorData, SessionConnectorDatas};
use crate::{
    connector,
    core::{errors, payments::ActionType},
    services::connector_integration_interface::ConnectorEnum,
};

#[derive(Clone)]
pub struct FraudCheckConnectorData {
    pub connector: ConnectorEnum,
    pub connector_name: enums::FrmConnectors,
}
pub enum ConnectorCallType {
    PreDetermined(ConnectorRoutingData),
    Retryable(Vec<ConnectorRoutingData>),
    SessionMultiple(SessionConnectorDatas),
}

#[derive(Clone)]
pub struct ConnectorRoutingData {
    pub connector_data: ConnectorData,
    pub network: Option<common_enums::CardNetwork>,
    // action_type is used for mandates currently
    pub action_type: Option<ActionType>,
}

impl FraudCheckConnectorData {
    pub fn get_connector_by_name(name: &str) -> CustomResult<Self, errors::ApiErrorResponse> {
        let connector_name = enums::FrmConnectors::from_str(name)
            .change_context(errors::ApiErrorResponse::IncorrectConnectorNameGiven)
            .attach_printable_lazy(|| {
                format!("unable to parse connector: {:?}", name.to_string())
            })?;
        let connector = Self::convert_connector(connector_name)?;
        Ok(Self {
            connector,
            connector_name,
        })
    }

    fn convert_connector(
        connector_name: enums::FrmConnectors,
    ) -> CustomResult<ConnectorEnum, errors::ApiErrorResponse> {
        match connector_name {
            enums::FrmConnectors::Signifyd => {
                Ok(ConnectorEnum::Old(Box::new(&connector::Signifyd)))
            }
            enums::FrmConnectors::Riskified => {
                Ok(ConnectorEnum::Old(Box::new(connector::Riskified::new())))
            }
        }
    }
}


// File: crates/router/src/types/api/configs.rs

#[derive(Clone, serde::Serialize, Debug, serde::Deserialize)]
pub struct Config {
    pub key: String,
    pub value: String,
}

#[derive(Clone, serde::Deserialize, Debug, serde::Serialize)]
pub struct ConfigUpdate {
    #[serde(skip_deserializing)]
    pub key: String,
    pub value: String,
}


// File: crates/router/src/types/api/payments.rs

#[cfg(feature = "v2")]
pub use api_models::payments::{
    PaymentAttemptListRequest, PaymentAttemptListResponse, PaymentsConfirmIntentRequest,
    PaymentsCreateIntentRequest, PaymentsIntentResponse, PaymentsUpdateIntentRequest,
    RecoveryPaymentsCreate,
};
#[cfg(feature = "v1")]
pub use api_models::payments::{
    PaymentListFilterConstraints, PaymentListResponse, PaymentListResponseV2, PaymentRetrieveBody,
    PaymentRetrieveBodyWithCredentials, PaymentsEligibilityRequest,
};
pub use api_models::{
    feature_matrix::{
        ConnectorFeatureMatrixResponse, FeatureMatrixListResponse, FeatureMatrixRequest,
    },
    payments::{
        Address, AddressDetails, Amount, ApplepayPaymentMethod, AuthenticationForStartResponse,
        Card, CryptoData, CustomerDetails, CustomerDetailsResponse, HyperswitchVaultSessionDetails,
        MandateAmountData, MandateData, MandateTransactionType, MandateType,
        MandateValidationFields, NextActionType, OpenBankingSessionToken, PayLaterData,
        PaymentIdType, PaymentListConstraints, PaymentListFilters, PaymentListFiltersV2,
        PaymentMethodData, PaymentMethodDataRequest, PaymentMethodDataResponse, PaymentOp,
        PaymentsAggregateResponse, PaymentsApproveRequest, PaymentsCancelPostCaptureRequest,
        PaymentsCancelRequest, PaymentsCaptureRequest, PaymentsCompleteAuthorizeRequest,
        PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse,
        PaymentsExtendAuthorizationRequest, PaymentsExternalAuthenticationRequest,
        PaymentsIncrementalAuthorizationRequest, PaymentsManualUpdateRequest,
        PaymentsPostSessionTokensRequest, PaymentsPostSessionTokensResponse,
        PaymentsRedirectRequest, PaymentsRedirectionResponse, PaymentsRejectRequest,
        PaymentsRequest, PaymentsResponse, PaymentsResponseForm, PaymentsRetrieveRequest,
        PaymentsSessionRequest, PaymentsSessionResponse, PaymentsStartRequest,
        PaymentsUpdateMetadataRequest, PaymentsUpdateMetadataResponse, PgRedirectResponse,
        PhoneDetails, RedirectionResponse, SessionToken, UrlDetails, VaultSessionDetails,
        VerifyRequest, VerifyResponse, VgsSessionDetails, WalletData,
    },
};
pub use common_types::payments::{AcceptanceType, CustomerAcceptance, OnlineMandate};
use error_stack::ResultExt;
pub use hyperswitch_domain_models::router_flow_types::payments::{
    Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize,
    CreateConnectorCustomer, CreateOrder, ExtendAuthorization, ExternalVaultProxy,
    IncrementalAuthorization, InitPayment, PSync, PaymentCreateIntent, PaymentGetIntent,
    PaymentMethodToken, PaymentUpdateIntent, PostCaptureVoid, PostProcessing, PostSessionTokens,
    PreProcessing, RecordAttempt, Reject, SdkSessionUpdate, Session, SetupMandate, UpdateMetadata,
    Void,
};
pub use hyperswitch_interfaces::api::payments::{
    ConnectorCustomer, MandateSetup, Payment, PaymentApprove, PaymentAuthorize,
    PaymentAuthorizeSessionToken, PaymentCapture, PaymentIncrementalAuthorization,
    PaymentPostCaptureVoid, PaymentPostSessionTokens, PaymentReject, PaymentSession,
    PaymentSessionUpdate, PaymentSync, PaymentToken, PaymentUpdateMetadata, PaymentVoid,
    PaymentsCompleteAuthorize, PaymentsCreateOrder, PaymentsPostProcessing, PaymentsPreProcessing,
    TaxCalculation,
};

pub use super::payments_v2::{
    ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2,
    PaymentAuthorizeV2, PaymentCaptureV2, PaymentExtendAuthorizationV2,
    PaymentIncrementalAuthorizationV2, PaymentPostCaptureVoidV2, PaymentPostSessionTokensV2,
    PaymentRejectV2, PaymentSessionUpdateV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2,
    PaymentUpdateMetadataV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2,
    PaymentsPostProcessingV2, PaymentsPreProcessingV2, TaxCalculationV2,
};
use crate::core::errors;

pub trait PaymentIdTypeExt {
    #[cfg(feature = "v1")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::PaymentId, errors::ValidationError>;

    #[cfg(feature = "v2")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::GlobalPaymentId, errors::ValidationError>;
}

impl PaymentIdTypeExt for PaymentIdType {
    #[cfg(feature = "v1")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::PaymentId, errors::ValidationError> {
        match self {
            Self::PaymentIntentId(id) => Ok(id.clone()),
            Self::ConnectorTransactionId(_)
            | Self::PaymentAttemptId(_)
            | Self::PreprocessingId(_) => Err(errors::ValidationError::IncorrectValueProvided {
                field_name: "payment_id",
            })
            .attach_printable("Expected payment intent ID but got connector transaction ID"),
        }
    }

    #[cfg(feature = "v2")]
    fn get_payment_intent_id(
        &self,
    ) -> errors::CustomResult<common_utils::id_type::GlobalPaymentId, errors::ValidationError> {
        match self {
            Self::PaymentIntentId(id) => Ok(id.clone()),
            Self::ConnectorTransactionId(_)
            | Self::PaymentAttemptId(_)
            | Self::PreprocessingId(_) => Err(errors::ValidationError::IncorrectValueProvided {
                field_name: "payment_id",
            })
            .attach_printable("Expected payment intent ID but got connector transaction ID"),
        }
    }
}

pub(crate) trait MandateValidationFieldsExt {
    fn validate_and_get_mandate_type(
        &self,
    ) -> errors::CustomResult<Option<MandateTransactionType>, errors::ValidationError>;
}

impl MandateValidationFieldsExt for MandateValidationFields {
    fn validate_and_get_mandate_type(
        &self,
    ) -> errors::CustomResult<Option<MandateTransactionType>, errors::ValidationError> {
        match (&self.mandate_data, &self.recurring_details) {
            (None, None) => Ok(None),
            (Some(_), Some(_)) => Err(errors::ValidationError::InvalidValue {
                message: "Expected one out of recurring_details and mandate_data but got both"
                    .to_string(),
            }
            .into()),
            (_, Some(_)) => Ok(Some(MandateTransactionType::RecurringMandateTransaction)),
            (Some(_), _) => Ok(Some(MandateTransactionType::NewMandateTransaction)),
        }
    }
}

#[cfg(feature = "v1")]
#[cfg(test)]
mod payments_test {
    use super::*;

    #[allow(dead_code)]
    fn card() -> Card {
        Card {
            card_number: "1234432112344321".to_string().try_into().unwrap(),
            card_exp_month: "12".to_string().into(),
            card_exp_year: "99".to_string().into(),
            card_holder_name: Some(masking::Secret::new("JohnDoe".to_string())),
            card_cvc: "123".to_string().into(),
            card_issuer: Some("HDFC".to_string()),
            card_network: Some(api_models::enums::CardNetwork::Visa),
            bank_code: None,
            card_issuing_country: None,
            card_type: None,
            nick_name: Some(masking::Secret::new("nick_name".into())),
        }
    }

    #[allow(dead_code)]
    fn payments_request() -> PaymentsRequest {
        PaymentsRequest {
            amount: Some(Amount::from(common_utils::types::MinorUnit::new(200))),
            payment_method_data: Some(PaymentMethodDataRequest {
                payment_method_data: Some(PaymentMethodData::Card(card())),
                billing: None,
            }),
            ..PaymentsRequest::default()
        }
    }

    //#[test] // FIXME: Fix test
    #[allow(dead_code)]
    fn verify_payments_request() {
        let pay_req = payments_request();
        let serialized =
            serde_json::to_string(&pay_req).expect("error serializing payments request");
        let _deserialized_pay_req: PaymentsRequest =
            serde_json::from_str(&serialized).expect("error de-serializing payments response");
        //assert_eq!(pay_req, deserialized_pay_req)
    }

    // Intended to test the serialization and deserialization of the enum PaymentIdType
    #[test]
    fn test_connector_id_type() {
        let sample_1 = PaymentIdType::PaymentIntentId(
            common_utils::id_type::PaymentId::try_from(std::borrow::Cow::Borrowed(
                "test_234565430uolsjdnf48i0",
            ))
            .unwrap(),
        );
        let s_sample_1 = serde_json::to_string(&sample_1).unwrap();
        let ds_sample_1 = serde_json::from_str::<PaymentIdType>(&s_sample_1).unwrap();
        assert_eq!(ds_sample_1, sample_1)
    }
}


// File: crates/router/src/types/api/disputes.rs

pub use hyperswitch_interfaces::{
    api::disputes::{
        AcceptDispute, DefendDispute, Dispute, DisputeSync, FetchDisputes, SubmitEvidence,
    },
    disputes::DisputePayload,
};
use masking::{Deserialize, Serialize};

use crate::types;

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct DisputeId {
    pub dispute_id: String,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct DisputeFetchQueryData {
    pub fetch_from: String,
    pub fetch_till: String,
}

pub use hyperswitch_domain_models::router_flow_types::dispute::{
    Accept, Defend, Dsync, Evidence, Fetch,
};

pub use super::disputes_v2::{
    AcceptDisputeV2, DefendDisputeV2, DisputeSyncV2, DisputeV2, FetchDisputesV2, SubmitEvidenceV2,
};

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct DisputeEvidence {
    pub cancellation_policy: Option<String>,
    pub customer_communication: Option<String>,
    pub customer_signature: Option<String>,
    pub receipt: Option<String>,
    pub refund_policy: Option<String>,
    pub service_documentation: Option<String>,
    pub shipping_documentation: Option<String>,
    pub invoice_showing_distinct_transactions: Option<String>,
    pub recurring_transaction_agreement: Option<String>,
    pub uncategorized_file: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct AttachEvidenceRequest {
    pub create_file_request: types::api::CreateFileRequest,
    pub evidence_type: EvidenceType,
}

#[derive(Debug, serde::Deserialize, strum::Display, strum::EnumString, Clone, serde::Serialize)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum EvidenceType {
    CancellationPolicy,
    CustomerCommunication,
    CustomerSignature,
    Receipt,
    RefundPolicy,
    ServiceDocumentation,
    ShippingDocumentation,
    InvoiceShowingDistinctTransactions,
    RecurringTransactionAgreement,
    UncategorizedFile,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct ProcessDisputePTData {
    pub connector_name: String,
    pub dispute_payload: types::DisputeSyncResponse,
    pub merchant_id: common_utils::id_type::MerchantId,
}

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct DisputeListPTData {
    pub connector_name: String,
    pub merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub profile_id: common_utils::id_type::ProfileId,
    pub created_from: time::PrimitiveDateTime,
    pub created_till: time::PrimitiveDateTime,
}


// File: crates/router/src/types/api/disputes_v2.rs

pub use hyperswitch_interfaces::api::disputes_v2::{
    AcceptDisputeV2, DefendDisputeV2, DisputeSyncV2, DisputeV2, FetchDisputesV2, SubmitEvidenceV2,
};


// File: crates/router/src/types/api/enums.rs

pub use api_models::enums::*;


// File: crates/router/src/types/api/files.rs

use api_models::enums::FileUploadProvider;
pub use hyperswitch_domain_models::router_flow_types::files::{Retrieve, Upload};
pub use hyperswitch_interfaces::api::files::{FilePurpose, FileUpload, RetrieveFile, UploadFile};
use masking::{Deserialize, Serialize};
use serde_with::serde_as;

pub use super::files_v2::{FileUploadV2, RetrieveFileV2, UploadFileV2};
use crate::{
    core::errors,
    types::{self, transformers::ForeignTryFrom},
};

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct FileId {
    pub file_id: String,
}

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct FileRetrieveRequest {
    pub file_id: String,
    pub dispute_id: Option<String>,
}

#[derive(Debug)]
pub enum FileDataRequired {
    Required,
    NotRequired,
}

impl ForeignTryFrom<FileUploadProvider> for types::Connector {
    type Error = error_stack::Report<errors::ApiErrorResponse>;
    fn foreign_try_from(item: FileUploadProvider) -> Result<Self, Self::Error> {
        match item {
            FileUploadProvider::Stripe => Ok(Self::Stripe),
            FileUploadProvider::Checkout => Ok(Self::Checkout),
            FileUploadProvider::Worldpayvantiv => Ok(Self::Worldpayvantiv),
            FileUploadProvider::Router => Err(errors::ApiErrorResponse::NotSupported {
                message: "File upload provider is not a connector".to_owned(),
            }
            .into()),
        }
    }
}

impl ForeignTryFrom<&types::Connector> for FileUploadProvider {
    type Error = error_stack::Report<errors::ApiErrorResponse>;
    fn foreign_try_from(item: &types::Connector) -> Result<Self, Self::Error> {
        match *item {
            types::Connector::Stripe => Ok(Self::Stripe),
            types::Connector::Checkout => Ok(Self::Checkout),
            types::Connector::Worldpayvantiv => Ok(Self::Worldpayvantiv),
            _ => Err(errors::ApiErrorResponse::NotSupported {
                message: "Connector not supported as file provider".to_owned(),
            }
            .into()),
        }
    }
}

#[serde_as]
#[derive(Debug, Clone, serde::Serialize)]
pub struct CreateFileRequest {
    pub file: Vec<u8>,
    pub file_name: Option<String>,
    pub file_size: i32,
    #[serde_as(as = "serde_with::DisplayFromStr")]
    pub file_type: mime::Mime,
    pub purpose: FilePurpose,
    pub dispute_id: Option<String>,
}


// File: crates/router/src/types/api/verify_connector.rs

pub mod paypal;
pub mod stripe;
use error_stack::ResultExt;

use crate::{
    consts,
    core::errors,
    services::{
        self,
        connector_integration_interface::{BoxedConnectorIntegrationInterface, ConnectorEnum},
    },
    types::{self, api, api::ConnectorCommon, domain, storage::enums as storage_enums},
    SessionState,
};

#[derive(Clone)]
pub struct VerifyConnectorData {
    pub connector: ConnectorEnum,
    pub connector_auth: types::ConnectorAuthType,
    pub card_details: domain::Card,
}

impl VerifyConnectorData {
    fn get_payment_authorize_data(&self) -> types::PaymentsAuthorizeData {
        types::PaymentsAuthorizeData {
            payment_method_data: domain::PaymentMethodData::Card(self.card_details.clone()),
            email: None,
            customer_name: None,
            amount: 1000,
            minor_amount: common_utils::types::MinorUnit::new(1000),
            confirm: true,
            order_tax_amount: None,
            currency: storage_enums::Currency::USD,
            metadata: None,
            mandate_id: None,
            webhook_url: None,
            customer_id: None,
            off_session: None,
            browser_info: None,
            session_token: None,
            order_details: None,
            order_category: None,
            capture_method: None,
            enrolled_for_3ds: false,
            router_return_url: None,
            surcharge_details: None,
            setup_future_usage: None,
            payment_experience: None,
            payment_method_type: None,
            setup_mandate_details: None,
            complete_authorize_url: None,
            related_transaction_id: None,
            request_extended_authorization: None,
            request_incremental_authorization: false,
            authentication_data: None,
            customer_acceptance: None,
            split_payments: None,
            merchant_order_reference_id: None,
            integrity_object: None,
            additional_payment_method_data: None,
            shipping_cost: None,
            merchant_account_id: None,
            merchant_config_currency: None,
            connector_testing_data: None,
            order_id: None,
            locale: None,
            payment_channel: None,
            enable_partial_authorization: None,
            enable_overcapture: None,
            is_stored_credential: None,
            mit_category: None,
            billing_descriptor: None,
            tokenization: None,
            partner_merchant_identifier_details: None,
        }
    }

    fn get_router_data<F, R1, R2>(
        &self,
        state: &SessionState,
        request_data: R1,
        access_token: Option<types::AccessToken>,
    ) -> types::RouterData<F, R1, R2> {
        let attempt_id =
            common_utils::generate_id_with_default_len(consts::VERIFY_CONNECTOR_ID_PREFIX);
        types::RouterData {
            flow: std::marker::PhantomData,
            status: storage_enums::AttemptStatus::Started,
            request: request_data,
            response: Err(errors::ApiErrorResponse::InternalServerError.into()),
            connector: self.connector.id().to_string(),
            auth_type: storage_enums::AuthenticationType::NoThreeDs,
            test_mode: None,
            attempt_id: attempt_id.clone(),
            description: None,
            customer_id: None,
            tenant_id: state.tenant.tenant_id.clone(),
            merchant_id: common_utils::id_type::MerchantId::default(),
            reference_id: None,
            access_token,
            session_token: None,
            payment_method: storage_enums::PaymentMethod::Card,
            payment_method_type: None,
            amount_captured: None,
            minor_amount_captured: None,
            preprocessing_id: None,
            connector_customer: None,
            connector_auth_type: self.connector_auth.clone(),
            connector_meta_data: None,
            connector_wallets_details: None,
            payment_method_token: None,
            connector_api_version: None,
            recurring_mandate_payment_data: None,
            payment_method_status: None,
            connector_request_reference_id: attempt_id,
            address: types::PaymentAddress::new(None, None, None, None),
            payment_id: common_utils::id_type::PaymentId::default()
                .get_string_repr()
                .to_owned(),
            #[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,
            apple_pay_flow: None,
            frm_metadata: None,
            refund_id: None,
            dispute_id: None,
            connector_response: None,
            integrity_check: Ok(()),
            additional_merchant_data: None,
            header_payload: None,
            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,
            authorized_amount: None,
        }
    }
}

#[async_trait::async_trait]
pub trait VerifyConnector {
    async fn verify(
        state: &SessionState,
        connector_data: VerifyConnectorData,
    ) -> errors::RouterResponse<()> {
        let authorize_data = connector_data.get_payment_authorize_data();
        let access_token = Self::get_access_token(state, connector_data.clone()).await?;
        let router_data = connector_data.get_router_data(state, authorize_data, access_token);

        let request = connector_data
            .connector
            .get_connector_integration()
            .build_request(&router_data, &state.conf.connectors)
            .change_context(errors::ApiErrorResponse::InvalidRequestData {
                message: "Payment request cannot be built".to_string(),
            })?
            .ok_or(errors::ApiErrorResponse::InternalServerError)?;

        let response =
            services::call_connector_api(&state.to_owned(), request, "verify_connector_request")
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)?;

        match response {
            Ok(_) => Ok(services::ApplicationResponse::StatusOk),
            Err(error_response) => {
                Self::handle_payment_error_response::<
                    api::Authorize,
                    types::PaymentFlowData,
                    types::PaymentsAuthorizeData,
                    types::PaymentsResponseData,
                >(
                    connector_data.connector.get_connector_integration(),
                    error_response,
                )
                .await
            }
        }
    }

    async fn get_access_token(
        _state: &SessionState,
        _connector_data: VerifyConnectorData,
    ) -> errors::CustomResult<Option<types::AccessToken>, errors::ApiErrorResponse> {
        // AccessToken is None for the connectors without the AccessToken Flow.
        // If a connector has that, then it should override this implementation.
        Ok(None)
    }

    async fn handle_payment_error_response<F, ResourceCommonData, Req, Resp>(
        // connector: &(dyn api::Connector + Sync),
        connector: BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>,
        error_response: types::Response,
    ) -> errors::RouterResponse<()> {
        let error = connector
            .get_error_response(error_response, None)
            .change_context(errors::ApiErrorResponse::InternalServerError)?;
        Err(errors::ApiErrorResponse::InvalidRequestData {
            message: error.reason.unwrap_or(error.message),
        }
        .into())
    }

    async fn handle_access_token_error_response<F, ResourceCommonData, Req, Resp>(
        connector: BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>,
        error_response: types::Response,
    ) -> errors::RouterResult<Option<types::AccessToken>> {
        let error = connector
            .get_error_response(error_response, None)
            .change_context(errors::ApiErrorResponse::InternalServerError)?;
        Err(errors::ApiErrorResponse::InvalidRequestData {
            message: error.reason.unwrap_or(error.message),
        }
        .into())
    }
}


// File: crates/router/src/types/api/authentication_v2.rs

pub use hyperswitch_domain_models::router_request_types::authentication::MessageCategory;
pub use hyperswitch_interfaces::api::authentication_v2::ExternalAuthenticationV2;


// File: crates/router/src/types/api/payment_link.rs

pub use api_models::payments::RetrievePaymentLinkResponse;

use crate::{
    consts::DEFAULT_SESSION_EXPIRY,
    core::{errors::RouterResult, payment_link},
    types::storage::{self},
};

#[async_trait::async_trait]
pub(crate) trait PaymentLinkResponseExt: Sized {
    async fn from_db_payment_link(payment_link: storage::PaymentLink) -> RouterResult<Self>;
}

#[async_trait::async_trait]
impl PaymentLinkResponseExt for RetrievePaymentLinkResponse {
    async fn from_db_payment_link(payment_link: storage::PaymentLink) -> RouterResult<Self> {
        let session_expiry = payment_link.fulfilment_time.unwrap_or_else(|| {
            payment_link
                .created_at
                .saturating_add(time::Duration::seconds(DEFAULT_SESSION_EXPIRY))
        });
        let status = payment_link::check_payment_link_status(session_expiry);
        Ok(Self {
            link_to_pay: payment_link.link_to_pay,
            payment_link_id: payment_link.payment_link_id,
            amount: payment_link.amount,
            description: payment_link.description,
            created_at: payment_link.created_at,
            merchant_id: payment_link.merchant_id,
            expiry: payment_link.fulfilment_time,
            currency: payment_link.currency,
            status,
            secure_link: payment_link.secure_link,
        })
    }
}


// File: crates/router/src/types/api/poll.rs

#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
pub struct PollId {
    pub poll_id: String,
}


// File: crates/router/src/types/api/webhooks.rs

pub use api_models::webhooks::{
    AuthenticationIdType, IncomingWebhookDetails, IncomingWebhookEvent, MerchantWebhookConfig,
    ObjectReferenceId, OutgoingWebhook, OutgoingWebhookContent, WebhookFlow,
};
pub use hyperswitch_interfaces::webhooks::{IncomingWebhook, IncomingWebhookRequestDetails};


// File: crates/router/src/types/api/api_keys.rs

pub use api_models::api_keys::{
    ApiKeyExpiration, CreateApiKeyRequest, CreateApiKeyResponse, ListApiKeyConstraints,
    RetrieveApiKeyResponse, RevokeApiKeyResponse, UpdateApiKeyRequest,
};


// File: crates/router/src/types/api/payments_v2.rs

pub use hyperswitch_interfaces::api::payments_v2::{
    ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2,
    PaymentAuthorizeV2, PaymentCaptureV2, PaymentExtendAuthorizationV2,
    PaymentIncrementalAuthorizationV2, PaymentPostCaptureVoidV2, PaymentPostSessionTokensV2,
    PaymentRejectV2, PaymentSessionUpdateV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2,
    PaymentUpdateMetadataV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2,
    PaymentsPostProcessingV2, PaymentsPreProcessingV2, TaxCalculationV2,
};


// File: crates/router/src/types/api/customers.rs

use api_models::customers;
pub use api_models::customers::{
    CustomerDeleteResponse, CustomerListRequest, CustomerListRequestWithConstraints,
    CustomerListResponse, CustomerRequest, CustomerUpdateRequest, CustomerUpdateRequestInternal,
};
#[cfg(feature = "v2")]
use hyperswitch_domain_models::customer;
use serde::Serialize;

#[cfg(feature = "v1")]
use super::payments;
use crate::{
    newtype,
    types::{domain, ForeignFrom},
};

newtype!(
    pub CustomerResponse = customers::CustomerResponse,
    derives = (Debug, Clone, Serialize)
);

impl common_utils::events::ApiEventMetric for CustomerResponse {
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        self.0.get_api_event_type()
    }
}

#[cfg(feature = "v1")]
impl ForeignFrom<(domain::Customer, Option<payments::AddressDetails>)> for CustomerResponse {
    fn foreign_from((cust, address): (domain::Customer, Option<payments::AddressDetails>)) -> Self {
        customers::CustomerResponse {
            customer_id: cust.customer_id,
            name: cust.name,
            email: cust.email,
            phone: cust.phone,
            phone_country_code: cust.phone_country_code,
            description: cust.description,
            created_at: cust.created_at,
            metadata: cust.metadata,
            address,
            default_payment_method_id: cust.default_payment_method_id,
            tax_registration_id: cust.tax_registration_id,
        }
        .into()
    }
}

#[cfg(feature = "v2")]
impl ForeignFrom<customer::Customer> for CustomerResponse {
    fn foreign_from(cust: domain::Customer) -> Self {
        customers::CustomerResponse {
            id: cust.id,
            merchant_reference_id: cust.merchant_reference_id,
            connector_customer_ids: cust.connector_customer,
            name: cust.name,
            email: cust.email,
            phone: cust.phone,
            phone_country_code: cust.phone_country_code,
            description: cust.description,
            created_at: cust.created_at,
            metadata: cust.metadata,
            default_billing_address: None,
            default_shipping_address: None,
            default_payment_method_id: cust.default_payment_method_id,
            tax_registration_id: cust.tax_registration_id,
        }
        .into()
    }
}


// File: crates/router/src/types/api/authentication.rs

use std::str::FromStr;

use api_models::enums;
use common_utils::errors::CustomResult;
use error_stack::ResultExt;
pub use hyperswitch_domain_models::{
    router_flow_types::authentication::{
        Authentication, PostAuthentication, PreAuthentication, PreAuthenticationVersionCall,
    },
    router_request_types::authentication::MessageCategory,
};

use crate::{
    connector, core::errors, services::connector_integration_interface::ConnectorEnum,
    types::storage,
};

#[derive(Clone, serde::Deserialize, Debug, serde::Serialize)]
pub struct AcquirerDetails {
    pub acquirer_bin: String,
    pub acquirer_merchant_mid: String,
    pub acquirer_country_code: Option<String>,
}

#[derive(Clone, serde::Deserialize, Debug, serde::Serialize)]
pub struct AuthenticationResponse {
    pub trans_status: common_enums::TransactionStatus,
    pub acs_url: Option<url::Url>,
    pub challenge_request: Option<String>,
    pub challenge_request_key: Option<String>,
    pub acs_reference_number: Option<String>,
    pub acs_trans_id: Option<String>,
    pub three_dsserver_trans_id: Option<String>,
    pub acs_signed_content: Option<String>,
}

impl TryFrom<storage::Authentication> for AuthenticationResponse {
    type Error = error_stack::Report<errors::ApiErrorResponse>;
    fn try_from(authentication: storage::Authentication) -> Result<Self, Self::Error> {
        let trans_status = authentication.trans_status.ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("trans_status must be populated in authentication table authentication call is successful")?;
        let acs_url = authentication
            .acs_url
            .map(|url| url::Url::from_str(&url))
            .transpose()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("not a valid URL")?;
        Ok(Self {
            trans_status,
            acs_url,
            challenge_request: authentication.challenge_request,
            acs_reference_number: authentication.acs_reference_number,
            acs_trans_id: authentication.acs_trans_id,
            three_dsserver_trans_id: authentication.threeds_server_transaction_id,
            acs_signed_content: authentication.acs_signed_content,
            challenge_request_key: authentication.challenge_request_key,
        })
    }
}

#[derive(Clone, serde::Deserialize, Debug, serde::Serialize)]
pub struct PostAuthenticationResponse {
    pub trans_status: String,
    pub authentication_value: Option<masking::Secret<String>>,
    pub eci: Option<String>,
}

#[derive(Clone)]
pub struct AuthenticationConnectorData {
    pub connector: ConnectorEnum,
    pub connector_name: enums::AuthenticationConnectors,
}

impl AuthenticationConnectorData {
    pub fn get_connector_by_name(name: &str) -> CustomResult<Self, errors::ApiErrorResponse> {
        let connector_name = enums::AuthenticationConnectors::from_str(name)
            .change_context(errors::ApiErrorResponse::IncorrectConnectorNameGiven)
            .attach_printable_lazy(|| format!("unable to parse connector: {name}"))?;
        let connector = Self::convert_connector(connector_name)?;
        Ok(Self {
            connector,
            connector_name,
        })
    }

    fn convert_connector(
        connector_name: enums::AuthenticationConnectors,
    ) -> CustomResult<ConnectorEnum, errors::ApiErrorResponse> {
        match connector_name {
            enums::AuthenticationConnectors::Threedsecureio => {
                Ok(ConnectorEnum::Old(Box::new(&connector::Threedsecureio)))
            }
            enums::AuthenticationConnectors::Netcetera => {
                Ok(ConnectorEnum::Old(Box::new(&connector::Netcetera)))
            }
            enums::AuthenticationConnectors::Gpayments => {
                Ok(ConnectorEnum::Old(Box::new(connector::Gpayments::new())))
            }
            enums::AuthenticationConnectors::CtpMastercard => {
                Ok(ConnectorEnum::Old(Box::new(&connector::CtpMastercard)))
            }
            enums::AuthenticationConnectors::CtpVisa => Ok(ConnectorEnum::Old(Box::new(
                connector::UnifiedAuthenticationService::new(),
            ))),
            enums::AuthenticationConnectors::UnifiedAuthenticationService => Ok(
                ConnectorEnum::Old(Box::new(connector::UnifiedAuthenticationService::new())),
            ),
            enums::AuthenticationConnectors::Juspaythreedsserver => Ok(ConnectorEnum::Old(
                Box::new(connector::Juspaythreedsserver::new()),
            )),
            enums::AuthenticationConnectors::Cardinal => Ok(ConnectorEnum::Old(Box::new(
                connector::UnifiedAuthenticationService::new(),
            ))),
        }
    }
}


// File: crates/router/src/types/api/routing.rs

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,
}


// File: crates/router/src/types/api/ephemeral_key.rs

pub use api_models::ephemeral_key::*;


// File: crates/router/src/types/api/mandates.rs

use ::payment_methods::controller::PaymentMethodsController;
use api_models::mandates;
pub use api_models::mandates::{MandateId, MandateResponse, MandateRevokedResponse};
use common_utils::ext_traits::OptionExt;
use error_stack::ResultExt;
use serde::{Deserialize, Serialize};

use crate::{
    core::{
        errors::{self, RouterResult, StorageErrorExt},
        payment_methods,
    },
    newtype,
    routes::SessionState,
    types::{
        api, domain,
        storage::{self, enums as storage_enums},
    },
};

newtype!(
    pub MandateCardDetails = mandates::MandateCardDetails,
    derives = (Default, Debug, Deserialize, Serialize)
);

#[async_trait::async_trait]
pub(crate) trait MandateResponseExt: Sized {
    async fn from_db_mandate(
        state: &SessionState,
        key_store: domain::MerchantKeyStore,
        mandate: storage::Mandate,
        merchant_account: &domain::MerchantAccount,
    ) -> RouterResult<Self>;
}

#[cfg(feature = "v1")]
#[async_trait::async_trait]
impl MandateResponseExt for MandateResponse {
    async fn from_db_mandate(
        state: &SessionState,
        key_store: domain::MerchantKeyStore,
        mandate: storage::Mandate,
        merchant_account: &domain::MerchantAccount,
    ) -> RouterResult<Self> {
        let db = &*state.store;
        let payment_method = db
            .find_payment_method(
                &key_store,
                &mandate.payment_method_id,
                merchant_account.storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?;

        let pm = payment_method
            .get_payment_method_type()
            .get_required_value("payment_method")
            .change_context(errors::ApiErrorResponse::PaymentMethodNotFound)
            .attach_printable("payment_method not found")?;

        let card = if pm == storage_enums::PaymentMethod::Card {
            // if locker is disabled , decrypt the payment method data
            let card_details = if state.conf.locker.locker_enabled {
                let card = payment_methods::cards::get_card_from_locker(
                    state,
                    &payment_method.customer_id,
                    &payment_method.merchant_id,
                    payment_method
                        .locker_id
                        .as_ref()
                        .unwrap_or(payment_method.get_id()),
                )
                .await?;

                payment_methods::transformers::get_card_detail(&payment_method, card)
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed while getting card details")?
            } else {
                let platform = domain::Platform::new(
                    merchant_account.clone(),
                    key_store.clone(),
                    merchant_account.clone(),
                    key_store,
                );
                payment_methods::cards::PmCards {
                    state,
                    platform: &platform,
                }
                .get_card_details_without_locker_fallback(&payment_method)
                .await?
            };

            Some(MandateCardDetails::from(card_details).into_inner())
        } else {
            None
        };
        let payment_method_type = payment_method
            .get_payment_method_subtype()
            .map(|pmt| pmt.to_string());
        let user_agent = mandate.get_user_agent_extended().unwrap_or_default();
        Ok(Self {
            mandate_id: mandate.mandate_id,
            customer_acceptance: Some(api::payments::CustomerAcceptance {
                acceptance_type: if mandate.customer_ip_address.is_some() {
                    api::payments::AcceptanceType::Online
                } else {
                    api::payments::AcceptanceType::Offline
                },
                accepted_at: mandate.customer_accepted_at,
                online: Some(api::payments::OnlineMandate {
                    ip_address: mandate.customer_ip_address,
                    user_agent,
                }),
            }),
            card,
            status: mandate.mandate_status,
            payment_method: pm.to_string(),
            payment_method_type,
            payment_method_id: mandate.payment_method_id,
        })
    }
}

#[cfg(feature = "v2")]
#[async_trait::async_trait]
impl MandateResponseExt for MandateResponse {
    async fn from_db_mandate(
        state: &SessionState,
        key_store: domain::MerchantKeyStore,
        mandate: storage::Mandate,
        merchant_account: &domain::MerchantAccount,
    ) -> RouterResult<Self> {
        todo!()
    }
}

#[cfg(feature = "v1")]
impl From<api::payment_methods::CardDetailFromLocker> for MandateCardDetails {
    fn from(card_details_from_locker: api::payment_methods::CardDetailFromLocker) -> Self {
        mandates::MandateCardDetails {
            last4_digits: card_details_from_locker.last4_digits,
            card_exp_month: card_details_from_locker.expiry_month.clone(),
            card_exp_year: card_details_from_locker.expiry_year.clone(),
            card_holder_name: card_details_from_locker.card_holder_name,
            card_token: card_details_from_locker.card_token,
            scheme: card_details_from_locker.scheme,
            issuer_country: card_details_from_locker.issuer_country,
            card_fingerprint: card_details_from_locker.card_fingerprint,
            card_isin: card_details_from_locker.card_isin,
            card_issuer: card_details_from_locker.card_issuer,
            card_network: card_details_from_locker.card_network,
            card_type: card_details_from_locker.card_type,
            nick_name: card_details_from_locker.nick_name,
        }
        .into()
    }
}

#[cfg(feature = "v2")]
impl From<api::payment_methods::CardDetailFromLocker> for MandateCardDetails {
    fn from(card_details_from_locker: api::payment_methods::CardDetailFromLocker) -> Self {
        mandates::MandateCardDetails {
            last4_digits: card_details_from_locker.last4_digits,
            card_exp_month: card_details_from_locker.expiry_month.clone(),
            card_exp_year: card_details_from_locker.expiry_year.clone(),
            card_holder_name: card_details_from_locker.card_holder_name,
            card_token: None,
            scheme: None,
            issuer_country: card_details_from_locker
                .issuer_country
                .map(|country| country.to_string()),
            card_fingerprint: card_details_from_locker.card_fingerprint,
            card_isin: card_details_from_locker.card_isin,
            card_issuer: card_details_from_locker.card_issuer,
            card_network: card_details_from_locker.card_network,
            card_type: card_details_from_locker
                .card_type
                .as_ref()
                .map(|c| c.to_string()),
            nick_name: card_details_from_locker.nick_name,
        }
        .into()
    }
}