// File: crates/hyperswitch_domain_models/src/payments/payment_intent.rs
// Module: hyperswitch_domain_models
// Public functions: 4
// Public structs: 6

use common_types::primitive_wrappers;
#[cfg(feature = "v1")]
use common_utils::consts::PAYMENTS_LIST_MAX_LIMIT_V2;
#[cfg(feature = "v2")]
use common_utils::errors::ParsingError;
#[cfg(feature = "v2")]
use common_utils::ext_traits::{Encode, ValueExt};
use common_utils::{
    consts::PAYMENTS_LIST_MAX_LIMIT_V1,
    crypto::Encryptable,
    encryption::Encryption,
    errors::{CustomResult, ValidationError},
    id_type,
    pii::{self, Email},
    type_name,
    types::{
        keymanager::{self, KeyManagerState, ToEncryptable},
        CreatedBy, MinorUnit,
    },
};
use diesel_models::{
    PaymentIntent as DieselPaymentIntent, PaymentIntentNew as DieselPaymentIntentNew,
};
use error_stack::ResultExt;
#[cfg(feature = "v2")]
use masking::ExposeInterface;
use masking::{Deserialize, PeekInterface, Secret};
use serde::Serialize;
use time::PrimitiveDateTime;

#[cfg(all(feature = "v1", feature = "olap"))]
use super::payment_attempt::PaymentAttempt;
use super::PaymentIntent;
#[cfg(feature = "v2")]
use crate::address::Address;
#[cfg(feature = "v2")]
use crate::routing;
use crate::{
    behaviour,
    merchant_key_store::MerchantKeyStore,
    type_encryption::{crypto_operation, CryptoOperation},
};
#[cfg(feature = "v1")]
use crate::{errors, RemoteStorageObject};

#[async_trait::async_trait]
pub trait PaymentIntentInterface {
    type Error;
    async fn update_payment_intent(
        &self,
        state: &KeyManagerState,
        this: PaymentIntent,
        payment_intent: PaymentIntentUpdate,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, Self::Error>;

    async fn insert_payment_intent(
        &self,
        state: &KeyManagerState,
        new: PaymentIntent,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, Self::Error>;

    #[cfg(feature = "v1")]
    async fn find_payment_intent_by_payment_id_merchant_id(
        &self,
        state: &KeyManagerState,
        payment_id: &id_type::PaymentId,
        merchant_id: &id_type::MerchantId,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, Self::Error>;
    #[cfg(feature = "v2")]
    async fn find_payment_intent_by_merchant_reference_id_profile_id(
        &self,
        state: &KeyManagerState,
        merchant_reference_id: &id_type::PaymentReferenceId,
        profile_id: &id_type::ProfileId,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: &common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, Self::Error>;

    #[cfg(feature = "v2")]
    async fn find_payment_intent_by_id(
        &self,
        state: &KeyManagerState,
        id: &id_type::GlobalPaymentId,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, Self::Error>;

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn filter_payment_intent_by_constraints(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        filters: &PaymentIntentFetchConstraints,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<Vec<PaymentIntent>, Self::Error>;

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn filter_payment_intents_by_time_range_constraints(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        time_range: &common_utils::types::TimeRange,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<Vec<PaymentIntent>, Self::Error>;

    #[cfg(feature = "olap")]
    async fn get_intent_status_with_count(
        &self,
        merchant_id: &id_type::MerchantId,
        profile_id_list: Option<Vec<id_type::ProfileId>>,
        constraints: &common_utils::types::TimeRange,
    ) -> error_stack::Result<Vec<(common_enums::IntentStatus, i64)>, Self::Error>;

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn get_filtered_payment_intents_attempt(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        constraints: &PaymentIntentFetchConstraints,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<Vec<(PaymentIntent, PaymentAttempt)>, Self::Error>;

    #[cfg(all(feature = "v2", feature = "olap"))]
    async fn get_filtered_payment_intents_attempt(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        constraints: &PaymentIntentFetchConstraints,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<
        Vec<(
            PaymentIntent,
            Option<super::payment_attempt::PaymentAttempt>,
        )>,
        Self::Error,
    >;

    #[cfg(all(feature = "v2", feature = "olap"))]
    async fn get_filtered_active_attempt_ids_for_total_count(
        &self,
        merchant_id: &id_type::MerchantId,
        constraints: &PaymentIntentFetchConstraints,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<Vec<Option<String>>, Self::Error>;

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn get_filtered_active_attempt_ids_for_total_count(
        &self,
        merchant_id: &id_type::MerchantId,
        constraints: &PaymentIntentFetchConstraints,
        storage_scheme: common_enums::MerchantStorageScheme,
    ) -> error_stack::Result<Vec<String>, Self::Error>;
}

#[derive(Clone, Debug, PartialEq, router_derive::DebugAsDisplay, Serialize, Deserialize)]
pub struct CustomerData {
    pub name: Option<Secret<String>>,
    pub email: Option<Email>,
    pub phone: Option<Secret<String>>,
    pub phone_country_code: Option<String>,
    pub tax_registration_id: Option<Secret<String>>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize)]
pub struct PaymentIntentUpdateFields {
    pub amount: Option<MinorUnit>,
    pub currency: Option<common_enums::Currency>,
    pub shipping_cost: Option<MinorUnit>,
    pub tax_details: Option<diesel_models::TaxDetails>,
    pub skip_external_tax_calculation: Option<common_enums::TaxCalculationOverride>,
    pub skip_surcharge_calculation: Option<common_enums::SurchargeCalculationOverride>,
    pub surcharge_amount: Option<MinorUnit>,
    pub tax_on_surcharge: Option<MinorUnit>,
    pub routing_algorithm_id: Option<id_type::RoutingId>,
    pub capture_method: Option<common_enums::CaptureMethod>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub billing_address: Option<Encryptable<Address>>,
    pub shipping_address: Option<Encryptable<Address>>,
    pub customer_present: Option<common_enums::PresenceOfCustomerDuringPayment>,
    pub description: Option<common_utils::types::Description>,
    pub return_url: Option<common_utils::types::Url>,
    pub setup_future_usage: Option<common_enums::FutureUsage>,
    pub apply_mit_exemption: Option<common_enums::MitExemptionRequest>,
    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
    pub order_details: Option<Vec<Secret<diesel_models::types::OrderDetailsWithAmount>>>,
    pub allowed_payment_method_types: Option<Vec<common_enums::PaymentMethodType>>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub connector_metadata: Option<pii::SecretSerdeValue>,
    pub feature_metadata: Option<diesel_models::types::FeatureMetadata>,
    pub payment_link_config: Option<diesel_models::PaymentLinkConfigRequestForPayments>,
    pub request_incremental_authorization: Option<common_enums::RequestIncrementalAuthorization>,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub request_external_three_ds_authentication:
        Option<common_enums::External3dsAuthenticationRequest>,
    pub active_attempt_id: Option<Option<id_type::GlobalAttemptId>>,
    // updated_by is set internally, field not present in request
    pub updated_by: String,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub enable_partial_authorization: Option<primitive_wrappers::EnablePartialAuthorizationBool>,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Serialize)]
pub struct PaymentIntentUpdateFields {
    pub amount: MinorUnit,
    pub currency: common_enums::Currency,
    pub setup_future_usage: Option<common_enums::FutureUsage>,
    pub status: common_enums::IntentStatus,
    pub customer_id: Option<id_type::CustomerId>,
    pub shipping_address_id: Option<String>,
    pub billing_address_id: Option<String>,
    pub return_url: Option<String>,
    pub business_country: Option<common_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    pub description: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub metadata: Option<serde_json::Value>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub payment_confirm_source: Option<common_enums::PaymentSource>,
    pub updated_by: String,
    pub fingerprint_id: Option<String>,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub customer_details: Option<Encryptable<Secret<serde_json::Value>>>,
    pub billing_details: Option<Encryptable<Secret<serde_json::Value>>>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryptable<Secret<serde_json::Value>>>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub tax_details: Option<diesel_models::TaxDetails>,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub is_confirm_operation: bool,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub feature_metadata: Option<Secret<serde_json::Value>>,
    pub enable_partial_authorization: Option<primitive_wrappers::EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<primitive_wrappers::EnableOvercaptureBool>,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Serialize)]
pub enum PaymentIntentUpdate {
    ResponseUpdate {
        status: common_enums::IntentStatus,
        amount_captured: Option<MinorUnit>,
        updated_by: String,
        fingerprint_id: Option<String>,
        incremental_authorization_allowed: Option<bool>,
        feature_metadata: Option<Secret<serde_json::Value>>,
    },
    MetadataUpdate {
        metadata: serde_json::Value,
        updated_by: String,
    },
    Update(Box<PaymentIntentUpdateFields>),
    PaymentCreateUpdate {
        return_url: Option<String>,
        status: Option<common_enums::IntentStatus>,
        customer_id: Option<id_type::CustomerId>,
        shipping_address_id: Option<String>,
        billing_address_id: Option<String>,
        customer_details: Option<Encryptable<Secret<serde_json::Value>>>,
        updated_by: String,
    },
    MerchantStatusUpdate {
        status: common_enums::IntentStatus,
        shipping_address_id: Option<String>,
        billing_address_id: Option<String>,
        updated_by: String,
    },
    PGStatusUpdate {
        status: common_enums::IntentStatus,
        incremental_authorization_allowed: Option<bool>,
        updated_by: String,
        feature_metadata: Option<Secret<serde_json::Value>>,
    },
    PaymentAttemptAndAttemptCountUpdate {
        active_attempt_id: String,
        attempt_count: i16,
        updated_by: String,
    },
    StatusAndAttemptUpdate {
        status: common_enums::IntentStatus,
        active_attempt_id: String,
        attempt_count: i16,
        updated_by: String,
    },
    ApproveUpdate {
        status: common_enums::IntentStatus,
        merchant_decision: Option<String>,
        updated_by: String,
    },
    RejectUpdate {
        status: common_enums::IntentStatus,
        merchant_decision: Option<String>,
        updated_by: String,
    },
    SurchargeApplicableUpdate {
        surcharge_applicable: bool,
        updated_by: String,
    },
    IncrementalAuthorizationAmountUpdate {
        amount: MinorUnit,
    },
    AuthorizationCountUpdate {
        authorization_count: i32,
    },
    CompleteAuthorizeUpdate {
        shipping_address_id: Option<String>,
    },
    ManualUpdate {
        status: Option<common_enums::IntentStatus>,
        updated_by: String,
    },
    SessionResponseUpdate {
        tax_details: diesel_models::TaxDetails,
        shipping_address_id: Option<String>,
        updated_by: String,
        shipping_details: Option<Encryptable<Secret<serde_json::Value>>>,
    },
}

#[cfg(feature = "v1")]
impl PaymentIntentUpdate {
    pub fn is_confirm_operation(&self) -> bool {
        match self {
            Self::Update(value) => value.is_confirm_operation,
            _ => false,
        }
    }
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize)]
pub enum PaymentIntentUpdate {
    /// PreUpdate tracker of ConfirmIntent
    ConfirmIntent {
        status: common_enums::IntentStatus,
        active_attempt_id: Option<id_type::GlobalAttemptId>,
        updated_by: String,
    },
    /// PostUpdate tracker of ConfirmIntent
    ConfirmIntentPostUpdate {
        status: common_enums::IntentStatus,
        amount_captured: Option<MinorUnit>,
        updated_by: String,
        feature_metadata: Option<Box<diesel_models::types::FeatureMetadata>>,
    },
    /// SyncUpdate of ConfirmIntent in PostUpdateTrackers
    SyncUpdate {
        status: common_enums::IntentStatus,
        amount_captured: Option<MinorUnit>,
        updated_by: String,
    },
    CaptureUpdate {
        status: common_enums::IntentStatus,
        amount_captured: Option<MinorUnit>,
        updated_by: String,
    },
    /// Update the payment intent details on payment sdk session call, before calling the connector.
    SessionIntentUpdate {
        prerouting_algorithm: routing::PaymentRoutingInfo,
        updated_by: String,
    },
    RecordUpdate {
        status: common_enums::IntentStatus,
        feature_metadata: Box<Option<diesel_models::types::FeatureMetadata>>,
        updated_by: String,
        active_attempt_id: Option<id_type::GlobalAttemptId>,
    },
    /// UpdateIntent
    UpdateIntent(Box<PaymentIntentUpdateFields>),
    /// VoidUpdate for payment cancellation
    VoidUpdate {
        status: common_enums::IntentStatus,
        updated_by: String,
    },
}

#[cfg(feature = "v2")]
impl PaymentIntentUpdate {
    pub fn is_confirm_operation(&self) -> bool {
        matches!(self, Self::ConfirmIntent { .. })
    }
}

#[cfg(feature = "v1")]
#[derive(Clone, Debug, Default)]
pub struct PaymentIntentUpdateInternal {
    pub amount: Option<MinorUnit>,
    pub currency: Option<common_enums::Currency>,
    pub status: Option<common_enums::IntentStatus>,
    pub amount_captured: Option<MinorUnit>,
    pub customer_id: Option<id_type::CustomerId>,
    pub return_url: Option<String>,
    pub setup_future_usage: Option<common_enums::FutureUsage>,
    pub off_session: Option<bool>,
    pub metadata: Option<serde_json::Value>,
    pub billing_address_id: Option<String>,
    pub shipping_address_id: Option<String>,
    pub modified_at: Option<PrimitiveDateTime>,
    pub active_attempt_id: Option<String>,
    pub business_country: Option<common_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    pub description: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,
    pub attempt_count: Option<i16>,
    // Denotes the action(approve or reject) taken by merchant in case of manual review.
    // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
    pub merchant_decision: Option<String>,
    pub payment_confirm_source: Option<common_enums::PaymentSource>,

    pub updated_by: String,
    pub surcharge_applicable: Option<bool>,
    pub incremental_authorization_allowed: Option<bool>,
    pub authorization_count: Option<i32>,
    pub fingerprint_id: Option<String>,
    pub session_expiry: Option<PrimitiveDateTime>,
    pub request_external_three_ds_authentication: Option<bool>,
    pub frm_metadata: Option<pii::SecretSerdeValue>,
    pub customer_details: Option<Encryptable<Secret<serde_json::Value>>>,
    pub billing_details: Option<Encryptable<Secret<serde_json::Value>>>,
    pub merchant_order_reference_id: Option<String>,
    pub shipping_details: Option<Encryptable<Secret<serde_json::Value>>>,
    pub is_payment_processor_token_flow: Option<bool>,
    pub tax_details: Option<diesel_models::TaxDetails>,
    pub force_3ds_challenge: Option<bool>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub payment_channel: Option<common_enums::PaymentChannel>,
    pub feature_metadata: Option<Secret<serde_json::Value>>,
    pub tax_status: Option<common_enums::TaxStatus>,
    pub discount_amount: Option<MinorUnit>,
    pub order_date: Option<PrimitiveDateTime>,
    pub shipping_amount_tax: Option<MinorUnit>,
    pub duty_amount: Option<MinorUnit>,
    pub enable_partial_authorization: Option<primitive_wrappers::EnablePartialAuthorizationBool>,
    pub enable_overcapture: Option<primitive_wrappers::EnableOvercaptureBool>,
}

// This conversion is used in the `update_payment_intent` function
#[cfg(feature = "v2")]
impl TryFrom<PaymentIntentUpdate> for diesel_models::PaymentIntentUpdateInternal {
    type Error = error_stack::Report<ParsingError>;
    fn try_from(payment_intent_update: PaymentIntentUpdate) -> Result<Self, Self::Error> {
        match payment_intent_update {
            PaymentIntentUpdate::ConfirmIntent {
                status,
                active_attempt_id,
                updated_by,
            } => Ok(Self {
                status: Some(status),
                active_attempt_id: Some(active_attempt_id),
                prerouting_algorithm: None,
                modified_at: common_utils::date_time::now(),
                amount: None,
                amount_captured: None,
                currency: None,
                shipping_cost: None,
                tax_details: None,
                skip_external_tax_calculation: None,
                surcharge_applicable: None,
                surcharge_amount: None,
                tax_on_surcharge: None,
                routing_algorithm_id: None,
                capture_method: None,
                authentication_type: None,
                billing_address: None,
                shipping_address: None,
                customer_present: None,
                description: None,
                return_url: None,
                setup_future_usage: None,
                apply_mit_exemption: None,
                statement_descriptor: None,
                order_details: None,
                allowed_payment_method_types: None,
                metadata: None,
                connector_metadata: None,
                feature_metadata: None,
                payment_link_config: None,
                request_incremental_authorization: None,
                session_expiry: None,
                frm_metadata: None,
                request_external_three_ds_authentication: None,
                updated_by,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                enable_partial_authorization: None,
            }),

            PaymentIntentUpdate::ConfirmIntentPostUpdate {
                status,
                updated_by,
                amount_captured,
                feature_metadata,
            } => Ok(Self {
                status: Some(status),
                active_attempt_id: None,
                prerouting_algorithm: None,
                modified_at: common_utils::date_time::now(),
                amount_captured,
                amount: None,
                currency: None,
                shipping_cost: None,
                tax_details: None,
                skip_external_tax_calculation: None,
                surcharge_applicable: None,
                surcharge_amount: None,
                tax_on_surcharge: None,
                routing_algorithm_id: None,
                capture_method: None,
                authentication_type: None,
                billing_address: None,
                shipping_address: None,
                customer_present: None,
                description: None,
                return_url: None,
                setup_future_usage: None,
                apply_mit_exemption: None,
                statement_descriptor: None,
                order_details: None,
                allowed_payment_method_types: None,
                metadata: None,
                connector_metadata: None,
                feature_metadata: feature_metadata.map(|val| *val),
                payment_link_config: None,
                request_incremental_authorization: None,
                session_expiry: None,
                frm_metadata: None,
                request_external_three_ds_authentication: None,
                updated_by,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                enable_partial_authorization: None,
            }),
            PaymentIntentUpdate::SyncUpdate {
                status,
                amount_captured,
                updated_by,
            } => Ok(Self {
                status: Some(status),
                active_attempt_id: None,
                prerouting_algorithm: None,
                modified_at: common_utils::date_time::now(),
                amount: None,
                currency: None,
                amount_captured,
                shipping_cost: None,
                tax_details: None,
                skip_external_tax_calculation: None,
                surcharge_applicable: None,
                surcharge_amount: None,
                tax_on_surcharge: None,
                routing_algorithm_id: None,
                capture_method: None,
                authentication_type: None,
                billing_address: None,
                shipping_address: None,
                customer_present: None,
                description: None,
                return_url: None,
                setup_future_usage: None,
                apply_mit_exemption: None,
                statement_descriptor: None,
                order_details: None,
                allowed_payment_method_types: None,
                metadata: None,
                connector_metadata: None,
                feature_metadata: None,
                payment_link_config: None,
                request_incremental_authorization: None,
                session_expiry: None,
                frm_metadata: None,
                request_external_three_ds_authentication: None,
                updated_by,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                enable_partial_authorization: None,
            }),
            PaymentIntentUpdate::CaptureUpdate {
                status,
                amount_captured,
                updated_by,
            } => Ok(Self {
                status: Some(status),
                amount_captured,
                active_attempt_id: None,
                prerouting_algorithm: None,
                modified_at: common_utils::date_time::now(),
                amount: None,
                currency: None,
                shipping_cost: None,
                tax_details: None,
                skip_external_tax_calculation: None,
                surcharge_applicable: None,
                surcharge_amount: None,
                tax_on_surcharge: None,
                routing_algorithm_id: None,
                capture_method: None,
                authentication_type: None,
                billing_address: None,
                shipping_address: None,
                customer_present: None,
                description: None,
                return_url: None,
                setup_future_usage: None,
                apply_mit_exemption: None,
                statement_descriptor: None,
                order_details: None,
                allowed_payment_method_types: None,
                metadata: None,
                connector_metadata: None,
                feature_metadata: None,
                payment_link_config: None,
                request_incremental_authorization: None,
                session_expiry: None,
                frm_metadata: None,
                request_external_three_ds_authentication: None,
                updated_by,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                enable_partial_authorization: None,
            }),
            PaymentIntentUpdate::SessionIntentUpdate {
                prerouting_algorithm,
                updated_by,
            } => Ok(Self {
                status: None,
                active_attempt_id: None,
                modified_at: common_utils::date_time::now(),
                amount_captured: None,
                prerouting_algorithm: Some(
                    prerouting_algorithm
                        .encode_to_value()
                        .attach_printable("Failed to Serialize prerouting_algorithm")?,
                ),
                amount: None,
                currency: None,
                shipping_cost: None,
                tax_details: None,
                skip_external_tax_calculation: None,
                surcharge_applicable: None,
                surcharge_amount: None,
                tax_on_surcharge: None,
                routing_algorithm_id: None,
                capture_method: None,
                authentication_type: None,
                billing_address: None,
                shipping_address: None,
                customer_present: None,
                description: None,
                return_url: None,
                setup_future_usage: None,
                apply_mit_exemption: None,
                statement_descriptor: None,
                order_details: None,
                allowed_payment_method_types: None,
                metadata: None,
                connector_metadata: None,
                feature_metadata: None,
                payment_link_config: None,
                request_incremental_authorization: None,
                session_expiry: None,
                frm_metadata: None,
                request_external_three_ds_authentication: None,
                updated_by,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                enable_partial_authorization: None,
            }),
            PaymentIntentUpdate::UpdateIntent(boxed_intent) => {
                let PaymentIntentUpdateFields {
                    amount,
                    currency,
                    shipping_cost,
                    tax_details,
                    skip_external_tax_calculation,
                    skip_surcharge_calculation,
                    surcharge_amount,
                    tax_on_surcharge,
                    routing_algorithm_id,
                    capture_method,
                    authentication_type,
                    billing_address,
                    shipping_address,
                    customer_present,
                    description,
                    return_url,
                    setup_future_usage,
                    apply_mit_exemption,
                    statement_descriptor,
                    order_details,
                    allowed_payment_method_types,
                    metadata,
                    connector_metadata,
                    feature_metadata,
                    payment_link_config,
                    request_incremental_authorization,
                    session_expiry,
                    frm_metadata,
                    request_external_three_ds_authentication,
                    active_attempt_id,
                    updated_by,
                    force_3ds_challenge,
                    is_iframe_redirection_enabled,
                    enable_partial_authorization,
                } = *boxed_intent;
                Ok(Self {
                    status: None,
                    active_attempt_id,
                    prerouting_algorithm: None,
                    modified_at: common_utils::date_time::now(),
                    amount_captured: None,
                    amount,
                    currency,
                    shipping_cost,
                    tax_details,
                    skip_external_tax_calculation: skip_external_tax_calculation
                        .map(|val| val.as_bool()),
                    surcharge_applicable: skip_surcharge_calculation.map(|val| val.as_bool()),
                    surcharge_amount,
                    tax_on_surcharge,
                    routing_algorithm_id,
                    capture_method,
                    authentication_type,
                    billing_address: billing_address.map(Encryption::from),
                    shipping_address: shipping_address.map(Encryption::from),
                    customer_present: customer_present.map(|val| val.as_bool()),
                    description,
                    return_url,
                    setup_future_usage,
                    apply_mit_exemption: apply_mit_exemption.map(|val| val.as_bool()),
                    statement_descriptor,
                    order_details,
                    allowed_payment_method_types: allowed_payment_method_types
                        .map(|allowed_payment_method_types| {
                            allowed_payment_method_types.encode_to_value()
                        })
                        .and_then(|r| r.ok().map(Secret::new)),
                    metadata,
                    connector_metadata,
                    feature_metadata,
                    payment_link_config,
                    request_incremental_authorization,
                    session_expiry,
                    frm_metadata,
                    request_external_three_ds_authentication:
                        request_external_three_ds_authentication.map(|val| val.as_bool()),
                    updated_by,
                    force_3ds_challenge,
                    is_iframe_redirection_enabled,
                    enable_partial_authorization,
                })
            }
            PaymentIntentUpdate::RecordUpdate {
                status,
                feature_metadata,
                updated_by,
                active_attempt_id,
            } => Ok(Self {
                status: Some(status),
                amount_captured: None,
                active_attempt_id: Some(active_attempt_id),
                modified_at: common_utils::date_time::now(),
                amount: None,
                currency: None,
                shipping_cost: None,
                tax_details: None,
                skip_external_tax_calculation: None,
                surcharge_applicable: None,
                surcharge_amount: None,
                tax_on_surcharge: None,
                routing_algorithm_id: None,
                capture_method: None,
                authentication_type: None,
                billing_address: None,
                shipping_address: None,
                customer_present: None,
                description: None,
                return_url: None,
                setup_future_usage: None,
                apply_mit_exemption: None,
                statement_descriptor: None,
                order_details: None,
                allowed_payment_method_types: None,
                metadata: None,
                connector_metadata: None,
                feature_metadata: *feature_metadata,
                payment_link_config: None,
                request_incremental_authorization: None,
                prerouting_algorithm: None,
                session_expiry: None,
                frm_metadata: None,
                request_external_three_ds_authentication: None,
                updated_by,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                enable_partial_authorization: None,
            }),
            PaymentIntentUpdate::VoidUpdate { status, updated_by } => Ok(Self {
                status: Some(status),
                amount_captured: None,
                active_attempt_id: None,
                prerouting_algorithm: None,
                modified_at: common_utils::date_time::now(),
                amount: None,
                currency: None,
                shipping_cost: None,
                tax_details: None,
                skip_external_tax_calculation: None,
                surcharge_applicable: None,
                surcharge_amount: None,
                tax_on_surcharge: None,
                routing_algorithm_id: None,
                capture_method: None,
                authentication_type: None,
                billing_address: None,
                shipping_address: None,
                customer_present: None,
                description: None,
                return_url: None,
                setup_future_usage: None,
                apply_mit_exemption: None,
                statement_descriptor: None,
                order_details: None,
                allowed_payment_method_types: None,
                metadata: None,
                connector_metadata: None,
                feature_metadata: None,
                payment_link_config: None,
                request_incremental_authorization: None,
                session_expiry: None,
                frm_metadata: None,
                request_external_three_ds_authentication: None,
                updated_by,
                force_3ds_challenge: None,
                is_iframe_redirection_enabled: None,
                enable_partial_authorization: None,
            }),
        }
    }
}

#[cfg(feature = "v1")]
impl From<PaymentIntentUpdate> for PaymentIntentUpdateInternal {
    fn from(payment_intent_update: PaymentIntentUpdate) -> Self {
        match payment_intent_update {
            PaymentIntentUpdate::MetadataUpdate {
                metadata,
                updated_by,
            } => Self {
                metadata: Some(metadata),
                modified_at: Some(common_utils::date_time::now()),
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::Update(value) => Self {
                amount: Some(value.amount),
                currency: Some(value.currency),
                setup_future_usage: value.setup_future_usage,
                status: Some(value.status),
                customer_id: value.customer_id,
                shipping_address_id: value.shipping_address_id,
                billing_address_id: value.billing_address_id,
                return_url: value.return_url,
                business_country: value.business_country,
                business_label: value.business_label,
                description: value.description,
                statement_descriptor_name: value.statement_descriptor_name,
                statement_descriptor_suffix: value.statement_descriptor_suffix,
                order_details: value.order_details,
                metadata: value.metadata,
                payment_confirm_source: value.payment_confirm_source,
                updated_by: value.updated_by,
                session_expiry: value.session_expiry,
                fingerprint_id: value.fingerprint_id,
                request_external_three_ds_authentication: value
                    .request_external_three_ds_authentication,
                frm_metadata: value.frm_metadata,
                customer_details: value.customer_details,
                billing_details: value.billing_details,
                merchant_order_reference_id: value.merchant_order_reference_id,
                shipping_details: value.shipping_details,
                is_payment_processor_token_flow: value.is_payment_processor_token_flow,
                tax_details: value.tax_details,
                tax_status: value.tax_status,
                discount_amount: value.discount_amount,
                order_date: value.order_date,
                shipping_amount_tax: value.shipping_amount_tax,
                duty_amount: value.duty_amount,
                ..Default::default()
            },
            PaymentIntentUpdate::PaymentCreateUpdate {
                return_url,
                status,
                customer_id,
                shipping_address_id,
                billing_address_id,
                customer_details,
                updated_by,
            } => Self {
                return_url,
                status,
                customer_id,
                shipping_address_id,
                billing_address_id,
                customer_details,
                modified_at: Some(common_utils::date_time::now()),
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::PGStatusUpdate {
                status,
                updated_by,
                incremental_authorization_allowed,
                feature_metadata,
            } => Self {
                status: Some(status),
                modified_at: Some(common_utils::date_time::now()),
                updated_by,
                incremental_authorization_allowed,
                feature_metadata,
                ..Default::default()
            },
            PaymentIntentUpdate::MerchantStatusUpdate {
                status,
                shipping_address_id,
                billing_address_id,
                updated_by,
            } => Self {
                status: Some(status),
                shipping_address_id,
                billing_address_id,
                modified_at: Some(common_utils::date_time::now()),
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::ResponseUpdate {
                // amount,
                // currency,
                status,
                amount_captured,
                fingerprint_id,
                // customer_id,
                updated_by,
                incremental_authorization_allowed,
                feature_metadata,
            } => Self {
                // amount,
                // currency: Some(currency),
                status: Some(status),
                amount_captured,
                fingerprint_id,
                // customer_id,
                modified_at: Some(common_utils::date_time::now()),
                updated_by,
                incremental_authorization_allowed,
                feature_metadata,
                ..Default::default()
            },
            PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate {
                active_attempt_id,
                attempt_count,
                updated_by,
            } => Self {
                active_attempt_id: Some(active_attempt_id),
                attempt_count: Some(attempt_count),
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::StatusAndAttemptUpdate {
                status,
                active_attempt_id,
                attempt_count,
                updated_by,
            } => Self {
                status: Some(status),
                active_attempt_id: Some(active_attempt_id),
                attempt_count: Some(attempt_count),
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::ApproveUpdate {
                status,
                merchant_decision,
                updated_by,
            } => Self {
                status: Some(status),
                merchant_decision,
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::RejectUpdate {
                status,
                merchant_decision,
                updated_by,
            } => Self {
                status: Some(status),
                merchant_decision,
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::SurchargeApplicableUpdate {
                surcharge_applicable,
                updated_by,
            } => Self {
                surcharge_applicable: Some(surcharge_applicable),
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => Self {
                amount: Some(amount),
                ..Default::default()
            },
            PaymentIntentUpdate::AuthorizationCountUpdate {
                authorization_count,
            } => Self {
                authorization_count: Some(authorization_count),
                ..Default::default()
            },
            PaymentIntentUpdate::CompleteAuthorizeUpdate {
                shipping_address_id,
            } => Self {
                shipping_address_id,
                ..Default::default()
            },
            PaymentIntentUpdate::ManualUpdate { status, updated_by } => Self {
                status,
                modified_at: Some(common_utils::date_time::now()),
                updated_by,
                ..Default::default()
            },
            PaymentIntentUpdate::SessionResponseUpdate {
                tax_details,
                shipping_address_id,
                updated_by,
                shipping_details,
            } => Self {
                tax_details: Some(tax_details),
                shipping_address_id,
                updated_by,
                shipping_details,
                ..Default::default()
            },
        }
    }
}

#[cfg(feature = "v1")]
use diesel_models::{
    PaymentIntentUpdate as DieselPaymentIntentUpdate,
    PaymentIntentUpdateFields as DieselPaymentIntentUpdateFields,
};

// TODO: check where this conversion is used
// #[cfg(feature = "v2")]
// impl From<PaymentIntentUpdate> for DieselPaymentIntentUpdate {
//     fn from(value: PaymentIntentUpdate) -> Self {
//         match value {
//             PaymentIntentUpdate::ConfirmIntent { status, updated_by } => {
//                 Self::ConfirmIntent { status, updated_by }
//             }
//             PaymentIntentUpdate::ConfirmIntentPostUpdate { status, updated_by } => {
//                 Self::ConfirmIntentPostUpdate { status, updated_by }
//             }


// File: crates/router/src/types/storage/blocklist_fingerprint.rs
// Module: router

pub use diesel_models::blocklist_fingerprint::{BlocklistFingerprint, BlocklistFingerprintNew};


// Struct: PaymentIntentUpdateMems
// File: crates/diesel_models/src/kv.rs
// Module: diesel_models
// Implementations: 0

pub struct PaymentIntentUpdateMems


// Function: profile_retrieve
// File: crates/openapi/src/routes/profile.rs
// Module: openapi

pub fn profile_retrieve()


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

pub fn get_token(&self, state: &SessionState) -> UserResult<Secret<String>>


// Struct: ConnectorPTMapping
// File: crates/scheduler/src/consumer/types/process_data.rs
// Module: scheduler
// Implementations: 1
// Traits: Default

pub struct ConnectorPTMapping


// Struct: AdyenParamsWithThreeBaseUrls
// File: crates/hyperswitch_domain_models/src/connector_endpoints.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct AdyenParamsWithThreeBaseUrls


// Struct: StripebillingWebhookLineDataPeriod
// File: crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct StripebillingWebhookLineDataPeriod


// Implementation: impl KafkaMessage for for OutgoingWebhookEvent
// File: crates/router/src/events/outgoing_webhook_logs.rs
// Module: router
// Methods: 2 total (0 public)

impl KafkaMessage for for OutgoingWebhookEvent


// Function: list_orgs_for_user
// File: crates/router/src/routes/user.rs
// Module: router

pub fn list_orgs_for_user(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse


// Struct: CybersourceVoidRequest
// File: crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CybersourceVoidRequest


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

//! Secret strings
//!
//! There is not alias type by design.

use alloc::{
    str::FromStr,
    string::{String, ToString},
};

#[cfg(feature = "serde")]
use super::SerializableSecret;
use super::{Secret, Strategy};
use crate::StrongSecret;

#[cfg(feature = "serde")]
impl SerializableSecret for String {}

impl<I> FromStr for Secret<String, I>
where
    I: Strategy<String>,
{
    type Err = core::convert::Infallible;

    fn from_str(src: &str) -> Result<Self, Self::Err> {
        Ok(Self::new(src.to_string()))
    }
}

impl<I> FromStr for StrongSecret<String, I>
where
    I: Strategy<String>,
{
    type Err = core::convert::Infallible;

    fn from_str(src: &str) -> Result<Self, Self::Err> {
        Ok(Self::new(src.to_string()))
    }
}


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

pub fn retrieve_payment_method_from_vault_using_payment_token(
    state: &routes::SessionState,
    merchant_context: &domain::MerchantContext,
    profile: &domain::Profile,
    payment_token: &String,
    payment_method_type: &common_enums::PaymentMethod,
) -> RouterResult<(domain::PaymentMethod, domain::PaymentMethodVaultingData)>


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

impl ConnectorValidation for for Bamboraapac


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

impl Default for for SqlxClient


// Implementation: impl webhooks::IncomingWebhook for for Paysafe
// File: crates/hyperswitch_connectors/src/connectors/paysafe.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl webhooks::IncomingWebhook for for Paysafe


// Implementation: impl EuclidDirFilter for for ConditionalConfigs
// File: crates/common_types/src/payments.rs
// Module: common_types
// Methods: 0 total (0 public)

impl EuclidDirFilter for for ConditionalConfigs


// Implementation: impl api::PaymentSession for for Opayo
// File: crates/hyperswitch_connectors/src/connectors/opayo.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSession for for Opayo


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

pub fn authentication_post_sync_core(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    req: AuthenticationSyncPostUpdateRequest,
) -> RouterResponse<()>


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

pub struct PaymentsErrorResponse


// Struct: JuspaythreedsserverErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/juspaythreedsserver/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct JuspaythreedsserverErrorResponse


// Struct: ProfileSetter
// File: crates/hyperswitch_domain_models/src/business_profile.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct ProfileSetter


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

pub mod transformers;

use std::sync::LazyLock;

use common_enums::enums;
use common_utils::{
    errors::CustomResult,
    ext_traits::BytesExt,
    request::{Method, Request, RequestBuilder, RequestContent},
};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
        ExternalVaultInsertFlow, ExternalVaultRetrieveFlow,
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData, VaultRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentsResponseData, RefundsResponseData, SupportedPaymentMethods,
        VaultResponseData,
    },
    types::VaultRouterData,
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks,
};
use masking::{ExposeInterface, Mask};
use transformers as tokenex;

use crate::{constants::headers, types::ResponseRouterData};

#[derive(Clone)]
pub struct Tokenex;

impl api::Payment for Tokenex {}
impl api::PaymentSession for Tokenex {}
impl api::ConnectorAccessToken for Tokenex {}
impl api::MandateSetup for Tokenex {}
impl api::PaymentAuthorize for Tokenex {}
impl api::PaymentSync for Tokenex {}
impl api::PaymentCapture for Tokenex {}
impl api::PaymentVoid for Tokenex {}
impl api::Refund for Tokenex {}
impl api::RefundExecute for Tokenex {}
impl api::RefundSync for Tokenex {}
impl api::PaymentToken for Tokenex {}
impl api::ExternalVaultInsert for Tokenex {}
impl api::ExternalVault for Tokenex {}
impl api::ExternalVaultRetrieve for Tokenex {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Tokenex
{
    // Not Implemented (R)
}

pub mod auth_headers {
    pub const TOKENEX_ID: &str = "tx-tokenex-id";
    pub const TOKENEX_API_KEY: &str = "tx-apikey";
    pub const TOKENEX_SCHEME: &str = "tx-token-scheme";
    pub const TOKENEX_SCHEME_VALUE: &str = "PCI";
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Tokenex
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let auth = tokenex::TokenexAuthType::try_from(&req.connector_auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        let header = vec![
            (
                headers::CONTENT_TYPE.to_string(),
                self.get_content_type().to_string().into(),
            ),
            (
                auth_headers::TOKENEX_ID.to_string(),
                auth.tokenex_id.expose().into_masked(),
            ),
            (
                auth_headers::TOKENEX_API_KEY.to_string(),
                auth.api_key.expose().into_masked(),
            ),
            (
                auth_headers::TOKENEX_SCHEME.to_string(),
                auth_headers::TOKENEX_SCHEME_VALUE.to_string().into(),
            ),
        ];
        Ok(header)
    }
}

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

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

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

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

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let auth = tokenex::TokenexAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        Ok(vec![(
            headers::AUTHORIZATION.to_string(),
            auth.api_key.expose().into_masked(),
        )])
    }

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

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

        let (code, message) = response.error.split_once(':').unwrap_or(("", ""));

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: code.to_string(),
            message: message.to_string(),
            reason: Some(response.message),
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

impl ConnectorValidation for Tokenex {}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Tokenex {
    //TODO: implement sessions flow
}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Tokenex {}

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData> for Tokenex {}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Tokenex {}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Tokenex {}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Tokenex {}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Tokenex {}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Tokenex {}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Tokenex {}

impl ConnectorIntegration<ExternalVaultInsertFlow, VaultRequestData, VaultResponseData>
    for Tokenex
{
    fn get_url(
        &self,
        _req: &VaultRouterData<ExternalVaultInsertFlow>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}/v2/Pci/Tokenize", self.base_url(connectors)))
    }

    fn get_headers(
        &self,
        req: &VaultRouterData<ExternalVaultInsertFlow>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_request_body(
        &self,
        req: &VaultRouterData<ExternalVaultInsertFlow>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = tokenex::TokenexInsertRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &VaultRouterData<ExternalVaultInsertFlow>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::ExternalVaultInsertType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::ExternalVaultInsertType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::ExternalVaultInsertType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

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

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

impl ConnectorIntegration<ExternalVaultRetrieveFlow, VaultRequestData, VaultResponseData>
    for Tokenex
{
    fn get_url(
        &self,
        _req: &VaultRouterData<ExternalVaultRetrieveFlow>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}/v2/Pci/DetokenizeWithCvv",
            self.base_url(connectors)
        ))
    }

    fn get_headers(
        &self,
        req: &VaultRouterData<ExternalVaultRetrieveFlow>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_request_body(
        &self,
        req: &VaultRouterData<ExternalVaultRetrieveFlow>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = tokenex::TokenexRetrieveRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &VaultRouterData<ExternalVaultRetrieveFlow>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::ExternalVaultRetrieveType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::ExternalVaultRetrieveType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::ExternalVaultRetrieveType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

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

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

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

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

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

static TOKENEX_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> =
    LazyLock::new(SupportedPaymentMethods::new);

static TOKENEX_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Tokenex",
    description: "Tokenex connector",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: enums::ConnectorIntegrationStatus::Alpha,
};

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

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

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

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


// Struct: SignifydPaymentsRecordReturnRequest
// File: crates/hyperswitch_connectors/src/connectors/signifyd/transformers/api.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct SignifydPaymentsRecordReturnRequest


// Struct: PaymentIntentFilterRow
// File: crates/analytics/src/payment_intents/filters.rs
// Module: analytics
// Implementations: 0

pub struct PaymentIntentFilterRow


// Function: is_internal
// File: crates/router/src/services/authorization/roles.rs
// Module: router

pub fn is_internal(&self) -> bool


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

pub struct PaysafeRefundRequest


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

impl api::Refund for for Peachpayments


// Trait: RefundDistribution
// File: crates/analytics/src/refunds/distribution.rs
// Module: analytics

pub trait RefundDistribution<T>


// Struct: AcquirerData
// File: crates/api_models/src/three_ds_decision_rule.rs
// Module: api_models
// Implementations: 0

pub struct AcquirerData


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

impl RoleInterface for for KafkaStore


// Function: set_three_d_s_server_trans_i_d
// File: crates/hyperswitch_connectors/src/connectors/redsys/transformers.rs
// Module: hyperswitch_connectors

pub fn set_three_d_s_server_trans_i_d(mut self, three_d_s_server_trans_i_d: String) -> Self


// Function: default_response_headers
// File: crates/router/src/middleware.rs
// Module: router

// Documentation: Middleware for attaching default response headers. Headers with the same key already set in a response will not be overwritten.

pub fn default_response_headers() -> actix_web::middleware::DefaultHeaders


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

pub fn response_handler(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    payout_data: &PayoutData,
) -> RouterResult<payouts::PayoutCreateResponse>


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

impl PaymentCapture for for Payone


// Struct: FrmFulfillmentSignifydApiResponse
// File: crates/hyperswitch_connectors/src/connectors/signifyd/transformers/api.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FrmFulfillmentSignifydApiResponse


// Function: create_user_theme
// File: crates/router/src/routes/user/theme.rs
// Module: router

pub fn create_user_theme(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<theme_api::CreateUserThemeRequest>,
) -> HttpResponse


// Implementation: impl DelReply
// File: crates/redis_interface/src/types.rs
// Module: redis_interface
// Methods: 2 total (2 public)

impl DelReply


// Implementation: impl ConnectorSpecifications for for Zen
// File: crates/hyperswitch_connectors/src/connectors/zen.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl ConnectorSpecifications for for Zen


// File: crates/analytics/src/connector_events/core.rs
// Module: analytics
// Public functions: 1

use api_models::analytics::connector_events::ConnectorEventsRequest;
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;

use super::events::{get_connector_events, ConnectorEventsResult};
use crate::{errors::AnalyticsResult, types::FiltersError, AnalyticsProvider};

pub async fn connector_events_core(
    pool: &AnalyticsProvider,
    req: ConnectorEventsRequest,
    merchant_id: &common_utils::id_type::MerchantId,
) -> AnalyticsResult<Vec<ConnectorEventsResult>> {
    let data = match pool {
        AnalyticsProvider::Sqlx(_) => Err(FiltersError::NotImplemented(
            "Connector Events not implemented for SQLX",
        ))
        .attach_printable("SQL Analytics is not implemented for Connector Events"),
        AnalyticsProvider::Clickhouse(ckh_pool)
        | AnalyticsProvider::CombinedSqlx(_, ckh_pool)
        | AnalyticsProvider::CombinedCkh(_, ckh_pool) => {
            get_connector_events(merchant_id, req, ckh_pool).await
        }
    }
    .switch()?;
    Ok(data)
}


// Function: check_user_in_blacklist
// File: crates/router/src/services/authentication/blacklist.rs
// Module: router

pub fn check_user_in_blacklist<A: SessionStateInfo>(
    state: &A,
    user_id: &str,
    token_expiry: u64,
) -> RouterResult<bool>


// Struct: BankRedirectionPMData
// File: crates/hyperswitch_connectors/src/connectors/aci/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BankRedirectionPMData


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

pub struct CaptureTransactionData


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

impl KafkaStore


// File: crates/router/src/routes/configs.rs
// Module: router
// Public functions: 4

use actix_web::{web, HttpRequest, Responder};
use router_env::{instrument, tracing, Flow};

use super::app::AppState;
use crate::{
    core::{api_locking, configs},
    services::{api, authentication as auth},
    types::api as api_types,
};

#[cfg(feature = "v1")]
const ADMIN_API_AUTH: auth::AdminApiAuth = auth::AdminApiAuth;
#[cfg(feature = "v2")]
const ADMIN_API_AUTH: auth::V2AdminApiAuth = auth::V2AdminApiAuth;

#[instrument(skip_all, fields(flow = ?Flow::CreateConfigKey))]
pub async fn config_key_create(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<api_types::Config>,
) -> impl Responder {
    let flow = Flow::CreateConfigKey;
    let payload = json_payload.into_inner();

    api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _, data, _| configs::set_config(state, data),
        &ADMIN_API_AUTH,
        api_locking::LockAction::NotApplicable,
    )
    .await
}
#[instrument(skip_all, fields(flow = ?Flow::ConfigKeyFetch))]
pub async fn config_key_retrieve(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
) -> impl Responder {
    let flow = Flow::ConfigKeyFetch;
    let key = path.into_inner();

    api::server_wrap(
        flow,
        state,
        &req,
        &key,
        |state, _, key, _| configs::read_config(state, key),
        &ADMIN_API_AUTH,
        api_locking::LockAction::NotApplicable,
    )
    .await
}
#[instrument(skip_all, fields(flow = ?Flow::ConfigKeyUpdate))]
pub async fn config_key_update(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
    json_payload: web::Json<api_types::ConfigUpdate>,
) -> impl Responder {
    let flow = Flow::ConfigKeyUpdate;
    let mut payload = json_payload.into_inner();
    let key = path.into_inner();
    payload.key = key;

    api::server_wrap(
        flow,
        state,
        &req,
        &payload,
        |state, _, payload, _| configs::update_config(state, payload),
        &ADMIN_API_AUTH,
        api_locking::LockAction::NotApplicable,
    )
    .await
}

#[instrument(skip_all, fields(flow = ?Flow::ConfigKeyDelete))]
pub async fn config_key_delete(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
) -> impl Responder {
    let flow = Flow::ConfigKeyDelete;
    let key = path.into_inner();

    api::server_wrap(
        flow,
        state,
        &req,
        key,
        |state, _, key, _| configs::config_delete(state, key),
        &ADMIN_API_AUTH,
        api_locking::LockAction::NotApplicable,
    )
    .await
}


// Function: get_sdk_event_metrics_info
// File: crates/analytics/src/utils.rs
// Module: analytics

pub fn get_sdk_event_metrics_info() -> Vec<NameDescription>


// Implementation: impl ConnectorCommon for for Nexinets
// File: crates/hyperswitch_connectors/src/connectors/nexinets.rs
// Module: hyperswitch_connectors
// Methods: 5 total (0 public)

impl ConnectorCommon for for Nexinets


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

pub struct Score


// Trait: DynamicRoutingCache
// File: crates/router/src/core/routing/helpers.rs
// Module: router

pub trait DynamicRoutingCache


// Struct: MerchantAccountUpdate
// File: crates/api_models/src/admin.rs
// Module: api_models
// Implementations: 2

pub struct MerchantAccountUpdate


// Struct: CommonMandateReference
// File: crates/diesel_models/src/payment_method.rs
// Module: diesel_models
// Implementations: 1

pub struct CommonMandateReference


// Implementation: impl ApiEventMetric for for CurrencyConversionResponse
// File: crates/api_models/src/currency.rs
// Module: api_models
// Methods: 0 total (0 public)

impl ApiEventMetric for for CurrencyConversionResponse


// Struct: KafkaAuthentication
// File: crates/router/src/services/kafka/authentication.rs
// Module: router
// Implementations: 2
// Traits: super::KafkaMessage

pub struct KafkaAuthentication<'a>


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

pub struct CancelResponseData


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

pub struct GigadatPaymentResponse


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

pub fn new() -> &'static Self


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

pub struct BarclaycardErrorInformation


// Struct: WalletRequest
// File: crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct WalletRequest


// Function: create_role_v2
// File: crates/router/src/routes/user_role.rs
// Module: router

pub fn create_role_v2(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<role_api::CreateRoleV2Request>,
) -> HttpResponse


// File: crates/analytics/src/payment_intents/filters.rs
// Module: analytics
// Public functions: 1
// Public structs: 1

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

use crate::{
    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql, Window},
    types::{
        AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, FiltersError, FiltersResult,
        LoadRow,
    },
};

pub trait PaymentIntentFilterAnalytics: LoadRow<PaymentIntentFilterRow> {}

pub async fn get_payment_intent_filter_for_dimension<T>(
    dimension: PaymentIntentDimensions,
    merchant_id: &common_utils::id_type::MerchantId,
    time_range: &TimeRange,
    pool: &T,
) -> FiltersResult<Vec<PaymentIntentFilterRow>>
where
    T: AnalyticsDataSource + PaymentIntentFilterAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::PaymentIntent);

    query_builder.add_select_column(dimension).switch()?;
    time_range
        .set_filter_clause(&mut query_builder)
        .attach_printable("Error filtering time range")
        .switch()?;

    query_builder
        .add_filter_clause("merchant_id", merchant_id)
        .switch()?;

    query_builder.set_distinct();

    query_builder
        .execute_query::<PaymentIntentFilterRow, _>(pool)
        .await
        .change_context(FiltersError::QueryBuildingError)?
        .change_context(FiltersError::QueryExecutionFailure)
}

#[derive(Debug, serde::Serialize, Eq, PartialEq, serde::Deserialize)]
pub struct PaymentIntentFilterRow {
    pub status: Option<DBEnumWrapper<IntentStatus>>,
    pub currency: Option<DBEnumWrapper<Currency>>,
    pub profile_id: Option<String>,
    pub connector: Option<String>,
    pub authentication_type: Option<DBEnumWrapper<AuthenticationType>>,
    pub payment_method: Option<String>,
    pub payment_method_type: Option<String>,
    pub card_network: Option<String>,
    pub merchant_id: Option<String>,
    pub card_last_4: Option<String>,
    pub card_issuer: Option<String>,
    pub error_reason: Option<String>,
    pub customer_id: Option<String>,
}


// Function: get_payment_experience
// File: crates/connector_configs/src/transformer.rs
// Module: connector_configs

pub fn get_payment_experience(
        connector: Connector,
        payment_method_type: PaymentMethodType,
        payment_method: PaymentMethod,
        payment_experience: Option<api_models::enums::PaymentExperience>,
    ) -> Option<api_models::enums::PaymentExperience>


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

pub struct CaptureResponse


// Struct: PaymentMethodIntentCreate
// File: crates/api_models/src/payment_methods.rs
// Module: api_models
// Implementations: 0

pub struct PaymentMethodIntentCreate


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

impl Jpmorgan


// Implementation: impl OrganizationId
// File: crates/common_utils/src/id_type/organization.rs
// Module: common_utils
// Methods: 1 total (1 public)

impl OrganizationId


// Function: get_payment_link_status
// File: crates/router/src/core/payment_link.rs
// Module: router

pub fn get_payment_link_status(
    _state: SessionState,
    _merchant_context: domain::MerchantContext,
    _merchant_id: common_utils::id_type::MerchantId,
    _payment_id: common_utils::id_type::PaymentId,
) -> RouterResponse<services::PaymentLinkFormData>


// Implementation: impl UnifiedTranslations
// File: crates/diesel_models/src/query/unified_translations.rs
// Module: diesel_models
// Methods: 3 total (0 public)

impl UnifiedTranslations


// Struct: GetSubscriptionPlanPricesResponse
// File: crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct GetSubscriptionPlanPricesResponse