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

pub mod transformers;

use common_utils::{
    errors::CustomResult,
    ext_traits::BytesExt,
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector},
};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
    router_data::{AccessToken, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
        Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate,
    },
    router_request_types::{
        unified_authentication_service::{
            UasAuthenticationRequestData, UasAuthenticationResponseData,
            UasConfirmationRequestData, UasPostAuthenticationRequestData,
            UasPreAuthenticationRequestData,
        },
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData,
    },
    router_response_types::{PaymentsResponseData, RefundsResponseData},
    types::{
        UasAuthenticationConfirmationRouterData, UasAuthenticationRouterData,
        UasPostAuthenticationRouterData, UasPreAuthenticationRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    consts::NO_ERROR_MESSAGE,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks,
};
use transformers as unified_authentication_service;

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

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

impl UnifiedAuthenticationService {
    pub fn new() -> &'static Self {
        &Self {
            amount_converter: &FloatMajorUnitForConnector,
        }
    }
}

impl api::Payment for UnifiedAuthenticationService {}
impl api::PaymentSession for UnifiedAuthenticationService {}
impl api::ConnectorAccessToken for UnifiedAuthenticationService {}
impl api::MandateSetup for UnifiedAuthenticationService {}
impl api::PaymentAuthorize for UnifiedAuthenticationService {}
impl api::PaymentSync for UnifiedAuthenticationService {}
impl api::PaymentCapture for UnifiedAuthenticationService {}
impl api::PaymentVoid for UnifiedAuthenticationService {}
impl api::Refund for UnifiedAuthenticationService {}
impl api::RefundExecute for UnifiedAuthenticationService {}
impl api::RefundSync for UnifiedAuthenticationService {}
impl api::PaymentToken for UnifiedAuthenticationService {}
impl api::UnifiedAuthenticationService for UnifiedAuthenticationService {}
impl api::UasPreAuthentication for UnifiedAuthenticationService {}
impl api::UasPostAuthentication for UnifiedAuthenticationService {}
impl api::UasAuthenticationConfirmation for UnifiedAuthenticationService {}
impl api::UasAuthentication for UnifiedAuthenticationService {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for UnifiedAuthenticationService
{
}

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

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response>
    for UnifiedAuthenticationService
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        _req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let header = vec![
            (
                headers::CONTENT_TYPE.to_string(),
                self.get_content_type().to_string().into(),
            ),
            (
                headers::SOURCE.to_string(),
                self.get_content_type().to_string().into(),
            ),
        ];
        Ok(header)
    }
}

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

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

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

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

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

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

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

impl ConnectorValidation for UnifiedAuthenticationService {
    //TODO: implement functions when support enabled
}

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

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

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

impl
    ConnectorIntegration<
        AuthenticationConfirmation,
        UasConfirmationRequestData,
        UasAuthenticationResponseData,
    > for UnifiedAuthenticationService
{
    fn get_headers(
        &self,
        req: &UasAuthenticationConfirmationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::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: &UasAuthenticationConfirmationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}confirmation", self.base_url(connectors)))
    }

    fn get_request_body(
        &self,
        req: &UasAuthenticationConfirmationRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            req.request.transaction_amount,
            req.request.transaction_currency,
        )?;

        let connector_router_data =
            unified_authentication_service::UnifiedAuthenticationServiceRouterData::from((
                amount, req,
            ));
        let connector_req =
            unified_authentication_service::UnifiedAuthenticationServiceAuthenticateConfirmationRequest::try_from(
                &connector_router_data,
            )?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &UasAuthenticationConfirmationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<UasAuthenticationConfirmationRouterData, errors::ConnectorError> {
        let response: unified_authentication_service::UnifiedAuthenticationServiceAuthenticateConfirmationResponse =
            res.response
                .parse_struct("UnifiedAuthenticationService UnifiedAuthenticationServiceAuthenticateConfirmationResponse")
                .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<
        PreAuthenticate,
        UasPreAuthenticationRequestData,
        UasAuthenticationResponseData,
    > for UnifiedAuthenticationService
{
    fn get_headers(
        &self,
        req: &UasPreAuthenticationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::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: &UasPreAuthenticationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}pre_authentication_processing",
            self.base_url(connectors)
        ))
    }

    fn get_request_body(
        &self,
        req: &UasPreAuthenticationRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = if req.request.service_details.is_some() {
            let transaction_details = req.request.transaction_details.clone().ok_or(
                errors::ConnectorError::MissingRequiredField {
                    field_name: "transaction_details",
                },
            )?;
            let amount = utils::convert_amount(
                self.amount_converter,
                transaction_details
                    .amount
                    .ok_or(errors::ConnectorError::MissingRequiredField {
                        field_name: "amount",
                    })?,
                transaction_details.currency.ok_or(
                    errors::ConnectorError::MissingRequiredField {
                        field_name: "currency",
                    },
                )?,
            )?;

            let connector_router_data =
                unified_authentication_service::UnifiedAuthenticationServiceRouterData::from((
                    amount, req,
                ));
            unified_authentication_service::UnifiedAuthenticationServicePreAuthenticateRequest::try_from(
                        &connector_router_data,
                    )?
        } else {
            unified_authentication_service::UnifiedAuthenticationServicePreAuthenticateRequest::try_from(
                req,
            )?
        };
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &UasPreAuthenticationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<UasPreAuthenticationRouterData, errors::ConnectorError> {
        let response: unified_authentication_service::UnifiedAuthenticationServicePreAuthenticateResponse =
            res.response
                .parse_struct("UnifiedAuthenticationService UnifiedAuthenticationServicePreAuthenticateResponse")
                .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<
        PostAuthenticate,
        UasPostAuthenticationRequestData,
        UasAuthenticationResponseData,
    > for UnifiedAuthenticationService
{
    fn get_headers(
        &self,
        req: &UasPostAuthenticationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::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: &UasPostAuthenticationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}post_authentication_sync",
            self.base_url(connectors)
        ))
    }

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

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

    fn handle_response(
        &self,
        data: &UasPostAuthenticationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<UasPostAuthenticationRouterData, errors::ConnectorError> {
        let response: unified_authentication_service::UnifiedAuthenticationServicePostAuthenticateResponse =
            res.response
                .parse_struct("UnifiedAuthenticationService UnifiedAuthenticationServicePostAuthenticateResponse")
                .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<Authenticate, UasAuthenticationRequestData, UasAuthenticationResponseData>
    for UnifiedAuthenticationService
{
    fn get_headers(
        &self,
        req: &UasAuthenticationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::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: &UasAuthenticationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}authentication_initiation",
            self.base_url(connectors)
        ))
    }

    fn get_request_body(
        &self,
        req: &UasAuthenticationRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let transaction_details = req.request.transaction_details.clone();
        let amount = utils::convert_amount(
            self.amount_converter,
            transaction_details
                .amount
                .ok_or(errors::ConnectorError::MissingRequiredField {
                    field_name: "amount",
                })?,
            transaction_details
                .currency
                .ok_or(errors::ConnectorError::MissingRequiredField {
                    field_name: "currency",
                })?,
        )?;

        let connector_router_data =
            unified_authentication_service::UnifiedAuthenticationServiceRouterData::from((
                amount, req,
            ));
        let connector_req = unified_authentication_service::UnifiedAuthenticationServiceAuthenticateRequest::try_from(
                    &connector_router_data,
                )?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &UasAuthenticationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<UasAuthenticationRouterData, errors::ConnectorError> {
        let response: unified_authentication_service::UnifiedAuthenticationServiceAuthenticateResponse =
        res.response
            .parse_struct("UnifiedAuthenticationService UnifiedAuthenticationServiceAuthenticateResponse")
            .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<PSync, PaymentsSyncData, PaymentsResponseData>
    for UnifiedAuthenticationService
{
}

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

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

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

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

#[async_trait::async_trait]
impl webhooks::IncomingWebhook for UnifiedAuthenticationService {
    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))
    }
}

impl ConnectorSpecifications for UnifiedAuthenticationService {}


// Implementation: impl Storage
// File: crates/router_env/src/logger/storage.rs
// Module: router_env
// Methods: 2 total (2 public)

impl Storage


// Struct: SCA
// File: crates/hyperswitch_connectors/src/connectors/silverflow/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct SCA


// Function: from_storage
// File: crates/router/src/services/kafka/fraud_check.rs
// Module: router

pub fn from_storage(check: &'a FraudCheck) -> Self


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

pub struct ChargebackCase


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

pub struct BankRedirectRequest


// Function: connector_agnostic_mit_toggle
// File: crates/router/src/core/admin.rs
// Module: router

pub fn connector_agnostic_mit_toggle(
    state: SessionState,
    merchant_id: &id_type::MerchantId,
    profile_id: &id_type::ProfileId,
    connector_agnostic_mit_choice: admin_types::ConnectorAgnosticMitChoice,
) -> RouterResponse<admin_types::ConnectorAgnosticMitChoice>


// Function: create_email_client
// File: crates/router/src/routes/app.rs
// Module: router

pub fn create_email_client(
    settings: &settings::Settings<RawSecret>,
) -> Box<dyn EmailService>


// Function: find_by_capture_id
// File: crates/diesel_models/src/query/capture.rs
// Module: diesel_models

pub fn find_by_capture_id(conn: &PgPooledConn, capture_id: &str) -> StorageResult<Self>


// Function: get_id
// File: crates/hyperswitch_domain_models/src/customer.rs
// Module: hyperswitch_domain_models

pub fn get_id(&self) -> &id_type::GlobalCustomerId


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

pub struct UnifiedAuthenticationServicePreAuthenticateRequest


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

// Public submodules:
pub mod transformers;


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

pub fn get_gsm_decision(
    option_gsm: Option<hyperswitch_domain_models::gsm::GatewayStatusMap>,
) -> common_enums::GsmDecision


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

impl UnifiedTranslationsNew


// Function: get_application_builder
// File: crates/router/src/lib.rs
// Module: router

pub fn get_application_builder(
    request_body_limit: usize,
    cors: settings::CorsSettings,
) -> actix_web::App<
    impl ServiceFactory<
        ServiceRequest,
        Config = (),
        Response = actix_web::dev::ServiceResponse<impl MessageBody>,
        Error = actix_web::Error,
        InitError = (),
    >,
>


// Struct: NexixpayRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NexixpayRefundRequest


// Struct: ThreeDSRequestorPriorTransactionAuthenticationInformation
// File: crates/hyperswitch_connectors/src/connectors/netcetera/netcetera_types.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ThreeDSRequestorPriorTransactionAuthenticationInformation


// Struct: NuveiPayoutCardData
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NuveiPayoutCardData


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

impl api::Refund for for Xendit


// Function: get_module_name
// File: crates/test_utils/src/newman_runner.rs
// Module: test_utils

// Documentation: Getter for the `module_name` field

pub fn get_module_name(&self) -> Option<Module>


// Struct: Recon
// File: crates/router/src/routes/app.rs
// Module: router
// Implementations: 1

pub struct Recon


// Function: get_acs_trans_id
// File: crates/hyperswitch_domain_models/src/router_request_types/authentication.rs
// Module: hyperswitch_domain_models

pub fn get_acs_trans_id(&self) -> Option<String>


// Struct: Key
// File: crates/hyperswitch_connectors/src/connectors/santander/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Key


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

impl ConnectorValidation for for Opayo


// Struct: AdyenAccountHolder
// File: crates/hyperswitch_connectors/src/connectors/adyenplatform/transformers/payouts.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AdyenAccountHolder


// Function: convert_to_mandate_update
// File: crates/diesel_models/src/mandate.rs
// Module: diesel_models

pub fn convert_to_mandate_update(
        self,
        storage_scheme: MerchantStorageScheme,
    ) -> MandateUpdateInternal


// File: crates/api_models/src/refunds.rs
// Module: api_models
// Public functions: 2
// Public structs: 19

use std::collections::HashMap;

pub use common_utils::types::MinorUnit;
use common_utils::{pii, types::TimeRange};
use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;
use utoipa::ToSchema;

use super::payments::AmountFilter;
#[cfg(feature = "v1")]
use crate::admin;
use crate::{admin::MerchantConnectorInfo, enums};

#[cfg(feature = "v1")]
#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RefundRequest {
    /// The payment id against which refund is to be initiated
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "pay_mbabizu24mvu3mela5njyhpit4",
        value_type = String,
    )]
    pub payment_id: common_utils::id_type::PaymentId,

    /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment. If this is not passed by the merchant, this field shall be auto generated and provided in the API response. It is recommended to generate uuid(v4) as the refund_id.
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "ref_mbabizu24mvu3mela5njyhpit4"
    )]
    pub refund_id: Option<String>,

    /// The identifier for the Merchant Account
    #[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = Option<String>)]
    pub merchant_id: Option<common_utils::id_type::MerchantId>,

    /// Total amount for which the refund is to be initiated. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, this will default to the full payment amount
    #[schema(value_type = Option<i64> , minimum = 100, example = 6540)]
    pub amount: Option<MinorUnit>,

    /// Reason for the refund. Often useful for displaying to users and your customer support executive. In case the payment went through Stripe, this field needs to be passed with one of these enums: `duplicate`, `fraudulent`, or `requested_by_customer`
    #[schema(max_length = 255, example = "Customer returned the product")]
    pub reason: Option<String>,

    /// To indicate whether to refund needs to be instant or scheduled. Default value is instant
    #[schema(default = "Instant", example = "Instant")]
    pub refund_type: Option<RefundType>,

    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
    #[schema(value_type  = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    pub metadata: Option<pii::SecretSerdeValue>,

    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorDetailsWrap>)]
    pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,

    /// Charge specific fields for controlling the revert of funds from either platform or connected account
    #[schema(value_type = Option<SplitRefund>)]
    pub split_refunds: Option<common_types::refunds::SplitRefund>,
}

#[cfg(feature = "v2")]
#[derive(Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RefundsCreateRequest {
    /// The payment id against which refund is initiated
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "pay_mbabizu24mvu3mela5njyhpit4",
        value_type = String,
    )]
    pub payment_id: common_utils::id_type::GlobalPaymentId,

    /// Unique Identifier for the Refund given by the Merchant.
    #[schema(
        max_length = 64,
        min_length = 1,
        example = "ref_mbabizu24mvu3mela5njyhpit4",
        value_type = String,
    )]
    pub merchant_reference_id: common_utils::id_type::RefundReferenceId,

    /// The identifier for the Merchant Account
    #[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = Option<String>)]
    pub merchant_id: Option<common_utils::id_type::MerchantId>,

    /// Total amount for which the refund is to be initiated. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, this will default to the amount_captured of the payment
    #[schema(value_type = Option<i64> , minimum = 100, example = 6540)]
    pub amount: Option<MinorUnit>,

    /// Reason for the refund. Often useful for displaying to users and your customer support executive.
    #[schema(max_length = 255, example = "Customer returned the product")]
    pub reason: Option<String>,

    /// To indicate whether to refund needs to be instant or scheduled. Default value is instant
    #[schema(default = "Instant", example = "Instant")]
    pub refund_type: Option<RefundType>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type  = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    pub metadata: Option<pii::SecretSerdeValue>,

    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorAuthDetails>)]
    pub merchant_connector_details: Option<common_types::domain::MerchantConnectorAuthDetails>,
}

#[cfg(feature = "v1")]
#[derive(Default, Debug, Clone, Deserialize)]
pub struct RefundsRetrieveBody {
    pub force_sync: Option<bool>,
}

#[cfg(feature = "v2")]
#[derive(Default, Debug, Clone, Deserialize)]
pub struct RefundsRetrieveBody {
    pub force_sync: Option<bool>,
}

#[cfg(feature = "v2")]
#[derive(Default, Debug, Clone, Deserialize)]
pub struct RefundsRetrievePayload {
    /// `force_sync` with the connector to get refund details
    pub force_sync: Option<bool>,

    /// Merchant connector details used to make payments.
    pub merchant_connector_details: Option<common_types::domain::MerchantConnectorAuthDetails>,
}

#[cfg(feature = "v1")]
#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
pub struct RefundsRetrieveRequest {
    /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refund initiated against the same payment. If the identifiers is not defined by the merchant, this filed shall be auto generated and provide in the API response. It is recommended to generate uuid(v4) as the refund_id.
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "ref_mbabizu24mvu3mela5njyhpit4"
    )]
    pub refund_id: String,

    /// `force_sync` with the connector to get refund details
    /// (defaults to false)
    pub force_sync: Option<bool>,

    /// Merchant connector details used to make payments.
    pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
}

#[cfg(feature = "v2")]
#[derive(Debug, ToSchema, Clone, Deserialize, Serialize)]
pub struct RefundsRetrieveRequest {
    /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refund initiated against the same payment. If the identifiers is not defined by the merchant, this filed shall be auto generated and provide in the API response. It is recommended to generate uuid(v4) as the refund_id.
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "ref_mbabizu24mvu3mela5njyhpit4"
    )]
    pub refund_id: common_utils::id_type::GlobalRefundId,

    /// `force_sync` with the connector to get refund details
    /// (defaults to false)
    pub force_sync: Option<bool>,

    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorAuthDetails>)]
    pub merchant_connector_details: Option<common_types::domain::MerchantConnectorAuthDetails>,
}

#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RefundUpdateRequest {
    #[serde(skip)]
    pub refund_id: String,
    /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive
    #[schema(max_length = 255, example = "Customer returned the product")]
    pub reason: Option<String>,

    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
    #[schema(value_type  = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    pub metadata: Option<pii::SecretSerdeValue>,
}

#[cfg(feature = "v2")]
#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RefundMetadataUpdateRequest {
    /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive
    #[schema(max_length = 255, example = "Customer returned the product")]
    pub reason: Option<String>,

    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
    #[schema(value_type  = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    pub metadata: Option<pii::SecretSerdeValue>,
}

#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RefundManualUpdateRequest {
    #[serde(skip)]
    pub refund_id: String,
    /// Merchant ID
    #[schema(value_type = String)]
    pub merchant_id: common_utils::id_type::MerchantId,
    /// The status for refund
    pub status: Option<RefundStatus>,
    /// The code for the error
    pub error_code: Option<String>,
    /// The error message
    pub error_message: Option<String>,
}

#[cfg(feature = "v1")]
/// To indicate whether to refund needs to be instant or scheduled
#[derive(
    Default, Debug, Clone, Copy, ToSchema, Deserialize, Serialize, Eq, PartialEq, strum::Display,
)]
#[serde(rename_all = "snake_case")]
pub enum RefundType {
    Scheduled,
    #[default]
    Instant,
}

#[cfg(feature = "v2")]
/// To indicate whether the refund needs to be instant or scheduled
#[derive(
    Default, Debug, Clone, Copy, ToSchema, Deserialize, Serialize, Eq, PartialEq, strum::Display,
)]
#[serde(rename_all = "snake_case")]
pub enum RefundType {
    Scheduled,
    #[default]
    Instant,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundResponse {
    /// Unique Identifier for the refund
    pub refund_id: String,
    /// The payment id against which refund is initiated
    #[schema(value_type = String)]
    pub payment_id: common_utils::id_type::PaymentId,
    /// The refund amount, which should be less than or equal to the total payment amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc
    #[schema(value_type = i64 , minimum = 100, example = 6540)]
    pub amount: MinorUnit,
    /// The three-letter ISO currency code
    pub currency: String,
    /// The status for refund
    pub status: RefundStatus,
    /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive
    pub reason: Option<String>,
    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object
    #[schema(value_type = Option<Object>)]
    pub metadata: Option<pii::SecretSerdeValue>,
    /// The error message
    pub error_message: Option<String>,
    /// The code for the error
    pub error_code: Option<String>,
    /// Error code unified across the connectors is received here if there was an error while calling connector
    pub unified_code: Option<String>,
    /// Error message unified across the connectors is received here if there was an error while calling connector
    pub unified_message: Option<String>,
    /// The timestamp at which refund is created
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub created_at: Option<PrimitiveDateTime>,
    /// The timestamp at which refund is updated
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub updated_at: Option<PrimitiveDateTime>,
    /// The connector used for the refund and the corresponding payment
    #[schema(example = "stripe")]
    pub connector: String,
    /// The id of business profile for this refund
    #[schema(value_type = Option<String>)]
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    /// The merchant_connector_id of the processor through which this payment went through
    #[schema(value_type = Option<String>)]
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    /// Charge specific fields for controlling the revert of funds from either platform or connected account
    #[schema(value_type = Option<SplitRefund>,)]
    pub split_refunds: Option<common_types::refunds::SplitRefund>,
    /// Error code received from the issuer in case of failed refunds
    pub issuer_error_code: Option<String>,
    /// Error message received from the issuer in case of failed refunds
    pub issuer_error_message: Option<String>,
}

#[cfg(feature = "v1")]
impl RefundResponse {
    pub fn get_refund_id_as_string(&self) -> String {
        self.refund_id.clone()
    }
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundResponse {
    /// Global Refund Id for the refund
    #[schema(value_type = String)]
    pub id: common_utils::id_type::GlobalRefundId,
    /// The payment id against which refund is initiated
    #[schema(value_type = String)]
    pub payment_id: common_utils::id_type::GlobalPaymentId,
    /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment.
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "ref_mbabizu24mvu3mela5njyhpit4",
        value_type = Option<String>,
    )]
    pub merchant_reference_id: Option<common_utils::id_type::RefundReferenceId>,
    /// The refund amount
    #[schema(value_type = i64 , minimum = 100, example = 6540)]
    pub amount: MinorUnit,
    /// The three-letter ISO currency code
    #[schema(value_type = Currency)]
    pub currency: common_enums::Currency,
    /// The status for refund
    pub status: RefundStatus,
    /// An arbitrary string attached to the object
    pub reason: Option<String>,
    /// Metadata is useful for storing additional, unstructured information on an object
    #[schema(value_type = Option<Object>)]
    pub metadata: Option<pii::SecretSerdeValue>,
    /// The error details for the refund
    pub error_details: Option<RefundErrorDetails>,
    /// The timestamp at which refund is created
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    /// The timestamp at which refund is updated
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub updated_at: PrimitiveDateTime,
    /// The connector used for the refund and the corresponding payment
    #[schema(example = "stripe", value_type = Connector)]
    pub connector: enums::Connector,
    /// The id of business profile for this refund
    #[schema(value_type = String)]
    pub profile_id: common_utils::id_type::ProfileId,
    /// The merchant_connector_id of the processor through which this payment went through
    #[schema(value_type = String)]
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    /// The reference id of the connector for the refund
    pub connector_refund_reference_id: Option<String>,
}

#[cfg(feature = "v2")]
impl RefundResponse {
    pub fn get_refund_id_as_string(&self) -> String {
        self.id.get_string_repr().to_owned()
    }
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundErrorDetails {
    pub code: String,
    pub message: String,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundListRequest {
    /// The identifier for the payment
    #[schema(value_type = Option<String>)]
    pub payment_id: Option<common_utils::id_type::PaymentId>,
    /// The identifier for the refund
    pub refund_id: Option<String>,
    /// The identifier for business profile
    #[schema(value_type = Option<String>)]
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    /// Limit on the number of objects to return
    pub limit: Option<i64>,
    /// The starting point within a list of objects
    pub offset: Option<i64>,
    /// The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc)
    #[serde(flatten)]
    pub time_range: Option<TimeRange>,
    /// The amount to filter reufnds list. Amount takes two option fields start_amount and end_amount from which objects can be filtered as per required scenarios (less_than, greater_than, equal_to and range)
    pub amount_filter: Option<AmountFilter>,
    /// The list of connectors to filter refunds list
    pub connector: Option<Vec<String>>,
    /// The list of merchant connector ids to filter the refunds list for selected label
    #[schema(value_type = Option<Vec<String>>)]
    pub merchant_connector_id: Option<Vec<common_utils::id_type::MerchantConnectorAccountId>>,
    /// The list of currencies to filter refunds list
    #[schema(value_type = Option<Vec<Currency>>)]
    pub currency: Option<Vec<enums::Currency>>,
    /// The list of refund statuses to filter refunds list
    #[schema(value_type = Option<Vec<RefundStatus>>)]
    pub refund_status: Option<Vec<enums::RefundStatus>>,
}
#[cfg(feature = "v2")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundListRequest {
    /// The identifier for the payment
    #[schema(value_type = Option<String>)]
    pub payment_id: Option<common_utils::id_type::GlobalPaymentId>,
    /// The identifier for the refund
    #[schema(value_type = String)]
    pub refund_id: Option<common_utils::id_type::GlobalRefundId>,
    /// Limit on the number of objects to return
    pub limit: Option<i64>,
    /// The starting point within a list of objects
    pub offset: Option<i64>,
    /// The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc)
    #[serde(flatten)]
    pub time_range: Option<TimeRange>,
    /// The amount to filter reufnds list. Amount takes two option fields start_amount and end_amount from which objects can be filtered as per required scenarios (less_than, greater_than, equal_to and range)
    pub amount_filter: Option<AmountFilter>,
    /// The list of connectors to filter refunds list
    pub connector: Option<Vec<String>>,
    /// The list of merchant connector ids to filter the refunds list for selected label
    #[schema(value_type = Option<Vec<String>>)]
    pub connector_id_list: Option<Vec<common_utils::id_type::MerchantConnectorAccountId>>,
    /// The list of currencies to filter refunds list
    #[schema(value_type = Option<Vec<Currency>>)]
    pub currency: Option<Vec<enums::Currency>>,
    /// The list of refund statuses to filter refunds list
    #[schema(value_type = Option<Vec<RefundStatus>>)]
    pub refund_status: Option<Vec<enums::RefundStatus>>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, ToSchema)]
pub struct RefundListResponse {
    /// The number of refunds included in the list
    pub count: usize,
    /// The total number of refunds in the list
    pub total_count: i64,
    /// The List of refund response object
    pub data: Vec<RefundResponse>,
}

#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, ToSchema)]
pub struct RefundListMetaData {
    /// The list of available connector filters
    pub connector: Vec<String>,
    /// The list of available currency filters
    #[schema(value_type = Vec<Currency>)]
    pub currency: Vec<enums::Currency>,
    /// The list of available refund status filters
    #[schema(value_type = Vec<RefundStatus>)]
    pub refund_status: Vec<enums::RefundStatus>,
}

#[derive(Clone, Debug, serde::Serialize, ToSchema)]
pub struct RefundListFilters {
    /// The map of available connector filters, where the key is the connector name and the value is a list of MerchantConnectorInfo instances
    pub connector: HashMap<String, Vec<MerchantConnectorInfo>>,
    /// The list of available currency filters
    #[schema(value_type = Vec<Currency>)]
    pub currency: Vec<enums::Currency>,
    /// The list of available refund status filters
    #[schema(value_type = Vec<RefundStatus>)]
    pub refund_status: Vec<enums::RefundStatus>,
}

#[derive(Clone, Debug, serde::Serialize)]
pub struct RefundAggregateResponse {
    /// The list of refund status with their count
    pub status_with_count: HashMap<enums::RefundStatus, i64>,
}

/// The status for refunds
#[derive(
    Debug,
    Eq,
    Clone,
    Copy,
    PartialEq,
    Default,
    Deserialize,
    Serialize,
    ToSchema,
    strum::Display,
    strum::EnumIter,
)]
#[serde(rename_all = "snake_case")]
pub enum RefundStatus {
    Succeeded,
    Failed,
    #[default]
    Pending,
    Review,
}

impl From<enums::RefundStatus> for RefundStatus {
    fn from(status: enums::RefundStatus) -> Self {
        match status {
            enums::RefundStatus::Failure | enums::RefundStatus::TransactionFailure => Self::Failed,
            enums::RefundStatus::ManualReview => Self::Review,
            enums::RefundStatus::Pending => Self::Pending,
            enums::RefundStatus::Success => Self::Succeeded,
        }
    }
}

impl From<RefundStatus> for enums::RefundStatus {
    fn from(status: RefundStatus) -> Self {
        match status {
            RefundStatus::Failed => Self::Failure,
            RefundStatus::Review => Self::ManualReview,
            RefundStatus::Pending => Self::Pending,
            RefundStatus::Succeeded => Self::Success,
        }
    }
}


// Implementation: impl EmailClient for for AwsSes
// File: crates/external_services/src/email/ses.rs
// Module: external_services
// Methods: 2 total (0 public)

impl EmailClient for for AwsSes


// Struct: SiftPaymentsRequest
// File: crates/hyperswitch_connectors/src/connectors/sift/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct SiftPaymentsRequest


// Function: generate_feature_matrix
// File: crates/router/src/routes/feature_matrix.rs
// Module: router

pub fn generate_feature_matrix(
    state: app::SessionState,
    req: payment_types::FeatureMatrixRequest,
) -> RouterResponse<feature_matrix::FeatureMatrixListResponse>


// Struct: SubscriptionCreate
// File: crates/hyperswitch_domain_models/src/router_flow_types/subscriptions.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct SubscriptionCreate


// Struct: XenditPaymentResponse
// File: crates/hyperswitch_connectors/src/connectors/xendit/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct XenditPaymentResponse


// Struct: TransferReversals
// File: crates/hyperswitch_connectors/src/connectors/stripe/transformers/connect.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TransferReversals


// Function: get_response_payload
// File: crates/euclid_wasm/src/lib.rs
// Module: euclid_wasm

pub fn get_response_payload(input: JsValue) -> JsResult


// Struct: ApiKeyUpdateInternal
// File: crates/diesel_models/src/api_keys.rs
// Module: diesel_models
// Implementations: 0

pub struct ApiKeyUpdateInternal


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

pub mod transformers;

use common_enums::enums;
use common_utils::{
    errors::CustomResult,
    ext_traits::BytesExt,
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, StringMajorUnit, StringMajorUnitForConnector},
};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
        CompleteAuthorize,
    },
    router_request_types::{
        AccessTokenRequestData, CompleteAuthorizeData, PaymentMethodTokenizationData,
        PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData,
        PaymentsSyncData, RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, TokenizationRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorRedirectResponse,
        ConnectorSpecifications, ConnectorValidation,
    },
    configs::Connectors,
    consts, errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks,
};
use lazy_static::lazy_static;
use masking::{Mask, PeekInterface};
use transformers as mollie;

// use self::mollie::{webhook_headers, MollieWebhookBodyEventType};
use crate::{constants::headers, types::ResponseRouterData, utils::convert_amount};

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

impl Mollie {
    pub fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMajorUnitForConnector,
        }
    }
}

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

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Mollie
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.get_auth_header(&req.connector_auth_type)
    }
}

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

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

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

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

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

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

        Ok(ErrorResponse {
            status_code: response.status,
            code: response
                .title
                .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
            message: response.detail,
            reason: response.field,
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

impl ConnectorValidation for Mollie {}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Mollie {}

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

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Mollie
{
    fn get_headers(
        &self,
        req: &TokenizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::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: &TokenizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let base_url = connectors
            .mollie
            .secondary_base_url
            .as_ref()
            .ok_or(errors::ConnectorError::FailedToObtainIntegrationUrl)?;
        Ok(format!("{base_url}card-tokens"))
    }

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

    fn handle_response(
        &self,
        data: &TokenizationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<TokenizationRouterData, errors::ConnectorError>
    where
        PaymentsResponseData: Clone,
    {
        let response: mollie::MollieCardTokenResponse = res
            .response
            .parse_struct("MollieTokenResponse")
            .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<SetupMandate, SetupMandateRequestData, PaymentsResponseData> for Mollie {
    fn build_request(
        &self,
        _req: &RouterData<SetupMandate, SetupMandateRequestData, PaymentsResponseData>,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(
            errors::ConnectorError::NotImplemented("Setup Mandate flow for Mollie".to_string())
                .into(),
        )
    }
}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Mollie {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_url(
        &self,
        _req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}payments", self.base_url(connectors)))
    }

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.currency,
        )?;

        let router_obj = mollie::MollieRouterData::from((amount, req));
        let connector_req = mollie::MolliePaymentsRequest::try_from(&router_obj)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
        let response: mollie::MolliePaymentsResponse = res
            .response
            .parse_struct("MolliePaymentsResponse")
            .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 Mollie
{
}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Mollie {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_url(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}payments/{}",
            self.base_url(connectors),
            req.request
                .connector_transaction_id
                .get_connector_transaction_id()
                .change_context(errors::ConnectorError::RequestEncodingFailed)?
        ))
    }

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

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: mollie::MolliePaymentsResponse = res
            .response
            .parse_struct("mollie PaymentsSyncResponse")
            .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<Capture, PaymentsCaptureData, PaymentsResponseData> for Mollie {
    fn build_request(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(errors::ConnectorError::FlowNotSupported {
            flow: "Capture".to_string(),
            connector: self.id().to_string(),
        }
        .into())
    }
}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Mollie {
    fn build_request(
        &self,
        _req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(errors::ConnectorError::FlowNotSupported {
            flow: "Void".to_string(),
            connector: self.id().to_string(),
        }
        .into())
    }
}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Mollie {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::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> {
        Ok(format!(
            "{}payments/{}/refunds",
            self.base_url(connectors),
            req.request.connector_transaction_id
        ))
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_refund_amount,
            req.request.currency,
        )?;

        let router_obj = mollie::MollieRouterData::from((amount, req));
        let connector_req = mollie::MollieRefundRequest::try_from(&router_obj)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .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: mollie::RefundResponse = res
            .response
            .parse_struct("MollieRefundResponse")
            .change_context(errors::ConnectorError::RequestEncodingFailed)?;

        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<RSync, RefundsData, RefundsResponseData> for Mollie {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::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 connector_refund_id = req
            .request
            .connector_refund_id
            .clone()
            .ok_or(errors::ConnectorError::RequestEncodingFailed)?;
        Ok(format!(
            "{}payments/{}/refunds/{}",
            self.base_url(connectors),
            req.request.connector_transaction_id,
            connector_refund_id
        ))
    }

    fn build_request(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> 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)?)
                .build(),
        ))
    }

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

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

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

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

#[async_trait::async_trait]
impl webhooks::IncomingWebhook for Mollie {
    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> {
        Ok(api_models::webhooks::IncomingWebhookEvent::EventNotSupported)
    }

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

impl ConnectorRedirectResponse for Mollie {
    fn get_flow_type(
        &self,
        _query_params: &str,
        _json_payload: Option<serde_json::Value>,
        action: enums::PaymentAction,
    ) -> CustomResult<enums::CallConnectorAction, errors::ConnectorError> {
        match action {
            enums::PaymentAction::PSync
            | enums::PaymentAction::CompleteAuthorize
            | enums::PaymentAction::PaymentAuthenticateCompleteAuthorize => {
                Ok(enums::CallConnectorAction::Trigger)
            }
        }
    }
}

// impl ConnectorSpecifications for Mollie {}
lazy_static! {
    static ref MOLLIE_SUPPORTED_PAYMENT_METHODS: SupportedPaymentMethods = {
        let supported_capture_methods = vec![
            enums::CaptureMethod::Automatic,
            enums::CaptureMethod::SequentialAutomatic,
        ];
        let supported_card_network = vec![
            common_enums::CardNetwork::Visa,
            common_enums::CardNetwork::Mastercard,
            common_enums::CardNetwork::AmericanExpress,
            common_enums::CardNetwork::Discover,
            common_enums::CardNetwork::JCB,
            common_enums::CardNetwork::DinersClub,
            common_enums::CardNetwork::UnionPay,
            common_enums::CardNetwork::Interac,
            common_enums::CardNetwork::CartesBancaires,

        ];

        let mut mollie_supported_payment_methods = SupportedPaymentMethods::new();
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::Card,
            enums::PaymentMethodType::Credit,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_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(),
                        }
                    }),
                ),
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::Card,
            enums::PaymentMethodType::Debit,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_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(),
                        }
                    }),
                ),
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::BankRedirect,
            enums::PaymentMethodType::Eps,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::BankRedirect,
            enums::PaymentMethodType::Giropay,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::BankRedirect,
            enums::PaymentMethodType::Ideal,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::BankRedirect,
            enums::PaymentMethodType::Sofort,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::BankRedirect,
            enums::PaymentMethodType::Przelewy24,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::BankRedirect,
            enums::PaymentMethodType::BancontactCard,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::Wallet,
            enums::PaymentMethodType::Paypal,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::Wallet,
            enums::PaymentMethodType::ApplePay,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );
        mollie_supported_payment_methods.add(
            enums::PaymentMethod::BankDebit,
            enums::PaymentMethodType::Sepa,
            PaymentMethodDetails{
                mandates: common_enums::FeatureStatus::NotSupported,
                refunds: common_enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );

        mollie_supported_payment_methods
    };

    static ref MOLLIE_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
        display_name: "MOLLIE",
        description:
            "Mollie is a Developer-friendly processor providing simple and customizable payment solutions for businesses of all sizes.",
        connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
        integration_status: enums::ConnectorIntegrationStatus::Sandbox,
    };

    static ref MOLLIE_SUPPORTED_WEBHOOK_FLOWS: Vec<enums::EventClass> = Vec::new();

}

impl ConnectorSpecifications for Mollie {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&*MOLLIE_CONNECTOR_INFO)
    }

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

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


// Trait: EntityId
// File: crates/hyperswitch_constraint_graph/src/dense_map.rs
// Module: hyperswitch_constraint_graph

pub trait EntityId


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

pub struct PaymentInformationResponse