                    None
                }
            } else {
                logger::info!(
                    payment_method=?payment_data.payment_attempt.payment_method,
                    click_to_pay_enabled=?business_profile.is_click_to_pay_enabled,
                    "skipping unified authentication service call since payment conditions are not satisfied"
                );
                None
            }
        }
    })
}

pub enum PaymentExternalAuthenticationFlow {
    PreAuthenticationFlow {
        acquirer_details: Option<authentication::types::AcquirerDetails>,
        card: Box<hyperswitch_domain_models::payment_method_data::Card>,
        token: String,
    },
    PostAuthenticationFlow {
        authentication_id: id_type::AuthenticationId,
    },
}

#[cfg(feature = "v1")]
pub async fn get_payment_external_authentication_flow_during_confirm<F: Clone>(
    state: &SessionState,
    key_store: &domain::MerchantKeyStore,
    business_profile: &domain::Profile,
    payment_data: &mut PaymentData<F>,
    connector_call_type: &api::ConnectorCallType,
    mandate_type: Option<api_models::payments::MandateTransactionType>,
) -> RouterResult<Option<PaymentExternalAuthenticationFlow>> {
    let authentication_id = payment_data.payment_attempt.authentication_id.clone();
    let is_authentication_type_3ds = payment_data.payment_attempt.authentication_type
        == Some(common_enums::AuthenticationType::ThreeDs);
    let separate_authentication_requested = payment_data
        .payment_intent
        .request_external_three_ds_authentication
        .unwrap_or(false);
    let separate_three_ds_authentication_attempted = payment_data
        .payment_attempt
        .external_three_ds_authentication_attempted
        .unwrap_or(false);
    let connector_supports_separate_authn =
        authentication::utils::get_connector_data_if_separate_authn_supported(connector_call_type);
    logger::info!("is_pre_authn_call {:?}", authentication_id.is_none());
    logger::info!(
        "separate_authentication_requested {:?}",
        separate_authentication_requested
    );
    logger::info!(
        "payment connector supports external authentication: {:?}",
        connector_supports_separate_authn.is_some()
    );
    let card = payment_data.payment_method_data.as_ref().and_then(|pmd| {
        if let domain::PaymentMethodData::Card(card) = pmd {
            Some(card.clone())
        } else {
            None
        }
    });
    Ok(if separate_three_ds_authentication_attempted {
        authentication_id.map(|authentication_id| {
            PaymentExternalAuthenticationFlow::PostAuthenticationFlow { authentication_id }
        })
    } else if separate_authentication_requested
        && is_authentication_type_3ds
        && mandate_type
            != Some(api_models::payments::MandateTransactionType::RecurringMandateTransaction)
    {
        if let Some((connector_data, card)) = connector_supports_separate_authn.zip(card) {
            let token = payment_data
                .token
                .clone()
                .get_required_value("token")
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable(
                    "payment_data.token should not be None while making pre authentication call",
                )?;
            let payment_connector_mca = get_merchant_connector_account(
                state,
                &business_profile.merchant_id,
                None,
                key_store,
                business_profile.get_id(),
                connector_data.connector_name.to_string().as_str(),
                connector_data.merchant_connector_id.as_ref(),
            )
            .await?;
            let acquirer_details = payment_connector_mca
                .get_metadata()
                .clone()
                .and_then(|metadata| {
                    metadata
                    .peek()
                    .clone()
                    .parse_value::<authentication::types::AcquirerDetails>("AcquirerDetails")
                    .change_context(errors::ApiErrorResponse::PreconditionFailed {
                        message:
                            "acquirer_bin and acquirer_merchant_id not found in Payment Connector's Metadata"
                                .to_string(),
                    })
                    .inspect_err(|err| {
                        logger::error!(
                            "Failed to parse acquirer details from Payment Connector's Metadata: {:?}",
                            err
                        );
                    })
                    .ok()
                });
            Some(PaymentExternalAuthenticationFlow::PreAuthenticationFlow {
                card: Box::new(card),
                token,
                acquirer_details,
            })
        } else {
            None
        }
    } else {
        None
    })
}

pub fn get_redis_key_for_extended_card_info(
    merchant_id: &id_type::MerchantId,
    payment_id: &id_type::PaymentId,
) -> String {
    format!(
        "{}_{}_extended_card_info",
        merchant_id.get_string_repr(),
        payment_id.get_string_repr()
    )
}

pub fn check_integrity_based_on_flow<T, Request>(
    request: &Request,
    payment_response_data: &Result<PaymentsResponseData, ErrorResponse>,
) -> Result<(), common_utils::errors::IntegrityCheckError>
where
    T: FlowIntegrity,
    Request: GetIntegrityObject<T> + CheckIntegrity<Request, T>,
{
    let connector_transaction_id = match payment_response_data {
        Ok(resp_data) => match resp_data {
            PaymentsResponseData::TransactionResponse {
                connector_response_reference_id,
                ..
            } => connector_response_reference_id,
            PaymentsResponseData::TransactionUnresolvedResponse {
                connector_response_reference_id,
                ..
            } => connector_response_reference_id,
            PaymentsResponseData::PreProcessingResponse {
                connector_response_reference_id,
                ..
            } => connector_response_reference_id,
            _ => &None,
        },
        Err(_) => &None,
    };
    request.check_integrity(request, connector_transaction_id.to_owned())
}

pub async fn config_skip_saving_wallet_at_connector(
    db: &dyn StorageInterface,
    merchant_id: &id_type::MerchantId,
) -> CustomResult<Option<Vec<storage_enums::PaymentMethodType>>, errors::ApiErrorResponse> {
    let config = db
        .find_config_by_key_unwrap_or(
            &merchant_id.get_skip_saving_wallet_at_connector_key(),
            Some("[]".to_string()),
        )
        .await;
    Ok(match config {
        Ok(conf) => Some(
            serde_json::from_str::<Vec<storage_enums::PaymentMethodType>>(&conf.config)
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("skip_save_wallet_at_connector config parsing failed")?,
        ),
        Err(error) => {
            logger::error!(?error);
            None
        }
    })
}

#[cfg(feature = "v1")]
pub async fn override_setup_future_usage_to_on_session<F, D>(
    db: &dyn StorageInterface,
    payment_data: &mut D,
) -> CustomResult<(), errors::ApiErrorResponse>
where
    F: Clone,
    D: payments::OperationSessionGetters<F> + payments::OperationSessionSetters<F> + Send,
{
    if payment_data.get_payment_intent().setup_future_usage == Some(enums::FutureUsage::OffSession)
    {
        let skip_saving_wallet_at_connector_optional = config_skip_saving_wallet_at_connector(
            db,
            &payment_data.get_payment_intent().merchant_id,
        )
        .await?;

        if let Some(skip_saving_wallet_at_connector) = skip_saving_wallet_at_connector_optional {
            if let Some(payment_method_type) =
                payment_data.get_payment_attempt().get_payment_method_type()
            {
                if skip_saving_wallet_at_connector.contains(&payment_method_type) {
                    logger::debug!("Override setup_future_usage from off_session to on_session based on the merchant's skip_saving_wallet_at_connector configuration to avoid creating a connector mandate.");
                    payment_data
                        .set_setup_future_usage_in_payment_intent(enums::FutureUsage::OnSession);
                }
            }
        };
    };
    Ok(())
}

pub async fn validate_routing_id_with_profile_id(
    db: &dyn StorageInterface,
    routing_id: &id_type::RoutingId,
    profile_id: &id_type::ProfileId,
) -> CustomResult<(), errors::ApiErrorResponse> {
    let _routing_id = db
        .find_routing_algorithm_metadata_by_algorithm_id_profile_id(routing_id, profile_id)
        .await
        .map_err(|err| {
            if err.current_context().is_db_not_found() {
                logger::warn!(
                    "Routing id not found for routing id - {:?} and profile id - {:?}",
                    routing_id,
                    profile_id
                );
                err.change_context(errors::ApiErrorResponse::InvalidDataFormat {
                    field_name: "routing_algorithm_id".to_string(),
                    expected_format: "A valid routing_id that belongs to the business_profile"
                        .to_string(),
                })
            } else {
                err.change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to validate routing id")
            }
        })?;
    Ok(())
}

#[cfg(feature = "v1")]
pub async fn validate_merchant_connector_ids_in_connector_mandate_details(
    state: &SessionState,
    key_store: &domain::MerchantKeyStore,
    connector_mandate_details: &api_models::payment_methods::CommonMandateReference,
    merchant_id: &id_type::MerchantId,
    card_network: Option<api_enums::CardNetwork>,
) -> CustomResult<(), errors::ApiErrorResponse> {
    let db = &*state.store;
    let merchant_connector_account_list = db
        .find_merchant_connector_account_by_merchant_id_and_disabled_list(
            &state.into(),
            merchant_id,
            true,
            key_store,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::InternalServerError)?;

    let merchant_connector_account_details_hash_map: std::collections::HashMap<
        id_type::MerchantConnectorAccountId,
        domain::MerchantConnectorAccount,
    > = merchant_connector_account_list
        .iter()
        .map(|merchant_connector_account| {
            (
                merchant_connector_account.get_id(),
                merchant_connector_account.clone(),
            )
        })
        .collect();

    if let Some(payment_mandate_reference) = &connector_mandate_details.payments {
        let payments_map = payment_mandate_reference.0.clone();
        for (migrating_merchant_connector_id, migrating_connector_mandate_details) in payments_map {
            match (
                card_network.clone(),
                merchant_connector_account_details_hash_map.get(&migrating_merchant_connector_id),
            ) {
                (Some(enums::CardNetwork::Discover), Some(merchant_connector_account_details)) => {
                    if let ("cybersource", None) = (
                        merchant_connector_account_details.connector_name.as_str(),
                        migrating_connector_mandate_details
                            .original_payment_authorized_amount
                            .zip(
                                migrating_connector_mandate_details
                                    .original_payment_authorized_currency,
                            ),
                    ) {
                        Err(errors::ApiErrorResponse::MissingRequiredFields {
                            field_names: vec![
                                "original_payment_authorized_currency",
                                "original_payment_authorized_amount",
                            ],
                        })
                        .attach_printable(format!(
                            "Invalid connector_mandate_details provided for connector {migrating_merchant_connector_id:?}",

                        ))?
                    }
                }
                (_, Some(_)) => (),
                (_, None) => Err(errors::ApiErrorResponse::InvalidDataValue {
                    field_name: "merchant_connector_id",
                })
                .attach_printable_lazy(|| {
                    format!(
                        "{migrating_merchant_connector_id:?} invalid merchant connector id in connector_mandate_details",

                    )
                })?,
            }
        }
    } else {
        router_env::logger::error!("payment mandate reference not found");
    }
    Ok(())
}

pub fn validate_platform_request_for_marketplace(
    amount: api::Amount,
    split_payments: Option<common_types::payments::SplitPaymentsRequest>,
) -> Result<(), errors::ApiErrorResponse> {
    match split_payments {
        Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
            stripe_split_payment,
        )) => match amount {
            api::Amount::Zero => {
                if stripe_split_payment
                    .application_fees
                    .as_ref()
                    .map_or(MinorUnit::zero(), |amount| *amount)
                    != MinorUnit::zero()
                {
                    return Err(errors::ApiErrorResponse::InvalidDataValue {
                        field_name: "split_payments.stripe_split_payment.application_fees",
                    });
                }
            }
            api::Amount::Value(amount) => {
                if stripe_split_payment
                    .application_fees
                    .as_ref()
                    .map_or(MinorUnit::zero(), |amount| *amount)
                    > amount.into()
                {
                    return Err(errors::ApiErrorResponse::InvalidDataValue {
                        field_name: "split_payments.stripe_split_payment.application_fees",
                    });
                }
            }
        },
        Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(
            adyen_split_payment,
        )) => {
            let total_split_amount: i64 = adyen_split_payment
                .split_items
                .iter()
                .map(|split_item| {
                    split_item
                        .amount
                        .unwrap_or(MinorUnit::new(0))
                        .get_amount_as_i64()
                })
                .sum();

            match amount {
                api::Amount::Zero => {
                    if total_split_amount != 0 {
                        return Err(errors::ApiErrorResponse::InvalidDataValue {
                            field_name: "Sum of split amounts should be equal to the total amount",
                        });
                    }
                }
                api::Amount::Value(amount) => {
                    let i64_amount: i64 = amount.into();
                    if !adyen_split_payment.split_items.is_empty()
                        && i64_amount != total_split_amount
                    {
                        return Err(errors::ApiErrorResponse::PreconditionFailed {
                            message: "Sum of split amounts should be equal to the total amount"
                                .to_string(),
                        });
                    }
                }
            };
            adyen_split_payment
                .split_items
                .iter()
                .try_for_each(|split_item| {
                    match split_item.split_type {
                        common_enums::AdyenSplitType::BalanceAccount => {
                            if split_item.account.is_none() {
                                return Err(errors::ApiErrorResponse::MissingRequiredField {
                                    field_name:
                                        "split_payments.adyen_split_payment.split_items.account",
                                });
                            }
                        }
                        common_enums::AdyenSplitType::Commission
                        | enums::AdyenSplitType::Vat
                        | enums::AdyenSplitType::TopUp => {
                            if split_item.amount.is_none() {
                                return Err(errors::ApiErrorResponse::MissingRequiredField {
                                    field_name:
                                        "split_payments.adyen_split_payment.split_items.amount",
                                });
                            }
                            if let enums::AdyenSplitType::TopUp = split_item.split_type {
                                if split_item.account.is_none() {
                                    return Err(errors::ApiErrorResponse::MissingRequiredField {
                                        field_name:
                                            "split_payments.adyen_split_payment.split_items.account",
                                    });
                                }
                                if adyen_split_payment.store.is_some() {
                                    return Err(errors::ApiErrorResponse::PreconditionFailed {
                                        message: "Topup split payment is not available via Adyen Platform"
                                            .to_string(),
                                    });
                                }
                            }
                        }
                        enums::AdyenSplitType::AcquiringFees
                        | enums::AdyenSplitType::PaymentFee
                        | enums::AdyenSplitType::AdyenFees
                        | enums::AdyenSplitType::AdyenCommission
                        | enums::AdyenSplitType::AdyenMarkup
                        | enums::AdyenSplitType::Interchange
                        | enums::AdyenSplitType::SchemeFee => {}
                    };
                    Ok(())
                })?;
        }
        Some(common_types::payments::SplitPaymentsRequest::XenditSplitPayment(
            xendit_split_payment,
        )) => match xendit_split_payment {
            common_types::payments::XenditSplitRequest::MultipleSplits(
                xendit_multiple_split_payment,
            ) => {
                match amount {
                    api::Amount::Zero => {
                        let total_split_amount: i64 = xendit_multiple_split_payment
                            .routes
                            .iter()
                            .map(|route| {
                                route
                                    .flat_amount
                                    .unwrap_or(MinorUnit::new(0))
                                    .get_amount_as_i64()
                            })
                            .sum();

                        if total_split_amount != 0 {
                            return Err(errors::ApiErrorResponse::InvalidDataValue {
                                field_name:
                                    "Sum of split amounts should be equal to the total amount",
                            });
                        }
                    }
                    api::Amount::Value(amount) => {
                        let total_payment_amount: i64 = amount.into();
                        let total_split_amount: i64 = xendit_multiple_split_payment
                    .routes
                    .into_iter()
                    .map(|route| {
                        if route.flat_amount.is_none() && route.percent_amount.is_none() {
                            Err(errors::ApiErrorResponse::InvalidRequestData {
                                message: "Expected either split_payments.xendit_split_payment.routes.flat_amount or split_payments.xendit_split_payment.routes.percent_amount to be provided".to_string(),
                            })
                        } else if route.flat_amount.is_some() && route.percent_amount.is_some(){
                            Err(errors::ApiErrorResponse::InvalidRequestData {
                                message: "Expected either split_payments.xendit_split_payment.routes.flat_amount or split_payments.xendit_split_payment.routes.percent_amount, but not both".to_string(),
                            })
                        } else {
                            Ok(route
                                .flat_amount
                                .map(|amount| amount.get_amount_as_i64())
                                .or(route.percent_amount.map(|percentage| (percentage * total_payment_amount) / 100))
                                .unwrap_or(0))
                            }
                            })
                            .collect::<Result<Vec<i64>, _>>()?
                            .into_iter()
                            .sum();

                        if total_payment_amount < total_split_amount {
                            return Err(errors::ApiErrorResponse::PreconditionFailed {
                                message:
                                    "The sum of split amounts should not exceed the total amount"
                                        .to_string(),
                            });
                        }
                    }
                };
            }
            common_types::payments::XenditSplitRequest::SingleSplit(_) => (),
        },
        None => (),
    }
    Ok(())
}

pub async fn is_merchant_eligible_authentication_service(
    merchant_id: &id_type::MerchantId,
    state: &SessionState,
) -> RouterResult<bool> {
    let merchants_eligible_for_authentication_service = state
        .store
        .as_ref()
        .find_config_by_key_unwrap_or(
            consts::AUTHENTICATION_SERVICE_ELIGIBLE_CONFIG,
            Some("[]".to_string()),
        )
        .await;

    let auth_eligible_array: Vec<String> = match merchants_eligible_for_authentication_service {
        Ok(config) => serde_json::from_str(&config.config)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("unable to parse authentication service config")?,
        Err(err) => {
            logger::error!(
                "Error fetching authentication service enabled merchant config {:?}",
                err
            );
            Vec::new()
        }
    };

    Ok(auth_eligible_array.contains(&merchant_id.get_string_repr().to_owned()))
}

#[cfg(feature = "v1")]
pub async fn validate_allowed_payment_method_types_request(
    state: &SessionState,
    profile_id: &id_type::ProfileId,
    merchant_context: &domain::MerchantContext,
    allowed_payment_method_types: Option<Vec<common_enums::PaymentMethodType>>,
) -> CustomResult<(), errors::ApiErrorResponse> {
    if let Some(allowed_payment_method_types) = allowed_payment_method_types {
        let db = &*state.store;
        let all_connector_accounts = db
            .find_merchant_connector_account_by_merchant_id_and_disabled_list(
                &state.into(),
                merchant_context.get_merchant_account().get_id(),
                false,
                merchant_context.get_merchant_key_store(),
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to fetch merchant connector account for given merchant id")?;

        let filtered_connector_accounts = all_connector_accounts
            .filter_based_on_profile_and_connector_type(
                profile_id,
                ConnectorType::PaymentProcessor,
            );

        let supporting_payment_method_types: HashSet<_> = filtered_connector_accounts
            .iter()
            .flat_map(|connector_account| {
                connector_account
                    .payment_methods_enabled
                    .clone()
                    .unwrap_or_default()
                    .into_iter()
                    .map(|payment_methods_enabled| {
                        payment_methods_enabled
                            .parse_value::<api_models::admin::PaymentMethodsEnabled>(
                                "payment_methods_enabled",
                            )
                    })
                    .filter_map(|parsed_payment_method_result| {
                        parsed_payment_method_result
                            .inspect_err(|err| {
                                logger::error!(
                                    "Unable to deserialize payment methods enabled: {:?}",
                                    err
                                );
                            })
                            .ok()
                    })
                    .flat_map(|parsed_payment_methods_enabled| {
                        parsed_payment_methods_enabled
                            .payment_method_types
                            .unwrap_or_default()
                            .into_iter()
                            .map(|payment_method_type| payment_method_type.payment_method_type)
                    })
            })
            .collect();

        let unsupported_payment_methods: Vec<_> = allowed_payment_method_types
            .iter()
            .filter(|allowed_pmt| !supporting_payment_method_types.contains(allowed_pmt))
            .collect();

        if !unsupported_payment_methods.is_empty() {
            metrics::PAYMENT_METHOD_TYPES_MISCONFIGURATION_METRIC.add(
                1,
                router_env::metric_attributes!((
                    "merchant_id",
                    merchant_context.get_merchant_account().get_id().clone()
                )),
            );
        }

        fp_utils::when(
            unsupported_payment_methods.len() == allowed_payment_method_types.len(),
            || {
                Err(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration)
                    .attach_printable(format!(
                        "None of the allowed payment method types {allowed_payment_method_types:?} are configured for this merchant connector account.",

                    ))
            },
        )?;
    }

    Ok(())
}

async fn get_payment_update_enabled_for_client_auth(
    merchant_id: &id_type::MerchantId,
    state: &SessionState,
) -> bool {
    let key = merchant_id.get_payment_update_enabled_for_client_auth_key();
    let db = &*state.store;
    let update_enabled = db.find_config_by_key(key.as_str()).await;

    match update_enabled {
        Ok(conf) => conf.config.to_lowercase() == "true",
        Err(error) => {
            logger::error!(?error);
            false
        }
    }
}

pub async fn allow_payment_update_enabled_for_client_auth(
    merchant_id: &id_type::MerchantId,
    state: &SessionState,
    auth_flow: services::AuthFlow,
) -> Result<(), error_stack::Report<errors::ApiErrorResponse>> {
    match auth_flow {
        services::AuthFlow::Client => {
            if get_payment_update_enabled_for_client_auth(merchant_id, state).await {
                Ok(())
            } else {
                Err(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Client auth for payment update is not enabled.")
            }
        }
        services::AuthFlow::Merchant => Ok(()),
    }
}

#[cfg(feature = "v2")]
#[instrument(skip_all)]
pub async fn get_merchant_connector_account_v2(
    state: &SessionState,
    key_store: &domain::MerchantKeyStore,
    merchant_connector_id: Option<&id_type::MerchantConnectorAccountId>,
) -> RouterResult<domain::MerchantConnectorAccount> {
    let db = &*state.store;
    match merchant_connector_id {
        Some(merchant_connector_id) => db
            .find_merchant_connector_account_by_id(&state.into(), merchant_connector_id, key_store)
            .await
            .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
                id: merchant_connector_id.get_string_repr().to_string(),
            }),
        None => Err(errors::ApiErrorResponse::MissingRequiredField {
            field_name: "merchant_connector_id",
        })
        .attach_printable("merchant_connector_id is not provided"),
    }
}

pub fn is_stored_credential(
    recurring_details: &Option<RecurringDetails>,
    payment_token: &Option<String>,
    is_mandate: bool,
    is_stored_credential_prev: Option<bool>,
) -> Option<bool> {
    if is_stored_credential_prev == Some(true)
        || recurring_details.is_some()
        || payment_token.is_some()
        || is_mandate
    {
        Some(true)
    } else {
        is_stored_credential_prev
    }
}


// Struct: ResultsResponseData
// File: crates/hyperswitch_connectors/src/connectors/netcetera/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ResultsResponseData


// Struct: BucketInformationEventResponse
// File: crates/router/src/core/payments/routing/utils.rs
// Module: router
// Implementations: 0

pub struct BucketInformationEventResponse


// Struct: GpaymentsPostAuthenticationResponse
// File: crates/hyperswitch_connectors/src/connectors/gpayments/gpayments_types.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct GpaymentsPostAuthenticationResponse


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

impl api::RefundExecute for for Jpmorgan


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

pub fn record_attempt_core(
    state: SessionState,
    req_state: ReqState,
    merchant_context: domain::MerchantContext,
    profile: domain::Profile,
    req: api_models::payments::PaymentsAttemptRecordRequest,
    payment_id: id_type::GlobalPaymentId,
    header_payload: HeaderPayload,
) -> RouterResponse<api_models::payments::PaymentAttemptRecordResponse>


// Struct: GenericVariableInput
// File: crates/hyperswitch_connectors/src/connectors/braintree/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct GenericVariableInput<T>


// Struct: ErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/riskified/transformers/api.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ErrorResponse


// Function: get_new_merchant
// File: crates/router/src/types/domain/user.rs
// Module: router

pub fn get_new_merchant(&self) -> NewUserMerchant


// File: crates/masking/src/diesel.rs
// Module: masking

//! Diesel-related.

use diesel::{
    backend::Backend,
    deserialize::{self, FromSql, Queryable},
    expression::AsExpression,
    internal::derives::as_expression::Bound,
    serialize::{self, Output, ToSql},
    sql_types,
};

use crate::{Secret, Strategy, StrongSecret, ZeroizableSecret};

impl<S, I, T> AsExpression<T> for &Secret<S, I>
where
    T: sql_types::SingleValue,
    I: Strategy<S>,
{
    type Expression = Bound<T, Self>;
    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<S, I, T> AsExpression<T> for &&Secret<S, I>
where
    T: sql_types::SingleValue,
    I: Strategy<S>,
{
    type Expression = Bound<T, Self>;
    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<S, I, T, DB> ToSql<T, DB> for Secret<S, I>
where
    DB: Backend,
    S: ToSql<T, DB>,
    I: Strategy<S>,
{
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> serialize::Result {
        ToSql::<T, DB>::to_sql(&self.inner_secret, out)
    }
}

impl<DB, S, T, I> FromSql<T, DB> for Secret<S, I>
where
    DB: Backend,
    S: FromSql<T, DB>,
    I: Strategy<S>,
{
    fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
        S::from_sql(bytes).map(|raw| raw.into())
    }
}

impl<S, I, T> AsExpression<T> for Secret<S, I>
where
    T: sql_types::SingleValue,
    I: Strategy<S>,
{
    type Expression = Bound<T, Self>;
    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<ST, DB, S, I> Queryable<ST, DB> for Secret<S, I>
where
    DB: Backend,
    I: Strategy<S>,
    ST: sql_types::SingleValue,
    Self: FromSql<ST, DB>,
{
    type Row = Self;
    fn build(row: Self::Row) -> deserialize::Result<Self> {
        Ok(row)
    }
}

impl<S, I, T> AsExpression<T> for &StrongSecret<S, I>
where
    T: sql_types::SingleValue,
    S: ZeroizableSecret,
    I: Strategy<S>,
{
    type Expression = Bound<T, Self>;
    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<S, I, T> AsExpression<T> for &&StrongSecret<S, I>
where
    T: sql_types::SingleValue,
    S: ZeroizableSecret,
    I: Strategy<S>,
{
    type Expression = Bound<T, Self>;
    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<S, I, DB, T> ToSql<T, DB> for StrongSecret<S, I>
where
    DB: Backend,
    S: ToSql<T, DB> + ZeroizableSecret,
    I: Strategy<S>,
{
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> serialize::Result {
        ToSql::<T, DB>::to_sql(&self.inner_secret, out)
    }
}

impl<DB, S, I, T> FromSql<T, DB> for StrongSecret<S, I>
where
    DB: Backend,
    S: FromSql<T, DB> + ZeroizableSecret,
    I: Strategy<S>,
{
    fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
        S::from_sql(bytes).map(|raw| raw.into())
    }
}

impl<S, I, T> AsExpression<T> for StrongSecret<S, I>
where
    T: sql_types::SingleValue,
    S: ZeroizableSecret,
    I: Strategy<S>,
{
    type Expression = Bound<T, Self>;
    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<ST, DB, S, I> Queryable<ST, DB> for StrongSecret<S, I>
where
    I: Strategy<S>,
    DB: Backend,
    S: ZeroizableSecret,
    ST: sql_types::SingleValue,
    Self: FromSql<ST, DB>,
{
    type Row = Self;
    fn build(row: Self::Row) -> deserialize::Result<Self> {
        Ok(row)
    }
}


// Function: new
// File: crates/diesel_models/src/invoice.rs
// Module: diesel_models

pub fn new(
        subscription_id: common_utils::id_type::SubscriptionId,
        merchant_id: common_utils::id_type::MerchantId,
        profile_id: common_utils::id_type::ProfileId,
        merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
        payment_intent_id: Option<common_utils::id_type::PaymentId>,
        payment_method_id: Option<String>,
        customer_id: common_utils::id_type::CustomerId,
        amount: MinorUnit,
        currency: String,
        status: InvoiceStatus,
        provider_name: Connector,
        metadata: Option<SecretSerdeValue>,
    ) -> Self


// Module Structure
// File: crates/router/src/core/mandate.rs
// Module: router

// Public submodules:
pub mod helpers;
pub mod utils;


// Struct: OrderDetailsWithAmount
// File: crates/diesel_models/src/types.rs
// Module: diesel_models
// Implementations: 1
// Traits: masking::SerializableSecret

pub struct OrderDetailsWithAmount


// Struct: AirwallexIntentRequest
// File: crates/hyperswitch_connectors/src/connectors/airwallex/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AirwallexIntentRequest


// Function: payments_update
// File: crates/router/src/routes/payments.rs
// Module: router

pub fn payments_update(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<payment_types::PaymentsRequest>,
    path: web::Path<common_utils::id_type::PaymentId>,
) -> impl Responder


// Implementation: impl Serializer for for PIISerializer
// File: crates/masking/src/serde.rs
// Module: masking
// Methods: 31 total (0 public)

impl Serializer for for PIISerializer


// Implementation: impl ConnectorCommon for for Loonio
// File: crates/hyperswitch_connectors/src/connectors/loonio.rs
// Module: hyperswitch_connectors
// Methods: 6 total (0 public)

impl ConnectorCommon for for Loonio


// Implementation: impl GatewayStatusMap
// File: crates/diesel_models/src/query/gsm.rs
// Module: diesel_models
// Methods: 4 total (0 public)

impl GatewayStatusMap


// Struct: OnlineMandate
// File: crates/router/src/compatibility/stripe/payment_intents/types.rs
// Module: router
// Implementations: 0

pub struct OnlineMandate


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

pub struct RefundResponse


// Struct: CartDetails
// File: crates/hyperswitch_connectors/src/connectors/amazonpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CartDetails


// File: crates/analytics/src/payment_intents/metrics/sessionized_metrics/smart_retried_amount.rs
// Module: analytics

use std::collections::HashSet;

use api_models::{
    analytics::{
        payment_intents::{
            PaymentIntentDimensions, PaymentIntentFilters, PaymentIntentMetricsBucketIdentifier,
        },
        Granularity, TimeRange,
    },
    enums::IntentStatus,
};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

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

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

#[async_trait::async_trait]
impl<T> super::PaymentIntentMetric<T> for SmartRetriedAmount
where
    T: AnalyticsDataSource + super::PaymentIntentMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[PaymentIntentDimensions],
        auth: &AuthInfo,
        filters: &PaymentIntentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentIntentMetricsBucketIdentifier, PaymentIntentMetricRow)>>
    {
        let mut query_builder: QueryBuilder<T> =
            QueryBuilder::new(AnalyticsCollection::PaymentIntentSessionized);

        for dim in dimensions.iter() {
            query_builder.add_select_column(dim).switch()?;
        }
        query_builder
            .add_select_column(Aggregate::Sum {
                field: "amount",
                alias: Some("total"),
            })
            .switch()?;

        query_builder
            .add_select_column("(attempt_count = 1) as first_attempt")
            .switch()?;

        query_builder.add_select_column("currency").switch()?;
        query_builder
            .add_select_column(Aggregate::Min {
                field: "created_at",
                alias: Some("start_bucket"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Max {
                field: "created_at",
                alias: Some("end_bucket"),
            })
            .switch()?;

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

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

        query_builder
            .add_custom_filter_clause("attempt_count", "1", FilterTypes::Gt)
            .switch()?;
        query_builder
            .add_custom_filter_clause("status", IntentStatus::Succeeded, FilterTypes::Equal)
            .switch()?;
        time_range
            .set_filter_clause(&mut query_builder)
            .attach_printable("Error filtering time range")
            .switch()?;

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

        query_builder
            .add_group_by_clause("first_attempt")
            .attach_printable("Error grouping by first_attempt")
            .switch()?;
        query_builder
            .add_group_by_clause("currency")
            .attach_printable("Error grouping by currency")
            .switch()?;
        if let Some(granularity) = granularity {
            granularity
                .set_group_by_clause(&mut query_builder)
                .attach_printable("Error adding granularity")
                .switch()?;
        }

        query_builder
            .execute_query::<PaymentIntentMetricRow, _>(pool)
            .await
            .change_context(MetricsError::QueryBuildingError)?
            .change_context(MetricsError::QueryExecutionFailure)?
            .into_iter()
            .map(|i| {
                Ok((
                    PaymentIntentMetricsBucketIdentifier::new(
                        i.status.as_ref().map(|i| i.0),
                        i.currency.as_ref().map(|i| i.0),
                        i.profile_id.clone(),
                        i.connector.clone(),
                        i.authentication_type.as_ref().map(|i| i.0),
                        i.payment_method.clone(),
                        i.payment_method_type.clone(),
                        i.card_network.clone(),
                        i.merchant_id.clone(),
                        i.card_last_4.clone(),
                        i.card_issuer.clone(),
                        i.error_reason.clone(),
                        TimeRange {
                            start_time: match (granularity, i.start_bucket) {
                                (Some(g), Some(st)) => g.clip_to_start(st)?,
                                _ => time_range.start_time,
                            },
                            end_time: granularity.as_ref().map_or_else(
                                || Ok(time_range.end_time),
                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
                            )?,
                        },
                    ),
                    i,
                ))
            })
            .collect::<error_stack::Result<
                HashSet<(PaymentIntentMetricsBucketIdentifier, PaymentIntentMetricRow)>,
                crate::query::PostProcessingError,
            >>()
            .change_context(MetricsError::PostProcessingFailure)
    }
}


// Function: new
// File: crates/external_services/src/file_storage/aws_s3.rs
// Module: external_services

// Documentation: Creates a new AWS S3 file storage client.

pub fn new(config: &AwsFileStorageConfig) -> Self


// Function: perform_redis_lock
// File: crates/router/src/core/webhooks/utils.rs
// Module: router

pub fn perform_redis_lock<A>(
    state: &A,
    unique_locking_key: &str,
    merchant_id: common_utils::id_type::MerchantId,
) -> RouterResult<Option<String>>
where
    A: SessionStateInfo,


// Implementation: impl Responder
// File: crates/router/src/analytics.rs
// Module: router
// Methods: 0 total (0 public)

impl Responder


// Struct: ErrorDistributionRow
// File: crates/analytics/src/payments/accumulator.rs
// Module: analytics
// Implementations: 0

pub struct ErrorDistributionRow


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

pub struct BankOfAmericaStandardErrorResponse


// Struct: FiservCaptureRequest
// File: crates/hyperswitch_connectors/src/connectors/fiserv/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FiservCaptureRequest


// File: crates/euclid/src/types.rs
// Module: euclid
// Public functions: 4
// Public structs: 4

pub mod transformers;

use common_utils::types::MinorUnit;
use euclid_macros::EnumNums;
use serde::{Deserialize, Serialize};
use strum::VariantNames;

use crate::{
    dssa::types::EuclidAnalysable,
    enums,
    frontend::{
        ast,
        dir::{
            enums::{CustomerDeviceDisplaySize, CustomerDevicePlatform, CustomerDeviceType},
            DirKeyKind, DirValue, EuclidDirFilter,
        },
    },
};

pub type Metadata = std::collections::HashMap<String, serde_json::Value>;

#[derive(
    Debug,
    Clone,
    EnumNums,
    Hash,
    PartialEq,
    Eq,
    strum::Display,
    strum::VariantNames,
    strum::EnumString,
)]
pub enum EuclidKey {
    #[strum(serialize = "payment_method")]
    PaymentMethod,
    #[strum(serialize = "card_bin")]
    CardBin,
    #[strum(serialize = "metadata")]
    Metadata,
    #[strum(serialize = "mandate_type")]
    MandateType,
    #[strum(serialize = "mandate_acceptance_type")]
    MandateAcceptanceType,
    #[strum(serialize = "payment_type")]
    PaymentType,
    #[strum(serialize = "payment_method_type")]
    PaymentMethodType,
    #[strum(serialize = "card_network")]
    CardNetwork,
    #[strum(serialize = "authentication_type")]
    AuthenticationType,
    #[strum(serialize = "capture_method")]
    CaptureMethod,
    #[strum(serialize = "amount")]
    PaymentAmount,
    #[strum(serialize = "currency")]
    PaymentCurrency,
    #[cfg(feature = "payouts")]
    #[strum(serialize = "payout_currency")]
    PayoutCurrency,
    #[strum(serialize = "country", to_string = "business_country")]
    BusinessCountry,
    #[strum(serialize = "billing_country")]
    BillingCountry,
    #[strum(serialize = "business_label")]
    BusinessLabel,
    #[strum(serialize = "setup_future_usage")]
    SetupFutureUsage,
    #[strum(serialize = "issuer_name")]
    IssuerName,
    #[strum(serialize = "issuer_country")]
    IssuerCountry,
    #[strum(serialize = "acquirer_country")]
    AcquirerCountry,
    #[strum(serialize = "acquirer_fraud_rate")]
    AcquirerFraudRate,
    #[strum(serialize = "customer_device_type")]
    CustomerDeviceType,
    #[strum(serialize = "customer_device_display_size")]
    CustomerDeviceDisplaySize,
    #[strum(serialize = "customer_device_platform")]
    CustomerDevicePlatform,
}

impl EuclidDirFilter for DummyOutput {
    const ALLOWED: &'static [DirKeyKind] = &[
        DirKeyKind::AuthenticationType,
        DirKeyKind::PaymentMethod,
        DirKeyKind::CardType,
        DirKeyKind::PaymentCurrency,
        DirKeyKind::CaptureMethod,
        DirKeyKind::AuthenticationType,
        DirKeyKind::CardBin,
        DirKeyKind::PayLaterType,
        DirKeyKind::PaymentAmount,
        DirKeyKind::MetaData,
        DirKeyKind::MandateAcceptanceType,
        DirKeyKind::MandateType,
        DirKeyKind::PaymentType,
        DirKeyKind::SetupFutureUsage,
    ];
}
impl EuclidAnalysable for DummyOutput {
    fn get_dir_value_for_analysis(&self, rule_name: String) -> Vec<(DirValue, Metadata)> {
        self.outputs
            .iter()
            .map(|dummyc| {
                let metadata_key = "MetadataKey".to_string();
                let metadata_value = dummyc;
                (
                    DirValue::MetaData(MetadataValue {
                        key: metadata_key.clone(),
                        value: metadata_value.clone(),
                    }),
                    std::collections::HashMap::from_iter([(
                        "DUMMY_OUTPUT".to_string(),
                        serde_json::json!({
                            "rule_name":rule_name,
                             "Metadata_Key" :metadata_key,
                             "Metadata_Value" : metadata_value,
                        }),
                    )]),
                )
            })
            .collect()
    }
}
#[derive(Debug, Clone, Serialize)]
pub struct DummyOutput {
    pub outputs: Vec<String>,
}

#[derive(Debug, Clone, serde::Serialize, strum::Display)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum DataType {
    Number,
    EnumVariant,
    MetadataValue,
    StrValue,
}

impl EuclidKey {
    pub fn key_type(&self) -> DataType {
        match self {
            Self::PaymentMethod => DataType::EnumVariant,
            Self::CardBin => DataType::StrValue,
            Self::Metadata => DataType::MetadataValue,
            Self::PaymentMethodType => DataType::EnumVariant,
            Self::CardNetwork => DataType::EnumVariant,
            Self::AuthenticationType => DataType::EnumVariant,
            Self::CaptureMethod => DataType::EnumVariant,
            Self::PaymentAmount => DataType::Number,
            Self::PaymentCurrency => DataType::EnumVariant,
            #[cfg(feature = "payouts")]
            Self::PayoutCurrency => DataType::EnumVariant,
            Self::BusinessCountry => DataType::EnumVariant,
            Self::BillingCountry => DataType::EnumVariant,
            Self::MandateType => DataType::EnumVariant,
            Self::MandateAcceptanceType => DataType::EnumVariant,
            Self::PaymentType => DataType::EnumVariant,
            Self::BusinessLabel => DataType::StrValue,
            Self::SetupFutureUsage => DataType::EnumVariant,
            Self::IssuerName => DataType::StrValue,
            Self::IssuerCountry => DataType::EnumVariant,
            Self::AcquirerCountry => DataType::EnumVariant,
            Self::AcquirerFraudRate => DataType::Number,
            Self::CustomerDeviceType => DataType::EnumVariant,
            Self::CustomerDeviceDisplaySize => DataType::EnumVariant,
            Self::CustomerDevicePlatform => DataType::EnumVariant,
        }
    }
}

enums::collect_variants!(EuclidKey);

#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum NumValueRefinement {
    NotEqual,
    GreaterThan,
    LessThan,
    GreaterThanEqual,
    LessThanEqual,
}

impl From<ast::ComparisonType> for Option<NumValueRefinement> {
    fn from(comp_type: ast::ComparisonType) -> Self {
        match comp_type {
            ast::ComparisonType::Equal => None,
            ast::ComparisonType::NotEqual => Some(NumValueRefinement::NotEqual),
            ast::ComparisonType::GreaterThan => Some(NumValueRefinement::GreaterThan),
            ast::ComparisonType::LessThan => Some(NumValueRefinement::LessThan),
            ast::ComparisonType::LessThanEqual => Some(NumValueRefinement::LessThanEqual),
            ast::ComparisonType::GreaterThanEqual => Some(NumValueRefinement::GreaterThanEqual),
        }
    }
}

impl From<NumValueRefinement> for ast::ComparisonType {
    fn from(value: NumValueRefinement) -> Self {
        match value {
            NumValueRefinement::NotEqual => Self::NotEqual,
            NumValueRefinement::LessThan => Self::LessThan,
            NumValueRefinement::GreaterThan => Self::GreaterThan,
            NumValueRefinement::GreaterThanEqual => Self::GreaterThanEqual,
            NumValueRefinement::LessThanEqual => Self::LessThanEqual,
        }
    }
}

#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct StrValue {
    pub value: String,
}

#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct MetadataValue {
    pub key: String,
    pub value: String,
}

#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct NumValue {
    pub number: MinorUnit,
    pub refinement: Option<NumValueRefinement>,
}

impl NumValue {
    pub fn fits(&self, other: &Self) -> bool {
        let this_num = self.number;
        let other_num = other.number;

        match (&self.refinement, &other.refinement) {
            (None, None) => this_num == other_num,

            (Some(NumValueRefinement::GreaterThan), None) => other_num > this_num,

            (Some(NumValueRefinement::LessThan), None) => other_num < this_num,

            (Some(NumValueRefinement::NotEqual), Some(NumValueRefinement::NotEqual)) => {
                other_num == this_num
            }

            (Some(NumValueRefinement::GreaterThan), Some(NumValueRefinement::GreaterThan)) => {
                other_num > this_num
            }
            (Some(NumValueRefinement::LessThan), Some(NumValueRefinement::LessThan)) => {
                other_num < this_num
            }

            (Some(NumValueRefinement::GreaterThanEqual), None) => other_num >= this_num,
            (Some(NumValueRefinement::LessThanEqual), None) => other_num <= this_num,
            (
                Some(NumValueRefinement::GreaterThanEqual),
                Some(NumValueRefinement::GreaterThanEqual),
            ) => other_num >= this_num,

            (Some(NumValueRefinement::LessThanEqual), Some(NumValueRefinement::LessThanEqual)) => {
                other_num <= this_num
            }

            _ => false,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum EuclidValue {
    PaymentMethod(enums::PaymentMethod),
    CardBin(StrValue),
    Metadata(MetadataValue),
    PaymentMethodType(enums::PaymentMethodType),
    CardNetwork(enums::CardNetwork),
    AuthenticationType(enums::AuthenticationType),
    CaptureMethod(enums::CaptureMethod),
    PaymentType(enums::PaymentType),
    MandateAcceptanceType(enums::MandateAcceptanceType),
    MandateType(enums::MandateType),
    PaymentAmount(NumValue),
    PaymentCurrency(enums::Currency),
    #[cfg(feature = "payouts")]
    PayoutCurrency(enums::Currency),
    BusinessCountry(enums::Country),
    BillingCountry(enums::Country),
    BusinessLabel(StrValue),
    SetupFutureUsage(enums::SetupFutureUsage),
    IssuerName(StrValue),
    IssuerCountry(enums::Country),
    AcquirerCountry(enums::Country),
    AcquirerFraudRate(NumValue),
    CustomerDeviceType(CustomerDeviceType),
    CustomerDeviceDisplaySize(CustomerDeviceDisplaySize),
    CustomerDevicePlatform(CustomerDevicePlatform),
}

impl EuclidValue {
    pub fn get_num_value(&self) -> Option<NumValue> {
        match self {
            Self::PaymentAmount(val) => Some(val.clone()),
            _ => None,
        }
    }

    pub fn get_key(&self) -> EuclidKey {
        match self {
            Self::PaymentMethod(_) => EuclidKey::PaymentMethod,
            Self::CardBin(_) => EuclidKey::CardBin,
            Self::Metadata(_) => EuclidKey::Metadata,
            Self::PaymentMethodType(_) => EuclidKey::PaymentMethodType,
            Self::MandateType(_) => EuclidKey::MandateType,
            Self::PaymentType(_) => EuclidKey::PaymentType,
            Self::MandateAcceptanceType(_) => EuclidKey::MandateAcceptanceType,
            Self::CardNetwork(_) => EuclidKey::CardNetwork,
            Self::AuthenticationType(_) => EuclidKey::AuthenticationType,
            Self::CaptureMethod(_) => EuclidKey::CaptureMethod,
            Self::PaymentAmount(_) => EuclidKey::PaymentAmount,
            Self::PaymentCurrency(_) => EuclidKey::PaymentCurrency,
            #[cfg(feature = "payouts")]
            Self::PayoutCurrency(_) => EuclidKey::PayoutCurrency,
            Self::BusinessCountry(_) => EuclidKey::BusinessCountry,
            Self::BillingCountry(_) => EuclidKey::BillingCountry,
            Self::BusinessLabel(_) => EuclidKey::BusinessLabel,
            Self::SetupFutureUsage(_) => EuclidKey::SetupFutureUsage,
            Self::IssuerName(_) => EuclidKey::IssuerName,
            Self::IssuerCountry(_) => EuclidKey::IssuerCountry,
            Self::AcquirerCountry(_) => EuclidKey::AcquirerCountry,
            Self::AcquirerFraudRate(_) => EuclidKey::AcquirerFraudRate,
            Self::CustomerDeviceType(_) => EuclidKey::CustomerDeviceType,
            Self::CustomerDeviceDisplaySize(_) => EuclidKey::CustomerDeviceDisplaySize,
            Self::CustomerDevicePlatform(_) => EuclidKey::CustomerDevicePlatform,
        }
    }
}

#[cfg(test)]
mod global_type_tests {
    use super::*;

    #[test]
    fn test_num_value_fits_greater_than() {
        let val1 = NumValue {
            number: MinorUnit::new(10),
            refinement: Some(NumValueRefinement::GreaterThan),
        };
        let val2 = NumValue {
            number: MinorUnit::new(30),
            refinement: Some(NumValueRefinement::GreaterThan),
        };

        assert!(val1.fits(&val2))
    }

    #[test]
    fn test_num_value_fits_less_than() {
        let val1 = NumValue {
            number: MinorUnit::new(30),
            refinement: Some(NumValueRefinement::LessThan),
        };
        let val2 = NumValue {
            number: MinorUnit::new(10),
            refinement: Some(NumValueRefinement::LessThan),
        };

        assert!(val1.fits(&val2));
    }
}


// Implementation: impl ActivePaymentsMetricAccumulator for for CountAccumulator
// File: crates/analytics/src/active_payments/accumulator.rs
// Module: analytics
// Methods: 2 total (0 public)

impl ActivePaymentsMetricAccumulator for for CountAccumulator


// Struct: NoonActionOrder
// File: crates/hyperswitch_connectors/src/connectors/noon/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NoonActionOrder


// Struct: DatatransRouterData
// File: crates/hyperswitch_connectors/src/connectors/datatrans/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DatatransRouterData<T>


// Struct: SubmitEvidenceResponse
// File: crates/hyperswitch_domain_models/src/router_response_types/disputes.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct SubmitEvidenceResponse


// Function: merchant_account_update
// File: crates/openapi/src/routes/merchant_account.rs
// Module: openapi

pub fn merchant_account_update()


// Implementation: impl api::PaymentSync for for Checkout
// File: crates/hyperswitch_connectors/src/connectors/checkout.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSync for for Checkout


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

impl api::RefundExecute for for Braintree


// Implementation: impl common_utils::events::ApiEventMetric for for RelayResponse
// File: crates/api_models/src/relay.rs
// Module: api_models
// Methods: 0 total (0 public)

impl common_utils::events::ApiEventMetric for for RelayResponse


// File: crates/analytics/src/metrics.rs
// Module: analytics

use router_env::{global_meter, histogram_metric_f64, histogram_metric_u64};

global_meter!(GLOBAL_METER, "ROUTER_API");

histogram_metric_f64!(METRIC_FETCH_TIME, GLOBAL_METER);
histogram_metric_u64!(BUCKETS_FETCHED, GLOBAL_METER);

pub mod request;


// Function: new
// File: crates/hyperswitch_connectors/src/connectors/globalpay.rs
// Module: hyperswitch_connectors

pub fn new() -> &'static Self


// Struct: GigadatRouterData
// File: crates/hyperswitch_connectors/src/connectors/gigadat/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct GigadatRouterData<T>


// Function: make_pm_graph
// File: crates/router/src/core/payment_methods/utils.rs
// Module: router

pub fn make_pm_graph(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    domain_id: cgraph::DomainId,
    payment_methods: &[masking::Secret<serde_json::value::Value>],
    connector: String,
    pm_config_mapping: &settings::ConnectorFilters,
    supported_payment_methods_for_mandate: &settings::SupportedPaymentMethodsForMandate,
    supported_payment_methods_for_update_mandate: &settings::SupportedPaymentMethodsForMandate,
) -> Result<(), KgraphError>


// Implementation: impl FileUpload for for Checkout
// File: crates/hyperswitch_connectors/src/connectors/checkout.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl FileUpload for for Checkout


// Struct: DlocalPaymentsCaptureResponse
// File: crates/hyperswitch_connectors/src/connectors/dlocal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DlocalPaymentsCaptureResponse


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

impl api::PaymentVoid for for Authipay


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

impl api::PaymentVoid for for Trustpay


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

impl Ebanx


// Struct: NextFlow
// File: crates/router/src/types/domain/user/decision_manager.rs
// Module: router
// Implementations: 1

pub struct NextFlow


// Struct: ThreeDSDecisionRule
// File: crates/common_types/src/three_ds_decision_rule_engine.rs
// Module: common_types
// Implementations: 2
// Traits: EuclidDirFilter

pub struct ThreeDSDecisionRule


// Implementation: impl api::revenue_recovery_v2::BillingConnectorPaymentsSyncIntegrationV2 for for Recurly
// File: crates/hyperswitch_connectors/src/connectors/recurly.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::revenue_recovery_v2::BillingConnectorPaymentsSyncIntegrationV2 for for Recurly


// Struct: CheckoutAuthType
// File: crates/hyperswitch_connectors/src/connectors/checkout/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CheckoutAuthType


// Struct: PaystackPSyncData
// File: crates/hyperswitch_connectors/src/connectors/paystack/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaystackPSyncData


// Module Structure
// File: crates/hyperswitch_connectors/src/connectors/fiuu.rs
// Module: hyperswitch_connectors

// Public submodules:
pub mod transformers;


// Struct: PaymeRedirectResponseData
// File: crates/hyperswitch_connectors/src/connectors/payme/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaymeRedirectResponseData


// Function: proxy_create_domain_model
// File: crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
// Module: hyperswitch_domain_models

pub fn proxy_create_domain_model(
        payment_intent: &super::PaymentIntent,
        cell_id: id_type::CellId,
        storage_scheme: storage_enums::MerchantStorageScheme,
        request: &api_models::payments::ProxyPaymentsRequest,
        encrypted_data: DecryptedPaymentAttempt,
    ) -> CustomResult<Self, errors::api_error_response::ApiErrorResponse>


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

pub struct CalSuccessRateEventResponse


// Struct: OrganizationCreateRequest
// File: crates/api_models/src/organization.rs
// Module: api_models
// Implementations: 0

pub struct OrganizationCreateRequest


// Struct: RoutableConnectorChoice
// File: crates/euclid/src/frontend/ast.rs
// Module: euclid
// Implementations: 0

pub struct RoutableConnectorChoice


// Struct: GpayDashboardPayLoad
// File: crates/connector_configs/src/common_config.rs
// Module: connector_configs
// Implementations: 0

pub struct GpayDashboardPayLoad


// File: crates/hyperswitch_connectors/src/connectors/itaubank.rs
// Module: hyperswitch_connectors
// Public functions: 1
// Public structs: 1

pub mod transformers;
use std::{fmt::Write, sync::LazyLock};

use api_models::webhooks::{IncomingWebhookEvent, ObjectReferenceId};
use common_enums::enums;
use common_utils::{
    errors::CustomResult,
    ext_traits::BytesExt,
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, StringMajorUnit, StringMajorUnitForConnector},
};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
    router_data::{AccessToken, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, SetupMandateRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    consts::{ACCEPT_HEADER, NO_ERROR_CODE, NO_ERROR_MESSAGE, USER_AGENT},
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
};
use masking::PeekInterface;
use transformers as itaubank;

use crate::{
    constants::headers,
    types::{RefreshTokenRouterData, ResponseRouterData},
    utils::{convert_amount, RefundsRequestData},
};

#[derive(Clone)]
pub struct Itaubank {
    amount_converter: &'static (dyn AmountConvertor<Output = StringMajorUnit> + Sync),
}

impl Itaubank {
    pub fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMajorUnitForConnector,
        }
    }
}

impl api::Payment for Itaubank {}
impl api::PaymentSession for Itaubank {}
impl api::ConnectorAccessToken for Itaubank {}
impl api::MandateSetup for Itaubank {}
impl api::PaymentAuthorize for Itaubank {}
impl api::PaymentSync for Itaubank {}
impl api::PaymentCapture for Itaubank {}
impl api::PaymentVoid for Itaubank {}
impl api::Refund for Itaubank {}
impl api::RefundExecute for Itaubank {}
impl api::RefundSync for Itaubank {}
impl api::PaymentToken for Itaubank {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Itaubank
{
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Itaubank
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let access_token =
            req.access_token
                .clone()
                .ok_or(errors::ConnectorError::MissingRequiredField {
                    field_name: "access_token",
                })?;

        let header = vec![
            (
                headers::AUTHORIZATION.to_string(),
                format!("Bearer {}", access_token.token.peek()).into(),
            ),
            (
                headers::ACCEPT.to_string(),
                ACCEPT_HEADER.to_string().into(),
            ),
            (
                headers::USER_AGENT.to_string(),
                USER_AGENT.to_string().into(),
            ),
            (
                headers::CONTENT_TYPE.to_string(),
                self.common_get_content_type().to_string().into(),
            ),
        ];

        Ok(header)
    }
}

impl ConnectorCommon for Itaubank {
    fn id(&self) -> &'static str {
        "itaubank"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Base
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.itaubank.base_url.as_ref()
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: itaubank::ItaubankErrorResponse = res
            .response
            .parse_struct("ItaubankErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        let reason = response
            .error
            .violacoes
            .map(|violacoes| {
                violacoes.iter().try_fold(String::new(), |mut acc, error| {
                    write!(
                        acc,
                        " razao - {}, propriedade - {}, valor - {};",
                        error.razao, error.propriedade, error.valor
                    )
                    .change_context(errors::ConnectorError::ResponseDeserializationFailed)
                    .attach_printable("Failed to concatenate error details")
                    .map(|_| acc)
                })
            })
            .transpose()?;

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.error.title.unwrap_or(NO_ERROR_CODE.to_string()),
            message: response
                .error
                .detail
                .unwrap_or(NO_ERROR_MESSAGE.to_string()),
            reason,
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

impl ConnectorValidation for Itaubank {}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Itaubank {}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Itaubank {
    fn get_url(
        &self,
        _req: &RefreshTokenRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}api/oauth/jwt", self.base_url(connectors)))
    }
    fn get_content_type(&self) -> &'static str {
        "application/x-www-form-urlencoded"
    }
    fn get_headers(
        &self,
        _req: &RefreshTokenRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let flow_header = vec![
            (
                headers::CONTENT_TYPE.to_string(),
                types::RefreshTokenType::get_content_type(self)
                    .to_string()
                    .into(),
            ),
            (
                headers::ACCEPT.to_string(),
                ACCEPT_HEADER.to_string().into(),
            ),
            (
                headers::USER_AGENT.to_string(),
                USER_AGENT.to_string().into(),
            ),
        ];
        Ok(flow_header)
    }
    fn get_request_body(
        &self,
        req: &RefreshTokenRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = itaubank::ItaubankAuthRequest::try_from(req)?;

        Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &RefreshTokenRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = itaubank::ItaubankAuthType::try_from(&req.connector_auth_type)?;
        let req = Some(
            RequestBuilder::new()
                .method(Method::Post)
                .attach_default_headers()
                .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
                .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
                .add_certificate(auth_details.certificate)
                .add_certificate_key(auth_details.certificate_key)
                .set_body(types::RefreshTokenType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        );

        Ok(req)
    }

    fn handle_response(
        &self,
        data: &RefreshTokenRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefreshTokenRouterData, errors::ConnectorError> {
        let response: itaubank::ItaubankUpdateTokenResponse = res
            .response
            .parse_struct("ItaubankUpdateTokenResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: itaubank::ItaubankTokenErrorResponse = res
            .response
            .parse_struct("ItaubankTokenErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_error_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.title.unwrap_or(NO_ERROR_CODE.to_string()),
            message: response
                .detail
                .to_owned()
                .or(response.user_message.to_owned())
                .unwrap_or(NO_ERROR_MESSAGE.to_string()),
            reason: response.detail.or(response.user_message),
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData>
    for Itaubank
{
    fn build_request(
        &self,
        _req: &SetupMandateRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(errors::ConnectorError::FlowNotSupported {
            flow: "setup mandate".to_string(),
            connector: "itaubank".to_string(),
        }
        .into())
    }
}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Itaubank {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}itau-ep9-gtw-pix-recebimentos-ext-v2/v2/cob",
            self.base_url(connectors)
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.currency,
        )?;

        let connector_router_data = itaubank::ItaubankRouterData::from((amount, req));
        let connector_req = itaubank::ItaubankPaymentsRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = itaubank::ItaubankAuthType::try_from(&req.connector_auth_type)?;
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsAuthorizeType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::PaymentsAuthorizeType::get_headers(
                    self, req, connectors,
                )?)
                .add_certificate(auth_details.certificate)
                .add_certificate_key(auth_details.certificate_key)
                .set_body(types::PaymentsAuthorizeType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
        let response: itaubank::ItaubankPaymentsResponse = res
            .response
            .parse_struct("Itaubank PaymentsAuthorizeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Itaubank {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}itau-ep9-gtw-pix-recebimentos-ext-v2/v2/cob/{}",
            self.base_url(connectors),
            req.request
                .connector_transaction_id
                .get_connector_transaction_id()
                .change_context(errors::ConnectorError::MissingConnectorTransactionID)?
        ))
    }

    fn build_request(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = itaubank::ItaubankAuthType::try_from(&req.connector_auth_type)?;
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
                .add_certificate(auth_details.certificate)
                .add_certificate_key(auth_details.certificate_key)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: itaubank::ItaubankPaymentsSyncResponse = res
            .response
            .parse_struct("itaubank PaymentsSyncResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Itaubank {
    fn get_headers(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    fn get_request_body(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
    }

    fn build_request(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = itaubank::ItaubankAuthType::try_from(&req.connector_auth_type)?;
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsCaptureType::get_headers(
                    self, req, connectors,
                )?)
                .add_certificate(auth_details.certificate)
                .add_certificate_key(auth_details.certificate_key)
                .set_body(types::PaymentsCaptureType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCaptureRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
        let response: itaubank::ItaubankPaymentsResponse = res
            .response
            .parse_struct("Itaubank PaymentsCaptureResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Itaubank {
    fn build_request(
        &self,
        _req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(errors::ConnectorError::FlowNotSupported {
            flow: "void".to_string(),
            connector: "itaubank".to_string(),
        }
        .into())
    }
}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Itaubank {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let itaubank_metadata = req.request.get_connector_metadata()?;
        let pix_data: itaubank::ItaubankMetaData = serde_json::from_value(itaubank_metadata)
            .change_context(errors::ConnectorError::MissingRequiredField {
                field_name: "itaubank_metadata",
            })?;
        Ok(format!(
            "{}itau-ep9-gtw-pix-recebimentos-ext-v2/v2/pix/{}/devolucao/{}",
            self.base_url(connectors),
            pix_data
                .pix_id
                .ok_or(errors::ConnectorError::MissingRequiredField {
                    field_name: "pix_id"
                })?,
            req.request.connector_transaction_id
        ))
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let refund_amount = convert_amount(
            self.amount_converter,
            req.request.minor_refund_amount,
            req.request.currency,
        )?;

        let connector_router_data = itaubank::ItaubankRouterData::from((refund_amount, req));
        let connector_req = itaubank::ItaubankRefundRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = itaubank::ItaubankAuthType::try_from(&req.connector_auth_type)?;
        let request = RequestBuilder::new()
            .method(Method::Put)
            .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(types::RefundExecuteType::get_headers(
                self, req, connectors,
            )?)
            .add_certificate(auth_details.certificate)
            .add_certificate_key(auth_details.certificate_key)
            .set_body(types::RefundExecuteType::get_request_body(
                self, req, connectors,
            )?)
            .build();
        Ok(Some(request))
    }

    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: itaubank::RefundResponse = res
            .response
            .parse_struct("itaubank RefundResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Itaubank {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let itaubank_metadata = req.request.get_connector_metadata()?;
        let pix_data: itaubank::ItaubankMetaData = serde_json::from_value(itaubank_metadata)
            .change_context(errors::ConnectorError::MissingRequiredField {
                field_name: "itaubank_metadata",
            })?;
        Ok(format!(
            "{}itau-ep9-gtw-pix-recebimentos-ext-v2/v2/pix/{}/devolucao/{}",
            self.base_url(connectors),
            pix_data
                .pix_id
                .ok_or(errors::ConnectorError::MissingRequiredField {
                    field_name: "pix_id"
                })?,
            req.request.connector_transaction_id
        ))
    }

    fn build_request(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = itaubank::ItaubankAuthType::try_from(&req.connector_auth_type)?;
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
                .add_certificate(auth_details.certificate)
                .add_certificate_key(auth_details.certificate_key)
                .set_body(types::RefundSyncType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: itaubank::RefundResponse = res
            .response
            .parse_struct("itaubank RefundResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[async_trait::async_trait]
impl IncomingWebhook for Itaubank {
    fn get_webhook_object_reference_id(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<ObjectReferenceId, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<IncomingWebhookEvent, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_resource_object(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }
}

static ITAUBANK_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> =
    LazyLock::new(|| {
        let mut itaubank_supported_payment_methods = SupportedPaymentMethods::new();
        let supported_capture_methods = vec![enums::CaptureMethod::Automatic];

        itaubank_supported_payment_methods.add(
            enums::PaymentMethod::BankTransfer,
            enums::PaymentMethodType::Pix,
            PaymentMethodDetails {
                mandates: enums::FeatureStatus::NotSupported,
                refunds: enums::FeatureStatus::Supported,
                supported_capture_methods,
                specific_features: None,
            },
        );

        itaubank_supported_payment_methods
    });

static ITAUBANK_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
        display_name: "Itaubank",
        description: "Itau Bank is a leading Brazilian financial institution offering a wide range of banking services, including retail banking, loans, and investment solutions.",
        connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
        integration_status: enums::ConnectorIntegrationStatus::Sandbox,
    };

static ITAUBANK_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 0] = [];

impl ConnectorSpecifications for Itaubank {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&ITAUBANK_CONNECTOR_INFO)
    }

    fn get_supported_payment_methods(&self) -> Option<&'static SupportedPaymentMethods> {
        Some(&*ITAUBANK_SUPPORTED_PAYMENT_METHODS)
    }

    fn get_supported_webhook_flows(&self) -> Option<&'static [enums::EventClass]> {
        Some(&ITAUBANK_SUPPORTED_WEBHOOK_FLOWS)
    }
}


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

pub fn get_vault_response_for_retrieve_payment_method_data_v1<F>(
    router_data: VaultRouterData<F>,
) -> RouterResult<hyperswitch_domain_models::vault::PaymentMethodVaultingData>


// Function: refresh_connector_auth
// File: crates/router/src/core/payouts/access_token.rs
// Module: router

pub fn refresh_connector_auth(
    state: &SessionState,
    connector: &api_types::ConnectorData,
    _merchant_context: &domain::MerchantContext,
    router_data: &types::RouterData<
        api_types::AccessTokenAuth,
        types::AccessTokenRequestData,
        types::AccessToken,
    >,
) -> RouterResult<Result<types::AccessToken, types::ErrorResponse>>


// Implementation: impl Responder
// File: crates/router/src/routes/routing.rs
// Module: router
// Methods: 0 total (0 public)

impl Responder


// Struct: FacilitapayPerson
// File: crates/hyperswitch_connectors/src/connectors/facilitapay/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FacilitapayPerson


// File: crates/router/src/db/invoice.rs
// Module: router

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

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

#[async_trait::async_trait]
pub trait InvoiceInterface {
    async fn insert_invoice_entry(
        &self,
        invoice_new: storage::invoice::InvoiceNew,
    ) -> CustomResult<storage::Invoice, errors::StorageError>;

    async fn find_invoice_by_invoice_id(
        &self,
        invoice_id: String,
    ) -> CustomResult<storage::Invoice, errors::StorageError>;

    async fn update_invoice_entry(
        &self,
        invoice_id: String,
        data: storage::invoice::InvoiceUpdate,
    ) -> CustomResult<storage::Invoice, errors::StorageError>;
}

#[async_trait::async_trait]
impl InvoiceInterface for Store {
    #[instrument(skip_all)]
    async fn insert_invoice_entry(
        &self,
        invoice_new: storage::invoice::InvoiceNew,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        invoice_new
            .insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn find_invoice_by_invoice_id(
        &self,
        invoice_id: String,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::Invoice::find_invoice_by_id_invoice_id(&conn, invoice_id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn update_invoice_entry(
        &self,
        invoice_id: String,
        data: storage::invoice::InvoiceUpdate,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::Invoice::update_invoice_entry(&conn, invoice_id, data)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl InvoiceInterface for MockDb {
    #[instrument(skip_all)]
    async fn insert_invoice_entry(
        &self,
        _invoice_new: storage::invoice::InvoiceNew,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn find_invoice_by_invoice_id(
        &self,
        _invoice_id: String,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn update_invoice_entry(
        &self,
        _invoice_id: String,
        _data: storage::invoice::InvoiceUpdate,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }
}

#[async_trait::async_trait]
impl InvoiceInterface for KafkaStore {
    #[instrument(skip_all)]
    async fn insert_invoice_entry(
        &self,
        invoice_new: storage::invoice::InvoiceNew,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        self.diesel_store.insert_invoice_entry(invoice_new).await
    }

    #[instrument(skip_all)]
    async fn find_invoice_by_invoice_id(
        &self,
        invoice_id: String,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        self.diesel_store
            .find_invoice_by_invoice_id(invoice_id)
            .await
    }

    #[instrument(skip_all)]
    async fn update_invoice_entry(
        &self,
        invoice_id: String,
        data: storage::invoice::InvoiceUpdate,
    ) -> CustomResult<storage::Invoice, errors::StorageError> {
        self.diesel_store
            .update_invoice_entry(invoice_id, data)
            .await
    }
}


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

pub fn reset_process_sync_task(
    db: &dyn StorageInterface,
    payment_attempt: &storage::PaymentAttempt,
    schedule_time: time::PrimitiveDateTime,
) -> Result<(), errors::ProcessTrackerError>


// Function: get_or_create_customer_details
// File: crates/router/src/core/payouts/helpers.rs
// Module: router

pub fn get_or_create_customer_details(
    _state: &SessionState,
    _customer_details: &CustomerDetails,
    _merchant_context: &domain::MerchantContext,
) -> RouterResult<Option<domain::Customer>>


// Implementation: impl api::PayoutFulfill for for Ebanx
// File: crates/hyperswitch_connectors/src/connectors/ebanx.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PayoutFulfill for for Ebanx