pub fn should_call_payout_connector_create_customer<'a>(
    state: &'a SessionState,
    connector: &'a api::ConnectorData,
    customer: &'a Option<domain::Customer>,
    merchant_connector_id: &'a domain::MerchantConnectorAccountTypeDetails,
) -> (bool, Option<&'a str>) {
    // Check if create customer is required for the connector
    match enums::PayoutConnectors::try_from(connector.connector_name) {
        Ok(connector) => {
            let connector_needs_customer = state
                .conf
                .connector_customer
                .payout_connector_list
                .contains(&connector);

            if connector_needs_customer {
                let connector_customer_details = customer
                    .as_ref()
                    .and_then(|customer| customer.get_connector_customer_id(merchant_connector_id));
                let should_call_connector = connector_customer_details.is_none();
                (should_call_connector, connector_customer_details)
            } else {
                (false, None)
            }
        }
        _ => (false, None),
    }
}

pub async fn get_gsm_record(
    state: &SessionState,
    error_code: Option<String>,
    error_message: Option<String>,
    connector_name: Option<String>,
    flow: &str,
) -> Option<hyperswitch_domain_models::gsm::GatewayStatusMap> {
    let connector_name = connector_name.unwrap_or_default();
    let get_gsm = || async {
        state.store.find_gsm_rule(
                connector_name.clone(),
                flow.to_string(),
                "sub_flow".to_string(),
                error_code.clone().unwrap_or_default(), // TODO: make changes in connector to get a mandatory code in case of success or error response
                error_message.clone().unwrap_or_default(),
            )
            .await
            .map_err(|err| {
                if err.current_context().is_db_not_found() {
                    logger::warn!(
                        "GSM miss for connector - {}, flow - {}, error_code - {:?}, error_message - {:?}",
                        connector_name,
                        flow,
                        error_code,
                        error_message
                    );
                    metrics::AUTO_PAYOUT_RETRY_GSM_MISS_COUNT.add( 1, &[]);
                } else {
                    metrics::AUTO_PAYOUT_RETRY_GSM_FETCH_FAILURE_COUNT.add( 1, &[]);
                };
                err.change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("failed to fetch decision from gsm")
            })
    };
    get_gsm()
        .await
        .inspect_err(|err| {
            // warn log should suffice here because we are not propagating this error
            logger::warn!(get_gsm_decision_fetch_error=?err, "error fetching gsm decision");
        })
        .ok()
}

pub fn is_payout_initiated(status: api_enums::PayoutStatus) -> bool {
    !matches!(
        status,
        api_enums::PayoutStatus::RequiresCreation
            | api_enums::PayoutStatus::RequiresConfirmation
            | api_enums::PayoutStatus::RequiresPayoutMethodData
            | api_enums::PayoutStatus::RequiresVendorAccountCreation
            | api_enums::PayoutStatus::Initiated
    )
}

pub(crate) fn validate_payout_status_against_not_allowed_statuses(
    payout_status: api_enums::PayoutStatus,
    not_allowed_statuses: &[api_enums::PayoutStatus],
    action: &'static str,
) -> Result<(), errors::ApiErrorResponse> {
    fp_utils::when(not_allowed_statuses.contains(&payout_status), || {
        Err(errors::ApiErrorResponse::PreconditionFailed {
            message: format!(
                "You cannot {action} this payout because it has status {payout_status}",
            ),
        })
    })
}

pub fn is_payout_terminal_state(status: api_enums::PayoutStatus) -> bool {
    !matches!(
        status,
        api_enums::PayoutStatus::RequiresCreation
            | api_enums::PayoutStatus::RequiresConfirmation
            | api_enums::PayoutStatus::RequiresPayoutMethodData
            | api_enums::PayoutStatus::RequiresVendorAccountCreation
            // Initiated by the underlying connector
            | api_enums::PayoutStatus::Pending
            | api_enums::PayoutStatus::Initiated
            | api_enums::PayoutStatus::RequiresFulfillment
    )
}

pub fn should_call_retrieve(status: api_enums::PayoutStatus) -> bool {
    matches!(
        status,
        api_enums::PayoutStatus::Pending | api_enums::PayoutStatus::Initiated
    )
}

pub fn is_payout_err_state(status: api_enums::PayoutStatus) -> bool {
    matches!(
        status,
        api_enums::PayoutStatus::Cancelled
            | api_enums::PayoutStatus::Failed
            | api_enums::PayoutStatus::Ineligible
    )
}

pub fn is_eligible_for_local_payout_cancellation(status: api_enums::PayoutStatus) -> bool {
    matches!(
        status,
        api_enums::PayoutStatus::RequiresCreation
            | api_enums::PayoutStatus::RequiresConfirmation
            | api_enums::PayoutStatus::RequiresPayoutMethodData
            | api_enums::PayoutStatus::RequiresVendorAccountCreation
    )
}

#[cfg(feature = "olap")]
pub(super) async fn filter_by_constraints(
    db: &dyn StorageInterface,
    constraints: &api::PayoutListConstraints,
    merchant_id: &id_type::MerchantId,
    storage_scheme: storage::enums::MerchantStorageScheme,
) -> CustomResult<Vec<storage::Payouts>, errors::StorageError> {
    let result = db
        .filter_payouts_by_constraints(merchant_id, &constraints.clone().into(), storage_scheme)
        .await?;
    Ok(result)
}

#[cfg(feature = "v2")]
pub async fn update_payouts_and_payout_attempt(
    _payout_data: &mut PayoutData,
    _merchant_context: &domain::MerchantContext,
    _req: &payouts::PayoutCreateRequest,
    _state: &SessionState,
) -> CustomResult<(), errors::ApiErrorResponse> {
    todo!()
}

#[cfg(feature = "v1")]
pub async fn update_payouts_and_payout_attempt(
    payout_data: &mut PayoutData,
    merchant_context: &domain::MerchantContext,
    req: &payouts::PayoutCreateRequest,
    state: &SessionState,
) -> CustomResult<(), errors::ApiErrorResponse> {
    let payout_attempt = payout_data.payout_attempt.to_owned();
    let status = payout_attempt.status;
    let payout_id = payout_attempt.payout_id.clone();
    // Verify update feasibility
    if is_payout_terminal_state(status) || is_payout_initiated(status) {
        return Err(report!(errors::ApiErrorResponse::InvalidRequestData {
            message: format!(
                "Payout {} cannot be updated for status {status}",
                payout_id.get_string_repr()
            ),
        }));
    }

    // Fetch customer details from request and create new or else use existing customer that was attached
    let customer = get_customer_details_from_request(req);
    let customer_id = if customer.customer_id.is_some()
        || customer.name.is_some()
        || customer.email.is_some()
        || customer.phone.is_some()
        || customer.phone_country_code.is_some()
    {
        payout_data.customer_details =
            get_or_create_customer_details(state, &customer, merchant_context).await?;
        payout_data
            .customer_details
            .as_ref()
            .map(|customer| customer.customer_id.clone())
    } else {
        payout_data.payouts.customer_id.clone()
    };

    let (billing_address, address_id) = resolve_billing_address_for_payout(
        state,
        req.billing.as_ref(),
        payout_data.payouts.address_id.as_ref(),
        payout_data.payment_method.as_ref(),
        merchant_context,
        customer_id.as_ref(),
        &payout_id,
    )
    .await?;

    // Update payout state with resolved billing address
    payout_data.billing_address = billing_address;

    // Update DB with new data
    let payouts = payout_data.payouts.to_owned();
    let amount = MinorUnit::from(req.amount.unwrap_or(payouts.amount.into()));
    let updated_payouts = storage::PayoutsUpdate::Update {
        amount,
        destination_currency: req
            .currency
            .to_owned()
            .unwrap_or(payouts.destination_currency),
        source_currency: req.currency.to_owned().unwrap_or(payouts.source_currency),
        description: req
            .description
            .to_owned()
            .clone()
            .or(payouts.description.clone()),
        recurring: req.recurring.to_owned().unwrap_or(payouts.recurring),
        auto_fulfill: req.auto_fulfill.to_owned().unwrap_or(payouts.auto_fulfill),
        return_url: req
            .return_url
            .to_owned()
            .clone()
            .or(payouts.return_url.clone()),
        entity_type: req.entity_type.to_owned().unwrap_or(payouts.entity_type),
        metadata: req.metadata.clone().or(payouts.metadata.clone()),
        status: Some(status),
        profile_id: Some(payout_attempt.profile_id.clone()),
        confirm: req.confirm.to_owned(),
        payout_type: req
            .payout_type
            .to_owned()
            .or(payouts.payout_type.to_owned()),
        address_id: address_id.clone(),
        customer_id: customer_id.clone(),
    };
    let db = &*state.store;
    payout_data.payouts = db
        .update_payout(
            &payouts,
            updated_payouts,
            &payout_attempt,
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Error updating payouts")?;
    let updated_business_country =
        payout_attempt
            .business_country
            .map_or(req.business_country.to_owned(), |c| {
                req.business_country
                    .to_owned()
                    .and_then(|nc| if nc != c { Some(nc) } else { None })
            });
    let updated_business_label =
        payout_attempt
            .business_label
            .map_or(req.business_label.to_owned(), |l| {
                req.business_label
                    .to_owned()
                    .and_then(|nl| if nl != l { Some(nl) } else { None })
            });
    if updated_business_country.is_some()
        || updated_business_label.is_some()
        || customer_id.is_some()
        || address_id.is_some()
    {
        let payout_attempt = &payout_data.payout_attempt;
        let updated_payout_attempt = storage::PayoutAttemptUpdate::BusinessUpdate {
            business_country: updated_business_country,
            business_label: updated_business_label,
            address_id,
            customer_id,
        };
        payout_data.payout_attempt = db
            .update_payout_attempt(
                payout_attempt,
                updated_payout_attempt,
                &payout_data.payouts,
                merchant_context.get_merchant_account().storage_scheme,
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Error updating payout_attempt")?;
    }
    Ok(())
}

pub(super) fn get_customer_details_from_request(
    request: &payouts::PayoutCreateRequest,
) -> CustomerDetails {
    let customer_id = request.get_customer_id().map(ToOwned::to_owned);

    let customer_name = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.name.clone())
        .or(request.name.clone());

    let customer_email = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.email.clone())
        .or(request.email.clone());

    let customer_phone = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.phone.clone())
        .or(request.phone.clone());

    let customer_phone_code = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.phone_country_code.clone())
        .or(request.phone_country_code.clone());

    let tax_registration_id = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.tax_registration_id.clone());

    CustomerDetails {
        customer_id,
        name: customer_name,
        email: customer_email,
        phone: customer_phone,
        phone_country_code: customer_phone_code,
        tax_registration_id,
    }
}

pub async fn get_translated_unified_code_and_message(
    state: &SessionState,
    unified_code: Option<&UnifiedCode>,
    unified_message: Option<&UnifiedMessage>,
    locale: &str,
) -> CustomResult<Option<UnifiedMessage>, errors::ApiErrorResponse> {
    Ok(unified_code
        .zip(unified_message)
        .async_and_then(|(code, message)| async {
            payment_helpers::get_unified_translation(
                state,
                code.0.clone(),
                message.0.clone(),
                locale.to_string(),
            )
            .await
            .map(UnifiedMessage::try_from)
        })
        .await
        .transpose()
        .change_context(errors::ApiErrorResponse::InvalidDataValue {
            field_name: "unified_message",
        })?
        .or_else(|| unified_message.cloned()))
}

pub async fn get_additional_payout_data(
    pm_data: &api::PayoutMethodData,
    db: &dyn StorageInterface,
    profile_id: &id_type::ProfileId,
) -> Option<payout_additional::AdditionalPayoutMethodData> {
    match pm_data {
        api::PayoutMethodData::Card(card_data) => {
            let card_isin = Some(card_data.card_number.get_card_isin());
            let enable_extended_bin =db
            .find_config_by_key_unwrap_or(
                format!("{}_enable_extended_card_bin", profile_id.get_string_repr()).as_str(),
             Some("false".to_string()))
            .await.map_err(|err| services::logger::error!(message="Failed to fetch the config", extended_card_bin_error=?err)).ok();

            let card_extended_bin = match enable_extended_bin {
                Some(config) if config.config == "true" => {
                    Some(card_data.card_number.get_extended_card_bin())
                }
                _ => None,
            };
            let last4 = Some(card_data.card_number.get_last4());

            let card_info = card_isin
                .clone()
                .async_and_then(|card_isin| async move {
                    db.get_card_info(&card_isin)
                        .await
                        .map_err(|error| services::logger::warn!(card_info_error=?error))
                        .ok()
                })
                .await
                .flatten()
                .map(|card_info| {
                    payout_additional::AdditionalPayoutMethodData::Card(Box::new(
                        payout_additional::CardAdditionalData {
                            card_issuer: card_info.card_issuer,
                            card_network: card_info.card_network.clone(),
                            bank_code: card_info.bank_code,
                            card_type: card_info.card_type,
                            card_issuing_country: card_info.card_issuing_country,
                            last4: last4.clone(),
                            card_isin: card_isin.clone(),
                            card_extended_bin: card_extended_bin.clone(),
                            card_exp_month: Some(card_data.expiry_month.clone()),
                            card_exp_year: Some(card_data.expiry_year.clone()),
                            card_holder_name: card_data.card_holder_name.clone(),
                        },
                    ))
                });
            Some(card_info.unwrap_or_else(|| {
                payout_additional::AdditionalPayoutMethodData::Card(Box::new(
                    payout_additional::CardAdditionalData {
                        card_issuer: None,
                        card_network: None,
                        bank_code: None,
                        card_type: None,
                        card_issuing_country: None,
                        last4,
                        card_isin,
                        card_extended_bin,
                        card_exp_month: Some(card_data.expiry_month.clone()),
                        card_exp_year: Some(card_data.expiry_year.clone()),
                        card_holder_name: card_data.card_holder_name.clone(),
                    },
                ))
            }))
        }
        api::PayoutMethodData::Bank(bank_data) => {
            Some(payout_additional::AdditionalPayoutMethodData::Bank(
                Box::new(bank_data.to_owned().into()),
            ))
        }
        api::PayoutMethodData::Wallet(wallet_data) => {
            Some(payout_additional::AdditionalPayoutMethodData::Wallet(
                Box::new(wallet_data.to_owned().into()),
            ))
        }
    }
}

pub async fn resolve_billing_address_for_payout(
    state: &SessionState,
    req_billing: Option<&api_models::payments::Address>,
    existing_address_id: Option<&String>,
    payment_method: Option<&hyperswitch_domain_models::payment_methods::PaymentMethod>,
    merchant_context: &domain::MerchantContext,
    customer_id: Option<&id_type::CustomerId>,
    payout_id: &id_type::PayoutId,
) -> RouterResult<(
    Option<hyperswitch_domain_models::address::Address>,
    Option<String>,
)> {
    let payout_id_as_payment_id = id_type::PaymentId::try_from(std::borrow::Cow::Owned(
        payout_id.get_string_repr().to_string(),
    ))
    .change_context(errors::ApiErrorResponse::InvalidRequestData {
        message: "payout_id contains invalid data for PaymentId conversion".to_string(),
    })
    .attach_printable("Error converting payout_id to PaymentId type")?;

    match (req_billing, existing_address_id, payment_method) {
        // Address in request
        (Some(_), _, _) => {
            let billing_address = payment_helpers::create_or_find_address_for_payment_by_request(
                state,
                req_billing,
                None,
                merchant_context.get_merchant_account().get_id(),
                customer_id,
                merchant_context.get_merchant_key_store(),
                &payout_id_as_payment_id,
                merchant_context.get_merchant_account().storage_scheme,
            )
            .await?;
            let address_id = billing_address.as_ref().map(|a| a.address_id.clone());
            let hyperswitch_address = billing_address
                .map(|addr| hyperswitch_domain_models::address::Address::from(&addr));
            Ok((hyperswitch_address, address_id))
        }

        // Existing address using address_id
        (None, Some(address_id), _) => {
            let billing_address = payment_helpers::create_or_find_address_for_payment_by_request(
                state,
                None,
                Some(address_id),
                merchant_context.get_merchant_account().get_id(),
                customer_id,
                merchant_context.get_merchant_key_store(),
                &payout_id_as_payment_id,
                merchant_context.get_merchant_account().storage_scheme,
            )
            .await?;
            let hyperswitch_address = billing_address
                .map(|addr| hyperswitch_domain_models::address::Address::from(&addr));
            Ok((hyperswitch_address, Some(address_id.clone())))
        }

        // Existing address in stored payment method
        (None, None, Some(pm)) => {
            pm.payment_method_billing_address.as_ref().map_or_else(
                || {
                    logger::info!("No billing address found in payment method");
                    Ok((None, None))
                },
                |encrypted_billing_address| {
                    logger::info!("Found encrypted billing address data in payment method");

                    #[cfg(feature = "v1")]
                    {
                        encrypted_billing_address
                            .clone()
                            .into_inner()
                            .expose()
                            .parse_value::<hyperswitch_domain_models::address::Address>(
                                "payment_method_billing_address",
                            )
                            .map(|domain_address| {
                                logger::info!("Successfully parsed as hyperswitch_domain_models::address::Address");
                                (Some(domain_address), None)
                            })
                            .map_err(|e| {
                                logger::error!("Failed to parse billing address into (hyperswitch_domain_models::address::Address): {:?}", e);
                                errors::ApiErrorResponse::InternalServerError
                            })
                            .attach_printable("Failed to parse stored billing address")
                    }

                    #[cfg(feature = "v2")]
                    {
                        // TODO: Implement v2 logic when needed
                        logger::warn!("v2 billing address resolution not yet implemented");
                        Ok((None, None))
                    }
                },
            )
        }

        (None, None, None) => Ok((None, None)),
    }
}


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

pub fn new() -> &'static Self


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

impl api::PaymentCapture for for Jpmorgan


// Implementation: impl TokenizationInterface for for KafkaStore
// File: crates/router/src/db/kafka_store.rs
// Module: router
// Methods: 0 total (0 public)

impl TokenizationInterface for for KafkaStore


// Function: delete_by_user_id
// File: crates/diesel_models/src/query/user.rs
// Module: diesel_models

pub fn delete_by_user_id(conn: &PgPooledConn, user_id: &str) -> StorageResult<bool>


// Implementation: impl api::Refund for for Noon
// File: crates/hyperswitch_connectors/src/connectors/noon.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Refund for for Noon


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

impl api::PaymentCapture for for Nordea


// Struct: UnifiedAuthenticationServiceRouterData
// File: crates/hyperswitch_connectors/src/connectors/unified_authentication_service/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct UnifiedAuthenticationServiceRouterData<T>


// Function: validate
// File: crates/router/src/configs/validations.rs
// Module: router

pub fn validate(&self) -> Result<(), ApplicationError>


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

impl PaymentVoid for for Netcetera


// Implementation: impl RevenueRecoveryInvoice
// File: crates/router/src/core/webhooks/recovery_incoming.rs
// Module: router
// Methods: 4 total (0 public)

impl RevenueRecoveryInvoice


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

impl api::PaymentToken for for Gocardless


// Struct: TokenioRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/tokenio/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TokenioRefundRequest


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

pub struct NewUserMerchant


// Implementation: impl EventInfo for for PaymentEvent
// File: crates/router/src/core/payments.rs
// Module: router
// Methods: 2 total (0 public)

impl EventInfo for for PaymentEvent


// Struct: CardStored
// File: crates/router/src/core/payment_methods/tokenize/card_executor.rs
// Module: router
// Implementations: 1
// Traits: State

pub struct CardStored


// Struct: BlackhawknetworkPaymentsRequest
// File: crates/hyperswitch_connectors/src/connectors/blackhawknetwork/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BlackhawknetworkPaymentsRequest


// Struct: SkipTwoFactorAuthQueryParam
// File: crates/api_models/src/user.rs
// Module: api_models
// Implementations: 0

pub struct SkipTwoFactorAuthQueryParam


// Function: get_four_digit_expiry_year
// File: crates/common_types/src/payments.rs
// Module: common_types

// Documentation: Get the four-digit expiration year from the Google Pay pre-decrypt data

pub fn get_four_digit_expiry_year(&self) -> Result<Secret<String>, errors::ValidationError>


// Function: get_dir_country_dir_value
// File: crates/kgraph_utils/src/transformers.rs
// Module: kgraph_utils

pub fn get_dir_country_dir_value(c: api_enums::Country) -> dir::enums::Country


// Struct: NovalnetTransaction
// File: crates/hyperswitch_connectors/src/connectors/novalnet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NovalnetTransaction


// Struct: PlaidSchedule
// File: crates/hyperswitch_connectors/src/connectors/plaid/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PlaidSchedule


// Struct: AuthenticationResponse
// File: crates/router/src/types/api/authentication.rs
// Module: router
// Implementations: 0

pub struct AuthenticationResponse


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

pub fn is_empty_result(&self) -> bool


// Implementation: impl RefundSync for for Threedsecureio
// File: crates/hyperswitch_connectors/src/connectors/threedsecureio.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl RefundSync for for Threedsecureio


// Struct: ChargebeePlanPriceItem
// File: crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ChargebeePlanPriceItem


// Function: call_proxy_api
// File: crates/router/src/core/revenue_recovery/api.rs
// Module: router

pub fn call_proxy_api(
    state: &SessionState,
    payment_intent: &payments_domain::PaymentIntent,
    revenue_recovery_payment_data: &storage::revenue_recovery::RevenueRecoveryPaymentData,
    revenue_recovery: &payments_api::PaymentRevenueRecoveryMetadata,
    payment_processor_token: &str,
) -> RouterResult<payments_domain::PaymentConfirmData<api_types::Authorize>>


// File: crates/hyperswitch_interfaces/src/api/files_v2.rs
// Module: hyperswitch_interfaces

//! Files V2 interface

use hyperswitch_domain_models::{
    router_data_v2::FilesFlowData,
    router_flow_types::{Retrieve, Upload},
    router_request_types::{RetrieveFileRequestData, UploadFileRequestData},
    router_response_types::{RetrieveFileResponse, UploadFileResponse},
};

use crate::api::{errors, files::FilePurpose, ConnectorCommon, ConnectorIntegrationV2};

/// trait UploadFileV2
pub trait UploadFileV2:
    ConnectorIntegrationV2<Upload, FilesFlowData, UploadFileRequestData, UploadFileResponse>
{
}

/// trait RetrieveFileV2
pub trait RetrieveFileV2:
    ConnectorIntegrationV2<Retrieve, FilesFlowData, RetrieveFileRequestData, RetrieveFileResponse>
{
}

/// trait FileUploadV2
pub trait FileUploadV2: ConnectorCommon + Sync + UploadFileV2 + RetrieveFileV2 {
    /// fn validate_file_upload_v2
    fn validate_file_upload_v2(
        &self,
        _purpose: FilePurpose,
        _file_size: i32,
        _file_type: mime::Mime,
    ) -> common_utils::errors::CustomResult<(), errors::ConnectorError> {
        Err(errors::ConnectorError::FileValidationFailed {
            reason: "".to_owned(),
        }
        .into())
    }
}


// Implementation: impl RequiredFromNullableWithDefault
// File: crates/diesel_models/src/lib.rs
// Module: diesel_models
// Methods: 1 total (1 public)

impl RequiredFromNullableWithDefault


// Function: spawn_error_handlers
// File: crates/drainer/src/handler.rs
// Module: drainer

pub fn spawn_error_handlers(&self, tx: mpsc::Sender<()


// File: crates/diesel_models/src/authentication.rs
// Module: diesel_models
// Public functions: 3
// Public structs: 3

use std::str::FromStr;

use common_utils::{
    encryption::Encryption,
    errors::{CustomResult, ValidationError},
    pii,
};
use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable};
use error_stack::ResultExt;
use serde::{self, Deserialize, Serialize};
use serde_json;

use crate::schema::authentication;

#[derive(
    Clone, Debug, Eq, PartialEq, Identifiable, Queryable, Selectable, Serialize, Deserialize,
)]
#[diesel(table_name = authentication,  primary_key(authentication_id), check_for_backend(diesel::pg::Pg))]
pub struct Authentication {
    pub authentication_id: common_utils::id_type::AuthenticationId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub authentication_connector: Option<String>,
    pub connector_authentication_id: Option<String>,
    pub authentication_data: Option<serde_json::Value>,
    pub payment_method_id: String,
    pub authentication_type: Option<common_enums::DecoupledAuthenticationType>,
    pub authentication_status: common_enums::AuthenticationStatus,
    pub authentication_lifecycle_status: common_enums::AuthenticationLifecycleStatus,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: time::PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: time::PrimitiveDateTime,
    pub error_message: Option<String>,
    pub error_code: Option<String>,
    pub connector_metadata: Option<serde_json::Value>,
    pub maximum_supported_version: Option<common_utils::types::SemanticVersion>,
    pub threeds_server_transaction_id: Option<String>,
    pub cavv: Option<String>,
    pub authentication_flow_type: Option<String>,
    pub message_version: Option<common_utils::types::SemanticVersion>,
    pub eci: Option<String>,
    pub trans_status: Option<common_enums::TransactionStatus>,
    pub acquirer_bin: Option<String>,
    pub acquirer_merchant_id: Option<String>,
    pub three_ds_method_data: Option<String>,
    pub three_ds_method_url: Option<String>,
    pub acs_url: Option<String>,
    pub challenge_request: Option<String>,
    pub acs_reference_number: Option<String>,
    pub acs_trans_id: Option<String>,
    pub acs_signed_content: Option<String>,
    pub profile_id: common_utils::id_type::ProfileId,
    pub payment_id: Option<common_utils::id_type::PaymentId>,
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    pub ds_trans_id: Option<String>,
    pub directory_server_id: Option<String>,
    pub acquirer_country_code: Option<String>,
    pub service_details: Option<serde_json::Value>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub authentication_client_secret: Option<String>,
    pub force_3ds_challenge: Option<bool>,
    pub psd2_sca_exemption_type: Option<common_enums::ScaExemptionType>,
    pub return_url: Option<String>,
    pub amount: Option<common_utils::types::MinorUnit>,
    pub currency: Option<common_enums::Currency>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub browser_info: Option<serde_json::Value>,
    pub email: Option<Encryption>,
    pub profile_acquirer_id: Option<common_utils::id_type::ProfileAcquirerId>,
    pub challenge_code: Option<String>,
    pub challenge_cancel: Option<String>,
    pub challenge_code_reason: Option<String>,
    pub message_extension: Option<pii::SecretSerdeValue>,
    pub challenge_request_key: Option<String>,
}

impl Authentication {
    pub fn is_separate_authn_required(&self) -> bool {
        self.maximum_supported_version
            .as_ref()
            .is_some_and(|version| version.get_major() == 2)
    }

    // get authentication_connector from authentication record and check if it is jwt flow
    pub fn is_jwt_flow(&self) -> CustomResult<bool, ValidationError> {
        Ok(self
            .authentication_connector
            .clone()
            .map(|connector| {
                common_enums::AuthenticationConnectors::from_str(&connector)
                    .change_context(ValidationError::InvalidValue {
                        message: "failed to parse authentication_connector".to_string(),
                    })
                    .map(|connector_enum| connector_enum.is_jwt_flow())
            })
            .transpose()?
            .unwrap_or(false))
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Insertable)]
#[diesel(table_name = authentication)]
pub struct AuthenticationNew {
    pub authentication_id: common_utils::id_type::AuthenticationId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub authentication_connector: Option<String>,
    pub connector_authentication_id: Option<String>,
    // pub authentication_data: Option<serde_json::Value>,
    pub payment_method_id: String,
    pub authentication_type: Option<common_enums::DecoupledAuthenticationType>,
    pub authentication_status: common_enums::AuthenticationStatus,
    pub authentication_lifecycle_status: common_enums::AuthenticationLifecycleStatus,
    pub error_message: Option<String>,
    pub error_code: Option<String>,
    pub connector_metadata: Option<serde_json::Value>,
    pub maximum_supported_version: Option<common_utils::types::SemanticVersion>,
    pub threeds_server_transaction_id: Option<String>,
    pub cavv: Option<String>,
    pub authentication_flow_type: Option<String>,
    pub message_version: Option<common_utils::types::SemanticVersion>,
    pub eci: Option<String>,
    pub trans_status: Option<common_enums::TransactionStatus>,
    pub acquirer_bin: Option<String>,
    pub acquirer_merchant_id: Option<String>,
    pub three_ds_method_data: Option<String>,
    pub three_ds_method_url: Option<String>,
    pub acs_url: Option<String>,
    pub challenge_request: Option<String>,
    pub acs_reference_number: Option<String>,
    pub acs_trans_id: Option<String>,
    pub acs_signed_content: Option<String>,
    pub profile_id: common_utils::id_type::ProfileId,
    pub payment_id: Option<common_utils::id_type::PaymentId>,
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    pub ds_trans_id: Option<String>,
    pub directory_server_id: Option<String>,
    pub acquirer_country_code: Option<String>,
    pub service_details: Option<serde_json::Value>,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub authentication_client_secret: Option<String>,
    pub force_3ds_challenge: Option<bool>,
    pub psd2_sca_exemption_type: Option<common_enums::ScaExemptionType>,
    pub return_url: Option<String>,
    pub amount: Option<common_utils::types::MinorUnit>,
    pub currency: Option<common_enums::Currency>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub browser_info: Option<serde_json::Value>,
    pub email: Option<Encryption>,
    pub profile_acquirer_id: Option<common_utils::id_type::ProfileAcquirerId>,
    pub challenge_code: Option<String>,
    pub challenge_cancel: Option<String>,
    pub challenge_code_reason: Option<String>,
    pub message_extension: Option<pii::SecretSerdeValue>,
    pub challenge_request_key: Option<String>,
}

#[derive(Debug)]
pub enum AuthenticationUpdate {
    PreAuthenticationVersionCallUpdate {
        maximum_supported_3ds_version: common_utils::types::SemanticVersion,
        message_version: common_utils::types::SemanticVersion,
    },
    PreAuthenticationThreeDsMethodCall {
        threeds_server_transaction_id: String,
        three_ds_method_data: Option<String>,
        three_ds_method_url: Option<String>,
        acquirer_bin: Option<String>,
        acquirer_merchant_id: Option<String>,
        connector_metadata: Option<serde_json::Value>,
    },
    PreAuthenticationUpdate {
        threeds_server_transaction_id: String,
        maximum_supported_3ds_version: common_utils::types::SemanticVersion,
        connector_authentication_id: String,
        three_ds_method_data: Option<String>,
        three_ds_method_url: Option<String>,
        message_version: common_utils::types::SemanticVersion,
        connector_metadata: Option<serde_json::Value>,
        authentication_status: common_enums::AuthenticationStatus,
        acquirer_bin: Option<String>,
        acquirer_merchant_id: Option<String>,
        directory_server_id: Option<String>,
        acquirer_country_code: Option<String>,
        billing_address: Option<Encryption>,
        shipping_address: Option<Encryption>,
        browser_info: Box<Option<serde_json::Value>>,
        email: Option<Encryption>,
    },
    AuthenticationUpdate {
        trans_status: common_enums::TransactionStatus,
        authentication_type: common_enums::DecoupledAuthenticationType,
        acs_url: Option<String>,
        challenge_request: Option<String>,
        acs_reference_number: Option<String>,
        acs_trans_id: Option<String>,
        acs_signed_content: Option<String>,
        connector_metadata: Option<serde_json::Value>,
        authentication_status: common_enums::AuthenticationStatus,
        ds_trans_id: Option<String>,
        eci: Option<String>,
        challenge_code: Option<String>,
        challenge_cancel: Option<String>,
        challenge_code_reason: Option<String>,
        message_extension: Option<pii::SecretSerdeValue>,
        challenge_request_key: Option<String>,
    },
    PostAuthenticationUpdate {
        trans_status: common_enums::TransactionStatus,
        eci: Option<String>,
        authentication_status: common_enums::AuthenticationStatus,
        challenge_cancel: Option<String>,
        challenge_code_reason: Option<String>,
    },
    ErrorUpdate {
        error_message: Option<String>,
        error_code: Option<String>,
        authentication_status: common_enums::AuthenticationStatus,
        connector_authentication_id: Option<String>,
    },
    PostAuthorizationUpdate {
        authentication_lifecycle_status: common_enums::AuthenticationLifecycleStatus,
    },
    AuthenticationStatusUpdate {
        trans_status: common_enums::TransactionStatus,
        authentication_status: common_enums::AuthenticationStatus,
    },
}

#[derive(Clone, Debug, Eq, PartialEq, AsChangeset, Serialize, Deserialize)]
#[diesel(table_name = authentication)]
pub struct AuthenticationUpdateInternal {
    pub connector_authentication_id: Option<String>,
    // pub authentication_data: Option<serde_json::Value>,
    pub payment_method_id: Option<String>,
    pub authentication_type: Option<common_enums::DecoupledAuthenticationType>,
    pub authentication_status: Option<common_enums::AuthenticationStatus>,
    pub authentication_lifecycle_status: Option<common_enums::AuthenticationLifecycleStatus>,
    pub modified_at: time::PrimitiveDateTime,
    pub error_message: Option<String>,
    pub error_code: Option<String>,
    pub connector_metadata: Option<serde_json::Value>,
    pub maximum_supported_version: Option<common_utils::types::SemanticVersion>,
    pub threeds_server_transaction_id: Option<String>,
    pub authentication_flow_type: Option<String>,
    pub message_version: Option<common_utils::types::SemanticVersion>,
    pub eci: Option<String>,
    pub trans_status: Option<common_enums::TransactionStatus>,
    pub acquirer_bin: Option<String>,
    pub acquirer_merchant_id: Option<String>,
    pub three_ds_method_data: Option<String>,
    pub three_ds_method_url: Option<String>,
    pub acs_url: Option<String>,
    pub challenge_request: Option<String>,
    pub acs_reference_number: Option<String>,
    pub acs_trans_id: Option<String>,
    pub acs_signed_content: Option<String>,
    pub ds_trans_id: Option<String>,
    pub directory_server_id: Option<String>,
    pub acquirer_country_code: Option<String>,
    pub service_details: Option<serde_json::Value>,
    pub force_3ds_challenge: Option<bool>,
    pub psd2_sca_exemption_type: Option<common_enums::ScaExemptionType>,
    pub billing_address: Option<Encryption>,
    pub shipping_address: Option<Encryption>,
    pub browser_info: Option<serde_json::Value>,
    pub email: Option<Encryption>,
    pub profile_acquirer_id: Option<common_utils::id_type::ProfileAcquirerId>,
    pub challenge_code: Option<String>,
    pub challenge_cancel: Option<String>,
    pub challenge_code_reason: Option<String>,
    pub message_extension: Option<pii::SecretSerdeValue>,
    pub challenge_request_key: Option<String>,
}

impl Default for AuthenticationUpdateInternal {
    fn default() -> Self {
        Self {
            connector_authentication_id: Default::default(),
            payment_method_id: Default::default(),
            authentication_type: Default::default(),
            authentication_status: Default::default(),
            authentication_lifecycle_status: Default::default(),
            modified_at: common_utils::date_time::now(),
            error_message: Default::default(),
            error_code: Default::default(),
            connector_metadata: Default::default(),
            maximum_supported_version: Default::default(),
            threeds_server_transaction_id: Default::default(),
            authentication_flow_type: Default::default(),
            message_version: Default::default(),
            eci: Default::default(),
            trans_status: Default::default(),
            acquirer_bin: Default::default(),
            acquirer_merchant_id: Default::default(),
            three_ds_method_data: Default::default(),
            three_ds_method_url: Default::default(),
            acs_url: Default::default(),
            challenge_request: Default::default(),
            acs_reference_number: Default::default(),
            acs_trans_id: Default::default(),
            acs_signed_content: Default::default(),
            ds_trans_id: Default::default(),
            directory_server_id: Default::default(),
            acquirer_country_code: Default::default(),
            service_details: Default::default(),
            force_3ds_challenge: Default::default(),
            psd2_sca_exemption_type: Default::default(),
            billing_address: Default::default(),
            shipping_address: Default::default(),
            browser_info: Default::default(),
            email: Default::default(),
            profile_acquirer_id: Default::default(),
            challenge_code: Default::default(),
            challenge_cancel: Default::default(),
            challenge_code_reason: Default::default(),
            message_extension: Default::default(),
            challenge_request_key: Default::default(),
        }
    }
}

impl AuthenticationUpdateInternal {
    pub fn apply_changeset(self, source: Authentication) -> Authentication {
        let Self {
            connector_authentication_id,
            payment_method_id,
            authentication_type,
            authentication_status,
            authentication_lifecycle_status,
            modified_at: _,
            error_code,
            error_message,
            connector_metadata,
            maximum_supported_version,
            threeds_server_transaction_id,
            authentication_flow_type,
            message_version,
            eci,
            trans_status,
            acquirer_bin,
            acquirer_merchant_id,
            three_ds_method_data,
            three_ds_method_url,
            acs_url,
            challenge_request,
            acs_reference_number,
            acs_trans_id,
            acs_signed_content,
            ds_trans_id,
            directory_server_id,
            acquirer_country_code,
            service_details,
            force_3ds_challenge,
            psd2_sca_exemption_type,
            billing_address,
            shipping_address,
            browser_info,
            email,
            profile_acquirer_id,
            challenge_code,
            challenge_cancel,
            challenge_code_reason,
            message_extension,
            challenge_request_key,
        } = self;
        Authentication {
            connector_authentication_id: connector_authentication_id
                .or(source.connector_authentication_id),
            payment_method_id: payment_method_id.unwrap_or(source.payment_method_id),
            authentication_type: authentication_type.or(source.authentication_type),
            authentication_status: authentication_status.unwrap_or(source.authentication_status),
            authentication_lifecycle_status: authentication_lifecycle_status
                .unwrap_or(source.authentication_lifecycle_status),
            modified_at: common_utils::date_time::now(),
            error_code: error_code.or(source.error_code),
            error_message: error_message.or(source.error_message),
            connector_metadata: connector_metadata.or(source.connector_metadata),
            maximum_supported_version: maximum_supported_version
                .or(source.maximum_supported_version),
            threeds_server_transaction_id: threeds_server_transaction_id
                .or(source.threeds_server_transaction_id),
            authentication_flow_type: authentication_flow_type.or(source.authentication_flow_type),
            message_version: message_version.or(source.message_version),
            eci: eci.or(source.eci),
            trans_status: trans_status.or(source.trans_status),
            acquirer_bin: acquirer_bin.or(source.acquirer_bin),
            acquirer_merchant_id: acquirer_merchant_id.or(source.acquirer_merchant_id),
            three_ds_method_data: three_ds_method_data.or(source.three_ds_method_data),
            three_ds_method_url: three_ds_method_url.or(source.three_ds_method_url),
            acs_url: acs_url.or(source.acs_url),
            challenge_request: challenge_request.or(source.challenge_request),
            acs_reference_number: acs_reference_number.or(source.acs_reference_number),
            acs_trans_id: acs_trans_id.or(source.acs_trans_id),
            acs_signed_content: acs_signed_content.or(source.acs_signed_content),
            ds_trans_id: ds_trans_id.or(source.ds_trans_id),
            directory_server_id: directory_server_id.or(source.directory_server_id),
            acquirer_country_code: acquirer_country_code.or(source.acquirer_country_code),
            service_details: service_details.or(source.service_details),
            force_3ds_challenge: force_3ds_challenge.or(source.force_3ds_challenge),
            psd2_sca_exemption_type: psd2_sca_exemption_type.or(source.psd2_sca_exemption_type),
            billing_address: billing_address.or(source.billing_address),
            shipping_address: shipping_address.or(source.shipping_address),
            browser_info: browser_info.or(source.browser_info),
            email: email.or(source.email),
            profile_acquirer_id: profile_acquirer_id.or(source.profile_acquirer_id),
            challenge_code: challenge_code.or(source.challenge_code),
            challenge_cancel: challenge_cancel.or(source.challenge_cancel),
            challenge_code_reason: challenge_code_reason.or(source.challenge_code_reason),
            message_extension: message_extension.or(source.message_extension),
            challenge_request_key: challenge_request_key.or(source.challenge_request_key),
            ..source
        }
    }
}

impl From<AuthenticationUpdate> for AuthenticationUpdateInternal {
    fn from(auth_update: AuthenticationUpdate) -> Self {
        match auth_update {
            AuthenticationUpdate::ErrorUpdate {
                error_message,
                error_code,
                authentication_status,
                connector_authentication_id,
            } => Self {
                error_code,
                error_message,
                authentication_status: Some(authentication_status),
                connector_authentication_id,
                authentication_type: None,
                authentication_lifecycle_status: None,
                modified_at: common_utils::date_time::now(),
                payment_method_id: None,
                connector_metadata: None,
                ..Default::default()
            },
            AuthenticationUpdate::PostAuthorizationUpdate {
                authentication_lifecycle_status,
            } => Self {
                connector_authentication_id: None,

                payment_method_id: None,
                authentication_type: None,
                authentication_status: None,
                authentication_lifecycle_status: Some(authentication_lifecycle_status),
                modified_at: common_utils::date_time::now(),
                error_message: None,
                error_code: None,
                connector_metadata: None,
                ..Default::default()
            },
            AuthenticationUpdate::PreAuthenticationUpdate {
                threeds_server_transaction_id,
                maximum_supported_3ds_version,
                connector_authentication_id,
                three_ds_method_data,
                three_ds_method_url,
                message_version,
                connector_metadata,
                authentication_status,
                acquirer_bin,
                acquirer_merchant_id,
                directory_server_id,
                acquirer_country_code,
                billing_address,
                shipping_address,
                browser_info,
                email,
            } => Self {
                threeds_server_transaction_id: Some(threeds_server_transaction_id),
                maximum_supported_version: Some(maximum_supported_3ds_version),
                connector_authentication_id: Some(connector_authentication_id),
                three_ds_method_data,
                three_ds_method_url,
                message_version: Some(message_version),
                connector_metadata,
                authentication_status: Some(authentication_status),
                acquirer_bin,
                acquirer_merchant_id,
                directory_server_id,
                acquirer_country_code,
                billing_address,
                shipping_address,
                browser_info: *browser_info,
                email,
                ..Default::default()
            },
            AuthenticationUpdate::AuthenticationUpdate {
                trans_status,
                authentication_type,
                acs_url,
                challenge_request,
                acs_reference_number,
                acs_trans_id,
                acs_signed_content,
                connector_metadata,
                authentication_status,
                ds_trans_id,
                eci,
                challenge_code,
                challenge_cancel,
                challenge_code_reason,
                message_extension,
                challenge_request_key,
            } => Self {
                trans_status: Some(trans_status),
                authentication_type: Some(authentication_type),
                acs_url,
                challenge_request,
                acs_reference_number,
                acs_trans_id,
                acs_signed_content,
                connector_metadata,
                authentication_status: Some(authentication_status),
                ds_trans_id,
                eci,
                challenge_code,
                challenge_cancel,
                challenge_code_reason,
                message_extension,
                challenge_request_key,
                ..Default::default()
            },
            AuthenticationUpdate::PostAuthenticationUpdate {
                trans_status,
                eci,
                authentication_status,
                challenge_cancel,
                challenge_code_reason,
            } => Self {
                trans_status: Some(trans_status),
                eci,
                authentication_status: Some(authentication_status),
                challenge_cancel,
                challenge_code_reason,
                ..Default::default()
            },
            AuthenticationUpdate::PreAuthenticationVersionCallUpdate {
                maximum_supported_3ds_version,
                message_version,
            } => Self {
                maximum_supported_version: Some(maximum_supported_3ds_version),
                message_version: Some(message_version),
                ..Default::default()
            },
            AuthenticationUpdate::PreAuthenticationThreeDsMethodCall {
                threeds_server_transaction_id,
                three_ds_method_data,
                three_ds_method_url,
                acquirer_bin,
                acquirer_merchant_id,
                connector_metadata,
            } => Self {
                threeds_server_transaction_id: Some(threeds_server_transaction_id),
                three_ds_method_data,
                three_ds_method_url,
                acquirer_bin,
                acquirer_merchant_id,
                connector_metadata,
                ..Default::default()
            },
            AuthenticationUpdate::AuthenticationStatusUpdate {
                trans_status,
                authentication_status,
            } => Self {
                trans_status: Some(trans_status),
                authentication_status: Some(authentication_status),
                ..Default::default()
            },
        }
    }
}


// Struct: ProcessingInformation
// File: crates/hyperswitch_connectors/src/connectors/barclaycard/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ProcessingInformation


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

impl api::ConnectorAccessToken for for Jpmorgan


// File: crates/api_models/src/events/connector_onboarding.rs
// Module: api_models

use common_utils::events::{ApiEventMetric, ApiEventsType};

use crate::connector_onboarding::{
    ActionUrlRequest, ActionUrlResponse, OnboardingStatus, OnboardingSyncRequest,
    ResetTrackingIdRequest,
};

common_utils::impl_api_event_type!(
    Miscellaneous,
    (
        ActionUrlRequest,
        ActionUrlResponse,
        OnboardingSyncRequest,
        OnboardingStatus,
        ResetTrackingIdRequest
    )
);


// Struct: InteracBankRedirect
// File: crates/hyperswitch_connectors/src/connectors/paysafe/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct InteracBankRedirect


// Implementation: impl api::RefundSync for for Dwolla
// File: crates/hyperswitch_connectors/src/connectors/dwolla.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundSync for for Dwolla


// File: crates/common_utils/src/id_type/tenant.rs
// Module: common_utils
// Public functions: 2

use crate::{
    consts::DEFAULT_GLOBAL_TENANT_ID,
    errors::{CustomResult, ValidationError},
};

crate::id_type!(
    TenantId,
    "A type for tenant_id that can be used for unique identifier for a tenant"
);
crate::impl_id_type_methods!(TenantId, "tenant_id");

// This is to display the `TenantId` as TenantId(abcd)
crate::impl_debug_id_type!(TenantId);
crate::impl_try_from_cow_str_id_type!(TenantId, "tenant_id");

crate::impl_serializable_secret_id_type!(TenantId);
crate::impl_queryable_id_type!(TenantId);
crate::impl_to_sql_from_sql_id_type!(TenantId);

impl TenantId {
    /// Get the default global tenant ID
    pub fn get_default_global_tenant_id() -> Self {
        Self(super::LengthId::new_unchecked(
            super::AlphaNumericId::new_unchecked(DEFAULT_GLOBAL_TENANT_ID.to_string()),
        ))
    }

    /// Get tenant id from String
    pub fn try_from_string(tenant_id: String) -> CustomResult<Self, ValidationError> {
        Self::try_from(std::borrow::Cow::from(tenant_id))
    }
}


// Struct: Zen
// File: crates/hyperswitch_connectors/src/connectors/zen.rs
// Module: hyperswitch_connectors
// Implementations: 18
// Traits: api::Payment, api::PaymentSession, api::ConnectorAccessToken, api::MandateSetup, api::PaymentAuthorize, api::PaymentSync, api::PaymentCapture, api::PaymentVoid, api::PaymentToken, api::Refund, api::RefundExecute, api::RefundSync, ConnectorCommon, ConnectorValidation, IncomingWebhook, ConnectorRedirectResponse, ConnectorSpecifications

pub struct Zen

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


// Function: unlink_routing_config_under_profile
// File: crates/router/src/core/routing.rs
// Module: router

pub fn unlink_routing_config_under_profile(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    profile_id: common_utils::id_type::ProfileId,
    transaction_type: &enums::TransactionType,
) -> RouterResponse<routing_types::RoutingDictionaryRecord>


// Function: insert
// File: crates/diesel_models/src/query/file.rs
// Module: diesel_models

pub fn insert(self, conn: &PgPooledConn) -> StorageResult<FileMetadata>


// Function: validate_dummy_connector_create
// File: crates/common_enums/src/connector_enums.rs
// Module: common_enums

pub fn validate_dummy_connector_create(self, is_dummy_connector_enabled: bool) -> bool


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

impl Santander


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

pub fn construct_cancel_router_data_v2<'a>(
    state: &'a SessionState,
    merchant_account: &domain::MerchantAccount,
    merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
    payment_data: &hyperswitch_domain_models::payments::PaymentCancelData<api::Void>,
    request: types::PaymentsCancelData,
    connector_request_reference_id: String,
    customer_id: Option<common_utils::id_type::CustomerId>,
    header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
) -> RouterResult<
    RouterDataV2<
        api::Void,
        flow_common_types::PaymentFlowData,
        types::PaymentsCancelData,
        types::PaymentsResponseData,
    >,
>


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

pub struct RefundResponse


// File: crates/router/src/core/payments/operations/payment_cancel_v2.rs
// Module: router
// Public structs: 1

use std::marker::PhantomData;

use api_models::enums::FrmSuggestion;
use async_trait::async_trait;
use common_enums;
use common_utils::{ext_traits::AsyncExt, id_type::GlobalPaymentId};
use error_stack::ResultExt;
use router_env::{instrument, tracing};

use super::{
    BoxedOperation, Domain, GetTracker, Operation, OperationSessionSetters, UpdateTracker,
    ValidateRequest, ValidateStatusForOperation,
};
use crate::{
    core::{
        errors::{self, CustomResult, RouterResult, StorageErrorExt},
        payments::operations,
    },
    routes::{app::ReqState, SessionState},
    types::{
        self,
        api::{self, ConnectorCallType, PaymentIdTypeExt},
        domain,
        storage::{self, enums},
        PaymentsCancelData,
    },
    utils::OptionExt,
};

#[derive(Debug, Clone, Copy)]
pub struct PaymentsCancel;

type BoxedCancelOperation<'b, F> = BoxedOperation<
    'b,
    F,
    api::PaymentsCancelRequest,
    hyperswitch_domain_models::payments::PaymentCancelData<F>,
>;

// Manual Operation trait implementation for V2
impl<F: Send + Clone + Sync> Operation<F, api::PaymentsCancelRequest> for &PaymentsCancel {
    type Data = hyperswitch_domain_models::payments::PaymentCancelData<F>;

    fn to_validate_request(
        &self,
    ) -> RouterResult<&(dyn ValidateRequest<F, api::PaymentsCancelRequest, Self::Data> + Send + Sync)>
    {
        Ok(*self)
    }

    fn to_get_tracker(
        &self,
    ) -> RouterResult<&(dyn GetTracker<F, Self::Data, api::PaymentsCancelRequest> + Send + Sync)>
    {
        Ok(*self)
    }

    fn to_domain(&self) -> RouterResult<&(dyn Domain<F, api::PaymentsCancelRequest, Self::Data>)> {
        Ok(*self)
    }

    fn to_update_tracker(
        &self,
    ) -> RouterResult<&(dyn UpdateTracker<F, Self::Data, api::PaymentsCancelRequest> + Send + Sync)>
    {
        Ok(*self)
    }
}

#[automatically_derived]
impl<F: Send + Clone + Sync> Operation<F, api::PaymentsCancelRequest> for PaymentsCancel {
    type Data = hyperswitch_domain_models::payments::PaymentCancelData<F>;

    fn to_validate_request(
        &self,
    ) -> RouterResult<&(dyn ValidateRequest<F, api::PaymentsCancelRequest, Self::Data> + Send + Sync)>
    {
        Ok(self)
    }

    fn to_get_tracker(
        &self,
    ) -> RouterResult<&(dyn GetTracker<F, Self::Data, api::PaymentsCancelRequest> + Send + Sync)>
    {
        Ok(self)
    }

    fn to_domain(&self) -> RouterResult<&dyn Domain<F, api::PaymentsCancelRequest, Self::Data>> {
        Ok(self)
    }

    fn to_update_tracker(
        &self,
    ) -> RouterResult<&(dyn UpdateTracker<F, Self::Data, api::PaymentsCancelRequest> + Send + Sync)>
    {
        Ok(self)
    }
}

#[cfg(feature = "v2")]
impl<F: Send + Clone + Sync>
    ValidateRequest<
        F,
        api::PaymentsCancelRequest,
        hyperswitch_domain_models::payments::PaymentCancelData<F>,
    > for PaymentsCancel
{
    #[instrument(skip_all)]
    fn validate_request(
        &self,
        _request: &api::PaymentsCancelRequest,
        merchant_context: &domain::MerchantContext,
    ) -> RouterResult<operations::ValidateResult> {
        Ok(operations::ValidateResult {
            merchant_id: merchant_context.get_merchant_account().get_id().to_owned(),
            storage_scheme: merchant_context.get_merchant_account().storage_scheme,
            requeue: false,
        })
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl<F: Send + Clone + Sync>
    GetTracker<
        F,
        hyperswitch_domain_models::payments::PaymentCancelData<F>,
        api::PaymentsCancelRequest,
    > for PaymentsCancel
{
    #[instrument(skip_all)]
    async fn get_trackers<'a>(
        &'a self,
        state: &'a SessionState,
        payment_id: &common_utils::id_type::GlobalPaymentId,
        request: &api::PaymentsCancelRequest,
        merchant_context: &domain::MerchantContext,
        profile: &domain::Profile,
        _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
    ) -> RouterResult<
        operations::GetTrackerResponse<hyperswitch_domain_models::payments::PaymentCancelData<F>>,
    > {
        let db = &*state.store;
        let key_manager_state = &state.into();

        let merchant_id = merchant_context.get_merchant_account().get_id();
        let storage_scheme = merchant_context.get_merchant_account().storage_scheme;
        let payment_intent = db
            .find_payment_intent_by_id(
                key_manager_state,
                payment_id,
                merchant_context.get_merchant_key_store(),
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
            .attach_printable("Failed to find payment intent for cancellation")?;

        self.validate_status_for_operation(payment_intent.status)?;

        let active_attempt_id = payment_intent.active_attempt_id.as_ref().ok_or_else(|| {
            errors::ApiErrorResponse::InvalidRequestData {
                message: "Payment cancellation not possible - no active payment attempt found"
                    .to_string(),
            }
        })?;

        let payment_attempt = db
            .find_payment_attempt_by_id(
                key_manager_state,
                merchant_context.get_merchant_key_store(),
                active_attempt_id,
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
            .attach_printable("Failed to find payment attempt for cancellation")?;

        let mut payment_data = hyperswitch_domain_models::payments::PaymentCancelData {
            flow: PhantomData,
            payment_intent,
            payment_attempt,
        };

        payment_data.set_cancellation_reason(request.cancellation_reason.clone());

        let get_trackers_response = operations::GetTrackerResponse { payment_data };

        Ok(get_trackers_response)
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl<F: Clone + Send + Sync>
    UpdateTracker<
        F,
        hyperswitch_domain_models::payments::PaymentCancelData<F>,
        api::PaymentsCancelRequest,
    > for PaymentsCancel
{
    #[instrument(skip_all)]
    async fn update_trackers<'b>(
        &'b self,
        state: &'b SessionState,
        req_state: ReqState,
        mut payment_data: hyperswitch_domain_models::payments::PaymentCancelData<F>,
        _customer: Option<domain::Customer>,
        storage_scheme: enums::MerchantStorageScheme,
        _updated_customer: Option<storage::CustomerUpdate>,
        merchant_key_store: &domain::MerchantKeyStore,
        _frm_suggestion: Option<FrmSuggestion>,
        _header_payload: hyperswitch_domain_models::payments::HeaderPayload,
    ) -> RouterResult<(
        BoxedCancelOperation<'b, F>,
        hyperswitch_domain_models::payments::PaymentCancelData<F>,
    )>
    where
        F: 'b + Send,
    {
        let db = &*state.store;
        let key_manager_state = &state.into();

        let payment_attempt_update = hyperswitch_domain_models::payments::payment_attempt::PaymentAttemptUpdate::VoidUpdate {
            status: enums::AttemptStatus::VoidInitiated,
            cancellation_reason: payment_data.payment_attempt.cancellation_reason.clone(),
            updated_by: storage_scheme.to_string(),
        };

        let updated_payment_attempt = db
            .update_payment_attempt(
                key_manager_state,
                merchant_key_store,
                payment_data.payment_attempt.clone(),
                payment_attempt_update,
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
            .attach_printable("Failed to update payment attempt for cancellation")?;
        payment_data.set_payment_attempt(updated_payment_attempt);

        Ok((Box::new(self), payment_data))
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl<F: Send + Clone + Sync>
    Domain<F, api::PaymentsCancelRequest, hyperswitch_domain_models::payments::PaymentCancelData<F>>
    for PaymentsCancel
{
    async fn get_customer_details<'a>(
        &'a self,
        _state: &SessionState,
        _payment_data: &mut hyperswitch_domain_models::payments::PaymentCancelData<F>,
        _merchant_key_store: &domain::MerchantKeyStore,
        _storage_scheme: enums::MerchantStorageScheme,
    ) -> CustomResult<(BoxedCancelOperation<'a, F>, Option<domain::Customer>), errors::StorageError>
    {
        Ok((Box::new(*self), None))
    }

    async fn make_pm_data<'a>(
        &'a self,
        _state: &'a SessionState,
        _payment_data: &mut hyperswitch_domain_models::payments::PaymentCancelData<F>,
        _storage_scheme: enums::MerchantStorageScheme,
        _merchant_key_store: &domain::MerchantKeyStore,
        _customer: &Option<domain::Customer>,
        _business_profile: &domain::Profile,
        _should_retry_with_pan: bool,
    ) -> RouterResult<(
        BoxedCancelOperation<'a, F>,
        Option<domain::PaymentMethodData>,
        Option<String>,
    )> {
        Ok((Box::new(*self), None, None))
    }

    async fn perform_routing<'a>(
        &'a self,
        _merchant_context: &domain::MerchantContext,
        _business_profile: &domain::Profile,
        state: &SessionState,
        payment_data: &mut hyperswitch_domain_models::payments::PaymentCancelData<F>,
    ) -> RouterResult<api::ConnectorCallType> {
        let payment_attempt = &payment_data.payment_attempt;
        let connector = payment_attempt
            .connector
            .as_ref()
            .get_required_value("connector")
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Connector not found for payment cancellation")?;

        let merchant_connector_id = payment_attempt
            .merchant_connector_id
            .as_ref()
            .get_required_value("merchant_connector_id")
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Merchant connector ID not found for payment cancellation")?;

        let connector_data = api::ConnectorData::get_connector_by_name(
            &state.conf.connectors,
            connector,
            api::GetToken::Connector,
            Some(merchant_connector_id.to_owned()),
        )
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Invalid connector name received")?;

        Ok(api::ConnectorCallType::PreDetermined(connector_data.into()))
    }
}

impl ValidateStatusForOperation for PaymentsCancel {
    fn validate_status_for_operation(
        &self,
        intent_status: common_enums::IntentStatus,
    ) -> Result<(), errors::ApiErrorResponse> {
        match intent_status {
            common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture
            | common_enums::IntentStatus::PartiallyCapturedAndCapturable
            | common_enums::IntentStatus::RequiresCapture => Ok(()),
            common_enums::IntentStatus::Succeeded
            | common_enums::IntentStatus::Failed
            | common_enums::IntentStatus::Cancelled
            | common_enums::IntentStatus::CancelledPostCapture
            | common_enums::IntentStatus::Processing
            | common_enums::IntentStatus::RequiresCustomerAction
            | common_enums::IntentStatus::RequiresMerchantAction
            | common_enums::IntentStatus::RequiresPaymentMethod
            | common_enums::IntentStatus::RequiresConfirmation
            | common_enums::IntentStatus::PartiallyCaptured
            | common_enums::IntentStatus::Conflicted
            | common_enums::IntentStatus::Expired => {
                Err(errors::ApiErrorResponse::PaymentUnexpectedState {
                    current_flow: format!("{self:?}"),
                    field_name: "status".to_string(),
                    current_value: intent_status.to_string(),
                    states: [
                        common_enums::IntentStatus::RequiresCapture,
                        common_enums::IntentStatus::PartiallyCapturedAndCapturable,
                        common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture,
                    ]
                    .map(|enum_value| enum_value.to_string())
                    .join(", "),
                })
            }
        }
    }
}


// Struct: Config
// File: crates/router/src/types/api/configs.rs
// Module: router
// Implementations: 0

pub struct Config