    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
                .set_body(types::RefundSyncType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: barclaycard::BarclaycardRsyncResponse = res
            .response
            .parse_struct("barclaycard RefundSyncResponse")
            .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<CompleteAuthorize, CompleteAuthorizeData, PaymentsResponseData>
    for Barclaycard
{
    fn get_headers(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }
    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }
    fn get_url(
        &self,
        _req: &PaymentsCompleteAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}pts/v2/payments/",
            ConnectorCommon::base_url(self, connectors)
        ))
    }
    fn get_request_body(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount_in_minor_unit = MinorUnit::new(req.request.amount);
        let amount = convert_amount(
            self.amount_converter,
            amount_in_minor_unit,
            req.request.currency,
        )?;
        let connector_router_data = barclaycard::BarclaycardRouterData::try_from((amount, req))?;

        let connector_req =
            barclaycard::BarclaycardPaymentsRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }
    fn build_request(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsCompleteAuthorizeType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::PaymentsCompleteAuthorizeType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsCompleteAuthorizeType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCompleteAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCompleteAuthorizeRouterData, errors::ConnectorError> {
        let response: barclaycard::BarclaycardPaymentsResponse = res
            .response
            .parse_struct("Barclaycard PaymentResponse")
            .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)
    }

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

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

        let attempt_status = match response.reason {
            Some(reason) => match reason {
                transformers::Reason::SystemError => Some(enums::AttemptStatus::Failure),
                transformers::Reason::ServerTimeout | transformers::Reason::ServiceTimeout => None,
            },
            None => None,
        };
        Ok(ErrorResponse {
            status_code: res.status_code,
            reason: response.status.clone(),
            code: response
                .status
                .unwrap_or(hyperswitch_interfaces::consts::NO_ERROR_CODE.to_string()),
            message: response
                .message
                .unwrap_or(hyperswitch_interfaces::consts::NO_ERROR_MESSAGE.to_string()),
            attempt_status,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

#[async_trait::async_trait]
impl webhooks::IncomingWebhook for Barclaycard {
    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 BARCLAYCARD_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::Mastercard,
            common_enums::CardNetwork::Visa,
            common_enums::CardNetwork::AmericanExpress,
            common_enums::CardNetwork::JCB,
            common_enums::CardNetwork::Discover,
            common_enums::CardNetwork::Maestro,
            common_enums::CardNetwork::Interac,
            common_enums::CardNetwork::DinersClub,
            common_enums::CardNetwork::CartesBancaires,
            common_enums::CardNetwork::UnionPay,
        ];

        let mut barclaycard_supported_payment_methods = SupportedPaymentMethods::new();

        barclaycard_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(),
                        }
                    }),
                ),
            },
        );

        barclaycard_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(),
                        }
                    }),
                ),
            },
        );

        barclaycard_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,
            },
        );

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

        barclaycard_supported_payment_methods
    });

static BARCLAYCARD_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "BarclayCard SmartPay Fuse",
    description: "Barclaycard, part of Barclays Bank UK PLC, is a leading global payment business that helps consumers, retailers and businesses to make and take payments flexibly, and to access short-term credit and point of sale finance.",
    connector_type: enums::HyperswitchConnectorCategory::BankAcquirer,
    integration_status: enums::ConnectorIntegrationStatus::Sandbox,
};

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

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

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

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


// Function: payment_authorize
// File: crates/router/src/routes/dummy_connector/core.rs
// Module: router

pub fn payment_authorize(
    state: SessionState,
    req: types::DummyConnectorPaymentConfirmRequest,
) -> types::DummyConnectorResponse<String>


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

pub fn get_payment_filters_profile(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
) -> impl Responder


// File: crates/router/src/db/user/sample_data.rs
// Module: router

use common_utils::types::keymanager::KeyManagerState;
#[cfg(feature = "v1")]
use diesel_models::user::sample_data::PaymentAttemptBatchNew;
use diesel_models::{
    dispute::{Dispute, DisputeNew},
    errors::DatabaseError,
    query::user::sample_data as sample_data_queries,
    refund::{Refund, RefundNew},
};
use error_stack::{Report, ResultExt};
use futures::{future::try_join_all, FutureExt};
use hyperswitch_domain_models::{
    behaviour::Conversion,
    merchant_key_store::MerchantKeyStore,
    payments::{payment_attempt::PaymentAttempt, PaymentIntent},
};
use storage_impl::{errors::StorageError, DataModelExt};

use crate::{connection::pg_connection_write, core::errors::CustomResult, services::Store};

#[async_trait::async_trait]
pub trait BatchSampleDataInterface {
    #[cfg(feature = "v1")]
    async fn insert_payment_intents_batch_for_sample_data(
        &self,
        state: &KeyManagerState,
        batch: Vec<PaymentIntent>,
        key_store: &MerchantKeyStore,
    ) -> CustomResult<Vec<PaymentIntent>, StorageError>;

    #[cfg(feature = "v1")]
    async fn insert_payment_attempts_batch_for_sample_data(
        &self,
        batch: Vec<PaymentAttemptBatchNew>,
    ) -> CustomResult<Vec<PaymentAttempt>, StorageError>;

    #[cfg(feature = "v1")]
    async fn insert_refunds_batch_for_sample_data(
        &self,
        batch: Vec<RefundNew>,
    ) -> CustomResult<Vec<Refund>, StorageError>;

    #[cfg(feature = "v1")]
    async fn insert_disputes_batch_for_sample_data(
        &self,
        batch: Vec<DisputeNew>,
    ) -> CustomResult<Vec<Dispute>, StorageError>;

    #[cfg(feature = "v1")]
    async fn delete_payment_intents_for_sample_data(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        key_store: &MerchantKeyStore,
    ) -> CustomResult<Vec<PaymentIntent>, StorageError>;

    #[cfg(feature = "v1")]
    async fn delete_payment_attempts_for_sample_data(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<PaymentAttempt>, StorageError>;

    #[cfg(feature = "v1")]
    async fn delete_refunds_for_sample_data(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<Refund>, StorageError>;

    #[cfg(feature = "v1")]
    async fn delete_disputes_for_sample_data(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<Dispute>, StorageError>;
}

#[async_trait::async_trait]
impl BatchSampleDataInterface for Store {
    #[cfg(feature = "v1")]
    async fn insert_payment_intents_batch_for_sample_data(
        &self,
        state: &KeyManagerState,
        batch: Vec<PaymentIntent>,
        key_store: &MerchantKeyStore,
    ) -> CustomResult<Vec<PaymentIntent>, StorageError> {
        let conn = pg_connection_write(self)
            .await
            .change_context(StorageError::DatabaseConnectionError)?;
        let new_intents = try_join_all(batch.into_iter().map(|payment_intent| async {
            payment_intent
                .construct_new()
                .await
                .change_context(StorageError::EncryptionError)
        }))
        .await?;
        sample_data_queries::insert_payment_intents(&conn, new_intents)
            .await
            .map_err(diesel_error_to_data_error)
            .map(|v| {
                try_join_all(v.into_iter().map(|payment_intent| {
                    PaymentIntent::convert_back(
                        state,
                        payment_intent,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                }))
                .map(|join_result| join_result.change_context(StorageError::DecryptionError))
            })?
            .await
    }

    #[cfg(feature = "v1")]
    async fn insert_payment_attempts_batch_for_sample_data(
        &self,
        batch: Vec<PaymentAttemptBatchNew>,
    ) -> CustomResult<Vec<PaymentAttempt>, StorageError> {
        let conn = pg_connection_write(self)
            .await
            .change_context(StorageError::DatabaseConnectionError)?;
        sample_data_queries::insert_payment_attempts(&conn, batch)
            .await
            .map_err(diesel_error_to_data_error)
            .map(|res| {
                res.into_iter()
                    .map(PaymentAttempt::from_storage_model)
                    .collect()
            })
    }

    #[cfg(feature = "v1")]
    async fn insert_refunds_batch_for_sample_data(
        &self,
        batch: Vec<RefundNew>,
    ) -> CustomResult<Vec<Refund>, StorageError> {
        let conn = pg_connection_write(self)
            .await
            .change_context(StorageError::DatabaseConnectionError)?;
        sample_data_queries::insert_refunds(&conn, batch)
            .await
            .map_err(diesel_error_to_data_error)
    }

    #[cfg(feature = "v1")]
    async fn insert_disputes_batch_for_sample_data(
        &self,
        batch: Vec<DisputeNew>,
    ) -> CustomResult<Vec<Dispute>, StorageError> {
        let conn = pg_connection_write(self)
            .await
            .change_context(StorageError::DatabaseConnectionError)?;
        sample_data_queries::insert_disputes(&conn, batch)
            .await
            .map_err(diesel_error_to_data_error)
    }

    #[cfg(feature = "v1")]
    async fn delete_payment_intents_for_sample_data(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        key_store: &MerchantKeyStore,
    ) -> CustomResult<Vec<PaymentIntent>, StorageError> {
        let conn = pg_connection_write(self)
            .await
            .change_context(StorageError::DatabaseConnectionError)?;
        sample_data_queries::delete_payment_intents(&conn, merchant_id)
            .await
            .map_err(diesel_error_to_data_error)
            .map(|v| {
                try_join_all(v.into_iter().map(|payment_intent| {
                    PaymentIntent::convert_back(
                        state,
                        payment_intent,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                }))
                .map(|join_result| join_result.change_context(StorageError::DecryptionError))
            })?
            .await
    }

    #[cfg(feature = "v1")]
    async fn delete_payment_attempts_for_sample_data(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<PaymentAttempt>, StorageError> {
        let conn = pg_connection_write(self)
            .await
            .change_context(StorageError::DatabaseConnectionError)?;
        sample_data_queries::delete_payment_attempts(&conn, merchant_id)
            .await
            .map_err(diesel_error_to_data_error)
            .map(|res| {
                res.into_iter()
                    .map(PaymentAttempt::from_storage_model)
                    .collect()
            })
    }

    #[cfg(feature = "v1")]
    async fn delete_refunds_for_sample_data(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<Refund>, StorageError> {
        let conn = pg_connection_write(self)
            .await
            .change_context(StorageError::DatabaseConnectionError)?;
        sample_data_queries::delete_refunds(&conn, merchant_id)
            .await
            .map_err(diesel_error_to_data_error)
    }

    #[cfg(feature = "v1")]
    async fn delete_disputes_for_sample_data(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<Dispute>, StorageError> {
        let conn = pg_connection_write(self)
            .await
            .change_context(StorageError::DatabaseConnectionError)?;
        sample_data_queries::delete_disputes(&conn, merchant_id)
            .await
            .map_err(diesel_error_to_data_error)
    }
}

#[async_trait::async_trait]
impl BatchSampleDataInterface for storage_impl::MockDb {
    #[cfg(feature = "v1")]
    async fn insert_payment_intents_batch_for_sample_data(
        &self,
        _state: &KeyManagerState,
        _batch: Vec<PaymentIntent>,
        _key_store: &MerchantKeyStore,
    ) -> CustomResult<Vec<PaymentIntent>, StorageError> {
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn insert_payment_attempts_batch_for_sample_data(
        &self,
        _batch: Vec<PaymentAttemptBatchNew>,
    ) -> CustomResult<Vec<PaymentAttempt>, StorageError> {
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn insert_refunds_batch_for_sample_data(
        &self,
        _batch: Vec<RefundNew>,
    ) -> CustomResult<Vec<Refund>, StorageError> {
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn insert_disputes_batch_for_sample_data(
        &self,
        _batch: Vec<DisputeNew>,
    ) -> CustomResult<Vec<Dispute>, StorageError> {
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn delete_payment_intents_for_sample_data(
        &self,
        _state: &KeyManagerState,
        _merchant_id: &common_utils::id_type::MerchantId,
        _key_store: &MerchantKeyStore,
    ) -> CustomResult<Vec<PaymentIntent>, StorageError> {
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn delete_payment_attempts_for_sample_data(
        &self,
        _merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<PaymentAttempt>, StorageError> {
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn delete_refunds_for_sample_data(
        &self,
        _merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<Refund>, StorageError> {
        Err(StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn delete_disputes_for_sample_data(
        &self,
        _merchant_id: &common_utils::id_type::MerchantId,
    ) -> CustomResult<Vec<Dispute>, StorageError> {
        Err(StorageError::MockDbError)?
    }
}

// TODO: This error conversion is re-used from storage_impl and is not DRY when it should be
// Ideally the impl's here should be defined in that crate avoiding this re-definition
fn diesel_error_to_data_error(diesel_error: Report<DatabaseError>) -> Report<StorageError> {
    let new_err = match diesel_error.current_context() {
        DatabaseError::DatabaseConnectionError => StorageError::DatabaseConnectionError,
        DatabaseError::NotFound => StorageError::ValueNotFound("Value not found".to_string()),
        DatabaseError::UniqueViolation => StorageError::DuplicateValue {
            entity: "entity ",
            key: None,
        },
        err => StorageError::DatabaseError(error_stack::report!(*err)),
    };
    diesel_error.change_context(new_err)
}


// Implementation: impl Worldline
// File: crates/hyperswitch_connectors/src/connectors/worldline.rs
// Module: hyperswitch_connectors
// Methods: 2 total (2 public)

impl Worldline


// Struct: CardsRefundResponse
// File: crates/hyperswitch_connectors/src/connectors/trustpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CardsRefundResponse


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

pub struct ExternalVaultProxyPaymentsData


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

impl api::MandateSetup for for Ebanx


// Implementation: impl DisputeMetricsAccumulator
// File: crates/analytics/src/disputes/accumulators.rs
// Module: analytics
// Methods: 1 total (1 public)

impl DisputeMetricsAccumulator


            routable_connector,
            #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
            business_profile,
        ))
        .await?;

        Ok(payment_data)
    }
}

#[cfg(feature = "v1")]
#[async_trait]
impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsRejectData> for PaymentResponse {
    async fn update_tracker<'b>(
        &'b self,
        db: &'b SessionState,
        mut payment_data: PaymentData<F>,
        router_data: types::RouterData<F, types::PaymentsRejectData, types::PaymentsResponseData>,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: enums::MerchantStorageScheme,
        locale: &Option<String>,
        #[cfg(all(feature = "v1", feature = "dynamic_routing"))] routable_connector: Vec<
            RoutableConnectorChoice,
        >,
        #[cfg(all(feature = "v1", feature = "dynamic_routing"))] business_profile: &domain::Profile,
    ) -> RouterResult<PaymentData<F>>
    where
        F: 'b + Send,
    {
        payment_data = Box::pin(payment_response_update_tracker(
            db,
            payment_data,
            router_data,
            key_store,
            storage_scheme,
            locale,
            #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
            routable_connector,
            #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
            business_profile,
        ))
        .await?;

        Ok(payment_data)
    }
}

#[cfg(feature = "v1")]
#[async_trait]
impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::SetupMandateRequestData>
    for PaymentResponse
{
    async fn update_tracker<'b>(
        &'b self,
        db: &'b SessionState,
        mut payment_data: PaymentData<F>,
        router_data: types::RouterData<
            F,
            types::SetupMandateRequestData,
            types::PaymentsResponseData,
        >,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: enums::MerchantStorageScheme,
        locale: &Option<String>,
        #[cfg(all(feature = "v1", feature = "dynamic_routing"))] routable_connector: Vec<
            RoutableConnectorChoice,
        >,
        #[cfg(all(feature = "v1", feature = "dynamic_routing"))] business_profile: &domain::Profile,
    ) -> RouterResult<PaymentData<F>>
    where
        F: 'b + Send,
    {
        payment_data.mandate_id = payment_data.mandate_id.or_else(|| {
            router_data.request.mandate_id.clone()
            // .map(api_models::payments::MandateIds::new)
        });

        payment_data = Box::pin(payment_response_update_tracker(
            db,
            payment_data,
            router_data,
            key_store,
            storage_scheme,
            locale,
            #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
            routable_connector,
            #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
            business_profile,
        ))
        .await?;

        Ok(payment_data)
    }

    async fn save_pm_and_mandate<'b>(
        &self,
        state: &SessionState,
        resp: &types::RouterData<F, types::SetupMandateRequestData, types::PaymentsResponseData>,
        merchant_context: &domain::MerchantContext,
        payment_data: &mut PaymentData<F>,
        business_profile: &domain::Profile,
    ) -> CustomResult<(), errors::ApiErrorResponse>
    where
        F: 'b + Clone + Send + Sync,
    {
        let payment_method_billing_address = payment_data.address.get_payment_method_billing();
        let billing_name = resp
            .address
            .get_payment_method_billing()
            .and_then(|billing_details| billing_details.address.as_ref())
            .and_then(|address| address.get_optional_full_name());

        let save_payment_data = tokenization::SavePaymentMethodData::from(resp);
        let customer_id = payment_data.payment_intent.customer_id.clone();
        let connector_name = payment_data
            .payment_attempt
            .connector
            .clone()
            .ok_or_else(|| {
                logger::error!("Missing required Param connector_name");
                errors::ApiErrorResponse::MissingRequiredField {
                    field_name: "connector_name",
                }
            })?;
        let connector_mandate_reference_id = payment_data
            .payment_attempt
            .connector_mandate_detail
            .as_ref()
            .map(|detail| ConnectorMandateReferenceId::foreign_from(detail.clone()));
        let vault_operation = payment_data.vault_operation.clone();
        let payment_method_info = payment_data.payment_method_info.clone();
        let merchant_connector_id = payment_data.payment_attempt.merchant_connector_id.clone();
        let tokenization::SavePaymentMethodDataResponse {
            payment_method_id,
            connector_mandate_reference_id,
            ..
        } = Box::pin(tokenization::save_payment_method(
            state,
            connector_name,
            save_payment_data,
            customer_id.clone(),
            merchant_context,
            resp.request.payment_method_type,
            billing_name,
            payment_method_billing_address,
            business_profile,
            connector_mandate_reference_id,
            merchant_connector_id.clone(),
            vault_operation,
            payment_method_info,
        ))
        .await?;

        payment_data.payment_method_info = if let Some(payment_method_id) = &payment_method_id {
            match state
                .store
                .find_payment_method(
                    &(state.into()),
                    merchant_context.get_merchant_key_store(),
                    payment_method_id,
                    merchant_context.get_merchant_account().storage_scheme,
                )
                .await
            {
                Ok(payment_method) => Some(payment_method),
                Err(error) => {
                    if error.current_context().is_db_not_found() {
                        logger::info!("Payment Method not found in db {:?}", error);
                        None
                    } else {
                        Err(error)
                            .change_context(errors::ApiErrorResponse::InternalServerError)
                            .attach_printable("Error retrieving payment method from db")
                            .map_err(|err| logger::error!(payment_method_retrieve=?err))
                            .ok()
                    }
                }
            }
        } else {
            None
        };
        let mandate_id = mandate::mandate_procedure(
            state,
            resp,
            &customer_id,
            payment_method_id.clone(),
            merchant_connector_id.clone(),
            merchant_context.get_merchant_account().storage_scheme,
            payment_data.payment_intent.get_id(),
        )
        .await?;
        payment_data.payment_attempt.payment_method_id = payment_method_id;
        payment_data.payment_attempt.mandate_id = mandate_id;
        payment_data.payment_attempt.connector_mandate_detail = connector_mandate_reference_id
            .clone()
            .map(ForeignFrom::foreign_from);
        payment_data.set_mandate_id(api_models::payments::MandateIds {
            mandate_id: None,
            mandate_reference_id: connector_mandate_reference_id.map(|connector_mandate_id| {
                MandateReferenceId::ConnectorMandateId(connector_mandate_id)
            }),
        });
        Ok(())
    }
}

#[cfg(feature = "v1")]
#[async_trait]
impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::CompleteAuthorizeData>
    for PaymentResponse
{
    async fn update_tracker<'b>(
        &'b self,
        db: &'b SessionState,
        payment_data: PaymentData<F>,
        response: types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: enums::MerchantStorageScheme,
        locale: &Option<String>,
        #[cfg(all(feature = "v1", feature = "dynamic_routing"))] routable_connector: Vec<
            RoutableConnectorChoice,
        >,
        #[cfg(all(feature = "v1", feature = "dynamic_routing"))] business_profile: &domain::Profile,
    ) -> RouterResult<PaymentData<F>>
    where
        F: 'b + Send,
    {
        Box::pin(payment_response_update_tracker(
            db,
            payment_data,
            response,
            key_store,
            storage_scheme,
            locale,
            #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
            routable_connector,
            #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
            business_profile,
        ))
        .await
    }

    async fn save_pm_and_mandate<'b>(
        &self,
        state: &SessionState,
        resp: &types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>,
        merchant_context: &domain::MerchantContext,
        payment_data: &mut PaymentData<F>,
        _business_profile: &domain::Profile,
    ) -> CustomResult<(), errors::ApiErrorResponse>
    where
        F: 'b + Clone + Send + Sync,
    {
        let (connector_mandate_id, mandate_metadata, connector_mandate_request_reference_id) = resp
            .response
            .clone()
            .ok()
            .and_then(|resp| {
                if let types::PaymentsResponseData::TransactionResponse {
                    mandate_reference, ..
                } = resp
                {
                    mandate_reference.map(|mandate_ref| {
                        (
                            mandate_ref.connector_mandate_id.clone(),
                            mandate_ref.mandate_metadata.clone(),
                            mandate_ref.connector_mandate_request_reference_id.clone(),
                        )
                    })
                } else {
                    None
                }
            })
            .unwrap_or((None, None, None));
        update_connector_mandate_details_for_the_flow(
            connector_mandate_id,
            mandate_metadata,
            connector_mandate_request_reference_id,
            payment_data,
        )?;

        update_payment_method_status_and_ntid(
            state,
            merchant_context.get_merchant_key_store(),
            payment_data,
            resp.status,
            resp.response.clone(),
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await?;
        Ok(())
    }
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
    state: &SessionState,
    mut payment_data: PaymentData<F>,
    router_data: types::RouterData<F, T, types::PaymentsResponseData>,
    key_store: &domain::MerchantKeyStore,
    storage_scheme: enums::MerchantStorageScheme,
    locale: &Option<String>,
    #[cfg(all(feature = "v1", feature = "dynamic_routing"))] routable_connectors: Vec<
        RoutableConnectorChoice,
    >,
    #[cfg(all(feature = "v1", feature = "dynamic_routing"))] business_profile: &domain::Profile,
) -> RouterResult<PaymentData<F>> {
    // Update additional payment data with the payment method response that we received from connector
    // This is for details like whether 3ds was upgraded and which version of 3ds was used
    // also some connectors might send card network details in the response, which is captured and stored

    let additional_payment_data = payment_data.payment_attempt.get_payment_method_data();

    let additional_payment_method_data = match payment_data.payment_method_data.clone() {
        Some(hyperswitch_domain_models::payment_method_data::PaymentMethodData::NetworkToken(_))
        | Some(hyperswitch_domain_models::payment_method_data::PaymentMethodData::CardDetailsForNetworkTransactionId(_)) => {
            payment_data.payment_attempt.payment_method_data.clone()
        }
        _ => {
            additional_payment_data
                .map(|_| {
                    update_additional_payment_data_with_connector_response_pm_data(
                        payment_data.payment_attempt.payment_method_data.clone(),
                        router_data
                            .connector_response
                            .as_ref()
                            .and_then(|connector_response| {
                                connector_response.additional_payment_method_data.clone()
                            }),
                    )
                })
                .transpose()?
                .flatten()
        }
    };

    router_data.payment_method_status.and_then(|status| {
        payment_data
            .payment_method_info
            .as_mut()
            .map(|info| info.status = status)
    });
    payment_data.whole_connector_response = router_data.raw_connector_response.clone();

    // TODO: refactor of gsm_error_category with respective feature flag
    #[allow(unused_variables)]
    let (capture_update, mut payment_attempt_update, gsm_error_category) = match router_data
        .response
        .clone()
    {
        Err(err) => {
            let auth_update = if Some(router_data.auth_type)
                != payment_data.payment_attempt.authentication_type
            {
                Some(router_data.auth_type)
            } else {
                None
            };
            let (capture_update, attempt_update, gsm_error_category) =
                match payment_data.multiple_capture_data {
                    Some(multiple_capture_data) => {
                        let capture_update = storage::CaptureUpdate::ErrorUpdate {
                            status: match err.status_code {
                                500..=511 => enums::CaptureStatus::Pending,
                                _ => enums::CaptureStatus::Failed,
                            },
                            error_code: Some(err.code),
                            error_message: Some(err.message),
                            error_reason: err.reason,
                        };
                        let capture_update_list = vec![(
                            multiple_capture_data.get_latest_capture().clone(),
                            capture_update,
                        )];
                        (
                            Some((multiple_capture_data, capture_update_list)),
                            auth_update.map(|auth_type| {
                                storage::PaymentAttemptUpdate::AuthenticationTypeUpdate {
                                    authentication_type: auth_type,
                                    updated_by: storage_scheme.to_string(),
                                }
                            }),
                            None,
                        )
                    }
                    None => {
                        let connector_name = router_data.connector.to_string();
                        let flow_name = core_utils::get_flow_name::<F>()?;
                        let option_gsm = payments_helpers::get_gsm_record(
                            state,
                            Some(err.code.clone()),
                            Some(err.message.clone()),
                            connector_name,
                            flow_name.clone(),
                        )
                        .await;

                        let gsm_unified_code =
                            option_gsm.as_ref().and_then(|gsm| gsm.unified_code.clone());
                        let gsm_unified_message =
                            option_gsm.clone().and_then(|gsm| gsm.unified_message);

                        let (unified_code, unified_message) = if let Some((code, message)) =
                            gsm_unified_code.as_ref().zip(gsm_unified_message.as_ref())
                        {
                            (code.to_owned(), message.to_owned())
                        } else {
                            (
                                consts::DEFAULT_UNIFIED_ERROR_CODE.to_owned(),
                                consts::DEFAULT_UNIFIED_ERROR_MESSAGE.to_owned(),
                            )
                        };
                        let unified_translated_message = locale
                            .as_ref()
                            .async_and_then(|locale_str| async {
                                payments_helpers::get_unified_translation(
                                    state,
                                    unified_code.to_owned(),
                                    unified_message.to_owned(),
                                    locale_str.to_owned(),
                                )
                                .await
                            })
                            .await
                            .or(Some(unified_message));

                        let status = match err.attempt_status {
                            // Use the status sent by connector in error_response if it's present
                            Some(status) => status,
                            None =>
                            // mark previous attempt status for technical failures in PSync flow
                            {
                                if flow_name == "PSync" {
                                    match err.status_code {
                                        // marking failure for 2xx because this is genuine payment failure
                                        200..=299 => enums::AttemptStatus::Failure,
                                        _ => router_data.status,
                                    }
                                } else if flow_name == "Capture" {
                                    match err.status_code {
                                        500..=511 => enums::AttemptStatus::Pending,
                                        // don't update the status for 429 error status
                                        429 => router_data.status,
                                        _ => enums::AttemptStatus::Failure,
                                    }
                                } else {
                                    match err.status_code {
                                        500..=511 => enums::AttemptStatus::Pending,
                                        _ => enums::AttemptStatus::Failure,
                                    }
                                }
                            }
                        };
                        (
                            None,
                            Some(storage::PaymentAttemptUpdate::ErrorUpdate {
                                connector: None,
                                status,
                                error_message: Some(Some(err.message.clone())),
                                error_code: Some(Some(err.code.clone())),
                                error_reason: Some(err.reason.clone()),
                                amount_capturable: router_data
                                    .request
                                    .get_amount_capturable(
                                        &payment_data,
                                        router_data
                                            .minor_amount_capturable
                                            .map(MinorUnit::get_amount_as_i64),
                                        status,
                                    )
                                    .map(MinorUnit::new),
                                updated_by: storage_scheme.to_string(),
                                unified_code: Some(Some(unified_code)),
                                unified_message: Some(unified_translated_message),
                                connector_transaction_id: err.connector_transaction_id.clone(),
                                payment_method_data: additional_payment_method_data,
                                authentication_type: auth_update,
                                issuer_error_code: err.network_decline_code.clone(),
                                issuer_error_message: err.network_error_message.clone(),
                                network_details: Some(ForeignFrom::foreign_from(&err)),
                            }),
                            option_gsm.and_then(|option_gsm| option_gsm.error_category),
                        )
                    }
                };
            (capture_update, attempt_update, gsm_error_category)
        }

        Ok(payments_response) => {
            // match on connector integrity check
            match router_data.integrity_check.clone() {
                Err(err) => {
                    let auth_update = if Some(router_data.auth_type)
                        != payment_data.payment_attempt.authentication_type
                    {
                        Some(router_data.auth_type)
                    } else {
                        None
                    };
                    let field_name = err.field_names;
                    let connector_transaction_id = err.connector_transaction_id;
                    (
                        None,
                        Some(storage::PaymentAttemptUpdate::ErrorUpdate {
                            connector: None,
                            status: enums::AttemptStatus::IntegrityFailure,
                            error_message: Some(Some("Integrity Check Failed!".to_string())),
                            error_code: Some(Some("IE".to_string())),
                            error_reason: Some(Some(format!(
                                "Integrity Check Failed! Value mismatched for fields {field_name}"
                            ))),
                            amount_capturable: None,
                            updated_by: storage_scheme.to_string(),
                            unified_code: None,
                            unified_message: None,
                            connector_transaction_id,
                            payment_method_data: None,
                            authentication_type: auth_update,
                            issuer_error_code: None,
                            issuer_error_message: None,
                            network_details: None,
                        }),
                        None,
                    )
                }
                Ok(()) => {
                    let attempt_status = payment_data.payment_attempt.status.to_owned();
                    let connector_status = router_data.status.to_owned();
                    let updated_attempt_status = match (
                        connector_status,
                        attempt_status,
                        payment_data.frm_message.to_owned(),
                    ) {
                        (
                            enums::AttemptStatus::Authorized,
                            enums::AttemptStatus::Unresolved,
                            Some(frm_message),
                        ) => match frm_message.frm_status {
                            enums::FraudCheckStatus::Fraud
                            | enums::FraudCheckStatus::ManualReview => attempt_status,
                            _ => router_data.get_attempt_status_for_db_update(
                                &payment_data,
                                router_data.amount_captured,
                                router_data
                                    .minor_amount_capturable
                                    .map(MinorUnit::get_amount_as_i64),
                            )?,
                        },
                        _ => router_data.get_attempt_status_for_db_update(
                            &payment_data,
                            router_data.amount_captured,
                            router_data
                                .minor_amount_capturable
                                .map(MinorUnit::get_amount_as_i64),
                        )?,
                    };
                    match payments_response {
                        types::PaymentsResponseData::PreProcessingResponse {
                            pre_processing_id,
                            connector_metadata,
                            connector_response_reference_id,
                            ..
                        } => {
                            let connector_transaction_id = match pre_processing_id.to_owned() {
                                types::PreprocessingResponseId::PreProcessingId(_) => None,

                                types::PreprocessingResponseId::ConnectorTransactionId(
                                    connector_txn_id,
                                ) => Some(connector_txn_id),
                            };
                            let preprocessing_step_id = match pre_processing_id {
                                types::PreprocessingResponseId::PreProcessingId(
                                    pre_processing_id,
                                ) => Some(pre_processing_id),
                                types::PreprocessingResponseId::ConnectorTransactionId(_) => None,
                            };
                            let payment_attempt_update =
                                storage::PaymentAttemptUpdate::PreprocessingUpdate {
                                    status: updated_attempt_status,
                                    payment_method_id: payment_data
                                        .payment_attempt
                                        .payment_method_id
                                        .clone(),
                                    connector_metadata,
                                    preprocessing_step_id,
                                    connector_transaction_id,
                                    connector_response_reference_id,
                                    updated_by: storage_scheme.to_string(),
                                };

                            (None, Some(payment_attempt_update), None)
                        }
                        types::PaymentsResponseData::TransactionResponse {
                            resource_id,
                            redirection_data,
                            connector_metadata,
                            connector_response_reference_id,
                            incremental_authorization_allowed,
                            charges,
                            ..
                        } => {
                            payment_data
                                .payment_intent
                                .incremental_authorization_allowed =
                                core_utils::get_incremental_authorization_allowed_value(
                                    incremental_authorization_allowed,
                                    payment_data
                                        .payment_intent
                                        .request_incremental_authorization,
                                );
                            let connector_transaction_id = match resource_id {
                                types::ResponseId::NoResponseId => None,
                                types::ResponseId::ConnectorTransactionId(ref id)
                                | types::ResponseId::EncodedData(ref id) => Some(id),
                            };
                            let resp_network_transaction_id = router_data.response.as_ref()
                                .map_err(|err| {
                                    logger::error!(error = ?err, "Failed to obtain the network_transaction_id from payment response");
                                })
                                .ok()
                                .and_then(|resp| resp.get_network_transaction_id());

                            let encoded_data = payment_data.payment_attempt.encoded_data.clone();

                            let authentication_data = (*redirection_data)
                                .as_ref()
                                .map(Encode::encode_to_value)
                                .transpose()
                                .change_context(errors::ApiErrorResponse::InternalServerError)
                                .attach_printable("Could not parse the connector response")?;

                            let auth_update = if Some(router_data.auth_type)
                                != payment_data.payment_attempt.authentication_type
                            {
                                Some(router_data.auth_type)
                            } else {
                                None
                            };

                            // incase of success, update error code and error message
                            let error_status =
                                if router_data.status == enums::AttemptStatus::Charged {
                                    Some(None)
                                } else {
                                    None
                                };
                            // update connector_mandate_details in case of Authorized/Charged Payment Status
                            if matches!(
                                router_data.status,
                                enums::AttemptStatus::Charged
                                    | enums::AttemptStatus::Authorized
                                    | enums::AttemptStatus::PartiallyAuthorized
                            ) {
                                payment_data
                                    .payment_intent
                                    .fingerprint_id
                                    .clone_from(&payment_data.payment_attempt.fingerprint_id);

                                if let Some(payment_method) =
                                    payment_data.payment_method_info.clone()
                                {
                                    // Parse value to check for mandates' existence
                                    let mandate_details = payment_method
                                        .get_common_mandate_reference()
                                        .change_context(
                                            errors::ApiErrorResponse::InternalServerError,
                                        )
                                        .attach_printable(
                                            "Failed to deserialize to Payment Mandate Reference ",
                                        )?;

                                    if let Some(mca_id) =
                                        payment_data.payment_attempt.merchant_connector_id.clone()
                                    {
                                        // check if the mandate has not already been set to active
                                        if !mandate_details.payments
                                            .as_ref()
                                            .and_then(|payments| payments.0.get(&mca_id))
                                                    .map(|payment_mandate_reference_record| payment_mandate_reference_record.connector_mandate_status == Some(common_enums::ConnectorMandateStatus::Active))
                                                    .unwrap_or(false)
                                    {

                                        let (connector_mandate_id, mandate_metadata,connector_mandate_request_reference_id) = payment_data.payment_attempt.connector_mandate_detail.clone()
                                        .map(|cmr| (cmr.connector_mandate_id, cmr.mandate_metadata,cmr.connector_mandate_request_reference_id))
                                        .unwrap_or((None, None,None));
                                        // Update the connector mandate details with the payment attempt connector mandate id
                                        let connector_mandate_details =
                                                    tokenization::update_connector_mandate_details(
                                                        Some(mandate_details),
                                                        payment_data.payment_attempt.payment_method_type,
                                                        Some(
                                                            payment_data
                                                                .payment_attempt
                                                                .net_amount
                                                                .get_total_amount()
                                                                .get_amount_as_i64(),
                                                        ),
                                                        payment_data.payment_attempt.currency,
                                                        payment_data.payment_attempt.merchant_connector_id.clone(),
                                                        connector_mandate_id,
                                                        mandate_metadata,
                                                        connector_mandate_request_reference_id
                                                    )?;
                                        // Update the payment method table with the active mandate record
                                        payment_methods::cards::update_payment_method_connector_mandate_details(
                                                        state,
                                                        key_store,
                                                        &*state.store,
                                                        payment_method,
                                                        connector_mandate_details,
                                                        storage_scheme,
                                                    )
                                                    .await
                                                    .change_context(errors::ApiErrorResponse::InternalServerError)
                                                    .attach_printable("Failed to update payment method in db")?;
                                    }
                                    }
                                }

                                metrics::SUCCESSFUL_PAYMENT.add(1, &[]);
                            }

                            let payment_method_id =
                                payment_data.payment_attempt.payment_method_id.clone();

                            let debit_routing_savings =
                                payment_data.payment_method_data.as_ref().and_then(|data| {
                                    payments_helpers::get_debit_routing_savings_amount(
                                        data,
                                        &payment_data.payment_attempt,
                                    )
                                });

                            utils::add_apple_pay_payment_status_metrics(
                                router_data.status,
                                router_data.apple_pay_flow.clone(),
                                payment_data.payment_attempt.connector.clone(),
                                payment_data.payment_attempt.merchant_id.clone(),
                            );
                            let is_overcapture_enabled = router_data
                                .connector_response
                                .as_ref()
                                .and_then(|connector_response| {
                                    connector_response.is_overcapture_enabled()
                                }).or_else(|| {
                                    payment_data.payment_intent
                                                    .enable_overcapture
                                                    .as_ref()
                                                    .map(|enable_overcapture| common_types::primitive_wrappers::OvercaptureEnabledBool::new(*enable_overcapture.deref()))
                                            });

                            let (capture_before, extended_authorization_applied) = router_data
                                .connector_response
                                .as_ref()
                                .and_then(|connector_response| {
                                    connector_response.get_extended_authorization_response_data()
                                })
                                .map(|extended_auth_resp| {
                                    (
                                        extended_auth_resp.capture_before,
                                        extended_auth_resp.extended_authentication_applied,
                                    )
                                })
                                .unwrap_or((None, None));
                            let (capture_updates, payment_attempt_update) = match payment_data
                                .multiple_capture_data
                            {
                                Some(multiple_capture_data) => {
                                    let (connector_capture_id, processor_capture_data) =
                                        match resource_id {
                                            types::ResponseId::NoResponseId => (None, None),
                                            types::ResponseId::ConnectorTransactionId(id)
                                            | types::ResponseId::EncodedData(id) => {
                                                let (txn_id, txn_data) =
                                                    ConnectorTransactionId::form_id_and_data(id);
                                                (Some(txn_id), txn_data)
                                            }
                                        };
                                    let capture_update = storage::CaptureUpdate::ResponseUpdate {
                                        status: enums::CaptureStatus::foreign_try_from(
                                            router_data.status,
                                        )?,
                                        connector_capture_id: connector_capture_id.clone(),
                                        connector_response_reference_id,
                                        processor_capture_data: processor_capture_data.clone(),
                                    };
                                    let capture_update_list = vec![(
                                        multiple_capture_data.get_latest_capture().clone(),
                                        capture_update,
                                    )];
                                    (Some((multiple_capture_data, capture_update_list)), auth_update.map(|auth_type| {
                                        storage::PaymentAttemptUpdate::AuthenticationTypeUpdate {
                                            authentication_type: auth_type,
                                            updated_by: storage_scheme.to_string(),
                                        }
                                    }))
                                }
                                None => (
                                    None,
                                    Some(storage::PaymentAttemptUpdate::ResponseUpdate {
                                        status: updated_attempt_status,
                                        connector: None,
                                        connector_transaction_id: connector_transaction_id.cloned(),
                                        authentication_type: auth_update,
                                        amount_capturable: router_data
                                            .request
                                            .get_amount_capturable(
                                                &payment_data,
                                                router_data
                                                    .minor_amount_capturable
                                                    .map(MinorUnit::get_amount_as_i64),
                                                updated_attempt_status,
                                            )
                                            .map(MinorUnit::new),
                                        payment_method_id,
                                        mandate_id: payment_data.payment_attempt.mandate_id.clone(),
                                        connector_metadata,
                                        payment_token: None,
                                        error_code: error_status.clone(),
                                        error_message: error_status.clone(),
                                        error_reason: error_status.clone(),
                                        unified_code: error_status.clone(),
                                        unified_message: error_status,
                                        connector_response_reference_id,
                                        updated_by: storage_scheme.to_string(),
                                        authentication_data,
                                        encoded_data,
                                        payment_method_data: additional_payment_method_data,
                                        capture_before,
                                        extended_authorization_applied,
                                        connector_mandate_detail: payment_data
                                            .payment_attempt
                                            .connector_mandate_detail
                                            .clone(),
                                        charges,
                                        setup_future_usage_applied: payment_data
                                            .payment_attempt
                                            .setup_future_usage_applied,
                                        debit_routing_savings,
                                        network_transaction_id: resp_network_transaction_id,
                                        is_overcapture_enabled,
                                    }),
                                ),
                            };

                            (capture_updates, payment_attempt_update, None)
                        }
                        types::PaymentsResponseData::TransactionUnresolvedResponse {
                            resource_id,
                            reason,
                            connector_response_reference_id,
                        } => {
                            let connector_transaction_id = match resource_id {
                                types::ResponseId::NoResponseId => None,
                                types::ResponseId::ConnectorTransactionId(id)
                                | types::ResponseId::EncodedData(id) => Some(id),
                            };
                            (
                                None,
                                Some(storage::PaymentAttemptUpdate::UnresolvedResponseUpdate {
                                    status: updated_attempt_status,
                                    connector: None,
                                    connector_transaction_id,
                                    payment_method_id: payment_data
                                        .payment_attempt
                                        .payment_method_id
                                        .clone(),
                                    error_code: Some(reason.clone().map(|cd| cd.code)),
                                    error_message: Some(reason.clone().map(|cd| cd.message)),
                                    error_reason: Some(reason.map(|cd| cd.message)),
                                    connector_response_reference_id,
                                    updated_by: storage_scheme.to_string(),
                                }),
                                None,
                            )
                        }
                        types::PaymentsResponseData::SessionResponse { .. } => (None, None, None),
                        types::PaymentsResponseData::SessionTokenResponse { .. } => {
                            (None, None, None)
                        }
                        types::PaymentsResponseData::TokenizationResponse { .. } => {
                            (None, None, None)
                        }
                        types::PaymentsResponseData::ConnectorCustomerResponse(..) => {
                            (None, None, None)
                        }
                        types::PaymentsResponseData::ThreeDSEnrollmentResponse { .. } => {
                            (None, None, None)
                        }
                        types::PaymentsResponseData::PostProcessingResponse { .. } => {
                            (None, None, None)
                        }
                        types::PaymentsResponseData::IncrementalAuthorizationResponse {
                            ..
                        } => (None, None, None),
                        types::PaymentsResponseData::PaymentResourceUpdateResponse { .. } => {
                            (None, None, None)
                        }
                        types::PaymentsResponseData::MultipleCaptureResponse {
                            capture_sync_response_list,
                        } => match payment_data.multiple_capture_data {
                            Some(multiple_capture_data) => {
                                let capture_update_list = response_to_capture_update(
                                    &multiple_capture_data,
                                    capture_sync_response_list,
                                )?;
                                (
                                    Some((multiple_capture_data, capture_update_list)),
                                    None,
                                    None,
                                )
                            }
                            None => (None, None, None),
                        },
                        types::PaymentsResponseData::PaymentsCreateOrderResponse { .. } => {
                            (None, None, None)
                        }
                    }
                }
            }
        }
    };
    payment_data.multiple_capture_data = match capture_update {
        Some((mut multiple_capture_data, capture_updates)) => {
            for (capture, capture_update) in capture_updates {
                let updated_capture = state
                    .store
                    .update_capture_with_capture_id(capture, capture_update, storage_scheme)
                    .await
                    .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
                multiple_capture_data.update_capture(updated_capture);
            }

            let authorized_amount = payment_data.payment_attempt.get_total_amount();

            payment_attempt_update = Some(storage::PaymentAttemptUpdate::AmountToCaptureUpdate {
                status: multiple_capture_data.get_attempt_status(authorized_amount),
                amount_capturable: authorized_amount
                    - multiple_capture_data.get_total_blocked_amount(),
                updated_by: storage_scheme.to_string(),
            });
            Some(multiple_capture_data)
        }
        None => None,
    };

    // Stage 1

    let payment_attempt = payment_data.payment_attempt.clone();

    let m_db = state.clone().store;
    let m_payment_attempt_update = payment_attempt_update.clone();
    let m_payment_attempt = payment_attempt.clone();

    let payment_attempt = payment_attempt_update
        .map(|payment_attempt_update| {
            PaymentAttempt::from_storage_model(
                payment_attempt_update
                    .to_storage_model()
                    .apply_changeset(payment_attempt.clone().to_storage_model()),
            )
        })
        .unwrap_or_else(|| payment_attempt);

    let payment_attempt_fut = tokio::spawn(
        async move {
            Box::pin(async move {
                Ok::<_, error_stack::Report<errors::ApiErrorResponse>>(
                    match m_payment_attempt_update {
                        Some(payment_attempt_update) => m_db
                            .update_payment_attempt_with_attempt_id(
                                m_payment_attempt,
                                payment_attempt_update,
                                storage_scheme,
                            )
                            .await
                            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?,
                        None => m_payment_attempt,
                    },
                )
            })
            .await
        }
        .in_current_span(),
    );

    payment_data.payment_attempt = payment_attempt;

    payment_data.authentication = match payment_data.authentication {
        Some(mut authentication_store) => {
            let authentication_update = storage::AuthenticationUpdate::PostAuthorizationUpdate {
                authentication_lifecycle_status: enums::AuthenticationLifecycleStatus::Used,
            };
            let updated_authentication = state
                .store
                .update_authentication_by_merchant_id_authentication_id(
                    authentication_store.authentication,
                    authentication_update,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
            authentication_store.authentication = updated_authentication;
            Some(authentication_store)
        }
        None => None,
    };

    let amount_captured = get_total_amount_captured(
        &router_data.request,
        router_data.amount_captured.map(MinorUnit::new),
        router_data.status,
        &payment_data,
    );

    let payment_intent_update = match &router_data.response {
        Err(_) => storage::PaymentIntentUpdate::PGStatusUpdate {
            status: api_models::enums::IntentStatus::foreign_from(
                payment_data.payment_attempt.status,
            ),
            updated_by: storage_scheme.to_string(),
            // make this false only if initial payment fails, if incremental authorization call fails don't make it false
            incremental_authorization_allowed: Some(false),
            feature_metadata: payment_data
                .payment_intent
                .feature_metadata
                .clone()
                .map(masking::Secret::new),
        },
        Ok(_) => storage::PaymentIntentUpdate::ResponseUpdate {
            status: api_models::enums::IntentStatus::foreign_from(
                payment_data.payment_attempt.status,
            ),
            amount_captured,
            updated_by: storage_scheme.to_string(),
            fingerprint_id: payment_data.payment_attempt.fingerprint_id.clone(),
            incremental_authorization_allowed: payment_data
                .payment_intent
                .incremental_authorization_allowed,
            feature_metadata: payment_data
                .payment_intent
                .feature_metadata
                .clone()
                .map(masking::Secret::new),
        },
    };

    let m_db = state.clone().store;
    let m_key_store = key_store.clone();
    let m_payment_data_payment_intent = payment_data.payment_intent.clone();
    let m_payment_intent_update = payment_intent_update.clone();
    let key_manager_state: KeyManagerState = state.into();
    let payment_intent_fut = tokio::spawn(
        async move {
            m_db.update_payment_intent(
                &key_manager_state,
                m_payment_data_payment_intent,
                m_payment_intent_update,
                &m_key_store,
                storage_scheme,
            )
            .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))
            .await
        }
        .in_current_span(),
    );

    // When connector requires redirection for mandate creation it can update the connector mandate_id during Psync and CompleteAuthorize
    let m_db = state.clone().store;
    let m_router_data_merchant_id = router_data.merchant_id.clone();
    let m_payment_method_id = payment_data.payment_attempt.payment_method_id.clone();
    let m_payment_data_mandate_id =
        payment_data
            .payment_attempt
            .mandate_id
            .clone()
            .or(payment_data
                .mandate_id
                .clone()
                .and_then(|mandate_ids| mandate_ids.mandate_id));
    let m_router_data_response = router_data.response.clone();
    let mandate_update_fut = tokio::spawn(
        async move {
            mandate::update_connector_mandate_id(
                m_db.as_ref(),
                &m_router_data_merchant_id,
                m_payment_data_mandate_id,
                m_payment_method_id,
                m_router_data_response,
                storage_scheme,
            )
            .await
        }
        .in_current_span(),
    );

    let (payment_intent, _, payment_attempt) = futures::try_join!(
        utils::flatten_join_error(payment_intent_fut),
        utils::flatten_join_error(mandate_update_fut),
        utils::flatten_join_error(payment_attempt_fut)
    )?;

    #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
    {
        if payment_intent.status.is_in_terminal_state()
            && business_profile.dynamic_routing_algorithm.is_some()
        {
            let dynamic_routing_algo_ref: api_models::routing::DynamicRoutingAlgorithmRef =
                business_profile
                    .dynamic_routing_algorithm
                    .clone()
                    .map(|val| val.parse_value("DynamicRoutingAlgorithmRef"))
                    .transpose()
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("unable to deserialize DynamicRoutingAlgorithmRef from JSON")?
                    .ok_or(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("DynamicRoutingAlgorithmRef not found in profile")?;

            let state = state.clone();


// Struct: ThemeNew
// File: crates/diesel_models/src/user/theme.rs
// Module: diesel_models
// Implementations: 1

pub struct ThemeNew


// File: crates/common_utils/src/encryption.rs
// Module: common_utils
// Public functions: 3
// Public structs: 1

use diesel::{
    backend::Backend,
    deserialize::{self, FromSql, Queryable},
    expression::AsExpression,
    serialize::ToSql,
    sql_types,
};
use masking::Secret;

use crate::{crypto::Encryptable, pii::EncryptionStrategy};

impl<DB> FromSql<sql_types::Binary, DB> for Encryption
where
    DB: Backend,
    Secret<Vec<u8>, EncryptionStrategy>: FromSql<sql_types::Binary, DB>,
{
    fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
        <Secret<Vec<u8>, EncryptionStrategy>>::from_sql(bytes).map(Self::new)
    }
}

impl<DB> ToSql<sql_types::Binary, DB> for Encryption
where
    DB: Backend,
    Secret<Vec<u8>, EncryptionStrategy>: ToSql<sql_types::Binary, DB>,
{
    fn to_sql<'b>(
        &'b self,
        out: &mut diesel::serialize::Output<'b, '_, DB>,
    ) -> diesel::serialize::Result {
        self.get_inner().to_sql(out)
    }
}

impl<DB> Queryable<sql_types::Binary, DB> for Encryption
where
    DB: Backend,
    Secret<Vec<u8>, EncryptionStrategy>: FromSql<sql_types::Binary, DB>,
{
    type Row = Secret<Vec<u8>, EncryptionStrategy>;
    fn build(row: Self::Row) -> deserialize::Result<Self> {
        Ok(Self { inner: row })
    }
}

#[derive(Debug, AsExpression, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
#[diesel(sql_type = sql_types::Binary)]
#[repr(transparent)]
pub struct Encryption {
    inner: Secret<Vec<u8>, EncryptionStrategy>,
}

impl<T: Clone> From<Encryptable<T>> for Encryption {
    fn from(value: Encryptable<T>) -> Self {
        Self::new(value.into_encrypted())
    }
}

impl Encryption {
    pub fn new(item: Secret<Vec<u8>, EncryptionStrategy>) -> Self {
        Self { inner: item }
    }

    #[inline]
    pub fn into_inner(self) -> Secret<Vec<u8>, EncryptionStrategy> {
        self.inner
    }

    #[inline]
    pub fn get_inner(&self) -> &Secret<Vec<u8>, EncryptionStrategy> {
        &self.inner
    }
}


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

impl ConnectorValidation for for Gocardless


// File: crates/hyperswitch_domain_models/src/payouts/payouts.rs
// Module: hyperswitch_domain_models
// Public structs: 3

use common_enums as storage_enums;
use common_utils::{id_type, pii, types::MinorUnit};
use serde::{Deserialize, Serialize};
use storage_enums::MerchantStorageScheme;
use time::PrimitiveDateTime;

use super::payout_attempt::PayoutAttempt;
#[cfg(feature = "olap")]
use super::PayoutFetchConstraints;

#[async_trait::async_trait]
pub trait PayoutsInterface {
    type Error;
    async fn insert_payout(
        &self,
        _payout: PayoutsNew,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Payouts, Self::Error>;

    async fn find_payout_by_merchant_id_payout_id(
        &self,
        _merchant_id: &id_type::MerchantId,
        _payout_id: &id_type::PayoutId,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Payouts, Self::Error>;

    async fn update_payout(
        &self,
        _this: &Payouts,
        _payout: PayoutsUpdate,
        _payout_attempt: &PayoutAttempt,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Payouts, Self::Error>;

    async fn find_optional_payout_by_merchant_id_payout_id(
        &self,
        _merchant_id: &id_type::MerchantId,
        _payout_id: &id_type::PayoutId,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Option<Payouts>, Self::Error>;

    #[cfg(feature = "olap")]
    async fn filter_payouts_by_constraints(
        &self,
        _merchant_id: &id_type::MerchantId,
        _filters: &PayoutFetchConstraints,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<Payouts>, Self::Error>;

    #[cfg(feature = "olap")]
    async fn filter_payouts_and_attempts(
        &self,
        _merchant_id: &id_type::MerchantId,
        _filters: &PayoutFetchConstraints,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<
        Vec<(
            Payouts,
            PayoutAttempt,
            Option<diesel_models::Customer>,
            Option<diesel_models::Address>,
        )>,
        Self::Error,
    >;

    #[cfg(feature = "olap")]
    async fn filter_payouts_by_time_range_constraints(
        &self,
        _merchant_id: &id_type::MerchantId,
        _time_range: &common_utils::types::TimeRange,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<Payouts>, Self::Error>;

    #[cfg(feature = "olap")]
    #[allow(clippy::too_many_arguments)]
    async fn get_total_count_of_filtered_payouts(
        &self,
        _merchant_id: &id_type::MerchantId,
        _active_payout_ids: &[id_type::PayoutId],
        _connector: Option<Vec<api_models::enums::PayoutConnectors>>,
        _currency: Option<Vec<storage_enums::Currency>>,
        _status: Option<Vec<storage_enums::PayoutStatus>>,
        _payout_method: Option<Vec<storage_enums::PayoutType>>,
    ) -> error_stack::Result<i64, Self::Error>;

    #[cfg(feature = "olap")]
    async fn filter_active_payout_ids_by_constraints(
        &self,
        _merchant_id: &id_type::MerchantId,
        _constraints: &PayoutFetchConstraints,
    ) -> error_stack::Result<Vec<id_type::PayoutId>, Self::Error>;
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Payouts {
    pub payout_id: id_type::PayoutId,
    pub merchant_id: id_type::MerchantId,
    pub customer_id: Option<id_type::CustomerId>,
    pub address_id: Option<String>,
    pub payout_type: Option<storage_enums::PayoutType>,
    pub payout_method_id: Option<String>,
    pub amount: MinorUnit,
    pub destination_currency: storage_enums::Currency,
    pub source_currency: storage_enums::Currency,
    pub description: Option<String>,
    pub recurring: bool,
    pub auto_fulfill: bool,
    pub return_url: Option<String>,
    pub entity_type: storage_enums::PayoutEntityType,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub created_at: PrimitiveDateTime,
    pub last_modified_at: PrimitiveDateTime,
    pub attempt_count: i16,
    pub profile_id: id_type::ProfileId,
    pub status: storage_enums::PayoutStatus,
    pub confirm: Option<bool>,
    pub payout_link_id: Option<String>,
    pub client_secret: Option<String>,
    pub priority: Option<storage_enums::PayoutSendPriority>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PayoutsNew {
    pub payout_id: id_type::PayoutId,
    pub merchant_id: id_type::MerchantId,
    pub customer_id: Option<id_type::CustomerId>,
    pub address_id: Option<String>,
    pub payout_type: Option<storage_enums::PayoutType>,
    pub payout_method_id: Option<String>,
    pub amount: MinorUnit,
    pub destination_currency: storage_enums::Currency,
    pub source_currency: storage_enums::Currency,
    pub description: Option<String>,
    pub recurring: bool,
    pub auto_fulfill: bool,
    pub return_url: Option<String>,
    pub entity_type: storage_enums::PayoutEntityType,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub created_at: PrimitiveDateTime,
    pub last_modified_at: PrimitiveDateTime,
    pub attempt_count: i16,
    pub profile_id: id_type::ProfileId,
    pub status: storage_enums::PayoutStatus,
    pub confirm: Option<bool>,
    pub payout_link_id: Option<String>,
    pub client_secret: Option<String>,
    pub priority: Option<storage_enums::PayoutSendPriority>,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum PayoutsUpdate {
    Update {
        amount: MinorUnit,
        destination_currency: storage_enums::Currency,
        source_currency: storage_enums::Currency,
        description: Option<String>,
        recurring: bool,
        auto_fulfill: bool,
        return_url: Option<String>,
        entity_type: storage_enums::PayoutEntityType,
        metadata: Option<pii::SecretSerdeValue>,
        profile_id: Option<id_type::ProfileId>,
        status: Option<storage_enums::PayoutStatus>,
        confirm: Option<bool>,
        payout_type: Option<storage_enums::PayoutType>,
        address_id: Option<String>,
        customer_id: Option<id_type::CustomerId>,
    },
    PayoutMethodIdUpdate {
        payout_method_id: String,
    },
    RecurringUpdate {
        recurring: bool,
    },
    AttemptCountUpdate {
        attempt_count: i16,
    },
    StatusUpdate {
        status: storage_enums::PayoutStatus,
    },
}

#[derive(Clone, Debug, Default)]
pub struct PayoutsUpdateInternal {
    pub amount: Option<MinorUnit>,
    pub destination_currency: Option<storage_enums::Currency>,
    pub source_currency: Option<storage_enums::Currency>,
    pub description: Option<String>,
    pub recurring: Option<bool>,
    pub auto_fulfill: Option<bool>,
    pub return_url: Option<String>,
    pub entity_type: Option<storage_enums::PayoutEntityType>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub payout_method_id: Option<String>,
    pub profile_id: Option<id_type::ProfileId>,
    pub status: Option<storage_enums::PayoutStatus>,
    pub attempt_count: Option<i16>,
    pub confirm: Option<bool>,
    pub payout_type: Option<common_enums::PayoutType>,
    pub address_id: Option<String>,
    pub customer_id: Option<id_type::CustomerId>,
}

impl From<PayoutsUpdate> for PayoutsUpdateInternal {
    fn from(payout_update: PayoutsUpdate) -> Self {
        match payout_update {
            PayoutsUpdate::Update {
                amount,
                destination_currency,
                source_currency,
                description,
                recurring,
                auto_fulfill,
                return_url,
                entity_type,
                metadata,
                profile_id,
                status,
                confirm,
                payout_type,
                address_id,
                customer_id,
            } => Self {
                amount: Some(amount),
                destination_currency: Some(destination_currency),
                source_currency: Some(source_currency),
                description,
                recurring: Some(recurring),
                auto_fulfill: Some(auto_fulfill),
                return_url,
                entity_type: Some(entity_type),
                metadata,
                profile_id,
                status,
                confirm,
                payout_type,
                address_id,
                customer_id,
                ..Default::default()
            },
            PayoutsUpdate::PayoutMethodIdUpdate { payout_method_id } => Self {
                payout_method_id: Some(payout_method_id),
                ..Default::default()
            },
            PayoutsUpdate::RecurringUpdate { recurring } => Self {
                recurring: Some(recurring),
                ..Default::default()
            },
            PayoutsUpdate::AttemptCountUpdate { attempt_count } => Self {
                attempt_count: Some(attempt_count),
                ..Default::default()
            },
            PayoutsUpdate::StatusUpdate { status } => Self {
                status: Some(status),
                ..Default::default()
            },
        }
    }
}


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

pub fn supports_file_storage_module(self) -> bool


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

pub struct PaymentIntentUpdateMems


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

pub fn update_merchant_account(
    state: web::Data<AppState>,
    req: HttpRequest,
    mid: web::Path<common_utils::id_type::MerchantId>,
    json_payload: web::Json<admin::MerchantAccountUpdate>,
) -> HttpResponse


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

pub mod api;
pub mod authentication;
pub mod authorization;
pub mod connector_integration_interface;
#[cfg(feature = "email")]
pub mod email;
pub mod encryption;
#[cfg(feature = "olap")]
pub mod jwt;
pub mod kafka;
pub mod logger;
pub mod pm_auth;

pub mod card_testing_guard;
#[cfg(feature = "olap")]
pub mod openidconnect;

use std::sync::Arc;

use error_stack::ResultExt;
pub use hyperswitch_interfaces::connector_integration_v2::{
    BoxedConnectorIntegrationV2, ConnectorIntegrationAnyV2, ConnectorIntegrationV2,
};
use masking::{ExposeInterface, StrongSecret};
#[cfg(feature = "kv_store")]
use storage_impl::kv_router_store::KVRouterStore;
use storage_impl::{config::TenantConfig, errors::StorageResult, redis::RedisStore, RouterStore};
use tokio::sync::oneshot;

pub use self::{api::*, encryption::*};
use crate::{configs::Settings, core::errors};

#[cfg(not(feature = "olap"))]
pub type StoreType = storage_impl::database::store::Store;
#[cfg(feature = "olap")]
pub type StoreType = storage_impl::database::store::ReplicaStore;

#[cfg(not(feature = "kv_store"))]
pub type Store = RouterStore<StoreType>;
#[cfg(feature = "kv_store")]
pub type Store = KVRouterStore<StoreType>;

/// # Panics
///
/// Will panic if hex decode of master key fails
#[allow(clippy::expect_used)]
pub async fn get_store(
    config: &Settings,
    tenant: &dyn TenantConfig,
    cache_store: Arc<RedisStore>,
    test_transaction: bool,
) -> StorageResult<Store> {
    let master_config = config.master_database.clone().into_inner();

    #[cfg(feature = "olap")]
    let replica_config = config.replica_database.clone().into_inner();

    #[allow(clippy::expect_used)]
    let master_enc_key = hex::decode(config.secrets.get_inner().master_enc_key.clone().expose())
        .map(StrongSecret::new)
        .expect("Failed to decode master key from hex");

    #[cfg(not(feature = "olap"))]
    let conf = master_config.into();
    #[cfg(feature = "olap")]
    // this would get abstracted, for all cases
    #[allow(clippy::useless_conversion)]
    let conf = (master_config.into(), replica_config.into());

    let store: RouterStore<StoreType> = if test_transaction {
        RouterStore::test_store(conf, tenant, &config.redis, master_enc_key).await?
    } else {
        RouterStore::from_config(
            conf,
            tenant,
            master_enc_key,
            cache_store,
            storage_impl::redis::cache::IMC_INVALIDATION_CHANNEL,
        )
        .await?
    };

    #[cfg(feature = "kv_store")]
    let store = KVRouterStore::from_store(
        store,
        config.drainer.stream_name.clone(),
        config.drainer.num_partitions,
        config.kv_config.ttl,
        config.kv_config.soft_kill,
    );

    Ok(store)
}

#[allow(clippy::expect_used)]
pub async fn get_cache_store(
    config: &Settings,
    shut_down_signal: oneshot::Sender<()>,
    _test_transaction: bool,
) -> StorageResult<Arc<RedisStore>> {
    RouterStore::<StoreType>::cache_store(&config.redis, shut_down_signal).await
}

#[inline]
pub fn generate_aes256_key() -> errors::CustomResult<[u8; 32], common_utils::errors::CryptoError> {
    use ring::rand::SecureRandom;

    let rng = ring::rand::SystemRandom::new();
    let mut key: [u8; 256 / 8] = [0_u8; 256 / 8];
    rng.fill(&mut key)
        .change_context(common_utils::errors::CryptoError::EncodingFailed)?;
    Ok(key)
}


// Struct: CustomerNew
// File: crates/diesel_models/src/customers.rs
// Module: diesel_models
// Implementations: 2

pub struct CustomerNew


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

impl AuthenticationInterface for for KafkaStore


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

pub struct PreconditionData


// Struct: FieldMeta
// File: crates/router_derive/src/macros/to_encryptable.rs
// Module: router_derive
// Implementations: 2
// Traits: Parse, quote::ToTokens

pub struct FieldMeta