// File: crates/router/src/core/payments/flows/complete_authorize_flow.rs
// Module: router
// Public functions: 1

use async_trait::async_trait;
use masking::ExposeInterface;

use super::{ConstructFlowSpecificData, Feature};
use crate::{
    core::{
        errors::{ApiErrorResponse, ConnectorErrorExt, RouterResult},
        payments::{self, access_token, helpers, transformers, PaymentData},
    },
    routes::{metrics, SessionState},
    services,
    types::{self, api, domain, transformers::ForeignTryFrom},
};

#[async_trait]
impl
    ConstructFlowSpecificData<
        api::CompleteAuthorize,
        types::CompleteAuthorizeData,
        types::PaymentsResponseData,
    > for PaymentData<api::CompleteAuthorize>
{
    #[cfg(feature = "v1")]
    async fn construct_router_data<'a>(
        &self,
        state: &SessionState,
        connector_id: &str,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
        merchant_connector_account: &helpers::MerchantConnectorAccountType,
        merchant_recipient_data: Option<types::MerchantRecipientData>,
        header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<
        types::RouterData<
            api::CompleteAuthorize,
            types::CompleteAuthorizeData,
            types::PaymentsResponseData,
        >,
    > {
        Box::pin(transformers::construct_payment_router_data::<
            api::CompleteAuthorize,
            types::CompleteAuthorizeData,
        >(
            state,
            self.clone(),
            connector_id,
            merchant_context,
            customer,
            merchant_connector_account,
            merchant_recipient_data,
            header_payload,
        ))
        .await
    }

    #[cfg(feature = "v2")]
    async fn construct_router_data<'a>(
        &self,
        state: &SessionState,
        connector_id: &str,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
        merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
        merchant_recipient_data: Option<types::MerchantRecipientData>,
        header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<
        types::RouterData<
            api::CompleteAuthorize,
            types::CompleteAuthorizeData,
            types::PaymentsResponseData,
        >,
    > {
        todo!()
    }
}

#[async_trait]
impl Feature<api::CompleteAuthorize, types::CompleteAuthorizeData>
    for types::RouterData<
        api::CompleteAuthorize,
        types::CompleteAuthorizeData,
        types::PaymentsResponseData,
    >
{
    async fn decide_flows<'a>(
        mut self,
        state: &SessionState,
        connector: &api::ConnectorData,
        call_connector_action: payments::CallConnectorAction,
        connector_request: Option<services::Request>,
        business_profile: &domain::Profile,
        header_payload: hyperswitch_domain_models::payments::HeaderPayload,
        _return_raw_connector_response: Option<bool>,
    ) -> RouterResult<Self> {
        let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
            api::CompleteAuthorize,
            types::CompleteAuthorizeData,
            types::PaymentsResponseData,
        > = connector.connector.get_connector_integration();

        let mut complete_authorize_router_data = services::execute_connector_processing_step(
            state,
            connector_integration,
            &self,
            call_connector_action.clone(),
            connector_request,
            None,
        )
        .await
        .to_payment_failed_response()?;
        match complete_authorize_router_data.response.clone() {
            Err(_) => Ok(complete_authorize_router_data),
            Ok(complete_authorize_response) => {
                // Check if the Capture API should be called based on the connector and other parameters
                if super::should_initiate_capture_flow(
                    &connector.connector_name,
                    self.request.customer_acceptance,
                    self.request.capture_method,
                    self.request.setup_future_usage,
                    complete_authorize_router_data.status,
                ) {
                    complete_authorize_router_data = Box::pin(process_capture_flow(
                        complete_authorize_router_data,
                        complete_authorize_response,
                        state,
                        connector,
                        call_connector_action.clone(),
                        business_profile,
                        header_payload,
                    ))
                    .await?;
                }
                Ok(complete_authorize_router_data)
            }
        }
    }

    async fn add_access_token<'a>(
        &self,
        state: &SessionState,
        connector: &api::ConnectorData,
        merchant_context: &domain::MerchantContext,
        creds_identifier: Option<&str>,
    ) -> RouterResult<types::AddAccessTokenResult> {
        Box::pin(access_token::add_access_token(
            state,
            connector,
            merchant_context,
            self,
            creds_identifier,
        ))
        .await
    }

    async fn add_payment_method_token<'a>(
        &mut self,
        state: &SessionState,
        connector: &api::ConnectorData,
        _tokenization_action: &payments::TokenizationAction,
        should_continue_payment: bool,
    ) -> RouterResult<types::PaymentMethodTokenResult> {
        // TODO: remove this and handle it in core
        if matches!(connector.connector_name, types::Connector::Payme) {
            let request = self.request.clone();
            payments::tokenization::add_payment_method_token(
                state,
                connector,
                &payments::TokenizationAction::TokenizeInConnector,
                self,
                types::PaymentMethodTokenizationData::try_from(request)?,
                should_continue_payment,
            )
            .await
        } else {
            Ok(types::PaymentMethodTokenResult {
                payment_method_token_result: Ok(None),
                is_payment_method_tokenization_performed: false,
                connector_response: None,
            })
        }
    }

    async fn build_flow_specific_connector_request(
        &mut self,
        state: &SessionState,
        connector: &api::ConnectorData,
        call_connector_action: payments::CallConnectorAction,
    ) -> RouterResult<(Option<services::Request>, bool)> {
        let request = match call_connector_action {
            payments::CallConnectorAction::Trigger => {
                let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
                    api::CompleteAuthorize,
                    types::CompleteAuthorizeData,
                    types::PaymentsResponseData,
                > = connector.connector.get_connector_integration();

                connector_integration
                    .build_request(self, &state.conf.connectors)
                    .to_payment_failed_response()?
            }
            _ => None,
        };

        Ok((request, true))
    }

    async fn preprocessing_steps<'a>(
        self,
        state: &SessionState,
        connector: &api::ConnectorData,
    ) -> RouterResult<Self> {
        complete_authorize_preprocessing_steps(state, &self, true, connector).await
    }
}

pub async fn complete_authorize_preprocessing_steps<F: Clone>(
    state: &SessionState,
    router_data: &types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>,
    confirm: bool,
    connector: &api::ConnectorData,
) -> RouterResult<types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>> {
    if confirm {
        let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
            api::PreProcessing,
            types::PaymentsPreProcessingData,
            types::PaymentsResponseData,
        > = connector.connector.get_connector_integration();

        let preprocessing_request_data =
            types::PaymentsPreProcessingData::try_from(router_data.request.to_owned())?;

        let preprocessing_response_data: Result<types::PaymentsResponseData, types::ErrorResponse> =
            Err(types::ErrorResponse::default());

        let preprocessing_router_data =
            helpers::router_data_type_conversion::<_, api::PreProcessing, _, _, _, _>(
                router_data.clone(),
                preprocessing_request_data,
                preprocessing_response_data,
            );

        let resp = services::execute_connector_processing_step(
            state,
            connector_integration,
            &preprocessing_router_data,
            payments::CallConnectorAction::Trigger,
            None,
            None,
        )
        .await
        .to_payment_failed_response()?;

        metrics::PREPROCESSING_STEPS_COUNT.add(
            1,
            router_env::metric_attributes!(
                ("connector", connector.connector_name.to_string()),
                ("payment_method", router_data.payment_method.to_string()),
            ),
        );

        let mut router_data_request = router_data.request.to_owned();

        if let Ok(types::PaymentsResponseData::TransactionResponse {
            connector_metadata, ..
        }) = &resp.response
        {
            connector_metadata.clone_into(&mut router_data_request.connector_meta);
        };

        let authorize_router_data = helpers::router_data_type_conversion::<_, F, _, _, _, _>(
            resp.clone(),
            router_data_request,
            resp.response,
        );

        Ok(authorize_router_data)
    } else {
        Ok(router_data.clone())
    }
}

impl<F>
    ForeignTryFrom<types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>>
    for types::PaymentsCaptureData
{
    type Error = error_stack::Report<ApiErrorResponse>;

    fn foreign_try_from(
        item: types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        let response = item
            .response
            .map_err(|err| ApiErrorResponse::ExternalConnectorError {
                code: err.code,
                message: err.message,
                connector: item.connector.clone().to_string(),
                status_code: err.status_code,
                reason: err.reason,
            })?;

        Ok(Self {
            amount_to_capture: item.request.amount,
            currency: item.request.currency,
            connector_transaction_id: types::PaymentsResponseData::get_connector_transaction_id(
                &response,
            )?,
            payment_amount: item.request.amount,
            multiple_capture_data: None,
            connector_meta: types::PaymentsResponseData::get_connector_metadata(&response)
                .map(|secret| secret.expose()),
            browser_info: None,
            metadata: None,
            capture_method: item.request.capture_method,
            minor_payment_amount: item.request.minor_amount,
            minor_amount_to_capture: item.request.minor_amount,
            integrity_object: None,
            split_payments: None,
            webhook_url: None,
        })
    }
}

async fn process_capture_flow(
    mut router_data: types::RouterData<
        api::CompleteAuthorize,
        types::CompleteAuthorizeData,
        types::PaymentsResponseData,
    >,
    complete_authorize_response: types::PaymentsResponseData,
    state: &SessionState,
    connector: &api::ConnectorData,
    call_connector_action: payments::CallConnectorAction,
    business_profile: &domain::Profile,
    header_payload: hyperswitch_domain_models::payments::HeaderPayload,
) -> RouterResult<
    types::RouterData<
        api::CompleteAuthorize,
        types::CompleteAuthorizeData,
        types::PaymentsResponseData,
    >,
> {
    // Convert RouterData into Capture RouterData
    let capture_router_data = helpers::router_data_type_conversion(
        router_data.clone(),
        types::PaymentsCaptureData::foreign_try_from(router_data.clone())?,
        Err(types::ErrorResponse::default()),
    );

    // Call capture request
    let post_capture_router_data = super::call_capture_request(
        capture_router_data,
        state,
        connector,
        call_connector_action,
        business_profile,
        header_payload,
    )
    .await;

    // Process capture response
    let (updated_status, updated_response) =
        super::handle_post_capture_response(complete_authorize_response, post_capture_router_data)?;

    router_data.status = updated_status;
    router_data.response = Ok(updated_response);
    Ok(router_data)
}


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

use std::sync::LazyLock;

use api_models::webhooks::{IncomingWebhookEvent, ObjectReferenceId};
use common_enums::enums;
use common_utils::{
    errors::CustomResult,
    ext_traits::{ByteSliceExt, ValueExt},
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, MinorUnit, MinorUnitForConnector},
};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
        IncrementalAuthorization,
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData,
        PaymentsSessionData, PaymentsSyncData, RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        PaymentsIncrementalAuthorizationRouterData, PaymentsSyncRouterData, RefundSyncRouterData,
        RefundsRouterData, SetupMandateRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    consts::NO_ERROR_MESSAGE,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::Response,
    webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
};
use masking::Maskable;
use router_env::{error, info};
use transformers::{
    self as archipel, ArchipelCardAuthorizationRequest, ArchipelIncrementalAuthorizationRequest,
    ArchipelPaymentsCancelRequest, ArchipelRefundRequest, ArchipelWalletAuthorizationRequest,
};

use crate::{
    constants::headers,
    types::ResponseRouterData,
    utils::{is_mandate_supported, PaymentMethodDataType, PaymentsAuthorizeRequestData},
};

pub mod transformers;

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

impl Archipel {
    pub const fn new() -> &'static Self {
        &Self {
            amount_converter: &MinorUnitForConnector,
        }
    }
}

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

fn build_env_specific_endpoint(
    base_url: &str,
    connector_metadata: &Option<common_utils::pii::SecretSerdeValue>,
) -> CustomResult<String, errors::ConnectorError> {
    let archipel_connector_metadata_object =
        transformers::ArchipelConfigData::try_from(connector_metadata)?;
    let endpoint_prefix = archipel_connector_metadata_object.platform_url;
    Ok(base_url.replace("{{merchant_endpoint_prefix}}", &endpoint_prefix))
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Archipel
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            self.get_content_type().to_string().into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }
}

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

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

    fn get_auth_header(
        &self,
        _auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        Ok(vec![])
    }

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

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

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let archipel_error: CustomResult<
            archipel::ArchipelErrorMessage,
            common_utils::errors::ParsingError,
        > = res.response.parse_struct("ArchipelErrorMessage");

        match archipel_error {
            Ok(err) => {
                event_builder.map(|i| i.set_error_response_body(&err));
                info!(connector_response=?err);

                Ok(ErrorResponse {
                    status_code: res.status_code,
                    code: err.code,
                    attempt_status: None,
                    connector_transaction_id: None,
                    message: err
                        .description
                        .clone()
                        .unwrap_or(NO_ERROR_MESSAGE.to_string()),
                    reason: err.description,
                    network_decline_code: None,
                    network_advice_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                })
            }
            Err(error) => {
                event_builder.map(|event| {
                    event.set_error(serde_json::json!({
                        "error": res.response.escape_ascii().to_string(),
                        "status_code": res.status_code
                    }))
                });
                error!(deserialization_error=?error);
                crate::utils::handle_json_response_deserialization_failure(res, "archipel")
            }
        }
    }
}

impl ConnectorValidation for Archipel {
    fn validate_mandate_payment(
        &self,
        pm_type: Option<enums::PaymentMethodType>,
        pm_data: PaymentMethodData,
    ) -> CustomResult<(), errors::ConnectorError> {
        let mandate_supported_pmd = std::collections::HashSet::from([PaymentMethodDataType::Card]);

        is_mandate_supported(pm_data, pm_type, mandate_supported_pmd, self.id())
    }
}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Archipel {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        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: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let capture_method = req
            .request
            .capture_method
            .ok_or(errors::ConnectorError::CaptureMethodNotSupported)?;
        let base_url =
            build_env_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?;
        match capture_method {
            enums::CaptureMethod::Automatic | enums::CaptureMethod::SequentialAutomatic => {
                Ok(format!("{}{}", base_url, "/pay"))
            }
            enums::CaptureMethod::Manual => Ok(format!("{}{}", base_url, "/authorize")),
            enums::CaptureMethod::ManualMultiple | enums::CaptureMethod::Scheduled => {
                Err(report!(errors::ConnectorError::CaptureMethodNotSupported))
            }
        }
    }

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let config_data: archipel::ArchipelConfigData = (&req.connector_meta_data).try_into()?;
        let amount = crate::utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.currency,
        )?;
        let router_data: archipel::ArchipelRouterData<_> =
            (amount, config_data.tenant_id, req).into();

        if req.request.is_wallet() {
            let request: ArchipelWalletAuthorizationRequest = router_data.try_into()?;
            Ok(RequestContent::Json(Box::new(request)))
        } else {
            let request: ArchipelCardAuthorizationRequest = router_data.try_into()?;
            Ok(RequestContent::Json(Box::new(request)))
        }
    }

    fn build_request(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = archipel::ArchipelAuthType::try_from(&req.connector_auth_type)?;
        let url = &self.get_url(req, connectors)?;
        let headers = self.get_headers(req, connectors)?;
        let body = self.get_request_body(req, connectors)?;

        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(url)
                .attach_default_headers()
                .headers(headers)
                .add_ca_certificate_pem(auth_details.ca_certificate)
                .set_body(body)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
        let response: archipel::ArchipelPaymentsResponse = res
            .response
            .parse_struct("ArchipelPaymentsResponse for Authorize flow")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|event| event.set_response_body(&response));
        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> {
        self.build_error_response(res, event_builder)
    }
}

impl
    ConnectorIntegration<
        IncrementalAuthorization,
        PaymentsIncrementalAuthorizationData,
        PaymentsResponseData,
    > for Archipel
{
    fn get_headers(
        &self,
        req: &PaymentsIncrementalAuthorizationRouterData,
        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: &PaymentsIncrementalAuthorizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let base_url =
            build_env_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?;
        let connector_payment_id = req.request.connector_transaction_id.clone();

        Ok(format!(
            "{}{}{}",
            base_url, "/incrementAuthorization/", connector_payment_id
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsIncrementalAuthorizationRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let config_data: archipel::ArchipelConfigData = (&req.connector_meta_data).try_into()?;
        let router_data: archipel::ArchipelRouterData<_> = (
            MinorUnit::new(req.request.additional_amount),
            config_data.tenant_id,
            req,
        )
            .into();
        let request: ArchipelIncrementalAuthorizationRequest = router_data.into();

        Ok(RequestContent::Json(Box::new(request)))
    }

    fn build_request(
        &self,
        req: &PaymentsIncrementalAuthorizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = archipel::ArchipelAuthType::try_from(&req.connector_auth_type)?;
        let url = &self.get_url(req, connectors)?;
        let headers = self.get_headers(req, connectors)?;
        let body = self.get_request_body(req, connectors)?;

        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(url)
                .attach_default_headers()
                .headers(headers)
                .add_ca_certificate_pem(auth_details.ca_certificate)
                .set_body(body)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsIncrementalAuthorizationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsIncrementalAuthorizationRouterData, errors::ConnectorError> {
        let response: archipel::ArchipelPaymentsResponse = res
            .response
            .parse_struct("ArchipelPaymentsResponse for IncrementalAuthorization flow")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|event| event.set_response_body(&response));
        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> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Archipel {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        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: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let base_url =
            build_env_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?;
        let metadata: archipel::ArchipelTransactionMetadata = req
            .request
            .connector_meta
            .clone()
            .and_then(|value| value.parse_value("ArchipelTransactionMetadata").ok())
            .ok_or_else(|| errors::ConnectorError::MissingConnectorTransactionID)?;

        Ok(format!(
            "{}{}{}",
            base_url, "/transactions/", metadata.transaction_id
        ))
    }

    fn build_request(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = archipel::ArchipelAuthType::try_from(&req.connector_auth_type)?;
        let url = &self.get_url(req, connectors)?;
        let headers = self.get_headers(req, connectors)?;

        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(url)
                .attach_default_headers()
                .headers(headers)
                .add_ca_certificate_pem(auth_details.ca_certificate)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: archipel::ArchipelPaymentsResponse = res
            .response
            .parse_struct("ArchipelPaymentsResponse for PSync flow")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|event| event.set_response_body(&response));
        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> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Archipel {
    fn get_headers(
        &self,
        req: &PaymentsCaptureRouterData,
        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: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let base_url =
            build_env_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?;

        Ok(format!(
            "{}{}{}",
            base_url, "/capture/", req.request.connector_transaction_id
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let config_data: archipel::ArchipelConfigData = (&req.connector_meta_data).try_into()?;
        let amount_to_capture = crate::utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount_to_capture,
            req.request.currency,
        )?;
        let router_data: archipel::ArchipelRouterData<_> =
            (amount_to_capture, config_data.tenant_id, req).into();
        let request: archipel::ArchipelCaptureRequest = router_data.into();

        Ok(RequestContent::Json(Box::new(request)))
    }

    fn build_request(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = archipel::ArchipelAuthType::try_from(&req.connector_auth_type)?;
        let url = &self.get_url(req, connectors)?;
        let headers = self.get_headers(req, connectors)?;
        let body = self.get_request_body(req, connectors)?;

        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(url)
                .attach_default_headers()
                .headers(headers)
                .add_ca_certificate_pem(auth_details.ca_certificate)
                .set_body(body)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCaptureRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
        let response: archipel::ArchipelPaymentsResponse = res
            .response
            .parse_struct("ArchipelPaymentsResponse for Capture flow")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|event| event.set_response_body(&response));
        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> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData>
    for Archipel
{
    fn get_headers(
        &self,
        req: &SetupMandateRouterData,
        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: &SetupMandateRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let base_url =
            build_env_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?;

        Ok(format!("{}{}", base_url, "/verify"))
    }

    fn get_request_body(
        &self,
        req: &SetupMandateRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let config_data: archipel::ArchipelConfigData = (&req.connector_meta_data).try_into()?;
        let router_data: archipel::ArchipelRouterData<_> =
            (MinorUnit::zero(), config_data.tenant_id, req).into();
        let request: ArchipelCardAuthorizationRequest = router_data.try_into()?;

        Ok(RequestContent::Json(Box::new(request)))
    }

    fn build_request(
        &self,
        req: &SetupMandateRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = archipel::ArchipelAuthType::try_from(&req.connector_auth_type)?;
        let url = &self.get_url(req, connectors)?;
        let headers = self.get_headers(req, connectors)?;
        let body = self.get_request_body(req, connectors)?;

        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(url)
                .attach_default_headers()
                .headers(headers)
                .add_ca_certificate_pem(auth_details.ca_certificate)
                .set_body(body)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &SetupMandateRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<SetupMandateRouterData, errors::ConnectorError> {
        let response: archipel::ArchipelPaymentsResponse = res
            .response
            .parse_struct("ArchipelPaymentsResponse for SetupMandate flow")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|event| event.set_response_body(&response));
        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> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Archipel {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        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: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let base_url =
            build_env_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?;

        Ok(format!(
            "{}{}{}",
            base_url, "/refund/", req.request.connector_transaction_id
        ))
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let config_data: archipel::ArchipelConfigData = (&req.connector_meta_data).try_into()?;
        let refund_amount = crate::utils::convert_amount(
            self.amount_converter,
            req.request.minor_refund_amount,
            req.request.currency,
        )?;
        let router_data: archipel::ArchipelRouterData<_> =
            (refund_amount, config_data.tenant_id, req).into();
        let request: ArchipelRefundRequest = router_data.into();

        Ok(RequestContent::Json(Box::new(request)))
    }

    fn build_request(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = archipel::ArchipelAuthType::try_from(&req.connector_auth_type)?;
        let url = &self.get_url(req, connectors)?;
        let headers = self.get_headers(req, connectors)?;
        let body = self.get_request_body(req, connectors)?;

        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(url)
                .attach_default_headers()
                .headers(headers)
                .add_ca_certificate_pem(auth_details.ca_certificate)
                .set_body(body)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: archipel::ArchipelRefundResponse = res
            .response
            .parse_struct("ArchipelRefundResponse for Execute flow")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|event| event.set_response_body(&response));
        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> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Archipel {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        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: &RefundSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let config_data: archipel::ArchipelConfigData = (&req.connector_meta_data).try_into()?;
        let platform_url = &config_data.platform_url;
        let metadata: archipel::ArchipelTransactionMetadata = req
            .request
            .connector_metadata
            .clone()
            .and_then(|value| value.parse_value("ArchipelTransactionMetadata").ok())
            .ok_or_else(|| errors::ConnectorError::MissingConnectorTransactionID)?;

        Ok(format!(
            "{platform_url}{}{}",
            "Transaction/v1/transactions/", metadata.transaction_id
        ))
    }

    fn build_request(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = archipel::ArchipelAuthType::try_from(&req.connector_auth_type)?;
        let url = &self.get_url(req, connectors)?;
        let headers = self.get_headers(req, connectors)?;

        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(url)
                .attach_default_headers()
                .headers(headers)
                .add_ca_certificate_pem(auth_details.ca_certificate)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: archipel::ArchipelRefundResponse = res
            .response
            .parse_struct("ArchipelRefundResponse for RSync flow")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|event| event.set_response_body(&response));
        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> {
        self.build_error_response(res, event_builder)
    }
}

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

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Archipel {
    // Not Implemented (R)
}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Archipel {
    // Not Implemented (R)
}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Archipel {
    fn get_headers(
        &self,
        req: &PaymentsCancelRouterData,
        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: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let base_url =
            build_env_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?;

        Ok(format!(
            "{}{}{}",
            base_url, "/cancel/", req.request.connector_transaction_id
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let config_data: archipel::ArchipelConfigData = (&req.connector_meta_data).try_into()?;
        let router_data: archipel::ArchipelRouterData<_> = (
            req.request
                .minor_amount
                .ok_or(errors::ConnectorError::MissingRequiredField {
                    field_name: "Amount",
                })?,
            config_data.tenant_id,
            req,
        )
            .into();
        let request: ArchipelPaymentsCancelRequest = router_data.into();

        Ok(RequestContent::Json(Box::new(request)))
    }

    fn build_request(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let auth_details = archipel::ArchipelAuthType::try_from(&req.connector_auth_type)?;
        let url = &self.get_url(req, connectors)?;
        let headers = self.get_headers(req, connectors)?;
        let body = self.get_request_body(req, connectors)?;

        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(url)
                .attach_default_headers()
                .headers(headers)
                .add_ca_certificate_pem(auth_details.ca_certificate)
                .set_body(body)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCancelRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCancelRouterData, errors::ConnectorError> {
        let response: archipel::ArchipelPaymentsResponse = res
            .response
            .parse_struct("ArchipelPaymentsResponse for Void flow")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|event| event.set_response_body(&response));
        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> {
        self.build_error_response(res, event_builder)
    }
}

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

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

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

static ARCHIPEL_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::DinersClub,
            common_enums::CardNetwork::Discover,
            common_enums::CardNetwork::CartesBancaires,
        ];

        let mut archipel_supported_payment_methods = SupportedPaymentMethods::new();

        archipel_supported_payment_methods.add(
            enums::PaymentMethod::Card,
            enums::PaymentMethodType::Credit,
            PaymentMethodDetails {
                mandates: enums::FeatureStatus::Supported,
                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(),
                        }
                    }),
                ),
            },
        );

        archipel_supported_payment_methods.add(
            enums::PaymentMethod::Card,
            enums::PaymentMethodType::Debit,
            PaymentMethodDetails {
                mandates: enums::FeatureStatus::Supported,
                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 {


// File: crates/euclid/src/backend.rs
// Module: euclid
// Public functions: 1
// Public structs: 1

pub mod inputs;
pub mod interpreter;
#[cfg(feature = "valued_jit")]
pub mod vir_interpreter;

pub use inputs::BackendInput;
pub use interpreter::InterpreterBackend;
#[cfg(feature = "valued_jit")]
pub use vir_interpreter::VirInterpreterBackend;

use crate::frontend::ast;

#[derive(Debug, Clone, serde::Serialize)]
pub struct BackendOutput<O> {
    pub rule_name: Option<String>,
    pub connector_selection: O,
}

impl<O> BackendOutput<O> {
    // get_connector_selection
    pub fn get_output(&self) -> &O {
        &self.connector_selection
    }
}

pub trait EuclidBackend<O>: Sized {
    type Error: serde::Serialize;

    fn with_program(program: ast::Program<O>) -> Result<Self, Self::Error>;

    fn execute(&self, input: BackendInput) -> Result<BackendOutput<O>, Self::Error>;
}


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

impl api::MandateSetup for for Chargebee


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

impl ConnectorCommon for for Dlocal


// Function: list_initial_attempts_by_merchant_id_primary_object_id
// File: crates/diesel_models/src/query/events.rs
// Module: diesel_models

pub fn list_initial_attempts_by_merchant_id_primary_object_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        primary_object_id: &str,
    ) -> StorageResult<Vec<Self>>


            .headers(types::RefundExecuteType::get_headers(
                self, req, connectors,
            )?)
            .set_body(types::RefundExecuteType::get_request_body(
                self, req, connectors,
            )?)
            .build();
        Ok(Some(request))
    }

    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: NuveiPaymentsResponse = res
            .response
            .parse_struct("NuveiPaymentsResponse")
            .switch()?;
        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,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

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

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Nuvei {
    fn handle_response(
        &self,
        data: &RefundsRouterData<RSync>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RouterData<RSync, RefundsData, RefundsResponseData>, errors::ConnectorError>
    {
        let nuvie_rsync_common_response: nuvei::PaymentDmnNotification = res
            .response
            .parse_struct("PaymentDmnNotification")
            .switch()?;
        event_builder.map(|i| i.set_response_body(&nuvie_rsync_common_response));
        router_env::logger::info!(connector_response=?nuvie_rsync_common_response);
        let response = NuveiTransactionSyncResponse::from(nuvie_rsync_common_response);

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

fn has_payout_prefix(id_option: &Option<String>) -> bool {
    // - Default value returns false if the Option is `None`.
    // - The argument is a closure that runs if the Option is `Some`.
    //   It takes the contained value (`s`) and its result is returned.
    id_option
        .as_deref()
        .is_some_and(|s| s.starts_with("payout_"))
}

#[async_trait::async_trait]
impl IncomingWebhook for Nuvei {
    fn get_webhook_source_verification_algorithm(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn crypto::VerifySignature + Send>, errors::ConnectorError> {
        Ok(Box::new(crypto::Sha256))
    }

    fn get_webhook_source_verification_signature(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        let webhook = get_webhook_object_from_body(request.body)?;

        let nuvei_notification_signature = match webhook {
            nuvei::NuveiWebhook::PaymentDmn(notification) => notification
                .advance_response_checksum
                .ok_or(errors::ConnectorError::WebhookSignatureNotFound)?,
            nuvei::NuveiWebhook::Chargeback(_) => {
                utils::get_header_key_value("Checksum", request.headers)?.to_string()
            }
        };

        hex::decode(nuvei_notification_signature)
            .change_context(errors::ConnectorError::WebhookSignatureNotFound)
    }

    fn get_webhook_source_verification_message(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        _merchant_id: &id_type::MerchantId,
        connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        // Parse the webhook payload
        let webhook = get_webhook_object_from_body(request.body)?;
        let secret_str = std::str::from_utf8(&connector_webhook_secrets.secret)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

        // Generate signature based on webhook type
        match webhook {
            nuvei::NuveiWebhook::PaymentDmn(notification) => {
                // For payment DMNs, use the same format as before
                let status = notification
                    .status
                    .as_ref()
                    .map(|s| format!("{s:?}").to_uppercase())
                    .unwrap_or_default();

                let to_sign = transformers::concat_strings(&[
                    secret_str.to_string(),
                    notification.total_amount,
                    notification.currency,
                    notification.response_time_stamp,
                    notification.ppp_transaction_id,
                    status,
                    notification.product_id.unwrap_or("NA".to_string()),
                ]);
                Ok(to_sign.into_bytes())
            }
            nuvei::NuveiWebhook::Chargeback(notification) => {
                // For chargeback notifications, use a different format based on Nuvei's documentation
                // Note: This is a placeholder - you'll need to adjust based on Nuvei's actual chargeback signature format
                let response = serde_json::to_string(&notification)
                    .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

                let to_sign = format!("{secret_str}{response}");
                Ok(to_sign.into_bytes())
            }
        }
    }

    fn get_webhook_object_reference_id(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        // Parse the webhook payload
        let webhook = get_webhook_object_from_body(request.body)?;
        // Extract transaction ID from the webhook
        match &webhook {
            nuvei::NuveiWebhook::PaymentDmn(notification) => {
                // if prefix contains 'payout_' then it is a payout related webhook
                if has_payout_prefix(&notification.client_request_id) {
                    #[cfg(feature = "payouts")]
                    {
                        Ok(api_models::webhooks::ObjectReferenceId::PayoutId(
                            PayoutIdType::PayoutAttemptId(
                                notification
                                    .client_request_id
                                    .clone()
                                    .ok_or(errors::ConnectorError::MissingConnectorTransactionID)?,
                            ),
                        ))
                    }
                    #[cfg(not(feature = "payouts"))]
                    {
                        Err(errors::ConnectorError::WebhookEventTypeNotFound.into())
                    }
                } else {
                    match notification.transaction_type {
                        Some(nuvei::NuveiTransactionType::Auth)
                        | Some(nuvei::NuveiTransactionType::Sale)
                        | Some(nuvei::NuveiTransactionType::Settle)
                        | Some(nuvei::NuveiTransactionType::Void)
                        | Some(nuvei::NuveiTransactionType::Auth3D)
                        | Some(nuvei::NuveiTransactionType::InitAuth3D) => {
                            Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                                PaymentIdType::ConnectorTransactionId(
                                    notification.transaction_id.clone().ok_or(
                                        errors::ConnectorError::MissingConnectorTransactionID,
                                    )?,
                                ),
                            ))
                        }
                        Some(nuvei::NuveiTransactionType::Credit) => {
                            Ok(api_models::webhooks::ObjectReferenceId::RefundId(
                                RefundIdType::ConnectorRefundId(
                                    notification
                                        .transaction_id
                                        .clone()
                                        .ok_or(errors::ConnectorError::MissingConnectorRefundID)?,
                                ),
                            ))
                        }
                        None => Err(errors::ConnectorError::WebhookEventTypeNotFound.into()),
                    }
                }
            }
            nuvei::NuveiWebhook::Chargeback(notification) => {
                Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                    PaymentIdType::ConnectorTransactionId(
                        notification.transaction_details.transaction_id.to_string(),
                    ),
                ))
            }
        }
    }

    fn get_webhook_event_type(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<IncomingWebhookEvent, errors::ConnectorError> {
        // Parse the webhook payload
        let webhook = get_webhook_object_from_body(request.body)?;

        // Map webhook type to event type
        match webhook {
            nuvei::NuveiWebhook::PaymentDmn(notification) => {
                if has_payout_prefix(&notification.client_request_id) {
                    #[cfg(feature = "payouts")]
                    {
                        if let Some((status, transaction_type)) =
                            notification.status.zip(notification.transaction_type)
                        {
                            nuvei::map_notification_to_event_for_payout(status, transaction_type)
                        } else {
                            Err(errors::ConnectorError::WebhookEventTypeNotFound.into())
                        }
                    }
                    #[cfg(not(feature = "payouts"))]
                    {
                        Err(errors::ConnectorError::WebhookEventTypeNotFound.into())
                    }
                } else if let Some((status, transaction_type)) =
                    notification.status.zip(notification.transaction_type)
                {
                    nuvei::map_notification_to_event(status, transaction_type)
                } else {
                    Err(errors::ConnectorError::WebhookEventTypeNotFound.into())
                }
            }
            nuvei::NuveiWebhook::Chargeback(notification) => {
                if let Some(dispute_event) = notification.chargeback.dispute_unified_status_code {
                    nuvei::map_dispute_notification_to_event(dispute_event)
                } else {
                    Err(errors::ConnectorError::WebhookEventTypeNotFound.into())
                }
            }
        }
    }

    fn get_webhook_resource_object(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        let notification = get_webhook_object_from_body(request.body)?;
        Ok(Box::new(notification))
    }

    fn get_dispute_details(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<disputes::DisputePayload, errors::ConnectorError> {
        let webhook = request
            .body
            .parse_struct::<nuvei::ChargebackNotification>("ChargebackNotification")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        let currency = webhook
            .chargeback
            .reported_currency
            .to_uppercase()
            .parse::<enums::Currency>()
            .map_err(|_| errors::ConnectorError::ResponseDeserializationFailed)?;
        let amount_minorunit = utils::convert_back_amount_to_minor_units(
            self.amount_converter_float_major_unit,
            webhook.chargeback.reported_amount,
            currency,
        )?;

        let amount = utils::convert_amount(
            self.amount_converter_string_minor_unit,
            amount_minorunit,
            currency,
        )?;
        let dispute_unified_status_code = webhook
            .chargeback
            .dispute_unified_status_code
            .ok_or(errors::ConnectorError::WebhookEventTypeNotFound)?;
        let connector_dispute_id = webhook
            .chargeback
            .dispute_id
            .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?;

        Ok(disputes::DisputePayload {
            amount,
            currency,
            dispute_stage: api_models::enums::DisputeStage::from(
                dispute_unified_status_code.clone(),
            ),
            connector_dispute_id,
            connector_reason: webhook.chargeback.chargeback_reason,
            connector_reason_code: webhook.chargeback.chargeback_reason_category,
            challenge_required_by: webhook.chargeback.dispute_due_date,
            connector_status: dispute_unified_status_code.to_string(),
            created_at: webhook.chargeback.date,
            updated_at: None,
        })
    }
}

fn get_webhook_object_from_body(
    body: &[u8],
) -> CustomResult<nuvei::NuveiWebhook, errors::ConnectorError> {
    let payments_response = serde_urlencoded::from_bytes::<nuvei::NuveiWebhook>(body)
        .change_context(errors::ConnectorError::ResponseDeserializationFailed);

    match payments_response {
        Ok(webhook) => Ok(webhook),
        Err(_) => body
            .parse_struct::<nuvei::NuveiWebhook>("NuveiWebhook")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed),
    }
}

impl ConnectorRedirectResponse for Nuvei {
    fn get_flow_type(
        &self,
        _query_params: &str,
        json_payload: Option<serde_json::Value>,
        action: PaymentAction,
    ) -> CustomResult<CallConnectorAction, errors::ConnectorError> {
        match action {
            PaymentAction::PSync | PaymentAction::PaymentAuthenticateCompleteAuthorize => {
                Ok(CallConnectorAction::Trigger)
            }
            PaymentAction::CompleteAuthorize => {
                if let Some(payload) = json_payload {
                    let redirect_response: nuvei::NuveiRedirectionResponse =
                        payload.parse_value("NuveiRedirectionResponse").switch()?;
                    let acs_response: nuvei::NuveiACSResponse =
                        utils::base64_decode(redirect_response.cres.expose())?
                            .as_slice()
                            .parse_struct("NuveiACSResponse")
                            .switch()?;
                    match acs_response.trans_status {
                        None | Some(nuvei::LiabilityShift::Failed) => {
                            Ok(CallConnectorAction::StatusUpdate {
                                status: enums::AttemptStatus::AuthenticationFailed,
                                error_code: None,
                                error_message: Some("3ds Authentication failed".to_string()),
                            })
                        }
                        _ => Ok(CallConnectorAction::Trigger),
                    }
                } else {
                    Ok(CallConnectorAction::Trigger)
                }
            }
        }
    }
}

static NUVEI_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::Visa,
        common_enums::CardNetwork::Mastercard,
        common_enums::CardNetwork::AmericanExpress,
        common_enums::CardNetwork::UnionPay,
        common_enums::CardNetwork::Interac,
        common_enums::CardNetwork::JCB,
        common_enums::CardNetwork::DinersClub,
        common_enums::CardNetwork::Discover,
        common_enums::CardNetwork::CartesBancaires,
    ];

    let mut nuvei_supported_payment_methods = SupportedPaymentMethods::new();

    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::Card,
        enums::PaymentMethodType::Credit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            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(),
                    }
                }),
            ),
        },
    );
    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::Card,
        enums::PaymentMethodType::Debit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            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(),
                    }
                }),
            ),
        },
    );

    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        enums::PaymentMethodType::Klarna,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        enums::PaymentMethodType::AfterpayClearpay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Ideal,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Giropay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Sofort,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Eps,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        enums::PaymentMethodType::ApplePay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        enums::PaymentMethodType::GooglePay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    nuvei_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        enums::PaymentMethodType::Paypal,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    nuvei_supported_payment_methods
});

static NUVEI_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
        display_name: "Nuvei",
        description: "Nuvei is the Canadian fintech company accelerating the business of clients around the world.",
        connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
        integration_status: enums::ConnectorIntegrationStatus::Beta,
    };

static NUVEI_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 2] =
    [enums::EventClass::Payments, enums::EventClass::Disputes];

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

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

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


// Struct: Browser
// File: crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Browser


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

impl api::PaymentToken for for Shift4


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

use std::collections::HashMap;

use api_models::{self, routing as routing_types};
use common_types::payments as common_payments_types;
use diesel_models::enums as storage_enums;
use euclid::{enums as dsl_enums, frontend::ast as dsl_ast};
use kgraph_utils::types;

use crate::{
    configs::settings,
    types::transformers::{ForeignFrom, ForeignInto},
};

impl ForeignFrom<routing_types::RoutableConnectorChoice> for dsl_ast::ConnectorChoice {
    fn foreign_from(from: routing_types::RoutableConnectorChoice) -> Self {
        Self {
            connector: from.connector,
        }
    }
}

impl ForeignFrom<storage_enums::CaptureMethod> for Option<dsl_enums::CaptureMethod> {
    fn foreign_from(value: storage_enums::CaptureMethod) -> Self {
        match value {
            storage_enums::CaptureMethod::Automatic => Some(dsl_enums::CaptureMethod::Automatic),
            storage_enums::CaptureMethod::SequentialAutomatic => {
                Some(dsl_enums::CaptureMethod::SequentialAutomatic)
            }
            storage_enums::CaptureMethod::Manual => Some(dsl_enums::CaptureMethod::Manual),
            _ => None,
        }
    }
}

impl ForeignFrom<common_payments_types::AcceptanceType> for dsl_enums::MandateAcceptanceType {
    fn foreign_from(from: common_payments_types::AcceptanceType) -> Self {
        match from {
            common_payments_types::AcceptanceType::Online => Self::Online,
            common_payments_types::AcceptanceType::Offline => Self::Offline,
        }
    }
}

impl ForeignFrom<api_models::payments::MandateType> for dsl_enums::MandateType {
    fn foreign_from(from: api_models::payments::MandateType) -> Self {
        match from {
            api_models::payments::MandateType::MultiUse(_) => Self::MultiUse,
            api_models::payments::MandateType::SingleUse(_) => Self::SingleUse,
        }
    }
}

impl ForeignFrom<storage_enums::MandateDataType> for dsl_enums::MandateType {
    fn foreign_from(from: storage_enums::MandateDataType) -> Self {
        match from {
            storage_enums::MandateDataType::MultiUse(_) => Self::MultiUse,
            storage_enums::MandateDataType::SingleUse(_) => Self::SingleUse,
        }
    }
}

impl ForeignFrom<settings::PaymentMethodFilterKey> for types::PaymentMethodFilterKey {
    fn foreign_from(from: settings::PaymentMethodFilterKey) -> Self {
        match from {
            settings::PaymentMethodFilterKey::PaymentMethodType(pmt) => {
                Self::PaymentMethodType(pmt)
            }
            settings::PaymentMethodFilterKey::CardNetwork(cn) => Self::CardNetwork(cn),
        }
    }
}
impl ForeignFrom<settings::CurrencyCountryFlowFilter> for types::CurrencyCountryFlowFilter {
    fn foreign_from(from: settings::CurrencyCountryFlowFilter) -> Self {
        Self {
            currency: from.currency,
            country: from.country,
            not_available_flows: from.not_available_flows.map(ForeignInto::foreign_into),
        }
    }
}
impl ForeignFrom<settings::NotAvailableFlows> for types::NotAvailableFlows {
    fn foreign_from(from: settings::NotAvailableFlows) -> Self {
        Self {
            capture_method: from.capture_method,
        }
    }
}
impl ForeignFrom<settings::PaymentMethodFilters> for types::PaymentMethodFilters {
    fn foreign_from(from: settings::PaymentMethodFilters) -> Self {
        let iter_map = from
            .0
            .into_iter()
            .map(|(key, val)| (key.foreign_into(), val.foreign_into()))
            .collect::<HashMap<_, _>>();
        Self(iter_map)
    }
}


// Struct: UnifiedTranslationsNew
// File: crates/diesel_models/src/unified_translations.rs
// Module: diesel_models
// Implementations: 0

pub struct UnifiedTranslationsNew


// Function: get_shipping
// File: crates/hyperswitch_domain_models/src/payment_address.rs
// Module: hyperswitch_domain_models

pub fn get_shipping(&self) -> Option<&Address>


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

pub struct UploadFileRequestData


// Trait: ApiModelToDieselModelConvertor
// File: crates/hyperswitch_domain_models/src/lib.rs
// Module: hyperswitch_domain_models

pub trait ApiModelToDieselModelConvertor<F>


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

pub struct Product


// File: crates/analytics/src/payments/metrics/sessionized_metrics/payment_count.rs
// Module: analytics

use std::collections::HashSet;

use api_models::analytics::{
    payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
    Granularity, TimeRange,
};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

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

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

#[async_trait::async_trait]
impl<T> super::PaymentMetric<T> for PaymentCount
where
    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[PaymentDimensions],
        auth: &AuthInfo,
        filters: &PaymentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
        let mut query_builder: QueryBuilder<T> =
            QueryBuilder::new(AnalyticsCollection::PaymentSessionized);

        for dim in dimensions.iter() {
            query_builder.add_select_column(dim).switch()?;
        }

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

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

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

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

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

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

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


// Struct: AffirmCancelResponse
// File: crates/hyperswitch_connectors/src/connectors/affirm/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AffirmCancelResponse


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

impl api::RefundSync for for Opayo


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

impl ApiEventMetric for for GetFrmMetricRequest


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

impl ConnectorCommon for for Volt


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

impl api::PaymentVoid for for Thunes


// Function: get_sso_auth_url
// File: crates/router/src/core/user.rs
// Module: router

pub fn get_sso_auth_url(
    state: SessionState,
    request: user_api::GetSsoAuthUrlRequest,
) -> UserResponse<()>


// Function: get_resolved_relation
// File: crates/hyperswitch_constraint_graph/src/types.rs
// Module: hyperswitch_constraint_graph

pub fn get_resolved_relation(prev_relation: Self, curr_relation: Self) -> Self


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

pub struct MobilePayRedirection


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

// Public submodules:
pub mod transformers;


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

impl api::RefundExecute for for Bluecode


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

pub struct GiftCardBalanceCheckRequestData


// Struct: GlobalPayPaymentMethodsRequest
// File: crates/hyperswitch_connectors/src/connectors/globalpay/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct GlobalPayPaymentMethodsRequest


// Function: new
// File: crates/api_models/src/errors/types.rs
// Module: api_models

pub fn new(
        sub_code: &'static str,
        error_identifier: u16,
        error_message: impl ToString,
        extra: Option<Extra>,
    ) -> Self


// Implementation: impl MerchantConnectorAccount
// File: crates/diesel_models/src/query/merchant_connector_account.rs
// Module: diesel_models
// Methods: 6 total (0 public)

impl MerchantConnectorAccount


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

pub struct ConsumerAuthenticationInformation