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

use std::str::FromStr;

use cards::CardNumber;
use masking::Secret;
use router::types::{self, domain, storage::enums};
use test_utils::connector_auth;

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

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

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

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

static CONNECTOR: DummyConnectorTest = DummyConnectorTest {};

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 card number.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_card_number() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_number: CardNumber::from_str("1234567891011").unwrap(),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card number is incorrect.".to_string(),
    );
}

// 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: domain::PaymentMethodData::Card(domain::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: domain::PaymentMethodData::Card(domain::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: domain::PaymentMethodData::Card(domain::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::RefundExecute for for Nexixpay
// File: crates/hyperswitch_connectors/src/connectors/nexixpay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundExecute for for Nexixpay


// Function: payouts_list_by_filter
// File: crates/router/src/routes/payouts.rs
// Module: router

pub fn payouts_list_by_filter(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<payout_types::PayoutListFilterConstraints>,
) -> HttpResponse


// Function: make_card_network_tokenization_request
// File: crates/router/src/core/payment_methods/network_tokenization.rs
// Module: router

pub fn make_card_network_tokenization_request(
    state: &routes::SessionState,
    card: &domain::CardDetail,
    optional_cvc: Option<Secret<String>>,
    customer_id: &id_type::CustomerId,
) -> CustomResult<
    (pm_types::CardNetworkTokenResponsePayload, Option<String>),
    errors::NetworkTokenizationError,
>


// Struct: PaymentMethodRecord
// File: crates/api_models/src/payment_methods.rs
// Module: api_models
// Implementations: 1

pub struct PaymentMethodRecord


// Struct: PaymentMethodTypeInfo
// File: crates/api_models/src/payouts.rs
// Module: api_models
// Implementations: 0

pub struct PaymentMethodTypeInfo


// Implementation: impl LabelInformation
// File: crates/api_models/src/routing.rs
// Module: api_models
// Methods: 2 total (2 public)

impl LabelInformation


// Struct: Database
// File: crates/storage_impl/src/config.rs
// Module: storage_impl
// Implementations: 2
// Traits: DbConnectionParams, Default

pub struct Database


// Function: update
// File: crates/diesel_models/src/query/payment_intent.rs
// Module: diesel_models

pub fn update(
        self,
        conn: &PgPooledConn,
        payment_intent_update: payment_intent::PaymentIntentUpdateInternal,
    ) -> StorageResult<Self>


// Function: create_new_authentication
// File: crates/router/src/core/unified_authentication_service.rs
// Module: router

pub fn create_new_authentication(
    state: &SessionState,
    merchant_id: common_utils::id_type::MerchantId,
    authentication_connector: Option<String>,
    profile_id: common_utils::id_type::ProfileId,
    payment_id: Option<common_utils::id_type::PaymentId>,
    merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    authentication_id: &common_utils::id_type::AuthenticationId,
    service_details: Option<payments::CtpServiceDetails>,
    authentication_status: common_enums::AuthenticationStatus,
    network_token: Option<payment_method_data::NetworkTokenData>,
    organization_id: common_utils::id_type::OrganizationId,
    force_3ds_challenge: Option<bool>,
    psd2_sca_exemption_type: Option<common_enums::ScaExemptionType>,
    acquirer_bin: Option<String>,
    acquirer_merchant_id: Option<String>,
    acquirer_country_code: Option<String>,
    amount: Option<common_utils::types::MinorUnit>,
    currency: Option<common_enums::Currency>,
    return_url: Option<String>,
    profile_acquirer_id: Option<common_utils::id_type::ProfileAcquirerId>,
) -> RouterResult<Authentication>


// Implementation: impl SchedulerInterface for for MockDb
// File: crates/scheduler/src/scheduler.rs
// Module: scheduler
// Methods: 0 total (0 public)

impl SchedulerInterface for for MockDb


// Struct: Address
// File: crates/router/src/types/domain/address.rs
// Module: router
// Implementations: 1
// Traits: behaviour::Conversion

pub struct Address


// Function: authentication_eligibility
// File: crates/router/src/routes/authentication.rs
// Module: router

pub fn authentication_eligibility(
    state: web::Data<app::AppState>,
    req: HttpRequest,
    json_payload: web::Json<AuthenticationEligibilityRequest>,
    path: web::Path<common_utils::id_type::AuthenticationId>,
) -> impl Responder


// File: crates/storage_impl/src/customers.rs
// Module: storage_impl

use common_utils::{id_type, pii};
use diesel_models::{customers, kv};
use error_stack::ResultExt;
use futures::future::try_join_all;
use hyperswitch_domain_models::{
    behaviour::{Conversion, ReverseConversion},
    customer as domain,
    merchant_key_store::MerchantKeyStore,
};
use masking::PeekInterface;
use router_env::{instrument, tracing};

#[cfg(feature = "v1")]
use crate::diesel_error_to_data_error;
use crate::{
    errors::StorageError,
    kv_router_store,
    redis::kv_store::{decide_storage_scheme, KvStorePartition, Op, PartitionKey},
    store::enums::MerchantStorageScheme,
    utils::{pg_connection_read, pg_connection_write},
    CustomResult, DatabaseStore, KeyManagerState, MockDb, RouterStore,
};

impl KvStorePartition for customers::Customer {}

#[cfg(feature = "v2")]
mod label {
    use common_utils::id_type;

    pub(super) const MODEL_NAME: &str = "customer_v2";
    pub(super) const CLUSTER_LABEL: &str = "cust";

    pub(super) fn get_global_id_label(global_customer_id: &id_type::GlobalCustomerId) -> String {
        format!(
            "customer_global_id_{}",
            global_customer_id.get_string_repr()
        )
    }

    pub(super) fn get_merchant_scoped_id_label(
        merchant_id: &id_type::MerchantId,
        merchant_reference_id: &id_type::CustomerId,
    ) -> String {
        format!(
            "customer_mid_{}_mrefid_{}",
            merchant_id.get_string_repr(),
            merchant_reference_id.get_string_repr()
        )
    }
}

#[async_trait::async_trait]
impl<T: DatabaseStore> domain::CustomerInterface for kv_router_store::KVRouterStore<T> {
    type Error = StorageError;
    #[instrument(skip_all)]
    // check customer not found in kv and fallback to db
    #[cfg(feature = "v1")]
    async fn find_customer_optional_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        let conn = pg_connection_read(self).await?;
        let maybe_result = self
            .find_optional_resource_by_id(
                state,
                key_store,
                storage_scheme,
                customers::Customer::find_optional_by_customer_id_merchant_id(
                    &conn,
                    customer_id,
                    merchant_id,
                ),
                kv_router_store::FindResourceBy::Id(
                    format!("cust_{}", customer_id.get_string_repr()),
                    PartitionKey::MerchantIdCustomerId {
                        merchant_id,
                        customer_id,
                    },
                ),
            )
            .await?;

        maybe_result.map_or(Ok(None), |customer: domain::Customer| match customer.name {
            Some(ref name) if name.peek() == pii::REDACTED => Err(StorageError::CustomerRedacted)?,
            _ => Ok(Some(customer)),
        })
    }

    #[instrument(skip_all)]
    // check customer not found in kv and fallback to db
    #[cfg(feature = "v1")]
    async fn find_customer_optional_with_redacted_customer_details_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        let conn = pg_connection_read(self).await?;
        self.find_optional_resource_by_id(
            state,
            key_store,
            storage_scheme,
            customers::Customer::find_optional_by_customer_id_merchant_id(
                &conn,
                customer_id,
                merchant_id,
            ),
            kv_router_store::FindResourceBy::Id(
                format!("cust_{}", customer_id.get_string_repr()),
                PartitionKey::MerchantIdCustomerId {
                    merchant_id,
                    customer_id,
                },
            ),
        )
        .await
    }

    #[cfg(feature = "v2")]
    async fn find_optional_by_merchant_id_merchant_reference_id(
        &self,
        state: &KeyManagerState,
        merchant_reference_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        let conn = pg_connection_read(self).await?;
        let maybe_result = self
            .find_optional_resource_by_id(
                state,
                key_store,
                storage_scheme,
                customers::Customer::find_optional_by_merchant_id_merchant_reference_id(
                    &conn,
                    merchant_reference_id,
                    merchant_id,
                ),
                kv_router_store::FindResourceBy::Id(
                    format!("cust_{}", merchant_reference_id.get_string_repr()),
                    PartitionKey::MerchantIdMerchantReferenceId {
                        merchant_id,
                        merchant_reference_id: merchant_reference_id.get_string_repr(),
                    },
                ),
            )
            .await?;

        maybe_result.map_or(Ok(None), |customer: domain::Customer| match customer.name {
            Some(ref name) if name.peek() == pii::REDACTED => Err(StorageError::CustomerRedacted)?,
            _ => Ok(Some(customer)),
        })
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn update_customer_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: id_type::CustomerId,
        merchant_id: id_type::MerchantId,
        customer: domain::Customer,
        customer_update: domain::CustomerUpdate,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_write(self).await?;
        let customer = Conversion::convert(customer)
            .await
            .change_context(StorageError::EncryptionError)?;
        let updated_customer = diesel_models::CustomerUpdateInternal::from(customer_update.clone())
            .apply_changeset(customer.clone());
        let key = PartitionKey::MerchantIdCustomerId {
            merchant_id: &merchant_id,
            customer_id: &customer_id,
        };
        let field = format!("cust_{}", customer_id.get_string_repr());
        self.update_resource(
            state,
            key_store,
            storage_scheme,
            customers::Customer::update_by_customer_id_merchant_id(
                &conn,
                customer_id.clone(),
                merchant_id.clone(),
                customer_update.clone().into(),
            ),
            updated_customer,
            kv_router_store::UpdateResourceParams {
                updateable: kv::Updateable::CustomerUpdate(kv::CustomerUpdateMems {
                    orig: customer.clone(),
                    update_data: customer_update.clone().into(),
                }),
                operation: Op::Update(key.clone(), &field, customer.updated_by.as_deref()),
            },
        )
        .await
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn find_customer_by_merchant_reference_id_merchant_id(
        &self,
        state: &KeyManagerState,
        merchant_reference_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_read(self).await?;
        let result: domain::Customer = self
            .find_resource_by_id(
                state,
                key_store,
                storage_scheme,
                customers::Customer::find_by_merchant_reference_id_merchant_id(
                    &conn,
                    merchant_reference_id,
                    merchant_id,
                ),
                kv_router_store::FindResourceBy::Id(
                    format!("cust_{}", merchant_reference_id.get_string_repr()),
                    PartitionKey::MerchantIdMerchantReferenceId {
                        merchant_id,
                        merchant_reference_id: merchant_reference_id.get_string_repr(),
                    },
                ),
            )
            .await?;

        match result.name {
            Some(ref name) if name.peek() == pii::REDACTED => Err(StorageError::CustomerRedacted)?,
            _ => Ok(result),
        }
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn find_customer_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_read(self).await?;
        let result: domain::Customer = self
            .find_resource_by_id(
                state,
                key_store,
                storage_scheme,
                customers::Customer::find_by_customer_id_merchant_id(
                    &conn,
                    customer_id,
                    merchant_id,
                ),
                kv_router_store::FindResourceBy::Id(
                    format!("cust_{}", customer_id.get_string_repr()),
                    PartitionKey::MerchantIdCustomerId {
                        merchant_id,
                        customer_id,
                    },
                ),
            )
            .await?;

        match result.name {
            Some(ref name) if name.peek() == pii::REDACTED => Err(StorageError::CustomerRedacted)?,
            _ => Ok(result),
        }
    }

    #[instrument(skip_all)]
    async fn list_customers_by_merchant_id(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        constraints: domain::CustomerListConstraints,
    ) -> CustomResult<Vec<domain::Customer>, StorageError> {
        self.router_store
            .list_customers_by_merchant_id(state, merchant_id, key_store, constraints)
            .await
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn insert_customer(
        &self,
        customer_data: domain::Customer,
        state: &KeyManagerState,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_write(self).await?;
        let id = customer_data.id.clone();
        let key = PartitionKey::GlobalId {
            id: id.get_string_repr(),
        };
        let identifier = format!("cust_{}", id.get_string_repr());
        let mut new_customer = customer_data
            .construct_new()
            .await
            .change_context(StorageError::EncryptionError)?;

        let decided_storage_scheme = Box::pin(decide_storage_scheme::<_, customers::Customer>(
            self,
            storage_scheme,
            Op::Insert,
        ))
        .await;
        new_customer.update_storage_scheme(decided_storage_scheme);

        let mut reverse_lookups = Vec::new();

        if let Some(ref merchant_ref_id) = new_customer.merchant_reference_id {
            let reverse_lookup_merchant_scoped_id =
                label::get_merchant_scoped_id_label(&new_customer.merchant_id, merchant_ref_id);
            reverse_lookups.push(reverse_lookup_merchant_scoped_id);
        }

        self.insert_resource(
            state,
            key_store,
            decided_storage_scheme,
            new_customer.clone().insert(&conn),
            new_customer.clone().into(),
            kv_router_store::InsertResourceParams {
                insertable: kv::Insertable::Customer(new_customer.clone()),
                reverse_lookups,
                identifier,
                key,
                resource_type: "customer",
            },
        )
        .await
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn insert_customer(
        &self,
        customer_data: domain::Customer,
        state: &KeyManagerState,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_write(self).await?;
        let key = PartitionKey::MerchantIdCustomerId {
            merchant_id: &customer_data.merchant_id.clone(),
            customer_id: &customer_data.customer_id.clone(),
        };
        let identifier = format!("cust_{}", customer_data.customer_id.get_string_repr());
        let mut new_customer = customer_data
            .construct_new()
            .await
            .change_context(StorageError::EncryptionError)?;
        let storage_scheme = Box::pin(decide_storage_scheme::<_, customers::Customer>(
            self,
            storage_scheme,
            Op::Insert,
        ))
        .await;
        new_customer.update_storage_scheme(storage_scheme);
        let customer = new_customer.clone().into();
        self.insert_resource(
            state,
            key_store,
            storage_scheme,
            new_customer.clone().insert(&conn),
            customer,
            kv_router_store::InsertResourceParams {
                insertable: kv::Insertable::Customer(new_customer.clone()),
                reverse_lookups: vec![],
                identifier,
                key,
                resource_type: "customer",
            },
        )
        .await
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn delete_customer_by_customer_id_merchant_id(
        &self,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
    ) -> CustomResult<bool, StorageError> {
        self.router_store
            .delete_customer_by_customer_id_merchant_id(customer_id, merchant_id)
            .await
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn find_customer_by_global_id(
        &self,
        state: &KeyManagerState,
        id: &id_type::GlobalCustomerId,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_read(self).await?;
        let result: domain::Customer = self
            .find_resource_by_id(
                state,
                key_store,
                storage_scheme,
                customers::Customer::find_by_global_id(&conn, id),
                kv_router_store::FindResourceBy::Id(
                    format!("cust_{}", id.get_string_repr()),
                    PartitionKey::GlobalId {
                        id: id.get_string_repr(),
                    },
                ),
            )
            .await?;

        if result.status == common_enums::DeleteStatus::Redacted {
            Err(StorageError::CustomerRedacted)?
        } else {
            Ok(result)
        }
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn update_customer_by_global_id(
        &self,
        state: &KeyManagerState,
        id: &id_type::GlobalCustomerId,
        customer: domain::Customer,
        customer_update: domain::CustomerUpdate,
        key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_write(self).await?;
        let customer = Conversion::convert(customer)
            .await
            .change_context(StorageError::EncryptionError)?;
        let database_call =
            customers::Customer::update_by_id(&conn, id.clone(), customer_update.clone().into());
        let key = PartitionKey::GlobalId {
            id: id.get_string_repr(),
        };
        let field = format!("cust_{}", id.get_string_repr());
        self.update_resource(
            state,
            key_store,
            storage_scheme,
            database_call,
            diesel_models::CustomerUpdateInternal::from(customer_update.clone())
                .apply_changeset(customer.clone()),
            kv_router_store::UpdateResourceParams {
                updateable: kv::Updateable::CustomerUpdate(kv::CustomerUpdateMems {
                    orig: customer.clone(),
                    update_data: customer_update.into(),
                }),
                operation: Op::Update(key.clone(), &field, customer.updated_by.as_deref()),
            },
        )
        .await
    }
}

#[async_trait::async_trait]
impl<T: DatabaseStore> domain::CustomerInterface for RouterStore<T> {
    type Error = StorageError;
    #[instrument(skip_all)]
    #[cfg(feature = "v1")]
    async fn find_customer_optional_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        let conn = pg_connection_read(self).await?;
        let maybe_customer: Option<domain::Customer> = self
            .find_optional_resource(
                state,
                key_store,
                customers::Customer::find_optional_by_customer_id_merchant_id(
                    &conn,
                    customer_id,
                    merchant_id,
                ),
            )
            .await?;
        maybe_customer.map_or(Ok(None), |customer| {
            // in the future, once #![feature(is_some_and)] is stable, we can make this more concise:
            // `if customer.name.is_some_and(|ref name| name == pii::REDACTED) ...`
            match customer.name {
                Some(ref name) if name.peek() == pii::REDACTED => {
                    Err(StorageError::CustomerRedacted)?
                }
                _ => Ok(Some(customer)),
            }
        })
    }

    #[instrument(skip_all)]
    #[cfg(feature = "v1")]
    async fn find_customer_optional_with_redacted_customer_details_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        let conn = pg_connection_read(self).await?;
        self.find_optional_resource(
            state,
            key_store,
            customers::Customer::find_optional_by_customer_id_merchant_id(
                &conn,
                customer_id,
                merchant_id,
            ),
        )
        .await
    }

    #[instrument(skip_all)]
    #[cfg(feature = "v2")]
    async fn find_optional_by_merchant_id_merchant_reference_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        let conn = pg_connection_read(self).await?;
        let maybe_customer: Option<domain::Customer> = self
            .find_optional_resource(
                state,
                key_store,
                customers::Customer::find_optional_by_merchant_id_merchant_reference_id(
                    &conn,
                    customer_id,
                    merchant_id,
                ),
            )
            .await?;
        maybe_customer.map_or(Ok(None), |customer| {
            // in the future, once #![feature(is_some_and)] is stable, we can make this more concise:
            // `if customer.name.is_some_and(|ref name| name == pii::REDACTED) ...`
            match customer.name {
                Some(ref name) if name.peek() == pii::REDACTED => {
                    Err(StorageError::CustomerRedacted)?
                }
                _ => Ok(Some(customer)),
            }
        })
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn update_customer_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: id_type::CustomerId,
        merchant_id: id_type::MerchantId,
        _customer: domain::Customer,
        customer_update: domain::CustomerUpdate,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_write(self).await?;
        self.call_database(
            state,
            key_store,
            customers::Customer::update_by_customer_id_merchant_id(
                &conn,
                customer_id,
                merchant_id.clone(),
                customer_update.into(),
            ),
        )
        .await
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn find_customer_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_read(self).await?;
        let customer: domain::Customer = self
            .call_database(
                state,
                key_store,
                customers::Customer::find_by_customer_id_merchant_id(
                    &conn,
                    customer_id,
                    merchant_id,
                ),
            )
            .await?;
        match customer.name {
            Some(ref name) if name.peek() == pii::REDACTED => Err(StorageError::CustomerRedacted)?,
            _ => Ok(customer),
        }
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn find_customer_by_merchant_reference_id_merchant_id(
        &self,
        state: &KeyManagerState,
        merchant_reference_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_read(self).await?;
        let customer: domain::Customer = self
            .call_database(
                state,
                key_store,
                customers::Customer::find_by_merchant_reference_id_merchant_id(
                    &conn,
                    merchant_reference_id,
                    merchant_id,
                ),
            )
            .await?;
        match customer.name {
            Some(ref name) if name.peek() == pii::REDACTED => Err(StorageError::CustomerRedacted)?,
            _ => Ok(customer),
        }
    }

    #[instrument(skip_all)]
    async fn list_customers_by_merchant_id(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        constraints: domain::CustomerListConstraints,
    ) -> CustomResult<Vec<domain::Customer>, StorageError> {
        let conn = pg_connection_read(self).await?;
        let customer_list_constraints =
            diesel_models::query::customers::CustomerListConstraints::from(constraints);
        self.find_resources(
            state,
            key_store,
            customers::Customer::list_by_merchant_id(&conn, merchant_id, customer_list_constraints),
        )
        .await
    }

    #[instrument(skip_all)]
    async fn insert_customer(
        &self,
        customer_data: domain::Customer,
        state: &KeyManagerState,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_write(self).await?;
        let customer_new = customer_data
            .construct_new()
            .await
            .change_context(StorageError::EncryptionError)?;
        self.call_database(state, key_store, customer_new.insert(&conn))
            .await
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn delete_customer_by_customer_id_merchant_id(
        &self,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
    ) -> CustomResult<bool, StorageError> {
        let conn = pg_connection_write(self).await?;
        customers::Customer::delete_by_customer_id_merchant_id(&conn, customer_id, merchant_id)
            .await
            .map_err(|error| {
                let new_err = diesel_error_to_data_error(*error.current_context());
                error.change_context(new_err)
            })
    }

    #[cfg(feature = "v2")]
    #[allow(clippy::too_many_arguments)]
    async fn update_customer_by_global_id(
        &self,
        state: &KeyManagerState,
        id: &id_type::GlobalCustomerId,
        _customer: domain::Customer,
        customer_update: domain::CustomerUpdate,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_write(self).await?;
        self.call_database(
            state,
            key_store,
            customers::Customer::update_by_id(&conn, id.clone(), customer_update.into()),
        )
        .await
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn find_customer_by_global_id(
        &self,
        state: &KeyManagerState,
        id: &id_type::GlobalCustomerId,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let conn = pg_connection_read(self).await?;
        let customer: domain::Customer = self
            .call_database(
                state,
                key_store,
                customers::Customer::find_by_global_id(&conn, id),
            )
            .await?;
        match customer.name {
            Some(ref name) if name.peek() == pii::REDACTED => Err(StorageError::CustomerRedacted)?,
            _ => Ok(customer),
        }
    }
}

#[async_trait::async_trait]
impl domain::CustomerInterface for MockDb {
    type Error = StorageError;
    #[cfg(feature = "v1")]
    async fn find_customer_optional_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        let customers = self.customers.lock().await;
        self.find_resource(state, key_store, customers, |customer| {
            customer.customer_id == *customer_id && &customer.merchant_id == merchant_id
        })
        .await
    }

    #[cfg(feature = "v1")]
    async fn find_customer_optional_with_redacted_customer_details_by_customer_id_merchant_id(
        &self,
        state: &KeyManagerState,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        let customers = self.customers.lock().await;
        self.find_resource(state, key_store, customers, |customer| {
            customer.customer_id == *customer_id && &customer.merchant_id == merchant_id
        })
        .await
    }

    #[cfg(feature = "v2")]
    async fn find_optional_by_merchant_id_merchant_reference_id(
        &self,
        _state: &KeyManagerState,
        _customer_id: &id_type::CustomerId,
        _merchant_id: &id_type::MerchantId,
        _key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Option<domain::Customer>, StorageError> {
        todo!()
    }

    async fn list_customers_by_merchant_id(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        key_store: &MerchantKeyStore,
        constraints: domain::CustomerListConstraints,
    ) -> CustomResult<Vec<domain::Customer>, StorageError> {
        let customers = self.customers.lock().await;

        let customers = try_join_all(
            customers
                .iter()
                .filter(|customer| customer.merchant_id == *merchant_id)
                .take(usize::from(constraints.limit))
                .skip(usize::try_from(constraints.offset.unwrap_or(0)).unwrap_or(0))
                .map(|customer| async {
                    customer
                        .to_owned()
                        .convert(
                            state,
                            key_store.key.get_inner(),
                            key_store.merchant_id.clone().into(),
                        )
                        .await
                        .change_context(StorageError::DecryptionError)
                }),
        )
        .await?;

        Ok(customers)
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn update_customer_by_customer_id_merchant_id(
        &self,
        _state: &KeyManagerState,
        _customer_id: id_type::CustomerId,
        _merchant_id: id_type::MerchantId,
        _customer: domain::Customer,
        _customer_update: domain::CustomerUpdate,
        _key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn find_customer_by_customer_id_merchant_id(
        &self,
        _state: &KeyManagerState,
        _customer_id: &id_type::CustomerId,
        _merchant_id: &id_type::MerchantId,
        _key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v2")]
    async fn find_customer_by_merchant_reference_id_merchant_id(
        &self,
        _state: &KeyManagerState,
        _merchant_reference_id: &id_type::CustomerId,
        _merchant_id: &id_type::MerchantId,
        _key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(StorageError::MockDbError)?
    }

    #[allow(clippy::panic)]
    async fn insert_customer(
        &self,
        customer_data: domain::Customer,
        state: &KeyManagerState,
        key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        let mut customers = self.customers.lock().await;

        let customer = Conversion::convert(customer_data)
            .await
            .change_context(StorageError::EncryptionError)?;

        customers.push(customer.clone());

        customer
            .convert(
                state,
                key_store.key.get_inner(),
                key_store.merchant_id.clone().into(),
            )
            .await
            .change_context(StorageError::DecryptionError)
    }

    #[cfg(feature = "v1")]
    async fn delete_customer_by_customer_id_merchant_id(
        &self,
        _customer_id: &id_type::CustomerId,
        _merchant_id: &id_type::MerchantId,
    ) -> CustomResult<bool, StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v2")]
    #[allow(clippy::too_many_arguments)]
    async fn update_customer_by_global_id(
        &self,
        _state: &KeyManagerState,
        _id: &id_type::GlobalCustomerId,
        _customer: domain::Customer,
        _customer_update: domain::CustomerUpdate,
        _key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v2")]
    async fn find_customer_by_global_id(
        &self,
        _state: &KeyManagerState,
        _id: &id_type::GlobalCustomerId,
        _key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::Customer, StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(StorageError::MockDbError)?
    }
}


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

impl api::PaymentVoid for for Gigadat


// Function: payments_core
// File: crates/router/src/core/payments.rs
// Module: router

pub fn payments_core<F, Res, Req, Op, FData, D>(
    state: SessionState,
    req_state: ReqState,
    merchant_context: domain::MerchantContext,
    profile_id: Option<id_type::ProfileId>,
    operation: Op,
    req: Req,
    auth_flow: services::AuthFlow,
    call_connector_action: CallConnectorAction,
    eligible_connectors: Option<Vec<enums::Connector>>,
    header_payload: HeaderPayload,
) -> RouterResponse<Res>
where
    F: Send + Clone + Sync,
    FData: Send + Sync + Clone + router_types::Capturable,
    Op: Operation<F, Req, Data = D> + Send + Sync + Clone,
    Req: Debug + Authenticate + Clone,
    D: OperationSessionGetters<F> + OperationSessionSetters<F> + Send + Sync + Clone,
    Res: transformers::ToResponse<F, D, Op>,
    // To create connector flow specific interface data
    D: ConstructFlowSpecificData<F, FData, router_types::PaymentsResponseData>,
    RouterData<F, FData, router_types::PaymentsResponseData>: Feature<F, FData>,

    // To construct connector flow specific api
    dyn api::Connector:
        services::api::ConnectorIntegration<F, FData, router_types::PaymentsResponseData>,

    // To perform router related operation for PaymentResponse
    PaymentResponse: Operation<F, FData, Data = D>,


// Implementation: impl ToTokens for for TryGetEnumMeta
// File: crates/router_derive/src/macros/try_get_enum.rs
// Module: router_derive
// Methods: 1 total (0 public)

impl ToTokens for for TryGetEnumMeta


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

pub struct PreAuthenticationData


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

pub fn get_req_state(&self) -> ReqState


                    connector_transaction_id: None, // Transaction id not created at connector
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                }),
                ..item.data
            })},
            (_, _) => {  Err(errors::ConnectorError::UnexpectedResponseError(
                bytes::Bytes::from("Only one of 'sale_response' or 'authorisation_response' is expected, but both were received".to_string()),
             ))?
            },
    }
    }
}

impl<F>
    TryFrom<ResponseRouterData<F, CnpOnlineResponse, SetupMandateRequestData, PaymentsResponseData>>
    for RouterData<F, SetupMandateRequestData, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<
            F,
            CnpOnlineResponse,
            SetupMandateRequestData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        match item.response.authorization_response.as_ref() {
            Some(auth_response) => {
                let status =
                    get_attempt_status(WorldpayvantivPaymentFlow::Sale, auth_response.response)?;
                if connector_utils::is_payment_failure(status) {
                    let network_decline_code = item
                        .response
                        .authorization_response
                        .as_ref()
                        .and_then(|pr| pr.enhanced_auth_response.as_ref())
                        .and_then(|ea| ea.network_response.as_ref())
                        .and_then(|nr| {
                            nr.network_fields
                                .iter()
                                .find(|f| {
                                    f.field_number == *worldpayvantiv_constants::MAC_FIELD_NUMBER
                                })
                                .and_then(|f| f.field_value.clone())
                        });

                    let network_error_message = network_decline_code
                        .as_ref()
                        .map(|_| auth_response.message.clone());
                    Ok(Self {
                        status,
                        response: Err(ErrorResponse {
                            code: auth_response.response.to_string(),
                            message: auth_response.message.clone(),
                            reason: Some(auth_response.message.clone()),
                            status_code: item.http_code,
                            attempt_status: None,
                            connector_transaction_id: Some(auth_response.order_id.clone()),
                            network_advice_code: None,
                            network_decline_code,
                            network_error_message,
                            connector_metadata: None,
                        }),
                        ..item.data
                    })
                } else {
                    let report_group = WorldpayvantivPaymentMetadata {
                        report_group: Some(auth_response.report_group.clone()),
                    };
                    let connector_metadata = Some(
                        report_group
                            .encode_to_value()
                            .change_context(errors::ConnectorError::ResponseHandlingFailed)?,
                    );
                    let mandate_reference_data = auth_response
                        .token_response
                        .clone()
                        .map(MandateReference::from);
                    let connector_response = auth_response
                        .fraud_result
                        .as_ref()
                        .map(get_connector_response);

                    Ok(Self {
                        status,
                        response: Ok(PaymentsResponseData::TransactionResponse {
                            resource_id: ResponseId::ConnectorTransactionId(
                                auth_response.cnp_txn_id.clone(),
                            ),
                            redirection_data: Box::new(None),
                            mandate_reference: Box::new(mandate_reference_data),
                            connector_metadata,
                            network_txn_id: auth_response
                                .network_transaction_id
                                .clone()
                                .map(|network_transaction_id| network_transaction_id.expose()),
                            connector_response_reference_id: Some(auth_response.order_id.clone()),
                            incremental_authorization_allowed: None,
                            charges: None,
                        }),
                        connector_response,
                        ..item.data
                    })
                }
            }
            None => Ok(Self {
                status: common_enums::AttemptStatus::Failure,
                response: Err(ErrorResponse {
                    code: item.response.response_code.clone(),
                    message: item.response.message.clone(),
                    reason: Some(item.response.message.clone()),
                    status_code: item.http_code,
                    attempt_status: None,
                    connector_transaction_id: None,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                }),
                ..item.data
            }),
        }
    }
}

impl From<TokenResponse> for MandateReference {
    fn from(token_data: TokenResponse) -> Self {
        Self {
            connector_mandate_id: Some(token_data.cnp_token.expose()),
            payment_method_id: None,
            mandate_metadata: None,
            connector_mandate_request_reference_id: None,
        }
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, VantivSyncResponse>> for RefundsRouterData<RSync> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<RSync, VantivSyncResponse>,
    ) -> Result<Self, Self::Error> {
        let refund_status = get_refund_status_for_rsync(item.response.payment_status)?;
        if connector_utils::is_refund_failure(refund_status) {
            let error_code = item
                .response
                .payment_detail
                .as_ref()
                .and_then(|detail| detail.response_reason_code.clone())
                .unwrap_or(consts::NO_ERROR_CODE.to_string());
            let error_message = item
                .response
                .payment_detail
                .as_ref()
                .and_then(|detail| detail.response_reason_message.clone())
                .unwrap_or(consts::NO_ERROR_MESSAGE.to_string());
            let connector_transaction_id = item
                .response
                .payment_detail
                .as_ref()
                .and_then(|detail| detail.payment_id.map(|id| id.to_string()));

            Ok(Self {
                response: Err(ErrorResponse {
                    code: error_code.clone(),
                    message: error_message.clone(),
                    reason: Some(error_message.clone()),
                    status_code: item.http_code,
                    attempt_status: None,
                    connector_transaction_id,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                }),
                ..item.data
            })
        } else {
            Ok(Self {
                response: Ok(RefundsResponseData {
                    connector_refund_id: item.response.payment_id.to_string(),
                    refund_status,
                }),
                ..item.data
            })
        }
    }
}

fn determine_attempt_status<F>(
    item: &ResponseRouterData<F, VantivSyncResponse, PaymentsSyncData, PaymentsResponseData>,
) -> Result<common_enums::AttemptStatus, errors::ConnectorError> {
    if let Some(merchant_txn_id) = item
        .response
        .payment_detail
        .as_ref()
        .and_then(|payment_detail| payment_detail.merchant_txn_id.clone())
    {
        let flow_type = get_payment_flow_type(&merchant_txn_id)?;
        match item.response.payment_status {
            PaymentStatus::ProcessedSuccessfully => match flow_type {
                WorldpayvantivPaymentFlow::Sale | WorldpayvantivPaymentFlow::Capture => {
                    Ok(common_enums::AttemptStatus::Charged)
                }
                WorldpayvantivPaymentFlow::Auth => Ok(common_enums::AttemptStatus::Authorized),
                WorldpayvantivPaymentFlow::Void => Ok(common_enums::AttemptStatus::Voided),
                WorldpayvantivPaymentFlow::VoidPC => {
                    Ok(common_enums::AttemptStatus::VoidedPostCharge)
                }
            },
            PaymentStatus::TransactionDeclined => match flow_type {
                WorldpayvantivPaymentFlow::Sale | WorldpayvantivPaymentFlow::Capture => {
                    Ok(common_enums::AttemptStatus::Failure)
                }
                WorldpayvantivPaymentFlow::Auth => {
                    Ok(common_enums::AttemptStatus::AuthorizationFailed)
                }
                WorldpayvantivPaymentFlow::Void => Ok(common_enums::AttemptStatus::VoidFailed),
                WorldpayvantivPaymentFlow::VoidPC => Ok(common_enums::AttemptStatus::VoidFailed),
            },
            PaymentStatus::PaymentStatusNotFound
            | PaymentStatus::NotYetProcessed
            | PaymentStatus::StatusUnavailable => Ok(item.data.status),
        }
    } else {
        Ok(item.data.status)
    }
}

fn get_refund_status_for_rsync(
    vantiv_status: PaymentStatus,
) -> Result<common_enums::RefundStatus, errors::ConnectorError> {
    match vantiv_status {
        PaymentStatus::ProcessedSuccessfully => Ok(common_enums::RefundStatus::Success),
        PaymentStatus::TransactionDeclined => Ok(common_enums::RefundStatus::Failure),
        PaymentStatus::NotYetProcessed
        | PaymentStatus::StatusUnavailable
        | PaymentStatus::PaymentStatusNotFound => Ok(common_enums::RefundStatus::Pending),
    }
}

#[derive(Debug, strum::Display, Serialize, Deserialize, PartialEq, Clone, Copy)]
pub enum WorldpayvantivResponseCode {
    #[serde(rename = "001")]
    #[strum(serialize = "001")]
    TransactionReceived,
    #[serde(rename = "000")]
    #[strum(serialize = "000")]
    Approved,
    #[serde(rename = "010")]
    #[strum(serialize = "010")]
    PartiallyApproved,
    #[serde(rename = "011")]
    #[strum(serialize = "011")]
    OfflineApproval,
    #[serde(rename = "013")]
    #[strum(serialize = "013")]
    OfflineApprovalUnableToGoOnline,
    #[serde(rename = "015")]
    #[strum(serialize = "015")]
    PendingShopperCheckoutCompletion,
    #[serde(rename = "016")]
    #[strum(serialize = "016")]
    ShopperCheckoutExpired,
    #[serde(rename = "100")]
    #[strum(serialize = "100")]
    ProcessingNetworkUnavailable,
    #[serde(rename = "101")]
    #[strum(serialize = "101")]
    IssuerUnavailable,
    #[serde(rename = "102")]
    #[strum(serialize = "102")]
    ReSubmitTransaction,
    #[serde(rename = "103")]
    #[strum(serialize = "103")]
    MerchantNotConfiguredForProcessingAtThisSite,
    #[serde(rename = "108")]
    #[strum(serialize = "108")]
    TryAgainLater,
    #[serde(rename = "110")]
    #[strum(serialize = "110")]
    InsufficientFunds,
    #[serde(rename = "111")]
    #[strum(serialize = "111")]
    AuthorizationAmountHasAlreadyBeenDepleted,
    #[serde(rename = "112")]
    #[strum(serialize = "112")]
    InsufficientFundsRetryAfter1Hour,
    #[serde(rename = "113")]
    #[strum(serialize = "113")]
    InsufficientFundsRetryAfter24Hour,
    #[serde(rename = "114")]
    #[strum(serialize = "114")]
    InsufficientFundsRetryAfter2Days,
    #[serde(rename = "115")]
    #[strum(serialize = "115")]
    InsufficientFundsRetryAfter4Days,
    #[serde(rename = "116")]
    #[strum(serialize = "116")]
    InsufficientFundsRetryAfter6Days,
    #[serde(rename = "117")]
    #[strum(serialize = "117")]
    InsufficientFundsRetryAfter8Days,
    #[serde(rename = "118")]
    #[strum(serialize = "118")]
    InsufficientFundsRetryAfter10Days,
    #[serde(rename = "120")]
    #[strum(serialize = "120")]
    CallIssuer,
    #[serde(rename = "121")]
    #[strum(serialize = "121")]
    CallAmex,
    #[serde(rename = "122")]
    #[strum(serialize = "122")]
    CallDinersClub,
    #[serde(rename = "123")]
    #[strum(serialize = "123")]
    CallDiscover,
    #[serde(rename = "124")]
    #[strum(serialize = "124")]
    CallJbs,
    #[serde(rename = "125")]
    #[strum(serialize = "125")]
    CallVisaMastercard,
    #[serde(rename = "126")]
    #[strum(serialize = "126")]
    CallIssuerUpdateCardholderData,
    #[serde(rename = "127")]
    #[strum(serialize = "127")]
    ExceedsApprovalAmountLimit,
    #[serde(rename = "130")]
    #[strum(serialize = "130")]
    CallIndicatedNumber,
    #[serde(rename = "131")]
    #[strum(serialize = "131")]
    UnacceptablePinTransactionDeclinedRetry,
    #[serde(rename = "132")]
    #[strum(serialize = "132")]
    PinNotChanged,
    #[serde(rename = "137")]
    #[strum(serialize = "137")]
    ConsumerMultiUseVirtualCardNumberSoftDecline,
    #[serde(rename = "138")]
    #[strum(serialize = "138")]
    ConsumerNonReloadablePrepaidCardSoftDecline,
    #[serde(rename = "139")]
    #[strum(serialize = "139")]
    ConsumerSingleUseVirtualCardNumberSoftDecline,
    #[serde(rename = "140")]
    #[strum(serialize = "140")]
    UpdateCardholderData,
    #[serde(rename = "141")]
    #[strum(serialize = "141")]
    ConsumerNonReloadablePrepaidCardApproved,
    #[serde(rename = "142")]
    #[strum(serialize = "142")]
    ConsumerSingleUseVirtualCardNumberApproved,
    #[serde(rename = "143")]
    #[strum(serialize = "143")]
    MerchantDoesntQualifyForProductCode,
    #[serde(rename = "145")]
    #[strum(serialize = "145")]
    Lifecycle,
    #[serde(rename = "146")]
    #[strum(serialize = "146")]
    Policy,
    #[serde(rename = "147")]
    #[strum(serialize = "147")]
    FraudSecurity,
    #[serde(rename = "148")]
    #[strum(serialize = "148")]
    InvalidOrExpiredCardContactCardholderToUpdate,
    #[serde(rename = "149")]
    #[strum(serialize = "149")]
    InvalidTransactionOrCardRestrictionVerifyInformationAndResubmit,
    #[serde(rename = "154")]
    #[strum(serialize = "154")]
    AtLeastOneOfOrigIdOrOrigCnpTxnIdIsRequired,
    #[serde(rename = "155")]
    #[strum(serialize = "155")]
    OrigCnpTxnIdIsRequiredWhenShowStatusOnlyIsUsed,
    #[serde(rename = "156")]
    #[strum(serialize = "156")]
    IncrementalAuthNotSupported,
    #[serde(rename = "157")]
    #[strum(serialize = "157")]
    SetAuthIndicatorToIncremental,
    #[serde(rename = "158")]
    #[strum(serialize = "158")]
    IncrementalValueForAuthIndicatorNotAllowedInThisAuthStructure,
    #[serde(rename = "159")]
    #[strum(serialize = "159")]
    CannotRequestAnIncrementalAuthIfOriginalAuthNotSetToEstimated,
    #[serde(rename = "161")]
    #[strum(serialize = "161")]
    TransactionMustReferenceTheEstimatedAuth,
    #[serde(rename = "162")]
    #[strum(serialize = "162")]
    IncrementedAuthExceedsMaxTransactionAmount,
    #[serde(rename = "170")]
    #[strum(serialize = "170")]
    SubmittedMccNotAllowed,
    #[serde(rename = "192")]
    #[strum(serialize = "192")]
    MerchantNotCertifiedEnabledForIias,
    #[serde(rename = "206")]
    #[strum(serialize = "206")]
    IssuerGeneratedError,
    #[serde(rename = "207")]
    #[strum(serialize = "207")]
    PickupCardOtherThanLostStolen,
    #[serde(rename = "209")]
    #[strum(serialize = "209")]
    InvalidAmountHardDecline,
    #[serde(rename = "211")]
    #[strum(serialize = "211")]
    ReversalUnsuccessful,
    #[serde(rename = "212")]
    #[strum(serialize = "212")]
    MissingData,
    #[serde(rename = "213")]
    #[strum(serialize = "213")]
    PickupCardLostCard,
    #[serde(rename = "214")]
    #[strum(serialize = "214")]
    PickupCardStolenCard,
    #[serde(rename = "215")]
    #[strum(serialize = "215")]
    RestrictedCard,
    #[serde(rename = "216")]
    #[strum(serialize = "216")]
    InvalidDeactivate,
    #[serde(rename = "217")]
    #[strum(serialize = "217")]
    CardAlreadyActive,
    #[serde(rename = "218")]
    #[strum(serialize = "218")]
    CardNotActive,
    #[serde(rename = "219")]
    #[strum(serialize = "219")]
    CardAlreadyDeactivate,
    #[serde(rename = "221")]
    #[strum(serialize = "221")]
    OverMaxBalance,
    #[serde(rename = "222")]
    #[strum(serialize = "222")]
    InvalidActivate,
    #[serde(rename = "223")]
    #[strum(serialize = "223")]
    NoTransactionFoundForReversal,
    #[serde(rename = "226")]
    #[strum(serialize = "226")]
    IncorrectCvv,
    #[serde(rename = "229")]
    #[strum(serialize = "229")]
    IllegalTransaction,
    #[serde(rename = "251")]
    #[strum(serialize = "251")]
    DuplicateTransaction,
    #[serde(rename = "252")]
    #[strum(serialize = "252")]
    SystemError,
    #[serde(rename = "253")]
    #[strum(serialize = "253")]
    DeconvertedBin,
    #[serde(rename = "254")]
    #[strum(serialize = "254")]
    MerchantDepleted,
    #[serde(rename = "255")]
    #[strum(serialize = "255")]
    GiftCardEscheated,
    #[serde(rename = "256")]
    #[strum(serialize = "256")]
    InvalidReversalTypeForCreditCardTransaction,
    #[serde(rename = "257")]
    #[strum(serialize = "257")]
    SystemErrorMessageFormatError,
    #[serde(rename = "258")]
    #[strum(serialize = "258")]
    SystemErrorCannotProcess,
    #[serde(rename = "271")]
    #[strum(serialize = "271")]
    RefundRejectedDueToPendingDepositStatus,
    #[serde(rename = "272")]
    #[strum(serialize = "272")]
    RefundRejectedDueToDeclinedDepositStatus,
    #[serde(rename = "273")]
    #[strum(serialize = "273")]
    RefundRejectedByTheProcessingNetwork,
    #[serde(rename = "284")]
    #[strum(serialize = "284")]
    CaptureCreditAndAuthReversalTagsCannotBeUsedForGiftCardTransactions,
    #[serde(rename = "301")]
    #[strum(serialize = "301")]
    InvalidAccountNumber,
    #[serde(rename = "302")]
    #[strum(serialize = "302")]
    AccountNumberDoesNotMatchPaymentType,
    #[serde(rename = "303")]
    #[strum(serialize = "303")]
    PickUpCard,
    #[serde(rename = "304")]
    #[strum(serialize = "304")]
    LostStolenCard,
    #[serde(rename = "305")]
    #[strum(serialize = "305")]
    ExpiredCard,
    #[serde(rename = "306")]
    #[strum(serialize = "306")]
    AuthorizationHasExpiredNoNeedToReverse,
    #[serde(rename = "307")]
    #[strum(serialize = "307")]
    RestrictedCardSoftDecline,
    #[serde(rename = "308")]
    #[strum(serialize = "308")]
    RestrictedCardChargeback,
    #[serde(rename = "309")]
    #[strum(serialize = "309")]
    RestrictedCardPrepaidCardFilteringService,
    #[serde(rename = "310")]
    #[strum(serialize = "310")]
    InvalidTrackData,
    #[serde(rename = "311")]
    #[strum(serialize = "311")]
    DepositIsAlreadyReferencedByAChargeback,
    #[serde(rename = "312")]
    #[strum(serialize = "312")]
    RestrictedCardInternationalCardFilteringService,
    #[serde(rename = "313")]
    #[strum(serialize = "313")]
    InternationalFilteringForIssuingCardCountry,
    #[serde(rename = "315")]
    #[strum(serialize = "315")]
    RestrictedCardAuthFraudVelocityFilteringService,
    #[serde(rename = "316")]
    #[strum(serialize = "316")]
    AutomaticRefundAlreadyIssued,
    #[serde(rename = "317")]
    #[strum(serialize = "317")]
    RestrictedCardCardUnderSanction,
    #[serde(rename = "318")]
    #[strum(serialize = "318")]
    RestrictedCardAuthFraudAdviceFilteringService,
    #[serde(rename = "319")]
    #[strum(serialize = "319")]
    RestrictedCardFraudAvsFilteringService,
    #[serde(rename = "320")]
    #[strum(serialize = "320")]
    InvalidExpirationDate,
    #[serde(rename = "321")]
    #[strum(serialize = "321")]
    InvalidMerchant,
    #[serde(rename = "322")]
    #[strum(serialize = "322")]
    InvalidTransaction,
    #[serde(rename = "323")]
    #[strum(serialize = "323")]
    NoSuchIssuer,
    #[serde(rename = "324")]
    #[strum(serialize = "324")]
    InvalidPin,
    #[serde(rename = "325")]
    #[strum(serialize = "325")]
    TransactionNotAllowedAtTerminal,
    #[serde(rename = "326")]
    #[strum(serialize = "326")]
    ExceedsNumberOfPinEntries,
    #[serde(rename = "327")]
    #[strum(serialize = "327")]
    CardholderTransactionNotPermitted,
    #[serde(rename = "328")]
    #[strum(serialize = "328")]
    CardholderRequestedThatRecurringOrInstallmentPaymentBeStopped,
    #[serde(rename = "330")]
    #[strum(serialize = "330")]
    InvalidPaymentType,
    #[serde(rename = "331")]
    #[strum(serialize = "331")]
    InvalidPosCapabilityForCardholderAuthorizedTerminalTransaction,
    #[serde(rename = "332")]
    #[strum(serialize = "332")]
    InvalidPosCardholderIdForCardholderAuthorizedTerminalTransaction,
    #[serde(rename = "335")]
    #[strum(serialize = "335")]
    ThisMethodOfPaymentDoesNotSupportAuthorizationReversals,
    #[serde(rename = "336")]
    #[strum(serialize = "336")]
    ReversalAmountDoesNotMatchAuthorizationAmount,
    #[serde(rename = "337")]
    #[strum(serialize = "337")]
    TransactionDidNotConvertToPinless,
    #[serde(rename = "340")]
    #[strum(serialize = "340")]
    InvalidAmountSoftDecline,
    #[serde(rename = "341")]
    #[strum(serialize = "341")]
    InvalidHealthcareAmounts,
    #[serde(rename = "346")]
    #[strum(serialize = "346")]
    InvalidBillingDescriptorPrefix,
    #[serde(rename = "347")]
    #[strum(serialize = "347")]
    InvalidBillingDescriptor,
    #[serde(rename = "348")]
    #[strum(serialize = "348")]
    InvalidReportGroup,
    #[serde(rename = "349")]
    #[strum(serialize = "349")]
    DoNotHonor,
    #[serde(rename = "350")]
    #[strum(serialize = "350")]
    GenericDecline, // Soft or Hard Decline
    #[serde(rename = "351")]
    #[strum(serialize = "351")]
    DeclineRequestPositiveId,
    #[serde(rename = "352")]
    #[strum(serialize = "352")]
    DeclineCvv2CidFail,
    #[serde(rename = "354")]
    #[strum(serialize = "354")]
    ThreeDSecureTransactionNotSupportedByMerchant,
    #[serde(rename = "356")]
    #[strum(serialize = "356")]
    InvalidPurchaseLevelIiiTheTransactionContainedBadOrMissingData,
    #[serde(rename = "357")]
    #[strum(serialize = "357")]
    MissingHealthcareIiasTagForAnFsaTransaction,
    #[serde(rename = "358")]
    #[strum(serialize = "358")]
    RestrictedByVantivDueToSecurityCodeMismatch,
    #[serde(rename = "360")]
    #[strum(serialize = "360")]
    NoTransactionFoundWithSpecifiedTransactionId,
    #[serde(rename = "361")]
    #[strum(serialize = "361")]
    AuthorizationNoLongerAvailable,
    #[serde(rename = "362")]
    #[strum(serialize = "362")]
    TransactionNotVoidedAlreadySettled,
    #[serde(rename = "363")]
    #[strum(serialize = "363")]
    AutoVoidOnRefund,
    #[serde(rename = "364")]
    #[strum(serialize = "364")]
    InvalidAccountNumberOriginalOrNocUpdatedECheckAccountRequired,
    #[serde(rename = "365")]
    #[strum(serialize = "365")]
    TotalCreditAmountExceedsCaptureAmount,
    #[serde(rename = "366")]
    #[strum(serialize = "366")]
    ExceedTheThresholdForSendingRedeposits,
    #[serde(rename = "367")]
    #[strum(serialize = "367")]
    DepositHasNotBeenReturnedForInsufficientNonSufficientFunds,
    #[serde(rename = "368")]
    #[strum(serialize = "368")]
    InvalidCheckNumber,
    #[serde(rename = "369")]
    #[strum(serialize = "369")]
    RedepositAgainstInvalidTransactionType,
    #[serde(rename = "370")]
    #[strum(serialize = "370")]
    InternalSystemErrorCallVantiv,
    #[serde(rename = "371")]
    #[strum(serialize = "371")]
    OriginalTransactionHasBeenProcessedFutureRedepositsCanceled,
    #[serde(rename = "372")]
    #[strum(serialize = "372")]
    SoftDeclineAutoRecyclingInProgress,
    #[serde(rename = "373")]
    #[strum(serialize = "373")]
    HardDeclineAutoRecyclingComplete,
    #[serde(rename = "375")]
    #[strum(serialize = "375")]
    MerchantIsNotEnabledForSurcharging,
    #[serde(rename = "376")]
    #[strum(serialize = "376")]
    ThisMethodOfPaymentDoesNotSupportSurcharging,
    #[serde(rename = "377")]
    #[strum(serialize = "377")]
    SurchargeIsNotValidForDebitOrPrepaidCards,
    #[serde(rename = "378")]
    #[strum(serialize = "378")]
    SurchargeCannotExceedsTheMaximumAllowedLimit,
    #[serde(rename = "379")]
    #[strum(serialize = "379")]
    TransactionDeclinedByTheProcessingNetwork,
    #[serde(rename = "380")]
    #[strum(serialize = "380")]
    SecondaryAmountCannotExceedTheSaleAmount,
    #[serde(rename = "381")]
    #[strum(serialize = "381")]
    ThisMethodOfPaymentDoesNotSupportSecondaryAmount,
    #[serde(rename = "382")]
    #[strum(serialize = "382")]
    SecondaryAmountCannotBeLessThanZero,
    #[serde(rename = "383")]
    #[strum(serialize = "383")]
    PartialTransactionIsNotSupportedWhenIncludingASecondaryAmount,
    #[serde(rename = "384")]
    #[strum(serialize = "384")]
    SecondaryAmountRequiredOnPartialRefundWhenUsedOnDeposit,
    #[serde(rename = "385")]
    #[strum(serialize = "385")]
    SecondaryAmountNotAllowedOnRefundIfNotIncludedOnDeposit,
    #[serde(rename = "386")]
    #[strum(serialize = "386")]
    ProcessingNetworkError,
    #[serde(rename = "401")]
    #[strum(serialize = "401")]
    InvalidEMail,
    #[serde(rename = "466")]
    #[strum(serialize = "466")]
    InvalidCombinationOfAccountFundingTransactionTypeAndMcc,
    #[serde(rename = "467")]
    #[strum(serialize = "467")]
    InvalidAccountFundingTransactionTypeForThisMethodOfPayment,
    #[serde(rename = "468")]
    #[strum(serialize = "468")]
    MissingOneOrMoreReceiverFieldsForAccountFundingTransaction,
    #[serde(rename = "469")]
    #[strum(serialize = "469")]
    InvalidRecurringRequestSeeRecurringResponseForDetails,
    #[serde(rename = "470")]
    #[strum(serialize = "470")]
    ApprovedRecurringSubscriptionCreated,
    #[serde(rename = "471")]
    #[strum(serialize = "471")]
    ParentTransactionDeclinedRecurringSubscriptionNotCreated,
    #[serde(rename = "472")]
    #[strum(serialize = "472")]
    InvalidPlanCode,
    #[serde(rename = "473")]
    #[strum(serialize = "473")]
    ScheduledRecurringPaymentProcessed,
    #[serde(rename = "475")]
    #[strum(serialize = "475")]
    InvalidSubscriptionId,
    #[serde(rename = "476")]
    #[strum(serialize = "476")]
    AddOnCodeAlreadyExists,
    #[serde(rename = "477")]
    #[strum(serialize = "477")]
    DuplicateAddOnCodesInRequests,
    #[serde(rename = "478")]
    #[strum(serialize = "478")]
    NoMatchingAddOnCodeForTheSubscription,
    #[serde(rename = "480")]
    #[strum(serialize = "480")]
    NoMatchingDiscountCodeForTheSubscription,
    #[serde(rename = "481")]
    #[strum(serialize = "481")]
    DuplicateDiscountCodesInRequest,
    #[serde(rename = "482")]
    #[strum(serialize = "482")]
    InvalidStartDate,
    #[serde(rename = "483")]
    #[strum(serialize = "483")]
    MerchantNotRegisteredForRecurringEngine,
    #[serde(rename = "484")]
    #[strum(serialize = "484")]
    InsufficientDataToUpdateSubscription,
    #[serde(rename = "485")]
    #[strum(serialize = "485")]
    InvalidBillingDate,
    #[serde(rename = "486")]
    #[strum(serialize = "486")]
    DiscountCodeAlreadyExists,
    #[serde(rename = "487")]
    #[strum(serialize = "487")]
    PlanCodeAlreadyExists,
    #[serde(rename = "500")]
    #[strum(serialize = "500")]
    TheAccountNumberWasChanged,
    #[serde(rename = "501")]
    #[strum(serialize = "501")]
    TheAccountWasClosed,
    #[serde(rename = "502")]
    #[strum(serialize = "502")]
    TheExpirationDateWasChanged,
    #[serde(rename = "503")]
    #[strum(serialize = "503")]
    TheIssuingBankDoesNotParticipateInTheUpdateProgram,
    #[serde(rename = "504")]
    #[strum(serialize = "504")]
    ContactTheCardholderForUpdatedInformation,
    #[serde(rename = "507")]
    #[strum(serialize = "507")]
    TheCardholderHasOptedOutOfTheUpdateProgram,
    #[serde(rename = "521")]
    #[strum(serialize = "521")]
    SoftDeclineCardReaderDecryptionServiceIsNotAvailable,
    #[serde(rename = "523")]
    #[strum(serialize = "523")]
    SoftDeclineDecryptionFailed,
    #[serde(rename = "524")]
    #[strum(serialize = "524")]
    HardDeclineInputDataIsInvalid,
    #[serde(rename = "530")]
    #[strum(serialize = "530")]
    ApplePayKeyMismatch,
    #[serde(rename = "531")]
    #[strum(serialize = "531")]
    ApplePayDecryptionFailed,
    #[serde(rename = "540")]
    #[strum(serialize = "540")]
    HardDeclineDecryptionFailed,
    #[serde(rename = "550")]
    #[strum(serialize = "550")]
    AdvancedFraudFilterScoreBelowThreshold,
    #[serde(rename = "555")]
    #[strum(serialize = "555")]
    SuspectedFraud,
    #[serde(rename = "560")]
    #[strum(serialize = "560")]
    SystemErrorContactWorldpayRepresentative,
    #[serde(rename = "561")]
    #[strum(serialize = "561")]
    AmazonPayAmazonUnavailable,
    #[serde(rename = "562")]
    #[strum(serialize = "562")]
    AmazonPayAmazonDeclined,
    #[serde(rename = "563")]
    #[strum(serialize = "563")]
    AmazonPayInvalidToken,
    #[serde(rename = "564")]
    #[strum(serialize = "564")]
    MerchantNotEnabledForAmazonPay,
    #[serde(rename = "565")]
    #[strum(serialize = "565")]
    TransactionNotSupportedBlockedByIssuer,
    #[serde(rename = "566")]
    #[strum(serialize = "566")]
    BlockedByCardholderContactCardholder,
    #[serde(rename = "601")]
    #[strum(serialize = "601")]
    SoftDeclinePrimaryFundingSourceFailed,
    #[serde(rename = "602")]
    #[strum(serialize = "602")]
    SoftDeclineBuyerHasAlternateFundingSource,
    #[serde(rename = "610")]
    #[strum(serialize = "610")]
    HardDeclineInvalidBillingAgreementId,
    #[serde(rename = "611")]
    #[strum(serialize = "611")]
    HardDeclinePrimaryFundingSourceFailed,
    #[serde(rename = "612")]
    #[strum(serialize = "612")]
    HardDeclineIssueWithPaypalAccount,
    #[serde(rename = "613")]
    #[strum(serialize = "613")]
    HardDeclinePayPalAuthorizationIdMissing,
    #[serde(rename = "614")]
    #[strum(serialize = "614")]
    HardDeclineConfirmedEmailAddressIsNotAvailable,
    #[serde(rename = "615")]
    #[strum(serialize = "615")]
    HardDeclinePayPalBuyerAccountDenied,
    #[serde(rename = "616")]
    #[strum(serialize = "616")]
    HardDeclinePayPalBuyerAccountRestricted,
    #[serde(rename = "617")]
    #[strum(serialize = "617")]
    HardDeclinePayPalOrderHasBeenVoidedExpiredOrCompleted,
    #[serde(rename = "618")]
    #[strum(serialize = "618")]
    HardDeclineIssueWithPayPalRefund,
    #[serde(rename = "619")]


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

impl api::PaymentToken for for Powertranz


// Struct: WellsfargopayoutCard
// File: crates/hyperswitch_connectors/src/connectors/wellsfargopayout/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct WellsfargopayoutCard


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

impl ConnectorAccessToken for for Netcetera


// Struct: PaymentIntents
// File: crates/router/src/compatibility/stripe/app.rs
// Module: router
// Implementations: 1

pub struct PaymentIntents


// Implementation: impl ConnectorValidation for for Volt
// File: crates/hyperswitch_connectors/src/connectors/volt.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl ConnectorValidation for for Volt


// Implementation: impl AppState
// File: crates/drainer/src/settings.rs
// Module: drainer
// Methods: 1 total (0 public)

impl AppState


// Function: get_aggregates_for_disputes
// File: crates/router/src/core/disputes.rs
// Module: router

pub fn get_aggregates_for_disputes(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
    time_range: common_utils::types::TimeRange,
) -> RouterResponse<dispute_models::DisputesAggregateResponse>


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

pub use hyperswitch_domain_models::{
    router_request_types::authentication::{
        AcquirerDetails, AuthNFlowType, ChallengeParams, ConnectorAuthenticationRequestData,
        ConnectorPostAuthenticationRequestData, PreAuthNRequestData, PreAuthenticationData,
    },
    router_response_types::AuthenticationResponseData,
};

use super::{api, RouterData};
use crate::services;

pub type PreAuthNRouterData =
    RouterData<api::PreAuthentication, PreAuthNRequestData, AuthenticationResponseData>;

pub type PreAuthNVersionCallRouterData =
    RouterData<api::PreAuthenticationVersionCall, PreAuthNRequestData, AuthenticationResponseData>;

pub type ConnectorAuthenticationRouterData =
    RouterData<api::Authentication, ConnectorAuthenticationRequestData, AuthenticationResponseData>;

pub type ConnectorPostAuthenticationRouterData = RouterData<
    api::PostAuthentication,
    ConnectorPostAuthenticationRequestData,
    AuthenticationResponseData,
>;

pub type ConnectorAuthenticationType = dyn services::ConnectorIntegration<
    api::Authentication,
    ConnectorAuthenticationRequestData,
    AuthenticationResponseData,
>;

pub type ConnectorPostAuthenticationType = dyn services::ConnectorIntegration<
    api::PostAuthentication,
    ConnectorPostAuthenticationRequestData,
    AuthenticationResponseData,
>;

pub type ConnectorPreAuthenticationType = dyn services::ConnectorIntegration<
    api::PreAuthentication,
    PreAuthNRequestData,
    AuthenticationResponseData,
>;

pub type ConnectorPreAuthenticationVersionCallType = dyn services::ConnectorIntegration<
    api::PreAuthenticationVersionCall,
    PreAuthNRequestData,
    AuthenticationResponseData,
>;