// File: crates/router/src/types/api/connector_mapping.rs
// Module: router
// Public functions: 4
// Public structs: 1

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::Bluecode => {
                    Ok(ConnectorEnum::Old(Box::new(connector::Bluecode::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::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::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::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)))
                }
                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::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),
        }
    }
}


// Implementation: impl api::RefundExecute for for Tesouro
// File: crates/hyperswitch_connectors/src/connectors/tesouro.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundExecute for for Tesouro


// Struct: NetworkTokenizedCard
// File: crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NetworkTokenizedCard


// Function: start_tokenize_data_workflow
// File: crates/router/src/core/payment_methods/vault.rs
// Module: router

pub fn start_tokenize_data_workflow(
    state: &routes::SessionState,
    tokenize_tracker: &storage::ProcessTracker,
) -> Result<(), errors::ProcessTrackerError>


// Struct: BitpayAuthType
// File: crates/hyperswitch_connectors/src/connectors/bitpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BitpayAuthType


// Implementation: impl api::PaymentSession for for Opennode
// File: crates/hyperswitch_connectors/src/connectors/opennode.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSession for for Opennode


// File: crates/analytics/src/refunds/metrics/sessionized_metrics/refund_error_message.rs
// Module: analytics

use std::collections::HashSet;

use api_models::analytics::{
    refunds::{RefundDimensions, RefundFilters, RefundMetricsBucketIdentifier},
    Granularity, TimeRange,
};
use common_utils::errors::ReportSwitchExt;
use diesel_models::enums as storage_enums;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use super::RefundMetricRow;
use crate::{
    enums::AuthInfo,
    query::{
        Aggregate, FilterTypes, GroupByClause, Order, QueryBuilder, QueryFilter, SeriesBucket,
        ToSql, Window,
    },
    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
};

#[derive(Default)]
pub(crate) struct RefundErrorMessage;

#[async_trait::async_trait]
impl<T> super::RefundMetric<T> for RefundErrorMessage
where
    T: AnalyticsDataSource + super::RefundMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[RefundDimensions],
        auth: &AuthInfo,
        filters: &RefundFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(RefundMetricsBucketIdentifier, RefundMetricRow)>> {
        let mut inner_query_builder: QueryBuilder<T> =
            QueryBuilder::new(AnalyticsCollection::RefundSessionized);
        inner_query_builder
            .add_select_column("sum(sign_flag)")
            .switch()?;

        inner_query_builder
            .add_custom_filter_clause(
                RefundDimensions::RefundErrorMessage,
                "NULL",
                FilterTypes::IsNotNull,
            )
            .switch()?;

        time_range
            .set_filter_clause(&mut inner_query_builder)
            .attach_printable("Error filtering time range for inner query")
            .switch()?;

        let inner_query_string = inner_query_builder
            .build_query()
            .attach_printable("Error building inner query")
            .change_context(MetricsError::QueryBuildingError)?;

        let mut outer_query_builder: QueryBuilder<T> =
            QueryBuilder::new(AnalyticsCollection::RefundSessionized);

        for dim in dimensions.iter() {
            outer_query_builder.add_select_column(dim).switch()?;
        }

        outer_query_builder
            .add_select_column("sum(sign_flag) AS count")
            .switch()?;

        outer_query_builder
            .add_select_column(format!("({inner_query_string}) AS total"))
            .switch()?;

        outer_query_builder
            .add_select_column(Aggregate::Min {
                field: "created_at",
                alias: Some("start_bucket"),
            })
            .switch()?;

        outer_query_builder
            .add_select_column(Aggregate::Max {
                field: "created_at",
                alias: Some("end_bucket"),
            })
            .switch()?;

        filters
            .set_filter_clause(&mut outer_query_builder)
            .switch()?;

        auth.set_filter_clause(&mut outer_query_builder).switch()?;

        time_range
            .set_filter_clause(&mut outer_query_builder)
            .attach_printable("Error filtering time range for outer query")
            .switch()?;

        outer_query_builder
            .add_filter_clause(
                RefundDimensions::RefundStatus,
                storage_enums::RefundStatus::Failure,
            )
            .switch()?;

        outer_query_builder
            .add_custom_filter_clause(
                RefundDimensions::RefundErrorMessage,
                "NULL",
                FilterTypes::IsNotNull,
            )
            .switch()?;

        for dim in dimensions.iter() {
            outer_query_builder
                .add_group_by_clause(dim)
                .attach_printable("Error grouping by dimensions")
                .switch()?;
        }

        if let Some(granularity) = granularity {
            granularity
                .set_group_by_clause(&mut outer_query_builder)
                .attach_printable("Error adding granularity")
                .switch()?;
        }

        outer_query_builder
            .add_order_by_clause("count", Order::Descending)
            .attach_printable("Error adding order by clause")
            .switch()?;

        let filtered_dimensions: Vec<&RefundDimensions> = dimensions
            .iter()
            .filter(|&&dim| dim != RefundDimensions::RefundErrorMessage)
            .collect();

        for dim in &filtered_dimensions {
            outer_query_builder
                .add_order_by_clause(*dim, Order::Ascending)
                .attach_printable("Error adding order by clause")
                .switch()?;
        }

        outer_query_builder
            .execute_query::<RefundMetricRow, _>(pool)
            .await
            .change_context(MetricsError::QueryBuildingError)?
            .change_context(MetricsError::QueryExecutionFailure)?
            .into_iter()
            .map(|i| {
                Ok((
                    RefundMetricsBucketIdentifier::new(
                        i.currency.as_ref().map(|i| i.0),
                        None,
                        i.connector.clone(),
                        i.refund_type.as_ref().map(|i| i.0.to_string()),
                        i.profile_id.clone(),
                        i.refund_reason.clone(),
                        i.refund_error_message.clone(),
                        TimeRange {
                            start_time: match (granularity, i.start_bucket) {
                                (Some(g), Some(st)) => g.clip_to_start(st)?,
                                _ => time_range.start_time,
                            },
                            end_time: granularity.as_ref().map_or_else(
                                || Ok(time_range.end_time),
                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
                            )?,
                        },
                    ),
                    i,
                ))
            })
            .collect::<error_stack::Result<
                HashSet<(RefundMetricsBucketIdentifier, RefundMetricRow)>,
                crate::query::PostProcessingError,
            >>()
            .change_context(MetricsError::PostProcessingFailure)
    }
}


// Function: payment_processor_token_retry_info
// File: crates/router/src/types/storage/revenue_recovery_redis_operation.rs
// Module: router

// Documentation: Calculate retry counts for exactly the last 30 days

pub fn payment_processor_token_retry_info(
        state: &SessionState,
        token: &PaymentProcessorTokenStatus,
        today: Date,
        network_type: Option<CardNetwork>,
    ) -> TokenRetryInfo


// Implementation: impl api::PaymentVoid for for Katapult
// File: crates/hyperswitch_connectors/src/connectors/katapult.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentVoid for for Katapult


// Function: new
// File: crates/currency_conversion/src/types.rs
// Module: currency_conversion

pub fn new(to_factor: Decimal, from_factor: Decimal) -> Self


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

impl api::PaymentAuthorize for for Authipay


// Struct: CaptureNew
// File: crates/diesel_models/src/capture.rs
// Module: diesel_models
// Implementations: 0

pub struct CaptureNew


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

impl api::PaymentAuthorize for for Inespay


// File: crates/router/tests/connectors/mpgs.rs
// Module: router

use hyperswitch_domain_models::payment_method_data::{Card, PaymentMethodData};
use masking::Secret;
use router::types::{self, api, storage::enums};
use test_utils::connector_auth;

use crate::utils::{self, ConnectorActions};

#[derive(Clone, Copy)]
struct MpgsTest;
impl ConnectorActions for MpgsTest {}
impl utils::Connector for MpgsTest {
    fn get_data(&self) -> api::ConnectorData {
        use router::connector::Mpgs;
        utils::construct_connector_data_old(
            Box::new(Mpgs::new()),
            types::Connector::Plaid,
            api::GetToken::Connector,
            None,
        )
    }

    fn get_auth_token(&self) -> types::ConnectorAuthType {
        utils::to_connector_auth_type(
            connector_auth::ConnectorAuthentication::new()
                .mpgs
                .expect("Missing connector authentication configuration")
                .into(),
        )
    }

    fn get_name(&self) -> String {
        "mpgs".to_string()
    }
}

static CONNECTOR: MpgsTest = MpgsTest {};

fn get_default_payment_info() -> Option<utils::PaymentInfo> {
    None
}

fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
    None
}

// Cards Positive Tests
// Creates a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_only_authorize_payment() {
    let response = CONNECTOR
        .authorize_payment(payment_method_details(), get_default_payment_info())
        .await
        .expect("Authorize payment response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized);
}

// Captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(payment_method_details(), None, get_default_payment_info())
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Partially captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(
            payment_method_details(),
            Some(types::PaymentsCaptureData {
                amount_to_capture: 50,
                ..utils::PaymentCaptureType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_authorized_payment() {
    let authorize_response = CONNECTOR
        .authorize_payment(payment_method_details(), get_default_payment_info())
        .await
        .expect("Authorize payment response");
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Authorized,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .expect("PSync response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
}

// Voids a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_void_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_void_payment(
            payment_method_details(),
            Some(types::PaymentsCancelData {
                connector_transaction_id: String::from(""),
                cancellation_reason: Some("requested_by_customer".to_string()),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .expect("Void payment response");
    assert_eq!(response.status, enums::AttemptStatus::Voided);
}

// Refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Synchronizes a refund using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_manually_captured_refund() {
    let refund_response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_make_payment() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_auto_captured_payment() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Charged,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                capture_method: Some(enums::CaptureMethod::Automatic),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(response.status, enums::AttemptStatus::Charged,);
}

// Refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_auto_captured_payment() {
    let response = CONNECTOR
        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_succeeded_payment() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        refund_response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_succeeded_payment_multiple_times() {
    CONNECTOR
        .make_payment_and_multiple_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await;
}

// Synchronizes a refund using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_refund() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Cards Negative scenarios
// Creates a payment with incorrect CVC.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_cvc: Secret::new("12345".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's security code is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry month.
#[actix_web::test]
async fn should_fail_payment_for_invalid_exp_month() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_exp_month: Secret::new("20".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration month is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry year.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_expiry_year() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_exp_year: Secret::new("2000".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration year is invalid.".to_string(),
    );
}

// Voids a payment using automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_fail_void_payment_for_auto_capture() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let void_response = CONNECTOR
        .void_payment(txn_id.unwrap(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        void_response.response.unwrap_err().message,
        "You cannot cancel this PaymentIntent because it has a status of succeeded."
    );
}

// Captures a payment using invalid connector payment id.
#[actix_web::test]
async fn should_fail_capture_for_invalid_payment() {
    let capture_response = CONNECTOR
        .capture_payment("123456789".to_string(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        capture_response.response.unwrap_err().message,
        String::from("No such payment_intent: '123456789'")
    );
}

// Refunds a payment with refund amount higher than payment amount.
#[actix_web::test]
async fn should_fail_for_refund_amount_higher_than_payment_amount() {
    let response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 150,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
    );
}

// Connector dependent test cases goes here

// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests


// Implementation: impl api::PayoutRecipientAccount for for Nomupay
// File: crates/hyperswitch_connectors/src/connectors/nomupay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PayoutRecipientAccount for for Nomupay


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

impl api::PaymentCapture for for Multisafepay


// Function: format_emv_field
// File: crates/hyperswitch_connectors/src/connectors/santander/transformers.rs
// Module: hyperswitch_connectors

pub fn format_emv_field(id: &str, value: &str) -> String


// Function: get_connector_customer_payment_processor_tokens
// File: crates/router/src/types/storage/revenue_recovery_redis_operation.rs
// Module: router

pub fn get_connector_customer_payment_processor_tokens(
        state: &SessionState,
        connector_customer_id: &str,
    ) -> CustomResult<HashMap<String, PaymentProcessorTokenStatus>, errors::StorageError>


// Struct: StripebillingRouterData
// File: crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct StripebillingRouterData<T>


// Struct: MerchantConnectorUpdate
// File: crates/api_models/src/admin.rs
// Module: api_models
// Implementations: 1

pub struct MerchantConnectorUpdate


// Struct: Store
// File: crates/drainer/src/services.rs
// Module: drainer
// Implementations: 1

pub struct Store


// Struct: Forex
// File: crates/router/src/routes/app.rs
// Module: router
// Implementations: 1

pub struct Forex


// Implementation: impl api::MandateSetup for for Worldpayvantiv
// File: crates/hyperswitch_connectors/src/connectors/worldpayvantiv.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::MandateSetup for for Worldpayvantiv


// Function: is_dispute_event
// File: crates/hyperswitch_connectors/src/connectors/airwallex/transformers.rs
// Module: hyperswitch_connectors

pub fn is_dispute_event(event_code: &AirwallexWebhookEventType) -> bool


// Struct: PaymentAuthRouterData
// File: crates/pm_auth/src/types.rs
// Module: pm_auth
// Implementations: 0

pub struct PaymentAuthRouterData<F, Request, Response>


// Struct: AdyenAddress
// File: crates/hyperswitch_connectors/src/connectors/adyenplatform/transformers/payouts.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AdyenAddress


// Function: list_invitable_roles_at_entity_level
// File: crates/router/src/routes/user_role.rs
// Module: router

pub fn list_invitable_roles_at_entity_level(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<role_api::ListRolesAtEntityLevelRequest>,
) -> HttpResponse


// File: crates/router/src/events/api_logs.rs
// Module: router
// Public functions: 1
// Public structs: 1

use actix_web::HttpRequest;
pub use common_utils::events::{ApiEventMetric, ApiEventsType};
use common_utils::impl_api_event_type;
use router_env::{tracing_actix_web::RequestId, types::FlowMetric};
use serde::Serialize;
use time::OffsetDateTime;

use super::EventType;
#[cfg(feature = "dummy_connector")]
use crate::routes::dummy_connector::types::{
    DummyConnectorPaymentCompleteRequest, DummyConnectorPaymentConfirmRequest,
    DummyConnectorPaymentRequest, DummyConnectorPaymentResponse,
    DummyConnectorPaymentRetrieveRequest, DummyConnectorRefundRequest,
    DummyConnectorRefundResponse, DummyConnectorRefundRetrieveRequest,
};
use crate::{
    core::payments::PaymentsRedirectResponseData,
    services::{authentication::AuthenticationType, kafka::KafkaMessage},
    types::api::{
        AttachEvidenceRequest, Config, ConfigUpdate, CreateFileRequest, DisputeFetchQueryData,
        DisputeId, FileId, FileRetrieveRequest, PollId,
    },
};

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct ApiEvent {
    tenant_id: common_utils::id_type::TenantId,
    merchant_id: Option<common_utils::id_type::MerchantId>,
    api_flow: String,
    created_at_timestamp: i128,
    request_id: String,
    latency: u128,
    status_code: i64,
    #[serde(flatten)]
    auth_type: AuthenticationType,
    request: String,
    user_agent: Option<String>,
    ip_addr: Option<String>,
    url_path: String,
    response: Option<String>,
    error: Option<serde_json::Value>,
    #[serde(flatten)]
    event_type: ApiEventsType,
    hs_latency: Option<u128>,
    http_method: String,
    #[serde(flatten)]
    infra_components: Option<serde_json::Value>,
}

impl ApiEvent {
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        tenant_id: common_utils::id_type::TenantId,
        merchant_id: Option<common_utils::id_type::MerchantId>,
        api_flow: &impl FlowMetric,
        request_id: &RequestId,
        latency: u128,
        status_code: i64,
        request: serde_json::Value,
        response: Option<serde_json::Value>,
        hs_latency: Option<u128>,
        auth_type: AuthenticationType,
        error: Option<serde_json::Value>,
        event_type: ApiEventsType,
        http_req: &HttpRequest,
        http_method: &http::Method,
        infra_components: Option<serde_json::Value>,
    ) -> Self {
        Self {
            tenant_id,
            merchant_id,
            api_flow: api_flow.to_string(),
            created_at_timestamp: OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000_000,
            request_id: request_id.as_hyphenated().to_string(),
            latency,
            status_code,
            request: request.to_string(),
            response: response.map(|resp| resp.to_string()),
            auth_type,
            error,
            ip_addr: http_req
                .connection_info()
                .realip_remote_addr()
                .map(ToOwned::to_owned),
            user_agent: http_req
                .headers()
                .get("user-agent")
                .and_then(|user_agent_value| user_agent_value.to_str().ok().map(ToOwned::to_owned)),
            url_path: http_req.path().to_string(),
            event_type,
            hs_latency,
            http_method: http_method.to_string(),
            infra_components,
        }
    }
}

impl KafkaMessage for ApiEvent {
    fn event_type(&self) -> EventType {
        EventType::ApiLogs
    }

    fn key(&self) -> String {
        self.request_id.clone()
    }
}

impl_api_event_type!(
    Miscellaneous,
    (
        Config,
        CreateFileRequest,
        FileId,
        FileRetrieveRequest,
        AttachEvidenceRequest,
        DisputeFetchQueryData,
        ConfigUpdate
    )
);

#[cfg(feature = "dummy_connector")]
impl_api_event_type!(
    Miscellaneous,
    (
        DummyConnectorPaymentCompleteRequest,
        DummyConnectorPaymentRequest,
        DummyConnectorPaymentResponse,
        DummyConnectorPaymentRetrieveRequest,
        DummyConnectorPaymentConfirmRequest,
        DummyConnectorRefundRetrieveRequest,
        DummyConnectorRefundResponse,
        DummyConnectorRefundRequest
    )
);

#[cfg(feature = "v1")]
impl ApiEventMetric for PaymentsRedirectResponseData {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::PaymentRedirectionResponse {
            connector: self.connector.clone(),
            payment_id: match &self.resource_id {
                api_models::payments::PaymentIdType::PaymentIntentId(id) => Some(id.clone()),
                _ => None,
            },
        })
    }
}

#[cfg(feature = "v2")]
impl ApiEventMetric for PaymentsRedirectResponseData {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::PaymentRedirectionResponse {
            payment_id: self.payment_id.clone(),
        })
    }
}

impl ApiEventMetric for DisputeId {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Dispute {
            dispute_id: self.dispute_id.clone(),
        })
    }
}

impl ApiEventMetric for PollId {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Poll {
            poll_id: self.poll_id.clone(),
        })
    }
}


// Function: new
// File: crates/hyperswitch_interfaces/src/events/routing_api_logs.rs
// Module: hyperswitch_interfaces

pub fn new(
        tenant_id: common_utils::id_type::TenantId,
        routable_connectors: String,
        flow: &str,
        request: serde_json::Value,
        url: String,
        method: ApiMethod,
        payment_id: String,
        profile_id: common_utils::id_type::ProfileId,
        merchant_id: common_utils::id_type::MerchantId,
        request_id: Option<RequestId>,
        routing_engine: RoutingEngine,
    ) -> Self


// Function: try_redis_get_else_try_database_get
// File: crates/router/src/utils/db_utils.rs
// Module: router

pub fn try_redis_get_else_try_database_get<F, RFut, DFut, T>(
    redis_fut: RFut,
    database_call_closure: F,
) -> error_stack::Result<T, errors::StorageError>
where
    F: FnOnce() -> DFut,
    RFut: futures::Future<Output = error_stack::Result<T, redis_interface::errors::RedisError>>,
    DFut: futures::Future<Output = error_stack::Result<T, errors::StorageError>>,


// Struct: KlarnaMeta
// File: crates/hyperswitch_connectors/src/connectors/klarna/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct KlarnaMeta


// Function: scope
// File: crates/router_derive/src/macros/generate_permissions.rs
// Module: router_derive

pub fn scope(&self) -> PermissionScope


// Struct: RazorpayOrderResponse
// File: crates/hyperswitch_connectors/src/connectors/razorpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RazorpayOrderResponse


// Struct: Bambora3DsResponse
// File: crates/hyperswitch_connectors/src/connectors/bambora/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Bambora3DsResponse


        ))
    }
}

impl PaymentUpdate {
    fn populate_payment_attempt_with_request(
        payment_attempt: &mut storage::PaymentAttempt,
        request: &api::PaymentsRequest,
    ) {
        request
            .business_sub_label
            .clone()
            .map(|bsl| payment_attempt.business_sub_label.replace(bsl));
        request
            .payment_method_type
            .map(|pmt| payment_attempt.payment_method_type.replace(pmt));
        request
            .payment_experience
            .map(|experience| payment_attempt.payment_experience.replace(experience));
        payment_attempt.amount_to_capture = request
            .amount_to_capture
            .or(payment_attempt.amount_to_capture);
        request
            .capture_method
            .map(|i| payment_attempt.capture_method.replace(i));
    }
    fn populate_payment_intent_with_request(
        payment_intent: &mut storage::PaymentIntent,
        request: &api::PaymentsRequest,
    ) {
        request
            .return_url
            .clone()
            .map(|i| payment_intent.return_url.replace(i.to_string()));

        payment_intent.business_country = request.business_country;

        payment_intent
            .business_label
            .clone_from(&request.business_label);

        request
            .description
            .clone()
            .map(|i| payment_intent.description.replace(i));

        request
            .statement_descriptor_name
            .clone()
            .map(|i| payment_intent.statement_descriptor_name.replace(i));

        request
            .statement_descriptor_suffix
            .clone()
            .map(|i| payment_intent.statement_descriptor_suffix.replace(i));

        request
            .client_secret
            .clone()
            .map(|i| payment_intent.client_secret.replace(i));
    }
}


// Struct: PaymentLinkBackgroundImageConfig
// File: crates/api_models/src/admin.rs
// Module: api_models
// Implementations: 0

pub struct PaymentLinkBackgroundImageConfig


// Function: get_event_handler
// File: crates/router/src/events.rs
// Module: router

pub fn get_event_handler(&self) -> StorageResult<EventsHandler>


// Struct: Fiserv
// File: crates/hyperswitch_connectors/src/connectors/fiserv.rs
// Module: hyperswitch_connectors
// Implementations: 17
// Traits: ConnectorCommon, api::ConnectorAccessToken, ConnectorValidation, api::Payment, api::PaymentToken, api::MandateSetup, api::PaymentVoid, api::PaymentSync, api::PaymentCapture, api::PaymentSession, api::PaymentAuthorize, api::Refund, api::RefundExecute, api::RefundSync, webhooks::IncomingWebhook, ConnectorSpecifications

pub struct Fiserv

ConnectorCommon api::ConnectorAccessToken ConnectorValidation api::Payment api::PaymentToken api::MandateSetup api::PaymentVoid api::PaymentSync api::PaymentCapture api::PaymentSession api::PaymentAuthorize api::Refund api::RefundExecute api::RefundSync webhooks::IncomingWebhook ConnectorSpecifications


// Implementation: impl Multisafepay
// File: crates/hyperswitch_connectors/src/connectors/multisafepay.rs
// Module: hyperswitch_connectors
// Methods: 1 total (1 public)

impl Multisafepay


// Function: call_unified_connector_service_for_webhook
// File: crates/router/src/core/unified_connector_service.rs
// Module: router

// Documentation: High-level abstraction for calling UCS webhook transformation This provides a clean interface similar to payment flow UCS calls

pub fn call_unified_connector_service_for_webhook(
    state: &SessionState,
    merchant_context: &MerchantContext,
    connector_name: &str,
    body: &actix_web::web::Bytes,
    request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>,
    merchant_connector_account: Option<
        &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount,
    >,
) -> RouterResult<(
    api_models::webhooks::IncomingWebhookEvent,
    bool,
    WebhookTransformData,
)>


// File: crates/diesel_models/src/payment_intent.rs
// Module: diesel_models
// Public functions: 4
// Public structs: 14

use common_enums::{PaymentMethodType, RequestIncrementalAuthorization};
use common_types::primitive_wrappers::{
    EnablePartialAuthorizationBool, RequestExtendedAuthorizationBool,
};
use common_utils::{encryption::Encryption, pii, types::MinorUnit};
use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable};
use masking::ExposeInterface;
use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;

#[cfg(feature = "v1")]
use crate::schema::payment_intent;
#[cfg(feature = "v2")]
use crate::schema_v2::payment_intent;
#[cfg(feature = "v2")]
use crate::types::{FeatureMetadata, OrderDetailsWithAmount};
#[cfg(feature = "v2")]
use crate::RequiredFromNullable;
use crate::{business_profile::PaymentLinkBackgroundImageConfig, enums as storage_enums};

#[cfg(feature = "v2")]
#[derive(Clone, Debug, PartialEq, Identifiable, Queryable, Serialize, Deserialize, Selectable)]
#[diesel(table_name = payment_intent, primary_key(id), check_for_backend(diesel::pg::Pg))]
pub struct PaymentIntent {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub status: storage_enums::IntentStatus,
    pub amount: MinorUnit,
    #[diesel(deserialize_as = RequiredFromNullable<storage_enums::Currency>)]
    pub currency: storage_enums::Currency,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::GlobalCustomerId>,
    pub description: Option<common_utils::types::Description>,
    pub return_url: Option<common_utils::types::Url>,
    pub metadata: Option<pii::SecretSerdeValue>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_synced: Option<PrimitiveDateTime>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub active_attempt_id: Option<common_utils::id_type::GlobalAttemptId>,
    #[diesel(deserialize_as = super::OptionalDieselArray<masking::Secret<OrderDetailsWithAmount>>)]
    pub order_details: Option<Vec<masking::Secret<OrderDetailsWithAmount>>>,
    pub allowed_payment_method_types: Option<pii::SecretSerdeValue>,
    pub connector_metadata: Option<pii::SecretSerdeValue>,
    pub feature_metadata: Option<FeatureMetadata>,
    pub attempt_count: i16,
    #[diesel(deserialize_as = RequiredFromNullable<common_utils::id_type::ProfileId>)]
    pub profile_id: common_utils::id_type::ProfileId,
    pub payment_link_id: Option<String>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub authorization_count: Option<i32>,
    #[diesel(deserialize_as = RequiredFromNullable<PrimitiveDateTime>)]
    pub session_expiry: PrimitiveDateTime,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub shipping_cost: Option<MinorUnit>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
    pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
    pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub force_3ds_challenge: Option<bool>,
    pub force_3ds_challenge_trigger: Option<bool>,
    pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub created_by: Option<String>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub is_payment_id_from_merchant: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
    pub merchant_reference_id: Option<common_utils::id_type::PaymentReferenceId>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub capture_method: Option<storage_enums::CaptureMethod>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub prerouting_algorithm: Option<serde_json::Value>,
    pub surcharge_amount: Option<MinorUnit>,
    pub tax_on_surcharge: Option<MinorUnit>,
    // Denotes the action(approve or reject) taken by merchant in case of manual review.
    // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
    pub frm_merchant_decision: Option<common_enums::MerchantDecision>,
    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
    pub enable_payment_link: Option<bool>,
    pub apply_mit_exemption: Option<bool>,
    pub customer_present: Option<bool>,
    pub routing_algorithm_id: Option<common_utils::id_type::RoutingId>,
    pub payment_link_config: Option<PaymentLinkConfigRequestForPayments>,
    pub id: common_utils::id_type::GlobalPaymentId,
    pub split_txns_enabled: Option<common_enums::SplitTxnsEnabled>,
    pub active_attempts_group_id: Option<String>,
    pub active_attempt_id_type: Option<common_enums::ActiveAttemptIDType>,
}

#[cfg(feature = "v1")]
#[derive(Clone, Debug, PartialEq, Identifiable, Queryable, Serialize, Deserialize, Selectable)]
#[diesel(table_name = payment_intent, primary_key(payment_id, merchant_id), check_for_backend(diesel::pg::Pg))]
pub struct PaymentIntent {
    pub payment_id: common_utils::id_type::PaymentId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub status: storage_enums::IntentStatus,
    pub amount: MinorUnit,
    pub currency: Option<storage_enums::Currency>,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub description: Option<String>,
    pub return_url: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub connector_id: Option<String>,
    pub shipping_address_id: Option<String>,
    pub billing_address_id: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_synced: Option<PrimitiveDateTime>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub off_session: Option<bool>,
    pub client_secret: Option<String>,
    pub active_attempt_id: String,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub allowed_payment_method_types: Option<serde_json::Value>,
    pub connector_metadata: Option<serde_json::Value>,
    pub feature_metadata: Option<serde_json::Value>,
    pub attempt_count: i16,
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    // Denotes the action(approve or reject) taken by merchant in case of manual review.
    // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
    pub merchant_decision: Option<String>,
    pub payment_link_id: Option<String>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub incremental_authorization_allowed: Option<bool>,
    pub authorization_count: Option<i32>,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub fingerprint_id: Option<String>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub charges: Option<pii::SecretSerdeValue>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub billing_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryption>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub shipping_cost: Option<MinorUnit>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
    pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
    pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub force_3ds_challenge: Option<bool>,
    pub force_3ds_challenge_trigger: Option<bool>,
    pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub created_by: Option<String>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub extended_return_url: Option<String>,
    pub is_payment_id_from_merchant: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
}

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression, PartialEq)]
#[diesel(sql_type = diesel::sql_types::Jsonb)]
pub struct PaymentLinkConfigRequestForPayments {
    /// custom theme for the payment link
    pub theme: Option<String>,
    /// merchant display logo
    pub logo: Option<String>,
    /// Custom merchant name for payment link
    pub seller_name: Option<String>,
    /// Custom layout for sdk
    pub sdk_layout: Option<String>,
    /// Display only the sdk for payment link
    pub display_sdk_only: Option<bool>,
    /// Enable saved payment method option for payment link
    pub enabled_saved_payment_method: Option<bool>,
    /// Hide card nickname field option for payment link
    pub hide_card_nickname_field: Option<bool>,
    /// Show card form by default for payment link
    pub show_card_form_by_default: Option<bool>,
    /// Dynamic details related to merchant to be rendered in payment link
    pub transaction_details: Option<Vec<PaymentLinkTransactionDetails>>,
    /// Configurations for the background image for details section
    pub background_image: Option<PaymentLinkBackgroundImageConfig>,
    /// Custom layout for details section
    pub details_layout: Option<common_enums::PaymentLinkDetailsLayout>,
    /// Text for payment link's handle confirm button
    pub payment_button_text: Option<String>,
    /// Skip the status screen after payment completion
    pub skip_status_screen: Option<bool>,
    /// Text for customizing message for card terms
    pub custom_message_for_card_terms: Option<String>,
    /// Custom background colour for payment link's handle confirm button
    pub payment_button_colour: Option<String>,
    /// Custom text colour for payment link's handle confirm button
    pub payment_button_text_colour: Option<String>,
    /// Custom background colour for the payment link
    pub background_colour: Option<String>,
    /// SDK configuration rules
    pub sdk_ui_rules:
        Option<std::collections::HashMap<String, std::collections::HashMap<String, String>>>,
    /// Payment link configuration rules
    pub payment_link_ui_rules:
        Option<std::collections::HashMap<String, std::collections::HashMap<String, String>>>,
    /// Flag to enable the button only when the payment form is ready for submission
    pub enable_button_only_on_form_ready: Option<bool>,
    /// Optional header for the SDK's payment form
    pub payment_form_header_text: Option<String>,
    /// Label type in the SDK's payment form
    pub payment_form_label_type: Option<common_enums::PaymentLinkSdkLabelType>,
    /// Boolean for controlling whether or not to show the explicit consent for storing cards
    pub show_card_terms: Option<common_enums::PaymentLinkShowSdkTerms>,
    /// Boolean to control payment button text for setup mandate calls
    pub is_setup_mandate_flow: Option<bool>,
    /// Hex color for the CVC icon during error state
    pub color_icon_card_cvc_error: Option<String>,
}

common_utils::impl_to_sql_from_sql_json!(PaymentLinkConfigRequestForPayments);

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)]
pub struct PaymentLinkTransactionDetails {
    /// Key for the transaction details
    pub key: String,
    /// Value for the transaction details
    pub value: String,
    /// UI configuration for the transaction details
    pub ui_configuration: Option<TransactionDetailsUiConfiguration>,
}

common_utils::impl_to_sql_from_sql_json!(PaymentLinkTransactionDetails);

#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)]
pub struct TransactionDetailsUiConfiguration {
    /// Position of the key-value pair in the UI
    pub position: Option<i8>,
    /// Whether the key should be bold
    pub is_key_bold: Option<bool>,
    /// Whether the value should be bold
    pub is_value_bold: Option<bool>,
}

common_utils::impl_to_sql_from_sql_json!(TransactionDetailsUiConfiguration);

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, diesel::AsExpression)]
#[diesel(sql_type = diesel::sql_types::Jsonb)]
pub struct TaxDetails {
    /// This is the tax related information that is calculated irrespective of any payment method.
    /// This is calculated when the order is created with shipping details
    pub default: Option<DefaultTax>,

    /// This is the tax related information that is calculated based on the payment method
    /// This is calculated when calling the /calculate_tax API
    pub payment_method_type: Option<PaymentMethodTypeTax>,
}

impl TaxDetails {
    /// Get the tax amount
    /// If default tax is present, return the default tax amount
    /// If default tax is not present, return the tax amount based on the payment method if it matches the provided payment method type
    pub fn get_tax_amount(&self, payment_method: Option<PaymentMethodType>) -> Option<MinorUnit> {
        self.payment_method_type
            .as_ref()
            .zip(payment_method)
            .filter(|(payment_method_type_tax, payment_method)| {
                payment_method_type_tax.pmt == *payment_method
            })
            .map(|(payment_method_type_tax, _)| payment_method_type_tax.order_tax_amount)
            .or_else(|| self.get_default_tax_amount())
    }

    /// Get the default tax amount
    pub fn get_default_tax_amount(&self) -> Option<MinorUnit> {
        self.default
            .as_ref()
            .map(|default_tax_details| default_tax_details.order_tax_amount)
    }
}

common_utils::impl_to_sql_from_sql_json!(TaxDetails);

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PaymentMethodTypeTax {
    pub order_tax_amount: MinorUnit,
    pub pmt: PaymentMethodType,
}

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct DefaultTax {
    pub order_tax_amount: MinorUnit,
}

#[cfg(feature = "v2")]
#[derive(
    Clone, Debug, PartialEq, Insertable, router_derive::DebugAsDisplay, Serialize, Deserialize,
)]
#[diesel(table_name = payment_intent)]
pub struct PaymentIntentNew {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub status: storage_enums::IntentStatus,
    pub amount: MinorUnit,
    pub currency: storage_enums::Currency,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::GlobalCustomerId>,
    pub description: Option<common_utils::types::Description>,
    pub return_url: Option<common_utils::types::Url>,
    pub metadata: Option<pii::SecretSerdeValue>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_synced: Option<PrimitiveDateTime>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub active_attempt_id: Option<common_utils::id_type::GlobalAttemptId>,
    #[diesel(deserialize_as = super::OptionalDieselArray<masking::Secret<OrderDetailsWithAmount>>)]
    pub order_details: Option<Vec<masking::Secret<OrderDetailsWithAmount>>>,
    pub allowed_payment_method_types: Option<pii::SecretSerdeValue>,
    pub connector_metadata: Option<pii::SecretSerdeValue>,
    pub feature_metadata: Option<FeatureMetadata>,
    pub attempt_count: i16,
    pub profile_id: common_utils::id_type::ProfileId,
    pub payment_link_id: Option<String>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub authorization_count: Option<i32>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub session_expiry: PrimitiveDateTime,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub shipping_cost: Option<MinorUnit>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub split_txns_enabled: Option<common_enums::SplitTxnsEnabled>,
    pub merchant_reference_id: Option<common_utils::id_type::PaymentReferenceId>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub capture_method: Option<storage_enums::CaptureMethod>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub prerouting_algorithm: Option<serde_json::Value>,
    pub surcharge_amount: Option<MinorUnit>,
    pub tax_on_surcharge: Option<MinorUnit>,
    pub frm_merchant_decision: Option<common_enums::MerchantDecision>,
    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
    pub enable_payment_link: Option<bool>,
    pub apply_mit_exemption: Option<bool>,
    pub id: common_utils::id_type::GlobalPaymentId,
    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub force_3ds_challenge: Option<bool>,
    pub force_3ds_challenge_trigger: Option<bool>,
    pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub routing_algorithm_id: Option<common_utils::id_type::RoutingId>,
    pub created_by: Option<String>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub is_payment_id_from_merchant: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
}

#[cfg(feature = "v1")]
#[derive(
    Clone, Debug, PartialEq, Insertable, router_derive::DebugAsDisplay, Serialize, Deserialize,
)]
#[diesel(table_name = payment_intent)]
pub struct PaymentIntentNew {
    pub payment_id: common_utils::id_type::PaymentId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub status: storage_enums::IntentStatus,
    pub amount: MinorUnit,
    pub currency: Option<storage_enums::Currency>,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub description: Option<String>,
    pub return_url: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub connector_id: Option<String>,
    pub shipping_address_id: Option<String>,
    pub billing_address_id: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_synced: Option<PrimitiveDateTime>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub off_session: Option<bool>,
    pub client_secret: Option<String>,
    pub active_attempt_id: String,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub allowed_payment_method_types: Option<serde_json::Value>,
    pub connector_metadata: Option<serde_json::Value>,
    pub feature_metadata: Option<serde_json::Value>,
    pub attempt_count: i16,
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    pub merchant_decision: Option<String>,
    pub payment_link_id: Option<String>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub incremental_authorization_allowed: Option<bool>,
    pub authorization_count: Option<i32>,
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub session_expiry: Option<PrimitiveDateTime>,
    pub fingerprint_id: Option<String>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub charges: Option<pii::SecretSerdeValue>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub billing_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryption>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub shipping_cost: Option<MinorUnit>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub request_extended_authorization: Option<RequestExtendedAuthorizationBool>,
    pub psd2_sca_exemption_type: Option<storage_enums::ScaExemptionType>,
    pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
    pub platform_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub force_3ds_challenge: Option<bool>,
    pub force_3ds_challenge_trigger: Option<bool>,
    pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub created_by: Option<String>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub extended_return_url: Option<String>,
    pub is_payment_id_from_merchant: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PaymentIntentUpdate {
    /// Update the payment intent details on payment intent confirmation, before calling the connector
    ConfirmIntent {
        status: storage_enums::IntentStatus,
        active_attempt_id: common_utils::id_type::GlobalAttemptId,
        updated_by: String,
    },
    /// Update the payment intent details on payment intent confirmation, after calling the connector
    ConfirmIntentPostUpdate {
        status: storage_enums::IntentStatus,
        amount_captured: Option<MinorUnit>,
        updated_by: String,
    },
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PaymentIntentUpdate {
    ResponseUpdate {
        status: storage_enums::IntentStatus,
        amount_captured: Option<MinorUnit>,
        fingerprint_id: Option<String>,
        updated_by: String,
        incremental_authorization_allowed: Option<bool>,
        feature_metadata: Option<masking::Secret<serde_json::Value>>,
    },
    MetadataUpdate {
        metadata: serde_json::Value,
        updated_by: String,
    },
    Update(Box<PaymentIntentUpdateFields>),
    PaymentCreateUpdate {
        return_url: Option<String>,
        status: Option<storage_enums::IntentStatus>,
        customer_id: Option<common_utils::id_type::CustomerId>,
        shipping_address_id: Option<String>,
        billing_address_id: Option<String>,
        customer_details: Option<Encryption>,
        updated_by: String,
    },
    MerchantStatusUpdate {
        status: storage_enums::IntentStatus,
        shipping_address_id: Option<String>,
        billing_address_id: Option<String>,
        updated_by: String,
    },
    PGStatusUpdate {
        status: storage_enums::IntentStatus,
        updated_by: String,
        incremental_authorization_allowed: Option<bool>,
        feature_metadata: Option<masking::Secret<serde_json::Value>>,
    },
    PaymentAttemptAndAttemptCountUpdate {
        active_attempt_id: String,
        attempt_count: i16,
        updated_by: String,
    },
    StatusAndAttemptUpdate {
        status: storage_enums::IntentStatus,
        active_attempt_id: String,
        attempt_count: i16,
        updated_by: String,
    },
    ApproveUpdate {
        status: storage_enums::IntentStatus,
        merchant_decision: Option<String>,
        updated_by: String,
    },
    RejectUpdate {
        status: storage_enums::IntentStatus,
        merchant_decision: Option<String>,
        updated_by: String,
    },
    SurchargeApplicableUpdate {
        surcharge_applicable: Option<bool>,
        updated_by: String,
    },
    IncrementalAuthorizationAmountUpdate {
        amount: MinorUnit,
    },
    AuthorizationCountUpdate {
        authorization_count: i32,
    },
    CompleteAuthorizeUpdate {
        shipping_address_id: Option<String>,
    },
    ManualUpdate {
        status: Option<storage_enums::IntentStatus>,
        updated_by: String,
    },
    SessionResponseUpdate {
        tax_details: TaxDetails,
        shipping_address_id: Option<String>,
        updated_by: String,
        shipping_details: Option<Encryption>,
    },
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaymentIntentUpdateFields {
    pub amount: MinorUnit,
    pub currency: storage_enums::Currency,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub status: storage_enums::IntentStatus,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub shipping_address: Option<Encryption>,
    pub billing_address: Option<Encryption>,
    pub return_url: Option<String>,
    pub description: Option<String>,
    pub statement_descriptor: Option<String>,
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub payment_channel: Option<Option<common_enums::PaymentChannel>>,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaymentIntentUpdateFields {
    pub amount: MinorUnit,
    pub currency: storage_enums::Currency,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub status: storage_enums::IntentStatus,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub shipping_address_id: Option<String>,
    pub billing_address_id: Option<String>,
    pub return_url: Option<String>,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    pub description: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub metadata: Option<serde_json::Value>,
    pub payment_confirm_source: Option<storage_enums::PaymentSource>,
    pub updated_by: String,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub fingerprint_id: Option<String>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryption>,
    pub billing_details: Option<Encryption>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryption>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub tax_details: Option<TaxDetails>,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub feature_metadata: Option<masking::Secret<serde_json::Value>>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<common_types::primitive_wrappers::EnableOvercaptureBool>,
}

// TODO: uncomment fields as necessary
#[cfg(feature = "v2")]
#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay, Serialize, Deserialize)]
#[diesel(table_name = payment_intent)]
pub struct PaymentIntentUpdateInternal {
    pub status: Option<storage_enums::IntentStatus>,
    pub prerouting_algorithm: Option<serde_json::Value>,
    pub amount_captured: Option<MinorUnit>,
    pub modified_at: PrimitiveDateTime,
    pub active_attempt_id: Option<Option<common_utils::id_type::GlobalAttemptId>>,
    pub amount: Option<MinorUnit>,
    pub currency: Option<storage_enums::Currency>,
    pub shipping_cost: Option<MinorUnit>,
    pub tax_details: Option<TaxDetails>,
    pub skip_external_tax_calculation: Option<bool>,
    pub surcharge_applicable: Option<bool>,
    pub surcharge_amount: Option<MinorUnit>,
    pub tax_on_surcharge: Option<MinorUnit>,
    pub routing_algorithm_id: Option<common_utils::id_type::RoutingId>,
    pub capture_method: Option<common_enums::CaptureMethod>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub customer_present: Option<bool>,
    pub description: Option<common_utils::types::Description>,
    pub return_url: Option<common_utils::types::Url>,
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub apply_mit_exemption: Option<bool>,
    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
    pub order_details: Option<Vec<masking::Secret<OrderDetailsWithAmount>>>,
    pub allowed_payment_method_types: Option<pii::SecretSerdeValue>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub connector_metadata: Option<pii::SecretSerdeValue>,
    pub feature_metadata: Option<FeatureMetadata>,
    pub payment_link_config: Option<PaymentLinkConfigRequestForPayments>,
    pub request_incremental_authorization: Option<RequestIncrementalAuthorization>,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub updated_by: String,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub enable_partial_authorization: Option<EnablePartialAuthorizationBool>,
}

#[cfg(feature = "v2")]
impl PaymentIntentUpdateInternal {
    pub fn apply_changeset(self, source: PaymentIntent) -> PaymentIntent {
        let Self {
            status,
            prerouting_algorithm,
            amount_captured,
            modified_at: _, // This will be ignored from self
            active_attempt_id,
            amount,
            currency,
            shipping_cost,
            tax_details,
            skip_external_tax_calculation,
            surcharge_applicable,
            surcharge_amount,
            tax_on_surcharge,
            routing_algorithm_id,
            capture_method,
            authentication_type,
            billing_address,
            shipping_address,
            customer_present,
            description,
            return_url,
            setup_future_usage,
            apply_mit_exemption,
            statement_descriptor,
            order_details,
            allowed_payment_method_types,
            metadata,
            connector_metadata,
            feature_metadata,
            payment_link_config,
            request_incremental_authorization,
            session_expiry,
            frm_metadata,
            request_external_three_ds_authentication,
            updated_by,
            force_3ds_challenge,
            is_iframe_redirection_enabled,
            enable_partial_authorization,
        } = self;

        PaymentIntent {
            status: status.unwrap_or(source.status),
            prerouting_algorithm: prerouting_algorithm.or(source.prerouting_algorithm),
            amount_captured: amount_captured.or(source.amount_captured),
            modified_at: common_utils::date_time::now(),
            active_attempt_id: match active_attempt_id {
                Some(v_option) => v_option,
                None => source.active_attempt_id,
            },
            amount: amount.unwrap_or(source.amount),
            currency: currency.unwrap_or(source.currency),
            shipping_cost: shipping_cost.or(source.shipping_cost),
            tax_details: tax_details.or(source.tax_details),
            skip_external_tax_calculation: skip_external_tax_calculation
                .or(source.skip_external_tax_calculation),
            surcharge_applicable: surcharge_applicable.or(source.surcharge_applicable),
            surcharge_amount: surcharge_amount.or(source.surcharge_amount),
            tax_on_surcharge: tax_on_surcharge.or(source.tax_on_surcharge),
            routing_algorithm_id: routing_algorithm_id.or(source.routing_algorithm_id),
            capture_method: capture_method.or(source.capture_method),
            authentication_type: authentication_type.or(source.authentication_type),
            billing_address: billing_address.or(source.billing_address),
            shipping_address: shipping_address.or(source.shipping_address),
            customer_present: customer_present.or(source.customer_present),
            description: description.or(source.description),
            return_url: return_url.or(source.return_url),
            setup_future_usage: setup_future_usage.or(source.setup_future_usage),
            apply_mit_exemption: apply_mit_exemption.or(source.apply_mit_exemption),
            statement_descriptor: statement_descriptor.or(source.statement_descriptor),
            order_details: order_details.or(source.order_details),
            allowed_payment_method_types: allowed_payment_method_types
                .or(source.allowed_payment_method_types),
            metadata: metadata.or(source.metadata),
            connector_metadata: connector_metadata.or(source.connector_metadata),
            feature_metadata: feature_metadata.or(source.feature_metadata),
            payment_link_config: payment_link_config.or(source.payment_link_config),
            request_incremental_authorization: request_incremental_authorization
                .or(source.request_incremental_authorization),
            session_expiry: session_expiry.unwrap_or(source.session_expiry),
            frm_metadata: frm_metadata.or(source.frm_metadata),
            request_external_three_ds_authentication: request_external_three_ds_authentication
                .or(source.request_external_three_ds_authentication),
            updated_by,
            force_3ds_challenge: force_3ds_challenge.or(source.force_3ds_challenge),
            is_iframe_redirection_enabled: is_iframe_redirection_enabled
                .or(source.is_iframe_redirection_enabled),
            // Fields from source
            merchant_id: source.merchant_id,
            customer_id: source.customer_id,


// Implementation: impl VerifyConnectorData
// File: crates/router/src/types/api/verify_connector.rs
// Module: router
// Methods: 2 total (0 public)

impl VerifyConnectorData


// Struct: NexinetsPaymentsMetadata
// File: crates/hyperswitch_connectors/src/connectors/nexinets/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NexinetsPaymentsMetadata


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

impl api::PaymentCapture for for Bambora


// Implementation: impl api::MandateSetup for for Gpayments
// File: crates/hyperswitch_connectors/src/connectors/gpayments.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::MandateSetup for for Gpayments