// File: crates/api_models/src/revenue_recovery_data_backfill.rs
// Module: api_models
// Public functions: 1
// Public structs: 8

use std::{collections::HashMap, fs::File, io::BufReader};

use actix_multipart::form::{tempfile::TempFile, MultipartForm};
use actix_web::{HttpResponse, ResponseError};
use common_enums::{CardNetwork, PaymentMethodType};
use common_utils::events::ApiEventMetric;
use csv::Reader;
use masking::Secret;
use serde::{Deserialize, Serialize};
use time::Date;

#[derive(Debug, Deserialize, Serialize)]
pub struct RevenueRecoveryBackfillRequest {
    pub bin_number: Option<Secret<String>>,
    pub customer_id_resp: String,
    pub connector_payment_id: Option<String>,
    pub token: Option<Secret<String>>,
    pub exp_date: Option<Secret<String>>,
    pub card_network: Option<CardNetwork>,
    pub payment_method_sub_type: Option<PaymentMethodType>,
    pub clean_bank_name: Option<String>,
    pub country_name: Option<String>,
    pub daily_retry_history: Option<String>,
}

#[derive(Debug, Serialize)]
pub struct UnlockStatusResponse {
    pub unlocked: bool,
}

#[derive(Debug, Serialize)]
pub struct RevenueRecoveryDataBackfillResponse {
    pub processed_records: usize,
    pub failed_records: usize,
}

#[derive(Debug, Serialize)]
pub struct CsvParsingResult {
    pub records: Vec<RevenueRecoveryBackfillRequest>,
    pub failed_records: Vec<CsvParsingError>,
}

#[derive(Debug, Serialize)]
pub struct CsvParsingError {
    pub row_number: usize,
    pub error: String,
}

/// Comprehensive card
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComprehensiveCardData {
    pub card_type: Option<String>,
    pub card_exp_month: Option<Secret<String>>,
    pub card_exp_year: Option<Secret<String>>,
    pub card_network: Option<CardNetwork>,
    pub card_issuer: Option<String>,
    pub card_issuing_country: Option<String>,
    pub daily_retry_history: Option<HashMap<Date, i32>>,
}

impl ApiEventMetric for RevenueRecoveryDataBackfillResponse {
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        Some(common_utils::events::ApiEventsType::Miscellaneous)
    }
}

impl ApiEventMetric for UnlockStatusResponse {
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        Some(common_utils::events::ApiEventsType::Miscellaneous)
    }
}

impl ApiEventMetric for CsvParsingResult {
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        Some(common_utils::events::ApiEventsType::Miscellaneous)
    }
}

impl ApiEventMetric for CsvParsingError {
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        Some(common_utils::events::ApiEventsType::Miscellaneous)
    }
}

#[derive(Debug, Clone, Serialize)]
pub enum BackfillError {
    InvalidCardType(String),
    DatabaseError(String),
    RedisError(String),
    CsvParsingError(String),
    FileProcessingError(String),
}

#[derive(serde::Deserialize)]
pub struct BackfillQuery {
    pub cutoff_time: Option<String>,
}

impl std::fmt::Display for BackfillError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::InvalidCardType(msg) => write!(f, "Invalid card type: {}", msg),
            Self::DatabaseError(msg) => write!(f, "Database error: {}", msg),
            Self::RedisError(msg) => write!(f, "Redis error: {}", msg),
            Self::CsvParsingError(msg) => write!(f, "CSV parsing error: {}", msg),
            Self::FileProcessingError(msg) => write!(f, "File processing error: {}", msg),
        }
    }
}

impl std::error::Error for BackfillError {}

impl ResponseError for BackfillError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::BadRequest().json(serde_json::json!({
            "error": self.to_string()
        }))
    }
}

#[derive(Debug, MultipartForm)]
pub struct RevenueRecoveryDataBackfillForm {
    #[multipart(rename = "file")]
    pub file: TempFile,
}

impl RevenueRecoveryDataBackfillForm {
    pub fn validate_and_get_records_with_errors(&self) -> Result<CsvParsingResult, BackfillError> {
        // Step 1: Open the file
        let file = File::open(self.file.file.path())
            .map_err(|error| BackfillError::FileProcessingError(error.to_string()))?;

        let mut csv_reader = Reader::from_reader(BufReader::new(file));

        // Step 2: Parse CSV into typed records
        let mut records = Vec::new();
        let mut failed_records = Vec::new();

        for (row_index, record_result) in csv_reader
            .deserialize::<RevenueRecoveryBackfillRequest>()
            .enumerate()
        {
            match record_result {
                Ok(record) => {
                    records.push(record);
                }
                Err(err) => {
                    failed_records.push(CsvParsingError {
                        row_number: row_index + 2, // +2 because enumerate starts at 0 and CSV has header row
                        error: err.to_string(),
                    });
                }
            }
        }

        Ok(CsvParsingResult {
            records,
            failed_records,
        })
    }
}


// Struct: ProxyRequestWrapper
// File: crates/router/src/core/proxy/utils.rs
// Module: router
// Implementations: 1

pub struct ProxyRequestWrapper


// Function: get_mca_id
// File: crates/hyperswitch_domain_models/src/merchant_connector_account.rs
// Module: hyperswitch_domain_models

pub fn get_mca_id(&self) -> Option<id_type::MerchantConnectorAccountId>


// Struct: User
// File: crates/pm_auth/src/connector/plaid/transformers.rs
// Module: pm_auth
// Implementations: 0

pub struct User


// Struct: CheckbookErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/checkbook/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CheckbookErrorResponse


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

pub struct RefundResponse


            Self::ResponseUpdate {
                debit_routing_savings,
                ..
            } => debit_routing_savings.as_ref(),
            Self::Update { .. }
            | Self::UpdateTrackers { .. }
            | Self::AuthenticationTypeUpdate { .. }
            | Self::ConfirmUpdate { .. }
            | Self::RejectUpdate { .. }
            | Self::BlocklistUpdate { .. }
            | Self::PaymentMethodDetailsUpdate { .. }
            | Self::ConnectorMandateDetailUpdate { .. }
            | Self::VoidUpdate { .. }
            | Self::UnresolvedResponseUpdate { .. }
            | Self::StatusUpdate { .. }
            | Self::ErrorUpdate { .. }
            | Self::CaptureUpdate { .. }
            | Self::AmountToCaptureUpdate { .. }
            | Self::PreprocessingUpdate { .. }
            | Self::ConnectorResponse { .. }
            | Self::IncrementalAuthorizationAmountUpdate { .. }
            | Self::AuthenticationUpdate { .. }
            | Self::ManualUpdate { .. }
            | Self::PostSessionTokensUpdate { .. } => None,
        }
    }
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize)]
pub struct ConfirmIntentResponseUpdate {
    pub status: storage_enums::AttemptStatus,
    pub connector_payment_id: Option<String>,
    pub updated_by: String,
    pub redirection_data: Option<router_response_types::RedirectForm>,
    pub connector_metadata: Option<pii::SecretSerdeValue>,
    pub amount_capturable: Option<MinorUnit>,
    pub connector_token_details: Option<diesel_models::ConnectorTokenDetails>,
    pub connector_response_reference_id: Option<String>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize)]
pub enum PaymentAttemptUpdate {
    /// Update the payment attempt on confirming the intent, before calling the connector
    ConfirmIntent {
        status: storage_enums::AttemptStatus,
        updated_by: String,
        connector: String,
        merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
        authentication_type: storage_enums::AuthenticationType,
        connector_request_reference_id: Option<String>,
        connector_response_reference_id: Option<String>,
    },
    /// Update the payment attempt on confirming the intent, before calling the connector, when payment_method_id is present
    ConfirmIntentTokenized {
        status: storage_enums::AttemptStatus,
        updated_by: String,
        connector: String,
        merchant_connector_id: id_type::MerchantConnectorAccountId,
        authentication_type: storage_enums::AuthenticationType,
        payment_method_id: id_type::GlobalPaymentMethodId,
    },
    /// Update the payment attempt on confirming the intent, after calling the connector on success response
    ConfirmIntentResponse(Box<ConfirmIntentResponseUpdate>),
    /// Update the payment attempt after force syncing with the connector
    SyncUpdate {
        status: storage_enums::AttemptStatus,
        amount_capturable: Option<MinorUnit>,
        updated_by: String,
    },
    PreCaptureUpdate {
        amount_to_capture: Option<MinorUnit>,
        updated_by: String,
    },
    /// Update the payment after attempting capture with the connector
    CaptureUpdate {
        status: storage_enums::AttemptStatus,
        amount_capturable: Option<MinorUnit>,
        updated_by: String,
    },
    /// Update the payment attempt on confirming the intent, after calling the connector on error response
    ErrorUpdate {
        status: storage_enums::AttemptStatus,
        amount_capturable: Option<MinorUnit>,
        error: ErrorDetails,
        updated_by: String,
        connector_payment_id: Option<String>,
    },
    VoidUpdate {
        status: storage_enums::AttemptStatus,
        cancellation_reason: Option<String>,
        updated_by: String,
    },
}

#[cfg(feature = "v2")]
impl ForeignIDRef for PaymentAttempt {
    fn foreign_id(&self) -> String {
        todo!()
    }
}

#[cfg(feature = "v1")]
impl ForeignIDRef for PaymentAttempt {
    fn foreign_id(&self) -> String {
        self.attempt_id.clone()
    }
}

#[cfg(feature = "v1")]
#[async_trait::async_trait]
impl behaviour::Conversion for PaymentAttempt {
    type DstType = DieselPaymentAttempt;
    type NewDstType = DieselPaymentAttemptNew;

    async fn convert(self) -> CustomResult<Self::DstType, ValidationError> {
        let card_network = self
            .payment_method_data
            .as_ref()
            .and_then(|data| data.as_object())
            .and_then(|card| card.get("card"))
            .and_then(|data| data.as_object())
            .and_then(|card| card.get("card_network"))
            .and_then(|network| network.as_str())
            .map(|network| network.to_string());
        let (connector_transaction_id, processor_transaction_data) = self
            .connector_transaction_id
            .map(ConnectorTransactionId::form_id_and_data)
            .map(|(txn_id, txn_data)| (Some(txn_id), txn_data))
            .unwrap_or((None, None));
        Ok(DieselPaymentAttempt {
            payment_id: self.payment_id,
            merchant_id: self.merchant_id,
            attempt_id: self.attempt_id,
            status: self.status,
            amount: self.net_amount.get_order_amount(),
            currency: self.currency,
            save_to_locker: self.save_to_locker,
            connector: self.connector,
            error_message: self.error_message,
            offer_amount: self.offer_amount,
            surcharge_amount: self.net_amount.get_surcharge_amount(),
            tax_amount: self.net_amount.get_tax_on_surcharge(),
            payment_method_id: self.payment_method_id,
            payment_method: self.payment_method,
            connector_transaction_id,
            capture_method: self.capture_method,
            capture_on: self.capture_on,
            confirm: self.confirm,
            authentication_type: self.authentication_type,
            created_at: self.created_at,
            modified_at: self.modified_at,
            last_synced: self.last_synced,
            cancellation_reason: self.cancellation_reason,
            amount_to_capture: self.amount_to_capture,
            mandate_id: self.mandate_id,
            browser_info: self.browser_info,
            error_code: self.error_code,
            payment_token: self.payment_token,
            connector_metadata: self.connector_metadata,
            payment_experience: self.payment_experience,
            payment_method_type: self.payment_method_type,
            payment_method_data: self.payment_method_data,
            business_sub_label: self.business_sub_label,
            straight_through_algorithm: self.straight_through_algorithm,
            preprocessing_step_id: self.preprocessing_step_id,
            mandate_details: self.mandate_details.map(Into::into),
            error_reason: self.error_reason,
            multiple_capture_count: self.multiple_capture_count,
            connector_response_reference_id: self.connector_response_reference_id,
            amount_capturable: self.amount_capturable,
            updated_by: self.updated_by,
            merchant_connector_id: self.merchant_connector_id,
            authentication_data: self.authentication_data,
            encoded_data: self.encoded_data,
            unified_code: self.unified_code,
            unified_message: self.unified_message,
            net_amount: Some(self.net_amount.get_total_amount()),
            external_three_ds_authentication_attempted: self
                .external_three_ds_authentication_attempted,
            authentication_connector: self.authentication_connector,
            authentication_id: self.authentication_id,
            mandate_data: self.mandate_data.map(Into::into),
            fingerprint_id: self.fingerprint_id,
            payment_method_billing_address_id: self.payment_method_billing_address_id,
            charge_id: self.charge_id,
            client_source: self.client_source,
            client_version: self.client_version,
            customer_acceptance: self.customer_acceptance,
            profile_id: self.profile_id,
            organization_id: self.organization_id,
            card_network,
            order_tax_amount: self.net_amount.get_order_tax_amount(),
            shipping_cost: self.net_amount.get_shipping_cost(),
            connector_mandate_detail: self.connector_mandate_detail,
            request_extended_authorization: self.request_extended_authorization,
            extended_authorization_applied: self.extended_authorization_applied,
            capture_before: self.capture_before,
            processor_transaction_data,
            card_discovery: self.card_discovery,
            charges: self.charges,
            issuer_error_code: self.issuer_error_code,
            issuer_error_message: self.issuer_error_message,
            setup_future_usage_applied: self.setup_future_usage_applied,
            // Below fields are deprecated. Please add any new fields above this line.
            connector_transaction_data: None,
            processor_merchant_id: Some(self.processor_merchant_id),
            created_by: self.created_by.map(|cb| cb.to_string()),
            routing_approach: self.routing_approach,
            connector_request_reference_id: self.connector_request_reference_id,
            network_transaction_id: self.network_transaction_id,
            is_overcapture_enabled: self.is_overcapture_enabled,
            network_details: self.network_details,
            is_stored_credential: self.is_stored_credential,
        })
    }

    async fn convert_back(
        _state: &KeyManagerState,
        storage_model: Self::DstType,
        _key: &Secret<Vec<u8>>,
        _key_manager_identifier: keymanager::Identifier,
    ) -> CustomResult<Self, ValidationError>
    where
        Self: Sized,
    {
        async {
            let connector_transaction_id = storage_model
                .get_optional_connector_transaction_id()
                .cloned();
            Ok::<Self, error_stack::Report<common_utils::errors::CryptoError>>(Self {
                payment_id: storage_model.payment_id,
                merchant_id: storage_model.merchant_id.clone(),
                attempt_id: storage_model.attempt_id,
                status: storage_model.status,
                net_amount: NetAmount::new(
                    storage_model.amount,
                    storage_model.shipping_cost,
                    storage_model.order_tax_amount,
                    storage_model.surcharge_amount,
                    storage_model.tax_amount,
                ),
                currency: storage_model.currency,
                save_to_locker: storage_model.save_to_locker,
                connector: storage_model.connector,
                error_message: storage_model.error_message,
                offer_amount: storage_model.offer_amount,
                payment_method_id: storage_model.payment_method_id,
                payment_method: storage_model.payment_method,
                connector_transaction_id,
                capture_method: storage_model.capture_method,
                capture_on: storage_model.capture_on,
                confirm: storage_model.confirm,
                authentication_type: storage_model.authentication_type,
                created_at: storage_model.created_at,
                modified_at: storage_model.modified_at,
                last_synced: storage_model.last_synced,
                cancellation_reason: storage_model.cancellation_reason,
                amount_to_capture: storage_model.amount_to_capture,
                mandate_id: storage_model.mandate_id,
                browser_info: storage_model.browser_info,
                error_code: storage_model.error_code,
                payment_token: storage_model.payment_token,
                connector_metadata: storage_model.connector_metadata,
                payment_experience: storage_model.payment_experience,
                payment_method_type: storage_model.payment_method_type,
                payment_method_data: storage_model.payment_method_data,
                business_sub_label: storage_model.business_sub_label,
                straight_through_algorithm: storage_model.straight_through_algorithm,
                preprocessing_step_id: storage_model.preprocessing_step_id,
                mandate_details: storage_model.mandate_details.map(Into::into),
                error_reason: storage_model.error_reason,
                multiple_capture_count: storage_model.multiple_capture_count,
                connector_response_reference_id: storage_model.connector_response_reference_id,
                amount_capturable: storage_model.amount_capturable,
                updated_by: storage_model.updated_by,
                authentication_data: storage_model.authentication_data,
                encoded_data: storage_model.encoded_data,
                merchant_connector_id: storage_model.merchant_connector_id,
                unified_code: storage_model.unified_code,
                unified_message: storage_model.unified_message,
                external_three_ds_authentication_attempted: storage_model
                    .external_three_ds_authentication_attempted,
                authentication_connector: storage_model.authentication_connector,
                authentication_id: storage_model.authentication_id,
                mandate_data: storage_model.mandate_data.map(Into::into),
                payment_method_billing_address_id: storage_model.payment_method_billing_address_id,
                fingerprint_id: storage_model.fingerprint_id,
                charge_id: storage_model.charge_id,
                client_source: storage_model.client_source,
                client_version: storage_model.client_version,
                customer_acceptance: storage_model.customer_acceptance,
                profile_id: storage_model.profile_id,
                organization_id: storage_model.organization_id,
                connector_mandate_detail: storage_model.connector_mandate_detail,
                request_extended_authorization: storage_model.request_extended_authorization,
                extended_authorization_applied: storage_model.extended_authorization_applied,
                capture_before: storage_model.capture_before,
                card_discovery: storage_model.card_discovery,
                charges: storage_model.charges,
                issuer_error_code: storage_model.issuer_error_code,
                issuer_error_message: storage_model.issuer_error_message,
                processor_merchant_id: storage_model
                    .processor_merchant_id
                    .unwrap_or(storage_model.merchant_id),
                created_by: storage_model
                    .created_by
                    .and_then(|created_by| created_by.parse::<CreatedBy>().ok()),
                setup_future_usage_applied: storage_model.setup_future_usage_applied,
                routing_approach: storage_model.routing_approach,
                connector_request_reference_id: storage_model.connector_request_reference_id,
                debit_routing_savings: None,
                network_transaction_id: storage_model.network_transaction_id,
                is_overcapture_enabled: storage_model.is_overcapture_enabled,
                network_details: storage_model.network_details,
                is_stored_credential: storage_model.is_stored_credential,
            })
        }
        .await
        .change_context(ValidationError::InvalidValue {
            message: "Failed while decrypting payment attempt".to_string(),
        })
    }

    async fn construct_new(self) -> CustomResult<Self::NewDstType, ValidationError> {
        let card_network = self
            .payment_method_data
            .as_ref()
            .and_then(|data| data.as_object())
            .and_then(|card| card.get("card"))
            .and_then(|data| data.as_object())
            .and_then(|card| card.get("card_network"))
            .and_then(|network| network.as_str())
            .map(|network| network.to_string());
        Ok(DieselPaymentAttemptNew {
            payment_id: self.payment_id,
            merchant_id: self.merchant_id,
            attempt_id: self.attempt_id,
            status: self.status,
            amount: self.net_amount.get_order_amount(),
            currency: self.currency,
            save_to_locker: self.save_to_locker,
            connector: self.connector,
            error_message: self.error_message,
            offer_amount: self.offer_amount,
            surcharge_amount: self.net_amount.get_surcharge_amount(),
            tax_amount: self.net_amount.get_tax_on_surcharge(),
            payment_method_id: self.payment_method_id,
            payment_method: self.payment_method,
            capture_method: self.capture_method,
            capture_on: self.capture_on,
            confirm: self.confirm,
            authentication_type: self.authentication_type,
            created_at: self.created_at,
            modified_at: self.modified_at,
            last_synced: self.last_synced,
            cancellation_reason: self.cancellation_reason,
            amount_to_capture: self.amount_to_capture,
            mandate_id: self.mandate_id,
            browser_info: self.browser_info,
            payment_token: self.payment_token,
            error_code: self.error_code,
            connector_metadata: self.connector_metadata,
            payment_experience: self.payment_experience,
            payment_method_type: self.payment_method_type,
            payment_method_data: self.payment_method_data,
            business_sub_label: self.business_sub_label,
            straight_through_algorithm: self.straight_through_algorithm,
            preprocessing_step_id: self.preprocessing_step_id,
            mandate_details: self.mandate_details.map(Into::into),
            error_reason: self.error_reason,
            connector_response_reference_id: self.connector_response_reference_id,
            multiple_capture_count: self.multiple_capture_count,
            amount_capturable: self.amount_capturable,
            updated_by: self.updated_by,
            merchant_connector_id: self.merchant_connector_id,
            authentication_data: self.authentication_data,
            encoded_data: self.encoded_data,
            unified_code: self.unified_code,
            unified_message: self.unified_message,
            net_amount: Some(self.net_amount.get_total_amount()),
            external_three_ds_authentication_attempted: self
                .external_three_ds_authentication_attempted,
            authentication_connector: self.authentication_connector,
            authentication_id: self.authentication_id,
            mandate_data: self.mandate_data.map(Into::into),
            fingerprint_id: self.fingerprint_id,
            payment_method_billing_address_id: self.payment_method_billing_address_id,
            client_source: self.client_source,
            client_version: self.client_version,
            customer_acceptance: self.customer_acceptance,
            profile_id: self.profile_id,
            organization_id: self.organization_id,
            card_network,
            order_tax_amount: self.net_amount.get_order_tax_amount(),
            shipping_cost: self.net_amount.get_shipping_cost(),
            connector_mandate_detail: self.connector_mandate_detail,
            request_extended_authorization: self.request_extended_authorization,
            extended_authorization_applied: self.extended_authorization_applied,
            capture_before: self.capture_before,
            card_discovery: self.card_discovery,
            processor_merchant_id: Some(self.processor_merchant_id),
            created_by: self.created_by.map(|cb| cb.to_string()),
            setup_future_usage_applied: self.setup_future_usage_applied,
            routing_approach: self.routing_approach,
            connector_request_reference_id: self.connector_request_reference_id,
            network_transaction_id: self.network_transaction_id,
            network_details: self.network_details,
            is_stored_credential: self.is_stored_credential,
        })
    }
}

#[cfg(feature = "v2")]
#[async_trait::async_trait]
impl behaviour::Conversion for PaymentAttempt {
    type DstType = DieselPaymentAttempt;
    type NewDstType = DieselPaymentAttemptNew;

    async fn convert(self) -> CustomResult<Self::DstType, ValidationError> {
        use common_utils::encryption::Encryption;

        let card_network = self
            .payment_method_data
            .as_ref()
            .and_then(|data| data.peek().as_object())
            .and_then(|card| card.get("card"))
            .and_then(|data| data.as_object())
            .and_then(|card| card.get("card_network"))
            .and_then(|network| network.as_str())
            .map(|network| network.to_string());

        let Self {
            payment_id,
            merchant_id,
            attempts_group_id,
            status,
            error,
            amount_details,
            authentication_type,
            created_at,
            modified_at,
            last_synced,
            cancellation_reason,
            browser_info,
            payment_token,
            connector_metadata,
            payment_experience,
            payment_method_data,
            routing_result,
            preprocessing_step_id,
            multiple_capture_count,
            connector_response_reference_id,
            updated_by,
            redirection_data,
            encoded_data,
            merchant_connector_id,
            external_three_ds_authentication_attempted,
            authentication_connector,
            authentication_id,
            fingerprint_id,
            client_source,
            client_version,
            customer_acceptance,
            profile_id,
            organization_id,
            payment_method_type,
            connector_payment_id,
            payment_method_subtype,
            authentication_applied,
            external_reference_id,
            id,
            payment_method_id,
            payment_method_billing_address,
            connector,
            connector_token_details,
            card_discovery,
            charges,
            feature_metadata,
            processor_merchant_id,
            created_by,
            connector_request_reference_id,
            network_transaction_id,
        } = self;

        let AttemptAmountDetails {
            net_amount,
            tax_on_surcharge,
            surcharge_amount,
            order_tax_amount,
            shipping_cost,
            amount_capturable,
            amount_to_capture,
        } = amount_details;

        let (connector_payment_id, connector_payment_data) = connector_payment_id
            .map(ConnectorTransactionId::form_id_and_data)
            .map(|(txn_id, txn_data)| (Some(txn_id), txn_data))
            .unwrap_or((None, None));
        let feature_metadata = feature_metadata.as_ref().map(From::from);

        Ok(DieselPaymentAttempt {
            payment_id,
            merchant_id,
            id,
            status,
            error_message: error.as_ref().map(|details| details.message.clone()),
            payment_method_id,
            payment_method_type_v2: payment_method_type,
            connector_payment_id,
            authentication_type,
            created_at,
            modified_at,
            last_synced,
            cancellation_reason,
            amount_to_capture,
            browser_info,
            error_code: error.as_ref().map(|details| details.code.clone()),
            payment_token,
            connector_metadata,
            payment_experience,
            payment_method_subtype,
            payment_method_data,
            preprocessing_step_id,
            error_reason: error.as_ref().and_then(|details| details.reason.clone()),
            multiple_capture_count,
            connector_response_reference_id,
            amount_capturable,
            updated_by,
            merchant_connector_id,
            redirection_data: redirection_data.map(From::from),
            encoded_data,
            unified_code: error
                .as_ref()
                .and_then(|details| details.unified_code.clone()),
            unified_message: error
                .as_ref()
                .and_then(|details| details.unified_message.clone()),
            net_amount,
            external_three_ds_authentication_attempted,
            authentication_connector,
            authentication_id,
            fingerprint_id,
            client_source,
            client_version,
            customer_acceptance,
            profile_id,
            organization_id,
            card_network,
            order_tax_amount,
            shipping_cost,
            routing_result,
            authentication_applied,
            external_reference_id,
            connector,
            surcharge_amount,
            tax_on_surcharge,
            payment_method_billing_address: payment_method_billing_address.map(Encryption::from),
            connector_payment_data,
            connector_token_details,
            card_discovery,
            request_extended_authorization: None,
            extended_authorization_applied: None,
            capture_before: None,
            charges,
            feature_metadata,
            network_advice_code: error
                .as_ref()
                .and_then(|details| details.network_advice_code.clone()),
            network_decline_code: error
                .as_ref()
                .and_then(|details| details.network_decline_code.clone()),
            network_error_message: error
                .as_ref()
                .and_then(|details| details.network_error_message.clone()),
            processor_merchant_id: Some(processor_merchant_id),
            created_by: created_by.map(|cb| cb.to_string()),
            connector_request_reference_id,
            network_transaction_id,
            is_overcapture_enabled: None,
            network_details: None,
            attempts_group_id,
            is_stored_credential: None,
        })
    }

    async fn convert_back(
        state: &KeyManagerState,
        storage_model: Self::DstType,
        key: &Secret<Vec<u8>>,
        key_manager_identifier: keymanager::Identifier,
    ) -> CustomResult<Self, ValidationError>
    where
        Self: Sized,
    {
        async {
            let connector_payment_id = storage_model
                .get_optional_connector_transaction_id()
                .cloned();

            let decrypted_data = crypto_operation(
                state,
                common_utils::type_name!(Self::DstType),
                CryptoOperation::BatchDecrypt(EncryptedPaymentAttempt::to_encryptable(
                    EncryptedPaymentAttempt {
                        payment_method_billing_address: storage_model
                            .payment_method_billing_address,
                    },
                )),
                key_manager_identifier,
                key.peek(),
            )
            .await
            .and_then(|val| val.try_into_batchoperation())?;

            let decrypted_data = EncryptedPaymentAttempt::from_encryptable(decrypted_data)
                .change_context(common_utils::errors::CryptoError::DecodingFailed)
                .attach_printable("Invalid batch operation data")?;

            let payment_method_billing_address = decrypted_data
                .payment_method_billing_address
                .map(|billing| {
                    billing.deserialize_inner_value(|value| value.parse_value("Address"))
                })
                .transpose()
                .change_context(common_utils::errors::CryptoError::DecodingFailed)
                .attach_printable("Error while deserializing Address")?;

            let amount_details = AttemptAmountDetails {
                net_amount: storage_model.net_amount,
                tax_on_surcharge: storage_model.tax_on_surcharge,
                surcharge_amount: storage_model.surcharge_amount,
                order_tax_amount: storage_model.order_tax_amount,
                shipping_cost: storage_model.shipping_cost,
                amount_capturable: storage_model.amount_capturable,
                amount_to_capture: storage_model.amount_to_capture,
            };

            let error = storage_model
                .error_code
                .zip(storage_model.error_message)
                .map(|(error_code, error_message)| ErrorDetails {
                    code: error_code,
                    message: error_message,
                    reason: storage_model.error_reason,
                    unified_code: storage_model.unified_code,
                    unified_message: storage_model.unified_message,
                    network_advice_code: storage_model.network_advice_code,
                    network_decline_code: storage_model.network_decline_code,
                    network_error_message: storage_model.network_error_message,
                });

            Ok::<Self, error_stack::Report<common_utils::errors::CryptoError>>(Self {
                payment_id: storage_model.payment_id,
                merchant_id: storage_model.merchant_id.clone(),
                attempts_group_id: storage_model.attempts_group_id,
                id: storage_model.id,
                status: storage_model.status,
                amount_details,
                error,
                payment_method_id: storage_model.payment_method_id,
                payment_method_type: storage_model.payment_method_type_v2,
                connector_payment_id,
                authentication_type: storage_model.authentication_type,
                created_at: storage_model.created_at,
                modified_at: storage_model.modified_at,
                last_synced: storage_model.last_synced,
                cancellation_reason: storage_model.cancellation_reason,
                browser_info: storage_model.browser_info,
                payment_token: storage_model.payment_token,
                connector_metadata: storage_model.connector_metadata,
                payment_experience: storage_model.payment_experience,
                payment_method_data: storage_model.payment_method_data,
                routing_result: storage_model.routing_result,
                preprocessing_step_id: storage_model.preprocessing_step_id,
                multiple_capture_count: storage_model.multiple_capture_count,
                connector_response_reference_id: storage_model.connector_response_reference_id,
                updated_by: storage_model.updated_by,
                redirection_data: storage_model.redirection_data.map(From::from),
                encoded_data: storage_model.encoded_data,
                merchant_connector_id: storage_model.merchant_connector_id,
                external_three_ds_authentication_attempted: storage_model
                    .external_three_ds_authentication_attempted,
                authentication_connector: storage_model.authentication_connector,
                authentication_id: storage_model.authentication_id,
                fingerprint_id: storage_model.fingerprint_id,
                charges: storage_model.charges,
                client_source: storage_model.client_source,
                client_version: storage_model.client_version,
                customer_acceptance: storage_model.customer_acceptance,
                profile_id: storage_model.profile_id,
                organization_id: storage_model.organization_id,
                payment_method_subtype: storage_model.payment_method_subtype,
                authentication_applied: storage_model.authentication_applied,
                external_reference_id: storage_model.external_reference_id,
                connector: storage_model.connector,
                payment_method_billing_address,
                connector_token_details: storage_model.connector_token_details,
                card_discovery: storage_model.card_discovery,
                feature_metadata: storage_model.feature_metadata.map(From::from),
                processor_merchant_id: storage_model
                    .processor_merchant_id
                    .unwrap_or(storage_model.merchant_id),
                created_by: storage_model
                    .created_by
                    .and_then(|created_by| created_by.parse::<CreatedBy>().ok()),
                connector_request_reference_id: storage_model.connector_request_reference_id,
                network_transaction_id: storage_model.network_transaction_id,
            })
        }
        .await
        .change_context(ValidationError::InvalidValue {
            message: "Failed while decrypting payment attempt".to_string(),
        })
    }

    async fn construct_new(self) -> CustomResult<Self::NewDstType, ValidationError> {
        use common_utils::encryption::Encryption;
        let Self {
            payment_id,
            merchant_id,
            attempts_group_id,
            status,
            error,
            amount_details,
            authentication_type,
            created_at,
            modified_at,
            last_synced,
            cancellation_reason,
            browser_info,
            payment_token,
            connector_metadata,
            payment_experience,
            payment_method_data,
            routing_result: _,
            preprocessing_step_id,
            multiple_capture_count,
            connector_response_reference_id,
            updated_by,
            redirection_data,
            encoded_data,
            merchant_connector_id,
            external_three_ds_authentication_attempted,
            authentication_connector,
            authentication_id,
            fingerprint_id,
            client_source,
            client_version,
            customer_acceptance,
            profile_id,
            organization_id,
            payment_method_type,
            connector_payment_id,
            payment_method_subtype,
            authentication_applied: _,
            external_reference_id: _,
            id,
            payment_method_id,
            payment_method_billing_address,
            connector,
            connector_token_details,
            card_discovery,
            charges,
            feature_metadata,
            processor_merchant_id,
            created_by,
            connector_request_reference_id,
            network_transaction_id,
        } = self;

        let card_network = payment_method_data
            .as_ref()
            .and_then(|data| data.peek().as_object())
            .and_then(|card| card.get("card"))
            .and_then(|data| data.as_object())
            .and_then(|card| card.get("card_network"))
            .and_then(|network| network.as_str())
            .map(|network| network.to_string());

        let error_details = error;

        Ok(DieselPaymentAttemptNew {
            payment_id,
            merchant_id,
            status,
            network_transaction_id,
            error_message: error_details
                .as_ref()
                .map(|details| details.message.clone()),
            surcharge_amount: amount_details.surcharge_amount,
            tax_on_surcharge: amount_details.tax_on_surcharge,
            payment_method_id,
            authentication_type,
            created_at,
            modified_at,
            last_synced,
            cancellation_reason,
            browser_info,
            payment_token,
            error_code: error_details.as_ref().map(|details| details.code.clone()),
            connector_metadata,
            payment_experience,
            payment_method_data,
            preprocessing_step_id,
            error_reason: error_details
                .as_ref()
                .and_then(|details| details.reason.clone()),
            connector_response_reference_id,
            multiple_capture_count,
            amount_capturable: amount_details.amount_capturable,
            updated_by,
            merchant_connector_id,
            redirection_data: redirection_data.map(From::from),
            encoded_data,
            unified_code: error_details
                .as_ref()
                .and_then(|details| details.unified_code.clone()),
            unified_message: error_details
                .as_ref()
                .and_then(|details| details.unified_message.clone()),
            net_amount: amount_details.net_amount,
            external_three_ds_authentication_attempted,
            authentication_connector,
            authentication_id,
            fingerprint_id,
            client_source,
            client_version,
            customer_acceptance,
            profile_id,
            organization_id,
            card_network,
            order_tax_amount: amount_details.order_tax_amount,
            shipping_cost: amount_details.shipping_cost,
            amount_to_capture: amount_details.amount_to_capture,
            payment_method_billing_address: payment_method_billing_address.map(Encryption::from),
            payment_method_subtype,
            connector_payment_id: connector_payment_id
                .as_ref()
                .map(|txn_id| ConnectorTransactionId::TxnId(txn_id.clone())),
            payment_method_type_v2: payment_method_type,
            id,
            charges,
            connector_token_details,
            card_discovery,
            extended_authorization_applied: None,
            request_extended_authorization: None,
            capture_before: None,
            feature_metadata: feature_metadata.as_ref().map(From::from),
            connector,
            network_advice_code: error_details
                .as_ref()
                .and_then(|details| details.network_advice_code.clone()),
            network_decline_code: error_details
                .as_ref()
                .and_then(|details| details.network_decline_code.clone()),
            network_error_message: error_details
                .as_ref()
                .and_then(|details| details.network_error_message.clone()),
            processor_merchant_id: Some(processor_merchant_id),
            created_by: created_by.map(|cb| cb.to_string()),
            connector_request_reference_id,
            network_details: None,
            attempts_group_id,
            is_stored_credential: None,
        })
    }
}

#[cfg(feature = "v2")]
impl From<PaymentAttemptUpdate> for diesel_models::PaymentAttemptUpdateInternal {
    fn from(update: PaymentAttemptUpdate) -> Self {
        match update {
            PaymentAttemptUpdate::ConfirmIntent {
                status,
                updated_by,
                connector,
                merchant_connector_id,
                authentication_type,
                connector_request_reference_id,
                connector_response_reference_id,
            } => Self {
                status: Some(status),
                payment_method_id: None,
                error_message: None,
                modified_at: common_utils::date_time::now(),
                browser_info: None,
                error_code: None,
                error_reason: None,
                updated_by,
                merchant_connector_id,
                unified_code: None,
                unified_message: None,
                connector_payment_id: None,
                connector_payment_data: None,
                connector: Some(connector),
                redirection_data: None,
                connector_metadata: None,
                amount_capturable: None,
                amount_to_capture: None,
                connector_token_details: None,
                authentication_type: Some(authentication_type),
                feature_metadata: None,
                network_advice_code: None,
                network_decline_code: None,
                network_error_message: None,
                connector_request_reference_id,
                connector_response_reference_id,
                cancellation_reason: None,
            },
            PaymentAttemptUpdate::ErrorUpdate {
                status,
                error,
                connector_payment_id,
                amount_capturable,
                updated_by,
            } => {
                // Apply automatic hashing for long connector payment IDs
                let (connector_payment_id, connector_payment_data) = connector_payment_id
                    .map(ConnectorTransactionId::form_id_and_data)
                    .map(|(txn_id, txn_data)| (Some(txn_id), txn_data))
                    .unwrap_or((None, None));

                Self {
                    status: Some(status),
                    payment_method_id: None,
                    error_message: Some(error.message),
                    error_code: Some(error.code),
                    modified_at: common_utils::date_time::now(),
                    browser_info: None,
                    error_reason: error.reason,
                    updated_by,
                    merchant_connector_id: None,
                    unified_code: None,
                    unified_message: None,
                    connector_payment_id,
                    connector_payment_data,
                    connector: None,
                    redirection_data: None,
                    connector_metadata: None,
                    amount_capturable,
                    amount_to_capture: None,
                    connector_token_details: None,
                    authentication_type: None,
                    feature_metadata: None,
                    network_advice_code: error.network_advice_code,
                    network_decline_code: error.network_decline_code,
                    network_error_message: error.network_error_message,
                    connector_request_reference_id: None,
                    connector_response_reference_id: None,
                    cancellation_reason: None,
                }
            }
            PaymentAttemptUpdate::ConfirmIntentResponse(confirm_intent_response_update) => {
                let ConfirmIntentResponseUpdate {
                    status,
                    connector_payment_id,
                    updated_by,
                    redirection_data,
                    connector_metadata,
                    amount_capturable,
                    connector_token_details,
                    connector_response_reference_id,
                } = *confirm_intent_response_update;

                // Apply automatic hashing for long connector payment IDs
                let (connector_payment_id, connector_payment_data) = connector_payment_id
                    .map(ConnectorTransactionId::form_id_and_data)
                    .map(|(txn_id, txn_data)| (Some(txn_id), txn_data))
                    .unwrap_or((None, None));
                Self {
                    status: Some(status),
                    payment_method_id: None,
                    amount_capturable,
                    error_message: None,
                    error_code: None,
                    modified_at: common_utils::date_time::now(),
                    browser_info: None,
                    error_reason: None,
                    updated_by,
                    merchant_connector_id: None,
                    unified_code: None,
                    unified_message: None,
                    connector_payment_id,
                    connector_payment_data,
                    connector: None,
                    redirection_data: redirection_data
                        .map(diesel_models::payment_attempt::RedirectForm::from),
                    connector_metadata,
                    amount_to_capture: None,
                    connector_token_details,
                    authentication_type: None,
                    feature_metadata: None,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_request_reference_id: None,
                    connector_response_reference_id,
                    cancellation_reason: None,
                }
            }
            PaymentAttemptUpdate::SyncUpdate {
                status,
                amount_capturable,
                updated_by,
            } => Self {
                status: Some(status),
                payment_method_id: None,
                amount_capturable,
                error_message: None,
                error_code: None,
                modified_at: common_utils::date_time::now(),
                browser_info: None,
                error_reason: None,
                updated_by,
                merchant_connector_id: None,
                unified_code: None,
                unified_message: None,
                connector_payment_id: None,
                connector_payment_data: None,
                connector: None,
                redirection_data: None,
                connector_metadata: None,
                amount_to_capture: None,
                connector_token_details: None,
                authentication_type: None,
                feature_metadata: None,
                network_advice_code: None,
                network_decline_code: None,
                network_error_message: None,
                connector_request_reference_id: None,
                connector_response_reference_id: None,
                cancellation_reason: None,
            },
            PaymentAttemptUpdate::CaptureUpdate {
                status,
                amount_capturable,
                updated_by,
            } => Self {
                status: Some(status),
                payment_method_id: None,
                amount_capturable,
                amount_to_capture: None,
                error_message: None,
                error_code: None,
                modified_at: common_utils::date_time::now(),
                browser_info: None,
                error_reason: None,
                updated_by,
                merchant_connector_id: None,
                unified_code: None,
                unified_message: None,
                connector_payment_id: None,
                connector_payment_data: None,
                connector: None,
                redirection_data: None,
                connector_metadata: None,
                connector_token_details: None,
                authentication_type: None,
                feature_metadata: None,
                network_advice_code: None,
                network_decline_code: None,
                network_error_message: None,
                connector_request_reference_id: None,
                connector_response_reference_id: None,
                cancellation_reason: None,
            },
            PaymentAttemptUpdate::PreCaptureUpdate {
                amount_to_capture,
                updated_by,
            } => Self {
                amount_to_capture,


// Struct: ProphetpayTokenRequest
// File: crates/hyperswitch_connectors/src/connectors/prophetpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ProphetpayTokenRequest


// Implementation: impl api::PaymentsPreProcessing for for Airwallex
// File: crates/hyperswitch_connectors/src/connectors/airwallex.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentsPreProcessing for for Airwallex


// Implementation: impl SurchargeCalculationOverride
// File: crates/common_enums/src/enums.rs
// Module: common_enums
// Methods: 1 total (1 public)

impl SurchargeCalculationOverride


// Implementation: impl Stop for for ServerHandle
// File: crates/router/src/lib.rs
// Module: router
// Methods: 1 total (0 public)

impl Stop for for ServerHandle


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

pub fn get_latest_capture(&self) -> &storage::Capture


// Function: validate_request_and_initiate_payment_method_collect_link
// File: crates/router/src/core/payment_methods/validator.rs
// Module: router

pub fn validate_request_and_initiate_payment_method_collect_link(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    req: &PaymentMethodCollectLinkRequest,
) -> RouterResult<PaymentMethodCollectLinkData>


// Struct: ConnectorCustomerResponseData
// File: crates/hyperswitch_domain_models/src/router_response_types.rs
// Module: hyperswitch_domain_models
// Implementations: 1

pub struct ConnectorCustomerResponseData


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

pub struct ThemeData


// Function: get_wise_webhooks_event
// File: crates/hyperswitch_connectors/src/connectors/wise/transformers.rs
// Module: hyperswitch_connectors

pub fn get_wise_webhooks_event(
    state: WiseSyncStatus,
) -> api_models::webhooks::IncomingWebhookEvent


// Implementation: impl Default for for AnalyticsConfig
// File: crates/analytics/src/lib.rs
// Module: analytics
// Methods: 1 total (0 public)

impl Default for for AnalyticsConfig


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

impl api::PaymentAuthorize for for Silverflow


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

pub struct PaymeAuthType


// File: crates/router_env/src/logger/config.rs
// Module: router_env
// Public functions: 6
// Public structs: 6

//! Logger-specific config.

use std::path::PathBuf;

use serde::Deserialize;

/// Config settings.
#[derive(Debug, Deserialize, Clone)]
pub struct Config {
    /// Logging to a file.
    pub log: Log,
}

/// Log config settings.
#[derive(Debug, Deserialize, Clone, Default)]
#[serde(default)]
pub struct Log {
    /// Logging to a file.
    pub file: LogFile,
    /// Logging to a console.
    pub console: LogConsole,
    /// Telemetry / tracing.
    pub telemetry: LogTelemetry,
}

/// Logging to a file.
#[derive(Debug, Deserialize, Clone)]
#[serde(default)]
pub struct LogFile {
    /// Whether you want to store log in log files.
    pub enabled: bool,
    /// Where to store log files.
    pub path: String,
    /// Name of log file without suffix.
    pub file_name: String,
    /// What gets into log files.
    pub level: Level,
    /// Directive which sets the log level for one or more crates/modules.
    pub filtering_directive: Option<String>,
    // pub do_async: bool, // is not used
    // pub rotation: u16,
}

/// Describes the level of verbosity of a span or event.
#[derive(Debug, Clone, Copy)]
pub struct Level(pub(super) tracing::Level);

impl Level {
    /// Returns the most verbose [`tracing::Level`]
    pub fn into_level(self) -> tracing::Level {
        self.0
    }
}

impl<'de> Deserialize<'de> for Level {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        use std::str::FromStr as _;

        let s = String::deserialize(deserializer)?;
        tracing::Level::from_str(&s)
            .map(Level)
            .map_err(serde::de::Error::custom)
    }
}

/// Logging to a console.
#[derive(Debug, Deserialize, Clone)]
#[serde(default)]
pub struct LogConsole {
    /// Whether you want to see log in your terminal.
    pub enabled: bool,
    /// What you see in your terminal.
    pub level: Level,
    /// Log format
    #[serde(default)]
    pub log_format: LogFormat,
    /// Directive which sets the log level for one or more crates/modules.
    pub filtering_directive: Option<String>,
}

/// Telemetry / tracing.
#[derive(Debug, Deserialize, Clone, Default)]
#[serde(default)]
pub struct LogTelemetry {
    /// Whether the traces pipeline is enabled.
    pub traces_enabled: bool,
    /// Whether the metrics pipeline is enabled.
    pub metrics_enabled: bool,
    /// Whether errors in setting up traces or metrics pipelines must be ignored.
    pub ignore_errors: bool,
    /// Sampling rate for traces
    pub sampling_rate: Option<f64>,
    /// Base endpoint URL to send metrics and traces to. Can optionally include the port number.
    pub otel_exporter_otlp_endpoint: Option<String>,
    /// Timeout (in milliseconds) for sending metrics and traces.
    pub otel_exporter_otlp_timeout: Option<u64>,
    /// Whether to use xray ID generator, (enable this if you plan to use AWS-XRAY)
    pub use_xray_generator: bool,
    /// Route Based Tracing
    pub route_to_trace: Option<Vec<String>>,
    /// Interval for collecting the metrics (such as gauge) in background thread
    pub bg_metrics_collection_interval_in_secs: Option<u16>,
}

/// Telemetry / tracing.
#[derive(Default, Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum LogFormat {
    /// Default pretty log format
    Default,
    /// JSON based structured logging
    #[default]
    Json,
    /// JSON based structured logging with pretty print
    PrettyJson,
}

impl Config {
    /// Default constructor.
    pub fn new() -> Result<Self, config::ConfigError> {
        Self::new_with_config_path(None)
    }

    /// Constructor expecting config path set explicitly.
    pub fn new_with_config_path(
        explicit_config_path: Option<PathBuf>,
    ) -> Result<Self, config::ConfigError> {
        // Configuration values are picked up in the following priority order (1 being least
        // priority):
        // 1. Defaults from the implementation of the `Default` trait.
        // 2. Values from config file. The config file accessed depends on the environment
        //    specified by the `RUN_ENV` environment variable. `RUN_ENV` can be one of
        //    `development`, `sandbox` or `production`. If nothing is specified for `RUN_ENV`,
        //    `/config/development.toml` file is read.
        // 3. Environment variables prefixed with `ROUTER` and each level separated by double
        //    underscores.
        //
        // Values in config file override the defaults in `Default` trait, and the values set using
        // environment variables override both the defaults and the config file values.

        let environment = crate::env::which();
        let config_path = Self::config_path(&environment.to_string(), explicit_config_path);

        let config = Self::builder(&environment.to_string())?
            .add_source(config::File::from(config_path).required(false))
            .add_source(config::Environment::with_prefix("ROUTER").separator("__"))
            .build()?;

        // The logger may not yet be initialized when constructing the application configuration
        #[allow(clippy::print_stderr)]
        serde_path_to_error::deserialize(config).map_err(|error| {
            crate::error!(%error, "Unable to deserialize configuration");
            eprintln!("Unable to deserialize application configuration: {error}");
            error.into_inner()
        })
    }

    /// Construct config builder extending it by fall-back defaults and setting config file to load.
    pub fn builder(
        environment: &str,
    ) -> Result<config::ConfigBuilder<config::builder::DefaultState>, config::ConfigError> {
        config::Config::builder()
            // Here, it should be `set_override()` not `set_default()`.
            // "env" can't be altered by config field.
            // Should be single source of truth.
            .set_override("env", environment)
    }

    /// Config path.
    pub fn config_path(environment: &str, explicit_config_path: Option<PathBuf>) -> PathBuf {
        let mut config_path = PathBuf::new();
        if let Some(explicit_config_path_val) = explicit_config_path {
            config_path.push(explicit_config_path_val);
        } else {
            let config_file_name = match environment {
                "production" => "production.toml",
                "sandbox" => "sandbox.toml",
                _ => "development.toml",
            };

            let config_directory = Self::get_config_directory();
            config_path.push(config_directory);
            config_path.push(config_file_name);
        }
        config_path
    }

    /// Get the Directory for the config file
    /// Read the env variable `CONFIG_DIR` or fallback to `config`
    pub fn get_config_directory() -> PathBuf {
        let mut config_path = PathBuf::new();

        let config_directory =
            std::env::var(crate::env::vars::CONFIG_DIR).unwrap_or_else(|_| "config".into());

        config_path.push(crate::env::workspace_path());
        config_path.push(config_directory);
        config_path
    }
}


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

//! Common ID types
//! The id type can be used to create specific id types with custom behaviour

mod api_key;
mod authentication;
mod client_secret;
mod customer;
#[cfg(feature = "v2")]
mod global_id;
mod invoice;
mod merchant;
mod merchant_connector_account;
mod organization;
mod payment;
mod payout;
mod profile;
mod profile_acquirer;
mod refunds;
mod relay;
mod routing;
mod subscription;
mod tenant;

use std::{borrow::Cow, fmt::Debug};

use diesel::{
    backend::Backend,
    deserialize::FromSql,
    expression::AsExpression,
    serialize::{Output, ToSql},
    sql_types,
};
pub use payout::PayoutId;
use serde::{Deserialize, Serialize};
use thiserror::Error;

#[cfg(feature = "v2")]
pub use self::global_id::{
    customer::GlobalCustomerId,
    payment::{GlobalAttemptId, GlobalPaymentId},
    payment_methods::{GlobalPaymentMethodId, GlobalPaymentMethodSessionId},
    refunds::GlobalRefundId,
    token::GlobalTokenId,
    CellId,
};
pub use self::{
    api_key::ApiKeyId,
    authentication::AuthenticationId,
    client_secret::ClientSecretId,
    customer::CustomerId,
    invoice::InvoiceId,
    merchant::MerchantId,
    merchant_connector_account::MerchantConnectorAccountId,
    organization::OrganizationId,
    payment::{PaymentId, PaymentReferenceId},
    profile::ProfileId,
    profile_acquirer::ProfileAcquirerId,
    refunds::RefundReferenceId,
    relay::RelayId,
    routing::RoutingId,
    subscription::SubscriptionId,
    tenant::TenantId,
};
use crate::{fp_utils::when, generate_id_with_default_len};

#[inline]
fn is_valid_id_character(input_char: char) -> bool {
    input_char.is_ascii_alphanumeric() || matches!(input_char, '_' | '-')
}

/// This functions checks for the input string to contain valid characters
/// Returns Some(char) if there are any invalid characters, else None
fn get_invalid_input_character(input_string: Cow<'static, str>) -> Option<char> {
    input_string
        .trim()
        .chars()
        .find(|&char| !is_valid_id_character(char))
}

#[derive(Debug, PartialEq, Hash, Serialize, Clone, Eq)]
/// A type for alphanumeric ids
pub(crate) struct AlphaNumericId(String);

#[derive(Debug, Deserialize, Hash, Serialize, Error, Eq, PartialEq)]
#[error("value `{0}` contains invalid character `{1}`")]
/// The error type for alphanumeric id
pub(crate) struct AlphaNumericIdError(String, char);

impl<'de> Deserialize<'de> for AlphaNumericId {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let deserialized_string = String::deserialize(deserializer)?;
        Self::from(deserialized_string.into()).map_err(serde::de::Error::custom)
    }
}

impl AlphaNumericId {
    /// Creates a new alphanumeric id from string by applying validation checks
    pub fn from(input_string: Cow<'static, str>) -> Result<Self, AlphaNumericIdError> {
        let invalid_character = get_invalid_input_character(input_string.clone());

        if let Some(invalid_character) = invalid_character {
            Err(AlphaNumericIdError(
                input_string.to_string(),
                invalid_character,
            ))?
        }

        Ok(Self(input_string.to_string()))
    }

    /// Create a new alphanumeric id without any validations
    pub(crate) fn new_unchecked(input_string: String) -> Self {
        Self(input_string)
    }

    /// Generate a new alphanumeric id of default length
    pub(crate) fn new(prefix: &str) -> Self {
        Self(generate_id_with_default_len(prefix))
    }
}

/// A common type of id that can be used for reference ids with length constraint
#[derive(Debug, Clone, Serialize, Hash, PartialEq, Eq, AsExpression)]
#[diesel(sql_type = sql_types::Text)]
pub(crate) struct LengthId<const MAX_LENGTH: u8, const MIN_LENGTH: u8>(AlphaNumericId);

/// Error generated from violation of constraints for MerchantReferenceId
#[derive(Debug, Error, PartialEq, Eq)]
pub(crate) enum LengthIdError {
    #[error("the maximum allowed length for this field is {0}")]
    /// Maximum length of string violated
    MaxLengthViolated(u8),

    #[error("the minimum required length for this field is {0}")]
    /// Minimum length of string violated
    MinLengthViolated(u8),

    #[error("{0}")]
    /// Input contains invalid characters
    AlphanumericIdError(AlphaNumericIdError),
}

impl From<AlphaNumericIdError> for LengthIdError {
    fn from(alphanumeric_id_error: AlphaNumericIdError) -> Self {
        Self::AlphanumericIdError(alphanumeric_id_error)
    }
}

impl<const MAX_LENGTH: u8, const MIN_LENGTH: u8> LengthId<MAX_LENGTH, MIN_LENGTH> {
    /// Generates new [MerchantReferenceId] from the given input string
    pub fn from(input_string: Cow<'static, str>) -> Result<Self, LengthIdError> {
        let trimmed_input_string = input_string.trim().to_string();
        let length_of_input_string = u8::try_from(trimmed_input_string.len())
            .map_err(|_| LengthIdError::MaxLengthViolated(MAX_LENGTH))?;

        when(length_of_input_string > MAX_LENGTH, || {
            Err(LengthIdError::MaxLengthViolated(MAX_LENGTH))
        })?;

        when(length_of_input_string < MIN_LENGTH, || {
            Err(LengthIdError::MinLengthViolated(MIN_LENGTH))
        })?;

        let alphanumeric_id = match AlphaNumericId::from(trimmed_input_string.into()) {
            Ok(valid_alphanumeric_id) => valid_alphanumeric_id,
            Err(error) => Err(LengthIdError::AlphanumericIdError(error))?,
        };

        Ok(Self(alphanumeric_id))
    }

    /// Generate a new MerchantRefId of default length with the given prefix
    pub fn new(prefix: &str) -> Self {
        Self(AlphaNumericId::new(prefix))
    }

    /// Use this function only if you are sure that the length is within the range
    pub(crate) fn new_unchecked(alphanumeric_id: AlphaNumericId) -> Self {
        Self(alphanumeric_id)
    }

    #[cfg(feature = "v2")]
    /// Create a new LengthId from aplhanumeric id
    pub(crate) fn from_alphanumeric_id(
        alphanumeric_id: AlphaNumericId,
    ) -> Result<Self, LengthIdError> {
        let length_of_input_string = alphanumeric_id.0.len();
        let length_of_input_string = u8::try_from(length_of_input_string)
            .map_err(|_| LengthIdError::MaxLengthViolated(MAX_LENGTH))?;

        when(length_of_input_string > MAX_LENGTH, || {
            Err(LengthIdError::MaxLengthViolated(MAX_LENGTH))
        })?;

        when(length_of_input_string < MIN_LENGTH, || {
            Err(LengthIdError::MinLengthViolated(MIN_LENGTH))
        })?;

        Ok(Self(alphanumeric_id))
    }
}

impl<'de, const MAX_LENGTH: u8, const MIN_LENGTH: u8> Deserialize<'de>
    for LengthId<MAX_LENGTH, MIN_LENGTH>
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let deserialized_string = String::deserialize(deserializer)?;
        Self::from(deserialized_string.into()).map_err(serde::de::Error::custom)
    }
}

impl<DB, const MAX_LENGTH: u8, const MIN_LENGTH: u8> ToSql<sql_types::Text, DB>
    for LengthId<MAX_LENGTH, MIN_LENGTH>
where
    DB: Backend,
    String: ToSql<sql_types::Text, DB>,
{
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
        self.0 .0.to_sql(out)
    }
}

impl<DB, const MAX_LENGTH: u8, const MIN_LENGTH: u8> FromSql<sql_types::Text, DB>
    for LengthId<MAX_LENGTH, MIN_LENGTH>
where
    DB: Backend,
    String: FromSql<sql_types::Text, DB>,
{
    fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
        let string_val = String::from_sql(value)?;
        Ok(Self(AlphaNumericId::new_unchecked(string_val)))
    }
}

/// An interface to generate object identifiers.
pub trait GenerateId {
    /// Generates a random object identifier.
    fn generate() -> Self;
}

#[cfg(test)]
mod alphanumeric_id_tests {
    #![allow(clippy::unwrap_used)]
    use super::*;

    const VALID_UNDERSCORE_ID_JSON: &str = r#""cus_abcdefghijklmnopqrstuv""#;
    const EXPECTED_VALID_UNDERSCORE_ID: &str = "cus_abcdefghijklmnopqrstuv";

    const VALID_HYPHEN_ID_JSON: &str = r#""cus-abcdefghijklmnopqrstuv""#;
    const VALID_HYPHEN_ID_STRING: &str = "cus-abcdefghijklmnopqrstuv";

    const INVALID_ID_WITH_SPACES: &str = r#""cus abcdefghijklmnopqrstuv""#;
    const INVALID_ID_WITH_EMOJIS: &str = r#""cus_abc🦀""#;

    #[test]
    fn test_id_deserialize_underscore() {
        let parsed_alphanumeric_id =
            serde_json::from_str::<AlphaNumericId>(VALID_UNDERSCORE_ID_JSON);
        let alphanumeric_id = AlphaNumericId::from(EXPECTED_VALID_UNDERSCORE_ID.into()).unwrap();

        assert_eq!(parsed_alphanumeric_id.unwrap(), alphanumeric_id);
    }

    #[test]
    fn test_id_deserialize_hyphen() {
        let parsed_alphanumeric_id = serde_json::from_str::<AlphaNumericId>(VALID_HYPHEN_ID_JSON);
        let alphanumeric_id = AlphaNumericId::from(VALID_HYPHEN_ID_STRING.into()).unwrap();

        assert_eq!(parsed_alphanumeric_id.unwrap(), alphanumeric_id);
    }

    #[test]
    fn test_id_deserialize_with_spaces() {
        let parsed_alphanumeric_id = serde_json::from_str::<AlphaNumericId>(INVALID_ID_WITH_SPACES);

        assert!(parsed_alphanumeric_id.is_err());
    }

    #[test]
    fn test_id_deserialize_with_emojis() {
        let parsed_alphanumeric_id = serde_json::from_str::<AlphaNumericId>(INVALID_ID_WITH_EMOJIS);

        assert!(parsed_alphanumeric_id.is_err());
    }
}

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

    const VALID_REF_ID_JSON: &str = r#""cus_abcdefghijklmnopqrstuv""#;
    const MAX_LENGTH: u8 = 36;
    const MIN_LENGTH: u8 = 6;

    const INVALID_REF_ID_JSON: &str = r#""cus abcdefghijklmnopqrstuv""#;
    const INVALID_REF_ID_LENGTH: &str = r#""cus_abcdefghijklmnopqrstuvwxyzabcdefghij""#;

    #[test]
    fn test_valid_reference_id() {
        let parsed_merchant_reference_id =
            serde_json::from_str::<LengthId<MAX_LENGTH, MIN_LENGTH>>(VALID_REF_ID_JSON);

        dbg!(&parsed_merchant_reference_id);

        assert!(parsed_merchant_reference_id.is_ok());
    }

    #[test]
    fn test_invalid_ref_id() {
        let parsed_merchant_reference_id =
            serde_json::from_str::<LengthId<MAX_LENGTH, MIN_LENGTH>>(INVALID_REF_ID_JSON);

        assert!(parsed_merchant_reference_id.is_err());
    }

    #[test]
    fn test_invalid_ref_id_error_message() {
        let parsed_merchant_reference_id =
            serde_json::from_str::<LengthId<MAX_LENGTH, MIN_LENGTH>>(INVALID_REF_ID_JSON);

        let expected_error_message =
            r#"value `cus abcdefghijklmnopqrstuv` contains invalid character ` `"#.to_string();

        let error_message = parsed_merchant_reference_id
            .err()
            .map(|error| error.to_string());

        assert_eq!(error_message, Some(expected_error_message));
    }

    #[test]
    fn test_invalid_ref_id_length() {
        let parsed_merchant_reference_id =
            serde_json::from_str::<LengthId<MAX_LENGTH, MIN_LENGTH>>(INVALID_REF_ID_LENGTH);

        dbg!(&parsed_merchant_reference_id);

        let expected_error_message =
            format!("the maximum allowed length for this field is {MAX_LENGTH}");

        assert!(parsed_merchant_reference_id
            .is_err_and(|error_string| error_string.to_string().eq(&expected_error_message)));
    }

    #[test]
    fn test_invalid_ref_id_length_error_type() {
        let parsed_merchant_reference_id =
            LengthId::<MAX_LENGTH, MIN_LENGTH>::from(INVALID_REF_ID_LENGTH.into());

        dbg!(&parsed_merchant_reference_id);

        assert!(
            parsed_merchant_reference_id.is_err_and(|error_type| matches!(
                error_type,
                LengthIdError::MaxLengthViolated(MAX_LENGTH)
            ))
        );
    }
}


// Function: new
// File: crates/api_models/src/organization.rs
// Module: api_models

pub fn new(org_type: OrganizationType, org_name: Option<String>) -> Self


// Implementation: impl NewUserRole
// File: crates/router/src/types/domain/user.rs
// Module: router
// Methods: 2 total (0 public)

impl NewUserRole


// Function: build_filter_array
// File: crates/analytics/src/opensearch.rs
// Module: analytics

pub fn build_filter_array(
        &self,
        case_sensitive_filters: Vec<&(String, Vec<Value>)


// Struct: Evoucher
// File: crates/connector_configs/src/connector.rs
// Module: connector_configs
// Implementations: 0

pub struct Evoucher


// Struct: CnpOnlineResponse
// File: crates/hyperswitch_connectors/src/connectors/worldpayvantiv/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CnpOnlineResponse


// Implementation: impl RequiredFieldsAndSurchargeForEnabledPaymentMethodTypes
// File: crates/router/src/core/payments/payment_methods.rs
// Module: router
// Methods: 1 total (0 public)

impl RequiredFieldsAndSurchargeForEnabledPaymentMethodTypes


// File: crates/api_models/src/locker_migration.rs
// Module: api_models
// Public structs: 1

#[derive(Debug, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MigrateCardResponse {
    pub status_message: String,
    pub status_code: String,
    pub customers_moved: usize,
    pub cards_moved: usize,
}


static RAPYD_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> = LazyLock::new(|| {
    let supported_capture_methods = vec![
        enums::CaptureMethod::Automatic,
        enums::CaptureMethod::Manual,
        enums::CaptureMethod::SequentialAutomatic,
    ];

    let supported_card_network = vec![
        common_enums::CardNetwork::AmericanExpress,
        common_enums::CardNetwork::Visa,
        common_enums::CardNetwork::JCB,
        common_enums::CardNetwork::DinersClub,
        common_enums::CardNetwork::UnionPay,
        common_enums::CardNetwork::Mastercard,
        common_enums::CardNetwork::Discover,
    ];

    let mut rapyd_supported_payment_methods = SupportedPaymentMethods::new();

    rapyd_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        enums::PaymentMethodType::ApplePay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

    rapyd_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        enums::PaymentMethodType::GooglePay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

    rapyd_supported_payment_methods.add(
        enums::PaymentMethod::Card,
        enums::PaymentMethodType::Credit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: Some(
                api_models::feature_matrix::PaymentMethodSpecificFeatures::Card({
                    api_models::feature_matrix::CardSpecificFeatures {
                        three_ds: common_enums::FeatureStatus::Supported,
                        no_three_ds: common_enums::FeatureStatus::Supported,
                        supported_card_networks: supported_card_network.clone(),
                    }
                }),
            ),
        },
    );

    rapyd_supported_payment_methods.add(
        enums::PaymentMethod::Card,
        enums::PaymentMethodType::Debit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: Some(
                api_models::feature_matrix::PaymentMethodSpecificFeatures::Card({
                    api_models::feature_matrix::CardSpecificFeatures {
                        three_ds: common_enums::FeatureStatus::Supported,
                        no_three_ds: common_enums::FeatureStatus::Supported,
                        supported_card_networks: supported_card_network.clone(),
                    }
                }),
            ),
        },
    );

    rapyd_supported_payment_methods
});

static RAPYD_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Rapyd",
    description: "Rapyd is a fintech company that enables businesses to collect payments in local currencies across the globe ",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: enums::ConnectorIntegrationStatus::Sandbox,
};

static RAPYD_SUPPORTED_WEBHOOK_FLOWS: [common_enums::EventClass; 3] = [
    enums::EventClass::Payments,
    enums::EventClass::Refunds,
    enums::EventClass::Disputes,
];

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

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

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


// Function: comparison_array
// File: crates/euclid/src/frontend/ast/parser.rs
// Module: euclid

pub fn comparison_array(input: &str) -> ParseResult<&str, Vec<ast::Comparison>>


// Implementation: impl std::fmt::Display for for PaymentOutcome
// File: crates/hyperswitch_connectors/src/connectors/worldpay/response.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl std::fmt::Display for for PaymentOutcome


// Struct: TokenizedBankTransferValue2
// File: crates/hyperswitch_domain_models/src/payment_method_data.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct TokenizedBankTransferValue2


// Function: retrieve_merchant_account
// File: crates/router/src/routes/admin.rs
// Module: router

pub fn retrieve_merchant_account(
    state: web::Data<AppState>,
    req: HttpRequest,
    mid: web::Path<common_utils::id_type::MerchantId>,
) -> HttpResponse


// File: crates/router/src/core/authentication.rs
// Module: router
// Public functions: 3

pub(crate) mod utils;

pub mod transformers;
pub mod types;

use api_models::payments;
use common_enums::Currency;
use common_utils::errors::CustomResult;
use error_stack::ResultExt;
use masking::ExposeInterface;

use super::errors::StorageErrorExt;
use crate::{
    core::{errors::ApiErrorResponse, payments as payments_core},
    routes::SessionState,
    types::{
        self as core_types, api,
        domain::{self},
        storage,
    },
    utils::check_if_pull_mechanism_for_external_3ds_enabled_from_connector_metadata,
};

#[allow(clippy::too_many_arguments)]
pub async fn perform_authentication(
    state: &SessionState,
    merchant_id: common_utils::id_type::MerchantId,
    authentication_connector: String,
    payment_method_data: domain::PaymentMethodData,
    payment_method: common_enums::PaymentMethod,
    billing_address: hyperswitch_domain_models::address::Address,
    shipping_address: Option<hyperswitch_domain_models::address::Address>,
    browser_details: Option<core_types::BrowserInformation>,
    merchant_connector_account: payments_core::helpers::MerchantConnectorAccountType,
    amount: Option<common_utils::types::MinorUnit>,
    currency: Option<Currency>,
    message_category: api::authentication::MessageCategory,
    device_channel: payments::DeviceChannel,
    authentication_data: storage::Authentication,
    return_url: Option<String>,
    sdk_information: Option<payments::SdkInformation>,
    threeds_method_comp_ind: payments::ThreeDsCompletionIndicator,
    email: Option<common_utils::pii::Email>,
    webhook_url: String,
    three_ds_requestor_url: String,
    psd2_sca_exemption_type: Option<common_enums::ScaExemptionType>,
    payment_id: common_utils::id_type::PaymentId,
    force_3ds_challenge: bool,
    merchant_key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
) -> CustomResult<api::authentication::AuthenticationResponse, ApiErrorResponse> {
    let router_data = transformers::construct_authentication_router_data(
        state,
        merchant_id,
        authentication_connector.clone(),
        payment_method_data,
        payment_method,
        billing_address,
        shipping_address,
        browser_details,
        amount,
        currency,
        message_category,
        device_channel,
        merchant_connector_account,
        authentication_data.clone(),
        return_url,
        sdk_information,
        threeds_method_comp_ind,
        email,
        webhook_url,
        three_ds_requestor_url,
        psd2_sca_exemption_type,
        payment_id,
        force_3ds_challenge,
    )?;
    let response = Box::pin(utils::do_auth_connector_call(
        state,
        authentication_connector.clone(),
        router_data,
    ))
    .await?;
    let authentication = utils::update_trackers(
        state,
        response.clone(),
        authentication_data,
        None,
        merchant_key_store,
    )
    .await?;
    response
        .response
        .map_err(|err| ApiErrorResponse::ExternalConnectorError {
            code: err.code,
            message: err.message,
            connector: authentication_connector,
            status_code: err.status_code,
            reason: err.reason,
        })?;
    api::authentication::AuthenticationResponse::try_from(authentication)
}

pub async fn perform_post_authentication(
    state: &SessionState,
    key_store: &domain::MerchantKeyStore,
    business_profile: domain::Profile,
    authentication_id: common_utils::id_type::AuthenticationId,
    payment_id: &common_utils::id_type::PaymentId,
) -> CustomResult<
    hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore,
    ApiErrorResponse,
> {
    let (authentication_connector, three_ds_connector_account) =
        utils::get_authentication_connector_data(state, key_store, &business_profile, None).await?;
    let is_pull_mechanism_enabled =
        check_if_pull_mechanism_for_external_3ds_enabled_from_connector_metadata(
            three_ds_connector_account
                .get_metadata()
                .map(|metadata| metadata.expose()),
        );
    let authentication = state
        .store
        .find_authentication_by_merchant_id_authentication_id(
            &business_profile.merchant_id,
            &authentication_id,
        )
        .await
        .to_not_found_response(ApiErrorResponse::InternalServerError)
        .attach_printable_lazy(|| {
            format!(
                "Error while fetching authentication record with authentication_id {}",
                authentication_id.get_string_repr()
            )
        })?;

    let authentication_update = if !authentication.authentication_status.is_terminal_status()
        && is_pull_mechanism_enabled
    {
        // trigger in case of authenticate flow
        let router_data = transformers::construct_post_authentication_router_data(
            state,
            authentication_connector.to_string(),
            business_profile,
            three_ds_connector_account,
            &authentication,
            payment_id,
        )?;
        let router_data =
            utils::do_auth_connector_call(state, authentication_connector.to_string(), router_data)
                .await?;
        utils::update_trackers(state, router_data, authentication, None, key_store).await?
    } else {
        // trigger in case of webhook flow
        authentication
    };

    // getting authentication value from temp locker before moving ahead with authrisation
    let tokenized_data = crate::core::payment_methods::vault::get_tokenized_data(
        state,
        authentication_id.get_string_repr(),
        false,
        key_store.key.get_inner(),
    )
    .await
    .inspect_err(|err| router_env::logger::error!(tokenized_data_result=?err))
    .attach_printable("cavv not present after authentication flow")
    .ok();

    let authentication_store =
        hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore {
            cavv: tokenized_data.map(|data| masking::Secret::new(data.value1)),
            authentication: authentication_update,
        };

    Ok(authentication_store)
}

#[allow(clippy::too_many_arguments)]
pub async fn perform_pre_authentication(
    state: &SessionState,
    key_store: &domain::MerchantKeyStore,
    card: hyperswitch_domain_models::payment_method_data::Card,
    token: String,
    business_profile: &domain::Profile,
    acquirer_details: Option<types::AcquirerDetails>,
    payment_id: common_utils::id_type::PaymentId,
    organization_id: common_utils::id_type::OrganizationId,
    force_3ds_challenge: Option<bool>,
    psd2_sca_exemption_type: Option<common_enums::ScaExemptionType>,
) -> CustomResult<
    hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore,
    ApiErrorResponse,
> {
    let (authentication_connector, three_ds_connector_account) =
        utils::get_authentication_connector_data(state, key_store, business_profile, None).await?;
    let authentication_connector_name = authentication_connector.to_string();
    let authentication = utils::create_new_authentication(
        state,
        business_profile.merchant_id.clone(),
        authentication_connector_name.clone(),
        token,
        business_profile.get_id().to_owned(),
        payment_id.clone(),
        three_ds_connector_account
            .get_mca_id()
            .ok_or(ApiErrorResponse::InternalServerError)
            .attach_printable("Error while finding mca_id from merchant_connector_account")?,
        organization_id,
        force_3ds_challenge,
        psd2_sca_exemption_type,
    )
    .await?;

    let authentication = if authentication_connector.is_separate_version_call_required() {
        let router_data: core_types::authentication::PreAuthNVersionCallRouterData =
            transformers::construct_pre_authentication_router_data(
                state,
                authentication_connector_name.clone(),
                card.clone(),
                &three_ds_connector_account,
                business_profile.merchant_id.clone(),
                payment_id.clone(),
            )?;
        let router_data = utils::do_auth_connector_call(
            state,
            authentication_connector_name.clone(),
            router_data,
        )
        .await?;

        let updated_authentication = utils::update_trackers(
            state,
            router_data,
            authentication,
            acquirer_details.clone(),
            key_store,
        )
        .await?;
        // from version call response, we will get to know the maximum supported 3ds version.
        // If the version is not greater than or equal to 3DS 2.0, We should not do the successive pre authentication call.
        if !updated_authentication.is_separate_authn_required() {
            return Ok(hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore{
                authentication: updated_authentication,
                cavv: None, // since cavv wont be present in pre_authentication step
            });
        }
        updated_authentication
    } else {
        authentication
    };

    let router_data: core_types::authentication::PreAuthNRouterData =
        transformers::construct_pre_authentication_router_data(
            state,
            authentication_connector_name.clone(),
            card,
            &three_ds_connector_account,
            business_profile.merchant_id.clone(),
            payment_id,
        )?;
    let router_data =
        utils::do_auth_connector_call(state, authentication_connector_name, router_data).await?;

    let authentication_update = utils::update_trackers(
        state,
        router_data,
        authentication,
        acquirer_details,
        key_store,
    )
    .await?;

    Ok(
        hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore {
            authentication: authentication_update,
            cavv: None, // since cavv wont be present in pre_authentication step
        },
    )
}


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

impl MandateSetup for for Plaid


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

pub struct GocardlessError


// Implementation: impl PaymentsDslInput
// File: crates/router/src/core/routing.rs
// Module: router
// Methods: 1 total (1 public)

impl PaymentsDslInput


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

impl api::RefundExecute for for Mpgs


// Struct: DeutschebankAccessTokenResponse
// File: crates/hyperswitch_connectors/src/connectors/deutschebank/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DeutschebankAccessTokenResponse


// Struct: CardExpirationMonth
// File: crates/cards/src/lib.rs
// Module: cards
// Implementations: 2
// Traits: Deref

pub struct CardExpirationMonth


// Struct: MifinityClient
// File: crates/hyperswitch_connectors/src/connectors/mifinity/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MifinityClient


// Struct: PayloadAuth
// File: crates/hyperswitch_connectors/src/connectors/payload/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PayloadAuth


// Implementation: impl State for for CardRequestValidated
// File: crates/router/src/core/payment_methods/tokenize/card_executor.rs
// Module: router
// Methods: 0 total (0 public)

impl State for for CardRequestValidated


// Struct: InespayRSyncResponseData
// File: crates/hyperswitch_connectors/src/connectors/inespay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct InespayRSyncResponseData


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

impl Responder


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

impl Responder


// Implementation: impl CardNetworkTokenizeExecutor
// File: crates/router/src/core/payment_methods/tokenize/card_executor.rs
// Module: router
// Methods: 5 total (0 public)

impl CardNetworkTokenizeExecutor


// Struct: CustomerListConstraints
// File: crates/hyperswitch_domain_models/src/customer.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct CustomerListConstraints


// Struct: NmiSyncRequest
// File: crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NmiSyncRequest


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

pub struct PreAuthNRequestData


// Struct: WellsfargoPaymentsCaptureRequest
// File: crates/hyperswitch_connectors/src/connectors/wellsfargo/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct WellsfargoPaymentsCaptureRequest


// Implementation: impl MerchantConnectorUpdate
// File: crates/api_models/src/admin.rs
// Module: api_models
// Methods: 1 total (1 public)

impl MerchantConnectorUpdate


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

// Public submodules:
pub mod transformers;