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

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

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

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

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

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

static CONNECTOR: SantanderTest = SantanderTest {};

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: 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


// Struct: StandardFlowCredentials
// File: crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct StandardFlowCredentials


// Function: retrieve_conditional_config
// File: crates/router/src/core/conditional_config.rs
// Module: router

pub fn retrieve_conditional_config(
    state: SessionState,
    merchant_context: domain::MerchantContext,
) -> RouterResponse<DecisionManagerResponse>


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

pub fn update_gateway_system_in_feature_metadata<F: Clone, D>(
    payment_data: &mut D,
    gateway_system: GatewaySystem,
) -> RouterResult<()>
where
    D: OperationSessionGetters<F> + OperationSessionSetters<F>,


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

pub struct SinglePurposeOrLoginTokenAuth


// Struct: ActionTypesBuilder
// File: crates/router/src/core/payments.rs
// Module: router
// Implementations: 1

pub struct ActionTypesBuilder


// Struct: RefundResponse
// File: crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RefundResponse


// Function: get_decision
// File: crates/common_types/src/domain.rs
// Module: common_types

// Documentation: Retrieves the decision from the retry feature data.

pub fn get_decision(&self) -> common_enums::GsmDecision


// Implementation: impl RedisResult
// File: crates/router_derive/src/lib.rs
// Module: router_derive
// Methods: 2 total (0 public)

impl RedisResult


        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64()),
        minor_amount_captured: payment_intent.amount_captured,
        payment_method_status: None,
        request: types::AcceptDisputeRequestData {
            dispute_id: dispute.dispute_id.clone(),
            connector_dispute_id: dispute.connector_dispute_id.clone(),
            dispute_status: dispute.dispute_status,
        },
        response: Err(ErrorResponse::default()),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        connector_customer: None,
        customer_id: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        connector_request_reference_id: get_connector_request_reference_id(
            &state.conf,
            merchant_context.get_merchant_account().get_id(),
            payment_intent,
            payment_attempt,
            &dispute.connector,
        )?,
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode,
        payment_method_balance: None,
        connector_api_version: None,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        dispute_id: Some(dispute.dispute_id.clone()),
        refund_id: None,
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };
    Ok(router_data)
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
pub async fn construct_submit_evidence_router_data<'a>(
    state: &'a SessionState,
    payment_intent: &'a storage::PaymentIntent,
    payment_attempt: &storage::PaymentAttempt,
    merchant_context: &domain::MerchantContext,
    dispute: &storage::Dispute,
    submit_evidence_request_data: types::SubmitEvidenceRequestData,
) -> RouterResult<types::SubmitEvidenceRouterData> {
    let connector_id = &dispute.connector;
    let profile_id = payment_intent
        .profile_id
        .as_ref()
        .get_required_value("profile_id")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("profile_id is not set in payment_intent")?
        .clone();

    let merchant_connector_account = helpers::get_merchant_connector_account(
        state,
        merchant_context.get_merchant_account().get_id(),
        None,
        merchant_context.get_merchant_key_store(),
        &profile_id,
        connector_id,
        payment_attempt.merchant_connector_id.as_ref(),
    )
    .await?;

    let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();
    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;
    let payment_method = payment_attempt
        .payment_method
        .get_required_value("payment_method_type")?;
    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        connector: connector_id.to_string(),
        payment_id: payment_attempt.payment_id.get_string_repr().to_owned(),
        tenant_id: state.tenant.tenant_id.clone(),
        attempt_id: payment_attempt.attempt_id.clone(),
        status: payment_attempt.status,
        payment_method,
        connector_auth_type: auth_type,
        description: None,
        address: PaymentAddress::default(),
        auth_type: payment_attempt.authentication_type.unwrap_or_default(),
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64()),
        minor_amount_captured: payment_intent.amount_captured,
        request: submit_evidence_request_data,
        response: Err(ErrorResponse::default()),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        connector_customer: None,
        customer_id: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        payment_method_balance: None,
        payment_method_status: None,
        connector_request_reference_id: get_connector_request_reference_id(
            &state.conf,
            merchant_context.get_merchant_account().get_id(),
            payment_intent,
            payment_attempt,
            connector_id,
        )?,
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode,
        connector_api_version: None,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: None,
        dispute_id: Some(dispute.dispute_id.clone()),
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };
    Ok(router_data)
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
pub async fn construct_upload_file_router_data<'a>(
    state: &'a SessionState,
    payment_intent: &'a storage::PaymentIntent,
    payment_attempt: &storage::PaymentAttempt,
    merchant_context: &domain::MerchantContext,
    create_file_request: &api::CreateFileRequest,
    dispute_data: storage::Dispute,
    connector_id: &str,
    file_key: String,
) -> RouterResult<types::UploadFileRouterData> {
    let profile_id = payment_intent
        .profile_id
        .as_ref()
        .get_required_value("profile_id")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("profile_id is not set in payment_intent")?
        .clone();

    let merchant_connector_account = helpers::get_merchant_connector_account(
        state,
        merchant_context.get_merchant_account().get_id(),
        None,
        merchant_context.get_merchant_key_store(),
        &profile_id,
        connector_id,
        payment_attempt.merchant_connector_id.as_ref(),
    )
    .await?;

    let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();
    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;
    let payment_method = payment_attempt
        .payment_method
        .get_required_value("payment_method_type")?;
    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        connector: connector_id.to_string(),
        payment_id: payment_attempt.payment_id.get_string_repr().to_owned(),
        tenant_id: state.tenant.tenant_id.clone(),
        attempt_id: payment_attempt.attempt_id.clone(),
        status: payment_attempt.status,
        payment_method,
        connector_auth_type: auth_type,
        description: None,
        address: PaymentAddress::default(),
        auth_type: payment_attempt.authentication_type.unwrap_or_default(),
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64()),
        minor_amount_captured: payment_intent.amount_captured,
        payment_method_status: None,
        request: types::UploadFileRequestData {
            file_key,
            file: create_file_request.file.clone(),
            file_type: create_file_request.file_type.clone(),
            file_size: create_file_request.file_size,
            dispute_id: dispute_data.dispute_id.clone(),
            connector_dispute_id: dispute_data.connector_dispute_id.clone(),
        },
        response: Err(ErrorResponse::default()),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        connector_customer: None,
        customer_id: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        payment_method_balance: None,
        connector_request_reference_id: get_connector_request_reference_id(
            &state.conf,
            merchant_context.get_merchant_account().get_id(),
            payment_intent,
            payment_attempt,
            connector_id,
        )?,
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode,
        connector_api_version: None,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: None,
        dispute_id: None,
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };
    Ok(router_data)
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
pub async fn construct_dispute_list_router_data<'a>(
    state: &'a SessionState,
    merchant_connector_account: MerchantConnectorAccount,
    req: types::FetchDisputesRequestData,
) -> RouterResult<types::FetchDisputesRouterData> {
    let merchant_id = merchant_connector_account.merchant_id.clone();
    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .change_context(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
            id: "ConnectorAuthType".to_string(),
        })?;

    Ok(types::RouterData {
        flow: PhantomData,
        merchant_id,
        customer_id: None,
        connector_customer: None,
        connector: merchant_connector_account.connector_name.clone(),
        payment_id: consts::IRRELEVANT_PAYMENT_INTENT_ID.to_owned(),
        tenant_id: state.tenant.tenant_id.clone(),
        attempt_id: consts::IRRELEVANT_PAYMENT_ATTEMPT_ID.to_owned(),
        status: common_enums::AttemptStatus::default(),
        payment_method: common_enums::PaymentMethod::default(),
        connector_auth_type: auth_type,
        description: None,
        address: PaymentAddress::default(),
        auth_type: common_enums::AuthenticationType::default(),
        connector_meta_data: merchant_connector_account.get_metadata().clone(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: None,
        minor_amount_captured: None,
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        payment_method_balance: None,
        connector_api_version: None,
        request: req,
        response: Err(ErrorResponse::default()),
        //TODO
        connector_request_reference_id:
            "IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_AUTHENTICATION_FLOW".to_owned(),
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode: None,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        dispute_id: None,
        refund_id: None,
        payment_method_status: None,
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    })
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
pub async fn construct_dispute_sync_router_data<'a>(
    state: &'a SessionState,
    payment_intent: &'a storage::PaymentIntent,
    payment_attempt: &storage::PaymentAttempt,
    merchant_context: &domain::MerchantContext,
    dispute: &storage::Dispute,
) -> RouterResult<types::DisputeSyncRouterData> {
    let _db = &*state.store;
    let connector_id = &dispute.connector;
    let profile_id = payment_intent
        .profile_id
        .as_ref()
        .get_required_value("profile_id")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("profile_id is not set in payment_intent")?
        .clone();

    let merchant_connector_account = helpers::get_merchant_connector_account(
        state,
        merchant_context.get_merchant_account().get_id(),
        None,
        merchant_context.get_merchant_key_store(),
        &profile_id,
        connector_id,
        payment_attempt.merchant_connector_id.as_ref(),
    )
    .await?;

    let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();
    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;
    let payment_method = payment_attempt
        .payment_method
        .get_required_value("payment_method")?;
    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        connector: connector_id.to_string(),
        payment_id: payment_attempt.payment_id.get_string_repr().to_owned(),
        tenant_id: state.tenant.tenant_id.clone(),
        attempt_id: payment_attempt.attempt_id.clone(),
        status: payment_attempt.status,
        payment_method,
        connector_auth_type: auth_type,
        description: None,
        address: PaymentAddress::default(),
        auth_type: payment_attempt.authentication_type.unwrap_or_default(),
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64()),
        minor_amount_captured: payment_intent.amount_captured,
        payment_method_status: None,
        request: types::DisputeSyncData {
            dispute_id: dispute.dispute_id.clone(),
            connector_dispute_id: dispute.connector_dispute_id.clone(),
        },
        response: Err(ErrorResponse::get_not_implemented()),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        customer_id: None,
        connector_customer: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        payment_method_balance: None,
        connector_request_reference_id: get_connector_request_reference_id(
            &state.conf,
            merchant_context.get_merchant_account().get_id(),
            payment_intent,
            payment_attempt,
            connector_id,
        )?,
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode,
        connector_api_version: None,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: None,
        dispute_id: Some(dispute.dispute_id.clone()),
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };
    Ok(router_data)
}

#[cfg(feature = "v2")]
pub async fn construct_payments_dynamic_tax_calculation_router_data<F: Clone>(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    payment_data: &mut PaymentData<F>,
    merchant_connector_account: &MerchantConnectorAccount,
) -> RouterResult<types::PaymentsTaxCalculationRouterData> {
    todo!()
}

#[cfg(feature = "v1")]
pub async fn construct_payments_dynamic_tax_calculation_router_data<F: Clone>(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    payment_data: &mut PaymentData<F>,
    merchant_connector_account: &MerchantConnectorAccount,
) -> RouterResult<types::PaymentsTaxCalculationRouterData> {
    let payment_intent = &payment_data.payment_intent.clone();
    let payment_attempt = &payment_data.payment_attempt.clone();

    #[cfg(feature = "v1")]
    let test_mode: Option<bool> = merchant_connector_account.test_mode;

    #[cfg(feature = "v2")]
    let test_mode = None;

    let connector_auth_type: types::ConnectorAuthType = merchant_connector_account
        .connector_account_details
        .clone()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed while parsing value for ConnectorAuthType")?;

    let shipping_address = payment_data
        .tax_data
        .clone()
        .map(|tax_data| tax_data.shipping_details)
        .clone()
        .ok_or(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Missing shipping_details")?;

    let order_details: Option<Vec<OrderDetailsWithAmount>> = payment_intent
        .order_details
        .clone()
        .map(|order_details| {
            order_details
                .iter()
                .map(|data| {
                    data.to_owned()
                        .parse_value("OrderDetailsWithAmount")
                        .change_context(errors::ApiErrorResponse::InvalidDataValue {
                            field_name: "OrderDetailsWithAmount",
                        })
                        .attach_printable("Unable to parse OrderDetailsWithAmount")
                })
                .collect::<Result<Vec<_>, _>>()
        })
        .transpose()?;

    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().to_owned(),
        customer_id: None,
        connector_customer: None,
        connector: merchant_connector_account.connector_name.clone(),
        payment_id: payment_attempt.payment_id.get_string_repr().to_owned(),
        attempt_id: payment_attempt.attempt_id.clone(),
        tenant_id: state.tenant.tenant_id.clone(),
        status: payment_attempt.status,
        payment_method: diesel_models::enums::PaymentMethod::default(),
        connector_auth_type,
        description: None,
        address: payment_data.address.clone(),
        auth_type: payment_attempt.authentication_type.unwrap_or_default(),
        connector_meta_data: None,
        connector_wallets_details: None,
        amount_captured: None,
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        payment_method_balance: None,
        connector_api_version: None,
        request: types::PaymentsTaxCalculationData {
            amount: payment_intent.amount,
            shipping_cost: payment_intent.shipping_cost,
            order_details,
            currency: payment_data.currency,
            shipping_address,
        },
        response: Err(ErrorResponse::default()),
        connector_request_reference_id: get_connector_request_reference_id(
            &state.conf,
            merchant_context.get_merchant_account().get_id(),
            payment_intent,
            payment_attempt,
            &merchant_connector_account.connector_name,
        )?,
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: None,
        dispute_id: None,
        connector_response: None,
        payment_method_status: None,
        minor_amount_captured: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };
    Ok(router_data)
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
pub async fn construct_defend_dispute_router_data<'a>(
    state: &'a SessionState,
    payment_intent: &'a storage::PaymentIntent,
    payment_attempt: &storage::PaymentAttempt,
    merchant_context: &domain::MerchantContext,
    dispute: &storage::Dispute,
) -> RouterResult<types::DefendDisputeRouterData> {
    let _db = &*state.store;
    let connector_id = &dispute.connector;
    let profile_id = payment_intent
        .profile_id
        .as_ref()
        .get_required_value("profile_id")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("profile_id is not set in payment_intent")?
        .clone();

    let merchant_connector_account = helpers::get_merchant_connector_account(
        state,
        merchant_context.get_merchant_account().get_id(),
        None,
        merchant_context.get_merchant_key_store(),
        &profile_id,
        connector_id,
        payment_attempt.merchant_connector_id.as_ref(),
    )
    .await?;

    let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();
    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;
    let payment_method = payment_attempt
        .payment_method
        .get_required_value("payment_method_type")?;
    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        connector: connector_id.to_string(),
        payment_id: payment_attempt.payment_id.get_string_repr().to_owned(),
        tenant_id: state.tenant.tenant_id.clone(),
        attempt_id: payment_attempt.attempt_id.clone(),
        status: payment_attempt.status,
        payment_method,
        connector_auth_type: auth_type,
        description: None,
        address: PaymentAddress::default(),
        auth_type: payment_attempt.authentication_type.unwrap_or_default(),
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64()),
        minor_amount_captured: payment_intent.amount_captured,
        payment_method_status: None,
        request: types::DefendDisputeRequestData {
            dispute_id: dispute.dispute_id.clone(),
            connector_dispute_id: dispute.connector_dispute_id.clone(),
        },
        response: Err(ErrorResponse::get_not_implemented()),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        customer_id: None,
        connector_customer: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        payment_method_balance: None,
        connector_request_reference_id: get_connector_request_reference_id(
            &state.conf,
            merchant_context.get_merchant_account().get_id(),
            payment_intent,
            payment_attempt,
            connector_id,
        )?,
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode,
        connector_api_version: None,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: None,
        dispute_id: Some(dispute.dispute_id.clone()),
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };
    Ok(router_data)
}

#[instrument(skip_all)]
pub async fn construct_retrieve_file_router_data<'a>(
    state: &'a SessionState,
    merchant_context: &domain::MerchantContext,
    file_metadata: &diesel_models::file::FileMetadata,
    dispute: Option<storage::Dispute>,
    connector_id: &str,
) -> RouterResult<types::RetrieveFileRouterData> {
    let profile_id = file_metadata
        .profile_id
        .as_ref()
        .ok_or(errors::ApiErrorResponse::MissingRequiredField {
            field_name: "profile_id",
        })
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("profile_id is not set in file_metadata")?;

    let merchant_connector_account = helpers::get_merchant_connector_account(
        state,
        merchant_context.get_merchant_account().get_id(),
        None,
        merchant_context.get_merchant_key_store(),
        profile_id,
        connector_id,
        file_metadata.merchant_connector_id.as_ref(),
    )
    .await?;

    let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();
    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;
    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        connector: connector_id.to_string(),
        tenant_id: state.tenant.tenant_id.clone(),
        customer_id: None,
        connector_customer: None,
        payment_id: common_utils::id_type::PaymentId::get_irrelevant_id("dispute")
            .get_string_repr()
            .to_owned(),
        attempt_id: IRRELEVANT_ATTEMPT_ID_IN_DISPUTE_FLOW.to_string(),
        status: diesel_models::enums::AttemptStatus::default(),
        payment_method: diesel_models::enums::PaymentMethod::default(),
        connector_auth_type: auth_type,
        description: None,
        address: PaymentAddress::default(),
        auth_type: diesel_models::enums::AuthenticationType::default(),
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: None,
        minor_amount_captured: None,
        payment_method_status: None,
        request: types::RetrieveFileRequestData {
            provider_file_id: file_metadata
                .provider_file_id
                .clone()
                .ok_or(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Missing provider file id")?,
            connector_dispute_id: dispute.map(|dispute_data| dispute_data.connector_dispute_id),
        },
        response: Err(ErrorResponse::default()),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        payment_method_balance: None,
        connector_request_reference_id: IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_DISPUTE_FLOW
            .to_string(),
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode,
        connector_api_version: None,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: None,
        dispute_id: None,
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };
    Ok(router_data)
}

pub fn is_merchant_enabled_for_payment_id_as_connector_request_id(
    conf: &Settings,
    merchant_id: &common_utils::id_type::MerchantId,
) -> bool {
    let config_map = &conf
        .connector_request_reference_id_config
        .merchant_ids_send_payment_id_as_connector_request_id;
    config_map.contains(merchant_id)
}

#[cfg(feature = "v1")]
pub fn get_connector_request_reference_id(
    conf: &Settings,
    merchant_id: &common_utils::id_type::MerchantId,
    payment_intent: &hyperswitch_domain_models::payments::PaymentIntent,
    payment_attempt: &hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt,
    connector_name: &str,
) -> CustomResult<String, errors::ApiErrorResponse> {
    let is_config_enabled_to_send_payment_id_as_connector_request_id =
        is_merchant_enabled_for_payment_id_as_connector_request_id(conf, merchant_id);

    let connector_data = api::ConnectorData::get_connector_by_name(
        &conf.connectors,
        connector_name,
        api::GetToken::Connector,
        payment_attempt.merchant_connector_id.clone(),
    )
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable_lazy(|| "Failed to construct connector data")?;

    let connector_request_reference_id = connector_data
        .connector
        .generate_connector_request_reference_id(
            payment_intent,
            payment_attempt,
            is_config_enabled_to_send_payment_id_as_connector_request_id,
        );
    Ok(connector_request_reference_id)
}

// TODO: Based on the connector configuration, the connector_request_reference_id should be generated
#[cfg(feature = "v2")]
pub fn get_connector_request_reference_id(
    conf: &Settings,
    merchant_id: &common_utils::id_type::MerchantId,
    payment_attempt: &hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt,
) -> String {
    todo!()
}

/// Validate whether the profile_id exists and is associated with the merchant_id
pub async fn validate_and_get_business_profile(
    db: &dyn StorageInterface,
    key_manager_state: &KeyManagerState,
    merchant_key_store: &domain::MerchantKeyStore,
    profile_id: Option<&common_utils::id_type::ProfileId>,
    merchant_id: &common_utils::id_type::MerchantId,
) -> RouterResult<Option<domain::Profile>> {
    profile_id
        .async_map(|profile_id| async {
            db.find_business_profile_by_profile_id(
                key_manager_state,
                merchant_key_store,
                profile_id,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::ProfileNotFound {
                id: profile_id.get_string_repr().to_owned(),
            })
        })
        .await
        .transpose()?
        .map(|business_profile| {
            // Check if the merchant_id of business profile is same as the current merchant_id
            if business_profile.merchant_id.ne(merchant_id) {
                Err(errors::ApiErrorResponse::AccessForbidden {
                    resource: business_profile.get_id().get_string_repr().to_owned(),
                }
                .into())
            } else {
                Ok(business_profile)
            }
        })
        .transpose()
}

fn connector_needs_business_sub_label(connector_name: &str) -> bool {
    let connectors_list = [Connector::Cybersource];
    connectors_list
        .map(|connector| connector.to_string())
        .contains(&connector_name.to_string())
}

/// Create the connector label
/// {connector_name}_{country}_{business_label}
pub fn get_connector_label(
    business_country: Option<api_models::enums::CountryAlpha2>,
    business_label: Option<&String>,
    business_sub_label: Option<&String>,
    connector_name: &str,
) -> Option<String> {
    business_country
        .zip(business_label)
        .map(|(business_country, business_label)| {
            let mut connector_label =
                format!("{connector_name}_{business_country}_{business_label}");

            // Business sub label is currently being used only for cybersource
            // To ensure backwards compatibality, cybersource mca's created before this change
            // will have the business_sub_label value as default.
            //
            // Even when creating the connector account, if no sub label is provided, default will be used
            if connector_needs_business_sub_label(connector_name) {
                if let Some(sub_label) = business_sub_label {
                    connector_label.push_str(&format!("_{sub_label}"));
                } else {
                    connector_label.push_str("_default"); // For backwards compatibality
                }
            }

            connector_label
        })
}

#[cfg(feature = "v1")]
/// If profile_id is not passed, use default profile if available, or
/// If business_details (business_country and business_label) are passed, get the business_profile
/// or return a `MissingRequiredField` error
#[allow(clippy::too_many_arguments)]
pub async fn get_profile_id_from_business_details(
    key_manager_state: &KeyManagerState,
    business_country: Option<api_models::enums::CountryAlpha2>,
    business_label: Option<&String>,
    merchant_context: &domain::MerchantContext,
    request_profile_id: Option<&common_utils::id_type::ProfileId>,
    db: &dyn StorageInterface,
    should_validate: bool,
) -> RouterResult<common_utils::id_type::ProfileId> {
    match request_profile_id.or(merchant_context
        .get_merchant_account()
        .default_profile
        .as_ref())
    {
        Some(profile_id) => {
            // Check whether this business profile belongs to the merchant
            if should_validate {
                let _ = validate_and_get_business_profile(
                    db,
                    key_manager_state,
                    merchant_context.get_merchant_key_store(),
                    Some(profile_id),
                    merchant_context.get_merchant_account().get_id(),
                )
                .await?;
            }
            Ok(profile_id.clone())
        }
        None => match business_country.zip(business_label) {
            Some((business_country, business_label)) => {
                let profile_name = format!("{business_country}_{business_label}");
                let business_profile = db
                    .find_business_profile_by_profile_name_merchant_id(
                        key_manager_state,
                        merchant_context.get_merchant_key_store(),
                        &profile_name,
                        merchant_context.get_merchant_account().get_id(),
                    )
                    .await
                    .to_not_found_response(errors::ApiErrorResponse::ProfileNotFound {
                        id: profile_name,
                    })?;

                Ok(business_profile.get_id().to_owned())
            }
            _ => Err(report!(errors::ApiErrorResponse::MissingRequiredField {
                field_name: "profile_id or business_country, business_label"
            })),
        },
    }
}

pub fn get_poll_id(merchant_id: &common_utils::id_type::MerchantId, unique_id: String) -> String {
    merchant_id.get_poll_id(&unique_id)
}

pub fn get_external_authentication_request_poll_id(
    payment_id: &common_utils::id_type::PaymentId,
) -> String {
    payment_id.get_external_authentication_request_poll_id()
}

pub fn get_modular_authentication_request_poll_id(
    authentication_id: &common_utils::id_type::AuthenticationId,
) -> String {
    authentication_id.get_external_authentication_request_poll_id()
}

pub fn get_html_redirect_response_popup(
    return_url_with_query_params: String,
) -> RouterResult<String> {
    Ok(html! {
        head {
            title { "Redirect Form" }
            (PreEscaped(format!(r#"
                    <script>
                        let return_url = "{return_url_with_query_params}";
                        try {{
                            // if inside iframe, send post message to parent for redirection
                            if (window.self !== window.parent) {{
                                window.parent.postMessage({{openurl_if_required: return_url}}, '*')
                            // if parent, redirect self to return_url
                            }} else {{
                                window.location.href = return_url
                            }}
                        }}
                        catch(err) {{
                            // if error occurs, send post message to parent and wait for 10 secs to redirect. if doesn't redirect, redirect self to return_url
                            window.parent.postMessage({{openurl_if_required: return_url}}, '*')
                            setTimeout(function() {{
                                window.location.href = return_url
                            }}, 10000);
                            console.log(err.message)
                        }}
                    </script>
                    "#)))
        }
    }
    .into_string())
}

#[cfg(feature = "v1")]
pub fn get_html_redirect_response_for_external_authentication(
    return_url_with_query_params: String,
    payment_response: &api_models::payments::PaymentsResponse,
    payment_id: common_utils::id_type::PaymentId,
    poll_config: &PollConfig,
) -> RouterResult<String> {
    // if intent_status is requires_customer_action then set poll_id, fetch poll config and do a poll_status post message, else do open_url post message to redirect to return_url
    let html = match payment_response.status {
            IntentStatus::RequiresCustomerAction => {
                // Request poll id sent to client for retrieve_poll_status api
                let req_poll_id = get_external_authentication_request_poll_id(&payment_id);
                let poll_frequency = poll_config.frequency;
                let poll_delay_in_secs = poll_config.delay_in_secs;


// Struct: GocardlessAuthType
// File: crates/hyperswitch_connectors/src/connectors/gocardless/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct GocardlessAuthType


                        web::get().to(|state, req, path: web::Query<RoutingRetrieveQuery>| {
                            routing::list_routing_configs(state, req, path, None)
                        }),
                    )
                    .route(web::post().to(|state, req, payload| {
                        routing::routing_create_config(state, req, payload, None)
                    })),
            )
            .service(web::resource("/list/profile").route(web::get().to(
                |state, req, query: web::Query<RoutingRetrieveQuery>| {
                    routing::list_routing_configs_for_profile(state, req, query, None)
                },
            )))
            .service(
                web::resource("/default").route(web::post().to(|state, req, payload| {
                    routing::routing_update_default_config(
                        state,
                        req,
                        payload,
                        &TransactionType::Payment,
                    )
                })),
            )
            .service(web::resource("/rule/migrate").route(web::post().to(
                |state, req, query: web::Query<RuleMigrationQuery>| {
                    routing::migrate_routing_rules_for_profile(state, req, query)
                },
            )))
            .service(
                web::resource("/deactivate").route(web::post().to(|state, req, payload| {
                    routing::routing_unlink_config(state, req, payload, None)
                })),
            )
            .service(
                web::resource("/decision")
                    .route(web::put().to(routing::upsert_decision_manager_config))
                    .route(web::get().to(routing::retrieve_decision_manager_config))
                    .route(web::delete().to(routing::delete_decision_manager_config)),
            )
            .service(
                web::resource("/decision/surcharge")
                    .route(web::put().to(routing::upsert_surcharge_decision_manager_config))
                    .route(web::get().to(routing::retrieve_surcharge_decision_manager_config))
                    .route(web::delete().to(routing::delete_surcharge_decision_manager_config)),
            )
            .service(
                web::resource("/default/profile/{profile_id}").route(web::post().to(
                    |state, req, path, payload| {
                        routing::routing_update_default_config_for_profile(
                            state,
                            req,
                            path,
                            payload,
                            &TransactionType::Payment,
                        )
                    },
                )),
            )
            .service(
                web::resource("/default/profile").route(web::get().to(|state, req| {
                    routing::routing_retrieve_default_config(state, req, &TransactionType::Payment)
                })),
            );

        #[cfg(feature = "dynamic_routing")]
        {
            route = route
                .service(
                    web::resource("/evaluate")
                        .route(web::post().to(routing::call_decide_gateway_open_router)),
                )
                .service(
                    web::resource("/feedback")
                        .route(web::post().to(routing::call_update_gateway_score_open_router)),
                )
        }

        #[cfg(feature = "payouts")]
        {
            route = route
                .service(
                    web::resource("/payouts")
                        .route(web::get().to(
                            |state, req, path: web::Query<RoutingRetrieveQuery>| {
                                routing::list_routing_configs(
                                    state,
                                    req,
                                    path,
                                    Some(TransactionType::Payout),
                                )
                            },
                        ))
                        .route(web::post().to(|state, req, payload| {
                            routing::routing_create_config(
                                state,
                                req,
                                payload,
                                Some(TransactionType::Payout),
                            )
                        })),
                )
                .service(web::resource("/payouts/list/profile").route(web::get().to(
                    |state, req, query: web::Query<RoutingRetrieveQuery>| {
                        routing::list_routing_configs_for_profile(
                            state,
                            req,
                            query,
                            Some(TransactionType::Payout),
                        )
                    },
                )))
                .service(web::resource("/payouts/active").route(web::get().to(
                    |state, req, query_params| {
                        routing::routing_retrieve_linked_config(
                            state,
                            req,
                            query_params,
                            Some(TransactionType::Payout),
                        )
                    },
                )))
                .service(
                    web::resource("/payouts/default")
                        .route(web::get().to(|state, req| {
                            routing::routing_retrieve_default_config(
                                state,
                                req,
                                &TransactionType::Payout,
                            )
                        }))
                        .route(web::post().to(|state, req, payload| {
                            routing::routing_update_default_config(
                                state,
                                req,
                                payload,
                                &TransactionType::Payout,
                            )
                        })),
                )
                .service(
                    web::resource("/payouts/{algorithm_id}/activate").route(web::post().to(
                        |state, req, path, payload| {
                            routing::routing_link_config(
                                state,
                                req,
                                path,
                                payload,
                                Some(TransactionType::Payout),
                            )
                        },
                    )),
                )
                .service(web::resource("/payouts/deactivate").route(web::post().to(
                    |state, req, payload| {
                        routing::routing_unlink_config(
                            state,
                            req,
                            payload,
                            Some(TransactionType::Payout),
                        )
                    },
                )))
                .service(
                    web::resource("/payouts/default/profile/{profile_id}").route(web::post().to(
                        |state, req, path, payload| {
                            routing::routing_update_default_config_for_profile(
                                state,
                                req,
                                path,
                                payload,
                                &TransactionType::Payout,
                            )
                        },
                    )),
                )
                .service(
                    web::resource("/payouts/default/profile").route(web::get().to(|state, req| {
                        routing::routing_retrieve_default_config_for_profiles(
                            state,
                            req,
                            &TransactionType::Payout,
                        )
                    })),
                );
        }

        route = route
            .service(
                web::resource("/{algorithm_id}")
                    .route(web::get().to(routing::routing_retrieve_config)),
            )
            .service(
                web::resource("/{algorithm_id}/activate").route(web::post().to(
                    |state, req, payload, path| {
                        routing::routing_link_config(state, req, path, payload, None)
                    },
                )),
            )
            .service(
                web::resource("/rule/evaluate")
                    .route(web::post().to(routing::evaluate_routing_rule)),
            );
        route
    }
}

#[cfg(feature = "oltp")]
pub struct Subscription;

#[cfg(all(feature = "oltp", feature = "v1"))]
impl Subscription {
    pub fn server(state: AppState) -> Scope {
        let route = web::scope("/subscriptions").app_data(web::Data::new(state.clone()));

        route
            .service(web::resource("/create").route(
                web::post().to(|state, req, payload| {
                    subscription::create_subscription(state, req, payload)
                }),
            ))
            .service(
                web::resource("/{subscription_id}/confirm").route(web::post().to(
                    |state, req, id, payload| {
                        subscription::confirm_subscription(state, req, id, payload)
                    },
                )),
            )
    }
}

pub struct Customers;

#[cfg(all(feature = "v2", any(feature = "olap", feature = "oltp")))]
impl Customers {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/v2/customers").app_data(web::Data::new(state));
        #[cfg(all(feature = "olap", feature = "v2"))]
        {
            route = route
                .service(web::resource("/list").route(web::get().to(customers::customers_list)))
                .service(
                    web::resource("/total-payment-methods")
                        .route(web::get().to(payment_methods::get_total_payment_method_count)),
                )
                .service(
                    web::resource("/{id}/saved-payment-methods")
                        .route(web::get().to(payment_methods::list_customer_payment_method_api)),
                )
        }
        #[cfg(all(feature = "oltp", feature = "v2"))]
        {
            route = route
                .service(web::resource("").route(web::post().to(customers::customers_create)))
                .service(
                    web::resource("/{id}")
                        .route(web::put().to(customers::customers_update))
                        .route(web::get().to(customers::customers_retrieve))
                        .route(web::delete().to(customers::customers_delete)),
                )
        }
        route
    }
}

#[cfg(all(feature = "v1", any(feature = "olap", feature = "oltp")))]
impl Customers {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/customers").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            route = route
                .service(
                    web::resource("/{customer_id}/mandates")
                        .route(web::get().to(customers::get_customer_mandates)),
                )
                .service(web::resource("/list").route(web::get().to(customers::customers_list)))
        }

        #[cfg(feature = "oltp")]
        {
            route = route
                .service(web::resource("").route(web::post().to(customers::customers_create)))
                .service(
                    web::resource("/payment_methods").route(
                        web::get().to(payment_methods::list_customer_payment_method_api_client),
                    ),
                )
                .service(
                    web::resource("/{customer_id}/payment_methods")
                        .route(web::get().to(payment_methods::list_customer_payment_method_api)),
                )
                .service(
                    web::resource("/{customer_id}/payment_methods/{payment_method_id}/default")
                        .route(web::post().to(payment_methods::default_payment_method_set_api)),
                )
                .service(
                    web::resource("/{customer_id}")
                        .route(web::get().to(customers::customers_retrieve))
                        .route(web::post().to(customers::customers_update))
                        .route(web::delete().to(customers::customers_delete)),
                )
        }

        route
    }
}
pub struct Refunds;

#[cfg(all(any(feature = "olap", feature = "oltp"), feature = "v1"))]
impl Refunds {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/refunds").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            route = route
                .service(web::resource("/list").route(web::post().to(refunds_list)))
                .service(web::resource("/profile/list").route(web::post().to(refunds_list_profile)))
                .service(web::resource("/filter").route(web::post().to(refunds_filter_list)))
                .service(web::resource("/v2/filter").route(web::get().to(get_refunds_filters)))
                .service(web::resource("/aggregate").route(web::get().to(get_refunds_aggregates)))
                .service(
                    web::resource("/profile/aggregate")
                        .route(web::get().to(get_refunds_aggregate_profile)),
                )
                .service(
                    web::resource("/v2/profile/filter")
                        .route(web::get().to(get_refunds_filters_profile)),
                )
                .service(
                    web::resource("/{id}/manual-update")
                        .route(web::put().to(refunds_manual_update)),
                );
        }
        #[cfg(feature = "oltp")]
        {
            route = route
                .service(web::resource("").route(web::post().to(refunds_create)))
                .service(web::resource("/sync").route(web::post().to(refunds_retrieve_with_body)))
                .service(
                    web::resource("/{id}")
                        .route(web::get().to(refunds_retrieve))
                        .route(web::post().to(refunds_update)),
                );
        }
        route
    }
}

#[cfg(all(feature = "v2", any(feature = "olap", feature = "oltp")))]
impl Refunds {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/v2/refunds").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            route =
                route.service(web::resource("/list").route(web::post().to(refunds::refunds_list)));
        }
        #[cfg(feature = "oltp")]
        {
            route = route
                .service(web::resource("").route(web::post().to(refunds::refunds_create)))
                .service(
                    web::resource("/{id}")
                        .route(web::get().to(refunds::refunds_retrieve))
                        .route(web::post().to(refunds::refunds_retrieve_with_gateway_creds)),
                )
                .service(
                    web::resource("/{id}/update-metadata")
                        .route(web::put().to(refunds::refunds_metadata_update)),
                );
        }

        route
    }
}

#[cfg(feature = "payouts")]
pub struct Payouts;

#[cfg(all(feature = "payouts", feature = "v1"))]
impl Payouts {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/payouts").app_data(web::Data::new(state));
        route = route.service(web::resource("/create").route(web::post().to(payouts_create)));

        #[cfg(feature = "olap")]
        {
            route = route
                .service(
                    web::resource("/list")
                        .route(web::get().to(payouts_list))
                        .route(web::post().to(payouts_list_by_filter)),
                )
                .service(
                    web::resource("/profile/list")
                        .route(web::get().to(payouts_list_profile))
                        .route(web::post().to(payouts_list_by_filter_profile)),
                )
                .service(
                    web::resource("/filter")
                        .route(web::post().to(payouts_list_available_filters_for_merchant)),
                )
                .service(
                    web::resource("/profile/filter")
                        .route(web::post().to(payouts_list_available_filters_for_profile)),
                );
        }
        route = route
            .service(
                web::resource("/{payout_id}")
                    .route(web::get().to(payouts_retrieve))
                    .route(web::put().to(payouts_update)),
            )
            .service(web::resource("/{payout_id}/confirm").route(web::post().to(payouts_confirm)))
            .service(web::resource("/{payout_id}/cancel").route(web::post().to(payouts_cancel)))
            .service(web::resource("/{payout_id}/fulfill").route(web::post().to(payouts_fulfill)));
        route
    }
}

#[cfg(all(feature = "v2", any(feature = "olap", feature = "oltp")))]
impl PaymentMethods {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/v2/payment-methods").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            route =
                route.service(web::resource("/filter").route(
                    web::get().to(
                        payment_methods::list_countries_currencies_for_connector_payment_method,
                    ),
                ));
        }
        #[cfg(feature = "oltp")]
        {
            route = route
                .service(
                    web::resource("")
                        .route(web::post().to(payment_methods::create_payment_method_api)),
                )
                .service(
                    web::resource("/create-intent")
                        .route(web::post().to(payment_methods::create_payment_method_intent_api)),
                );

            route = route.service(
                web::scope("/{id}")
                    .service(
                        web::resource("")
                            .route(web::get().to(payment_methods::payment_method_retrieve_api))
                            .route(web::delete().to(payment_methods::payment_method_delete_api)),
                    )
                    .service(web::resource("/list-enabled-payment-methods").route(
                        web::get().to(payment_methods::payment_method_session_list_payment_methods),
                    ))
                    .service(
                        web::resource("/update-saved-payment-method")
                            .route(web::put().to(payment_methods::payment_method_update_api)),
                    )
                    .service(
                        web::resource("/get-token")
                            .route(web::get().to(payment_methods::get_payment_method_token_data)),
                    ),
            );
        }

        route
    }
}
pub struct PaymentMethods;

#[cfg(all(feature = "v1", any(feature = "olap", feature = "oltp")))]
impl PaymentMethods {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/payment_methods").app_data(web::Data::new(state));
        #[cfg(feature = "olap")]
        {
            route =
                route.service(web::resource("/filter").route(
                    web::get().to(
                        payment_methods::list_countries_currencies_for_connector_payment_method,
                    ),
                ));
        }
        #[cfg(feature = "oltp")]
        {
            route = route
                .service(
                    web::resource("")
                        .route(web::post().to(payment_methods::create_payment_method_api))
                        .route(web::get().to(payment_methods::list_payment_method_api)), // TODO : added for sdk compatibility for now, need to deprecate this later
                )
                .service(
                    web::resource("/migrate")
                        .route(web::post().to(payment_methods::migrate_payment_method_api)),
                )
                .service(
                    web::resource("/migrate-batch")
                        .route(web::post().to(payment_methods::migrate_payment_methods)),
                )
                .service(
                    web::resource("/update-batch")
                        .route(web::post().to(payment_methods::update_payment_methods)),
                )
                .service(
                    web::resource("/tokenize-card")
                        .route(web::post().to(payment_methods::tokenize_card_api)),
                )
                .service(
                    web::resource("/tokenize-card-batch")
                        .route(web::post().to(payment_methods::tokenize_card_batch_api)),
                )
                .service(
                    web::resource("/collect")
                        .route(web::post().to(payment_methods::initiate_pm_collect_link_flow)),
                )
                .service(
                    web::resource("/collect/{merchant_id}/{collect_id}")
                        .route(web::get().to(payment_methods::render_pm_collect_link)),
                )
                .service(
                    web::resource("/{payment_method_id}")
                        .route(web::get().to(payment_methods::payment_method_retrieve_api))
                        .route(web::delete().to(payment_methods::payment_method_delete_api)),
                )
                .service(
                    web::resource("/{payment_method_id}/tokenize-card")
                        .route(web::post().to(payment_methods::tokenize_card_using_pm_api)),
                )
                .service(
                    web::resource("/{payment_method_id}/update")
                        .route(web::post().to(payment_methods::payment_method_update_api)),
                )
                .service(
                    web::resource("/{payment_method_id}/save")
                        .route(web::post().to(payment_methods::save_payment_method_api)),
                )
                .service(
                    web::resource("/auth/link").route(web::post().to(pm_auth::link_token_create)),
                )
                .service(
                    web::resource("/auth/exchange").route(web::post().to(pm_auth::exchange_token)),
                )
        }
        route
    }
}

#[cfg(all(feature = "v2", feature = "oltp"))]
pub struct PaymentMethodSession;

#[cfg(all(feature = "v2", feature = "oltp"))]
impl PaymentMethodSession {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/v2/payment-method-sessions").app_data(web::Data::new(state));
        route = route.service(
            web::resource("")
                .route(web::post().to(payment_methods::payment_methods_session_create)),
        );

        route =
            route.service(
                web::scope("/{payment_method_session_id}")
                    .service(
                        web::resource("")
                            .route(web::get().to(payment_methods::payment_methods_session_retrieve))
                            .route(web::put().to(payment_methods::payment_methods_session_update))
                            .route(web::delete().to(
                                payment_methods::payment_method_session_delete_saved_payment_method,
                            )),
                    )
                    .service(web::resource("/list-payment-methods").route(
                        web::get().to(payment_methods::payment_method_session_list_payment_methods),
                    ))
                    .service(
                        web::resource("/confirm")
                            .route(web::post().to(payment_methods::payment_method_session_confirm)),
                    )
                    .service(web::resource("/update-saved-payment-method").route(
                        web::put().to(
                            payment_methods::payment_method_session_update_saved_payment_method,
                        ),
                    )),
            );

        route
    }
}

#[cfg(all(feature = "v2", feature = "oltp"))]
pub struct Tokenization;

#[cfg(all(feature = "v2", feature = "oltp"))]
impl Tokenization {
    pub fn server(state: AppState) -> Scope {
        web::scope("/v2/tokenize")
            .app_data(web::Data::new(state))
            .service(
                web::resource("")
                    .route(web::post().to(tokenization_routes::create_token_vault_api)),
            )
            .service(
                web::resource("/{id}")
                    .route(web::delete().to(tokenization_routes::delete_tokenized_data_api)),
            )
    }
}

#[cfg(all(feature = "olap", feature = "recon", feature = "v1"))]
pub struct Recon;

#[cfg(all(feature = "olap", feature = "recon", feature = "v1"))]
impl Recon {
    pub fn server(state: AppState) -> Scope {
        web::scope("/recon")
            .app_data(web::Data::new(state))
            .service(
                web::resource("/{merchant_id}/update")
                    .route(web::post().to(recon_routes::update_merchant)),
            )
            .service(web::resource("/token").route(web::get().to(recon_routes::get_recon_token)))
            .service(
                web::resource("/request").route(web::post().to(recon_routes::request_for_recon)),
            )
            .service(
                web::resource("/verify_token")
                    .route(web::get().to(recon_routes::verify_recon_token)),
            )
    }
}

pub struct Hypersense;

impl Hypersense {
    pub fn server(state: AppState) -> Scope {
        web::scope("/hypersense")
            .app_data(web::Data::new(state))
            .service(
                web::resource("/token")
                    .route(web::get().to(hypersense_routes::get_hypersense_token)),
            )
            .service(
                web::resource("/verify_token")
                    .route(web::post().to(hypersense_routes::verify_hypersense_token)),
            )
            .service(
                web::resource("/signout")
                    .route(web::post().to(hypersense_routes::signout_hypersense_token)),
            )
    }
}

#[cfg(feature = "olap")]
pub struct Blocklist;

#[cfg(all(feature = "olap", feature = "v1"))]
impl Blocklist {
    pub fn server(state: AppState) -> Scope {
        web::scope("/blocklist")
            .app_data(web::Data::new(state))
            .service(
                web::resource("")
                    .route(web::get().to(blocklist::list_blocked_payment_methods))
                    .route(web::post().to(blocklist::add_entry_to_blocklist))
                    .route(web::delete().to(blocklist::remove_entry_from_blocklist)),
            )
            .service(
                web::resource("/toggle").route(web::post().to(blocklist::toggle_blocklist_guard)),
            )
    }
}

#[cfg(feature = "olap")]
pub struct Organization;

#[cfg(all(feature = "olap", feature = "v1"))]
impl Organization {
    pub fn server(state: AppState) -> Scope {
        web::scope("/organization")
            .app_data(web::Data::new(state))
            .service(web::resource("").route(web::post().to(admin::organization_create)))
            .service(
                web::resource("/{id}")
                    .route(web::get().to(admin::organization_retrieve))
                    .route(web::put().to(admin::organization_update)),
            )
    }
}

#[cfg(all(feature = "v2", feature = "olap"))]
impl Organization {
    pub fn server(state: AppState) -> Scope {
        web::scope("/v2/organizations")
            .app_data(web::Data::new(state))
            .service(web::resource("").route(web::post().to(admin::organization_create)))
            .service(
                web::scope("/{id}")
                    .service(
                        web::resource("")
                            .route(web::get().to(admin::organization_retrieve))
                            .route(web::put().to(admin::organization_update)),
                    )
                    .service(
                        web::resource("/merchant-accounts")
                            .route(web::get().to(admin::merchant_account_list)),
                    ),
            )
    }
}

pub struct MerchantAccount;

#[cfg(all(feature = "v2", feature = "olap"))]
impl MerchantAccount {
    pub fn server(state: AppState) -> Scope {
        web::scope("/v2/merchant-accounts")
            .app_data(web::Data::new(state))
            .service(web::resource("").route(web::post().to(admin::merchant_account_create)))
            .service(
                web::scope("/{id}")
                    .service(
                        web::resource("")
                            .route(web::get().to(admin::retrieve_merchant_account))
                            .route(web::put().to(admin::update_merchant_account)),
                    )
                    .service(
                        web::resource("/profiles").route(web::get().to(profiles::profiles_list)),
                    )
                    .service(
                        web::resource("/kv")
                            .route(web::post().to(admin::merchant_account_toggle_kv))
                            .route(web::get().to(admin::merchant_account_kv_status)),
                    ),
            )
    }
}

#[cfg(all(feature = "olap", feature = "v1"))]
impl MerchantAccount {
    pub fn server(state: AppState) -> Scope {
        let mut routes = web::scope("/accounts")
            .service(web::resource("").route(web::post().to(admin::merchant_account_create)))
            .service(web::resource("/list").route(web::get().to(admin::merchant_account_list)))
            .service(
                web::resource("/{id}/kv")
                    .route(web::post().to(admin::merchant_account_toggle_kv))
                    .route(web::get().to(admin::merchant_account_kv_status)),
            )
            .service(
                web::resource("/transfer")
                    .route(web::post().to(admin::merchant_account_transfer_keys)),
            )
            .service(
                web::resource("/kv").route(web::post().to(admin::merchant_account_toggle_all_kv)),
            )
            .service(
                web::resource("/{id}")
                    .route(web::get().to(admin::retrieve_merchant_account))
                    .route(web::post().to(admin::update_merchant_account))
                    .route(web::delete().to(admin::delete_merchant_account)),
            );
        if state.conf.platform.enabled {
            routes = routes.service(
                web::resource("/{id}/platform")
                    .route(web::post().to(admin::merchant_account_enable_platform_account)),
            )
        }
        routes.app_data(web::Data::new(state))
    }
}

pub struct MerchantConnectorAccount;

#[cfg(all(any(feature = "olap", feature = "oltp"), feature = "v2"))]
impl MerchantConnectorAccount {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/v2/connector-accounts").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            use super::admin::*;

            route = route
                .service(web::resource("").route(web::post().to(connector_create)))
                .service(
                    web::resource("/{id}")
                        .route(web::put().to(connector_update))
                        .route(web::get().to(connector_retrieve))
                        .route(web::delete().to(connector_delete)),
                );
        }
        route
    }
}

#[cfg(all(any(feature = "olap", feature = "oltp"), feature = "v1"))]
impl MerchantConnectorAccount {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/account").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            use super::admin::*;

            route = route
                .service(
                    web::resource("/connectors/verify")
                        .route(web::post().to(super::verify_connector::payment_connector_verify)),
                )
                .service(
                    web::resource("/{merchant_id}/connectors")
                        .route(web::post().to(connector_create))
                        .route(web::get().to(connector_list)),
                )
                .service(
                    web::resource("/{merchant_id}/connectors/{merchant_connector_id}")
                        .route(web::get().to(connector_retrieve))
                        .route(web::post().to(connector_update))
                        .route(web::delete().to(connector_delete)),
                );
        }
        #[cfg(feature = "oltp")]
        {
            route = route.service(
                web::resource("/payment_methods")
                    .route(web::get().to(payment_methods::list_payment_method_api)),
            );
        }
        route
    }
}

pub struct EphemeralKey;

#[cfg(all(feature = "v1", feature = "oltp"))]
impl EphemeralKey {
    pub fn server(config: AppState) -> Scope {
        web::scope("/ephemeral_keys")
            .app_data(web::Data::new(config))
            .service(web::resource("").route(web::post().to(ephemeral_key_create)))
            .service(web::resource("/{id}").route(web::delete().to(ephemeral_key_delete)))
    }
}

#[cfg(feature = "v2")]
impl EphemeralKey {
    pub fn server(config: AppState) -> Scope {
        web::scope("/v2/client-secret")
            .app_data(web::Data::new(config))
            .service(web::resource("").route(web::post().to(client_secret_create)))
            .service(web::resource("/{id}").route(web::delete().to(client_secret_delete)))
    }
}

pub struct Mandates;

#[cfg(all(any(feature = "olap", feature = "oltp"), feature = "v1"))]
impl Mandates {
    pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/mandates").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            route =
                route.service(web::resource("/list").route(web::get().to(retrieve_mandates_list)));
            route = route.service(web::resource("/{id}").route(web::get().to(get_mandate)));
        }
        #[cfg(feature = "oltp")]
        {
            route =
                route.service(web::resource("/revoke/{id}").route(web::post().to(revoke_mandate)));
        }
        route
    }
}

pub struct Webhooks;

#[cfg(all(feature = "oltp", feature = "v1"))]
impl Webhooks {
    pub fn server(config: AppState) -> Scope {
        use api_models::webhooks as webhook_type;

        #[allow(unused_mut)]
        let mut route = web::scope("/webhooks")
            .app_data(web::Data::new(config))
            .service(
                web::resource("/network_token_requestor/ref")
                    .route(
                        web::post().to(receive_network_token_requestor_incoming_webhook::<
                            webhook_type::OutgoingWebhook,
                        >),
                    )
                    .route(
                        web::get().to(receive_network_token_requestor_incoming_webhook::<
                            webhook_type::OutgoingWebhook,
                        >),
                    )
                    .route(
                        web::put().to(receive_network_token_requestor_incoming_webhook::<
                            webhook_type::OutgoingWebhook,
                        >),
                    ),
            )
            .service(
                web::resource("/{merchant_id}/{connector_id_or_name}")
                    .route(
                        web::post().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>),
                    )
                    .route(web::get().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>))
                    .route(
                        web::put().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>),
                    ),
            );

        #[cfg(feature = "frm")]
        {
            route = route.service(
                web::resource("/frm_fulfillment")
                    .route(web::post().to(frm_routes::frm_fulfillment)),
            );
        }

        route
    }
}

pub struct RelayWebhooks;

#[cfg(feature = "oltp")]
impl RelayWebhooks {
    pub fn server(state: AppState) -> Scope {
        use api_models::webhooks as webhook_type;
        web::scope("/webhooks/relay")
            .app_data(web::Data::new(state))
            .service(web::resource("/{merchant_id}/{connector_id}").route(
                web::post().to(receive_incoming_relay_webhook::<webhook_type::OutgoingWebhook>),
            ))
    }
}

#[cfg(all(feature = "oltp", feature = "v2"))]
impl Webhooks {
    pub fn server(config: AppState) -> Scope {
        use api_models::webhooks as webhook_type;

        #[allow(unused_mut)]
        let mut route = web::scope("/v2/webhooks")
            .app_data(web::Data::new(config))
            .service(
                web::resource("/{merchant_id}/{profile_id}/{connector_id}")
                    .route(
                        web::post().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>),
                    )
                    .route(web::get().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>))
                    .route(
                        web::put().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>),
                    ),
            );

        #[cfg(all(feature = "revenue_recovery", feature = "v2"))]
        {
            route = route.service(
                web::resource("/recovery/{merchant_id}/{profile_id}/{connector_id}").route(
                    web::post()
                        .to(recovery_receive_incoming_webhook::<webhook_type::OutgoingWebhook>),
                ),
            );
        }

        route
    }
}

pub struct Configs;

#[cfg(all(feature = "v1", any(feature = "olap", feature = "oltp")))]
impl Configs {
    pub fn server(config: AppState) -> Scope {
        web::scope("/configs")
            .app_data(web::Data::new(config))
            .service(web::resource("/").route(web::post().to(config_key_create)))
            .service(
                web::resource("/{key}")
                    .route(web::get().to(config_key_retrieve))
                    .route(web::post().to(config_key_update))
                    .route(web::delete().to(config_key_delete)),
            )
    }
}

#[cfg(all(feature = "v2", any(feature = "olap", feature = "oltp")))]
impl Configs {
    pub fn server(config: AppState) -> Scope {
        web::scope("/v2/configs")
            .app_data(web::Data::new(config))
            .service(web::resource("/").route(web::post().to(config_key_create)))
            .service(
                web::resource("/{key}")
                    .route(web::get().to(config_key_retrieve))
                    .route(web::post().to(config_key_update))
                    .route(web::delete().to(config_key_delete)),
            )
    }
}

pub struct ApplePayCertificatesMigration;

#[cfg(all(feature = "olap", feature = "v1"))]
impl ApplePayCertificatesMigration {
    pub fn server(state: AppState) -> Scope {
        web::scope("/apple_pay_certificates_migration")
            .app_data(web::Data::new(state))
            .service(web::resource("").route(
                web::post().to(apple_pay_certificates_migration::apple_pay_certificates_migration),
            ))
    }
}

pub struct Poll;

#[cfg(all(feature = "oltp", feature = "v1"))]
impl Poll {
    pub fn server(config: AppState) -> Scope {
        web::scope("/poll")
            .app_data(web::Data::new(config))
            .service(
                web::resource("/status/{poll_id}").route(web::get().to(poll::retrieve_poll_status)),
            )
    }
}

pub struct ApiKeys;

#[cfg(all(feature = "olap", feature = "v2"))]
impl ApiKeys {
    pub fn server(state: AppState) -> Scope {
        web::scope("/v2/api-keys")
            .app_data(web::Data::new(state))
            .service(web::resource("").route(web::post().to(api_keys::api_key_create)))
            .service(web::resource("/list").route(web::get().to(api_keys::api_key_list)))
            .service(
                web::resource("/{key_id}")
                    .route(web::get().to(api_keys::api_key_retrieve))
                    .route(web::put().to(api_keys::api_key_update))
                    .route(web::delete().to(api_keys::api_key_revoke)),
            )
    }
}

#[cfg(all(feature = "olap", feature = "v1"))]
impl ApiKeys {
    pub fn server(state: AppState) -> Scope {
        web::scope("/api_keys/{merchant_id}")
            .app_data(web::Data::new(state))
            .service(web::resource("").route(web::post().to(api_keys::api_key_create)))
            .service(web::resource("/list").route(web::get().to(api_keys::api_key_list)))
            .service(
                web::resource("/{key_id}")
                    .route(web::get().to(api_keys::api_key_retrieve))
                    .route(web::post().to(api_keys::api_key_update))
                    .route(web::delete().to(api_keys::api_key_revoke)),


// Struct: NuveiPayoutErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NuveiPayoutErrorResponse


// Struct: GenericTokenizationRequest
// File: crates/api_models/src/tokenization.rs
// Module: api_models
// Implementations: 0

pub struct GenericTokenizationRequest


// Struct: CashtocodeAuth
// File: crates/hyperswitch_connectors/src/connectors/cashtocode/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CashtocodeAuth


// Implementation: impl api::Payment for for Celero
// File: crates/hyperswitch_connectors/src/connectors/celero.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Payment for for Celero


// Struct: IssuerInformation
// File: crates/hyperswitch_connectors/src/connectors/bankofamerica/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct IssuerInformation


// Function: payments_update_metadata
// File: crates/openapi/src/routes/payments.rs
// Module: openapi

pub fn payments_update_metadata()