// File: crates/router/src/db/user_authentication_method.rs
// Module: router

use diesel_models::user_authentication_method as storage;
use error_stack::report;
use router_env::{instrument, tracing};

use super::MockDb;
use crate::{
    connection,
    core::errors::{self, CustomResult},
    services::Store,
};

#[async_trait::async_trait]
pub trait UserAuthenticationMethodInterface {
    async fn insert_user_authentication_method(
        &self,
        user_authentication_method: storage::UserAuthenticationMethodNew,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError>;

    async fn get_user_authentication_method_by_id(
        &self,
        id: &str,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError>;

    async fn list_user_authentication_methods_for_auth_id(
        &self,
        auth_id: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError>;

    async fn list_user_authentication_methods_for_owner_id(
        &self,
        owner_id: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError>;

    async fn update_user_authentication_method(
        &self,
        id: &str,
        user_authentication_method_update: storage::UserAuthenticationMethodUpdate,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError>;

    async fn list_user_authentication_methods_for_email_domain(
        &self,
        email_domain: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError>;
}

#[async_trait::async_trait]
impl UserAuthenticationMethodInterface for Store {
    #[instrument(skip_all)]
    async fn insert_user_authentication_method(
        &self,
        user_authentication_method: storage::UserAuthenticationMethodNew,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        user_authentication_method
            .insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn get_user_authentication_method_by_id(
        &self,
        id: &str,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::UserAuthenticationMethod::get_user_authentication_method_by_id(&conn, id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn list_user_authentication_methods_for_auth_id(
        &self,
        auth_id: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::UserAuthenticationMethod::list_user_authentication_methods_for_auth_id(
            &conn, auth_id,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn list_user_authentication_methods_for_owner_id(
        &self,
        owner_id: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::UserAuthenticationMethod::list_user_authentication_methods_for_owner_id(
            &conn, owner_id,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn update_user_authentication_method(
        &self,
        id: &str,
        user_authentication_method_update: storage::UserAuthenticationMethodUpdate,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::UserAuthenticationMethod::update_user_authentication_method(
            &conn,
            id,
            user_authentication_method_update,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn list_user_authentication_methods_for_email_domain(
        &self,
        email_domain: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::UserAuthenticationMethod::list_user_authentication_methods_for_email_domain(
            &conn,
            email_domain,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl UserAuthenticationMethodInterface for MockDb {
    async fn insert_user_authentication_method(
        &self,
        user_authentication_method: storage::UserAuthenticationMethodNew,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        let mut user_authentication_methods = self.user_authentication_methods.lock().await;
        let existing_auth_id = user_authentication_methods
            .iter()
            .find(|uam| uam.owner_id == user_authentication_method.owner_id)
            .map(|uam| uam.auth_id.clone());

        let auth_id = existing_auth_id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
        let user_authentication_method = storage::UserAuthenticationMethod {
            id: uuid::Uuid::new_v4().to_string(),
            auth_id,
            owner_id: user_authentication_method.auth_id,
            owner_type: user_authentication_method.owner_type,
            auth_type: user_authentication_method.auth_type,
            public_config: user_authentication_method.public_config,
            private_config: user_authentication_method.private_config,
            allow_signup: user_authentication_method.allow_signup,
            created_at: user_authentication_method.created_at,
            last_modified_at: user_authentication_method.last_modified_at,
            email_domain: user_authentication_method.email_domain,
        };

        user_authentication_methods.push(user_authentication_method.clone());
        Ok(user_authentication_method)
    }

    #[instrument(skip_all)]
    async fn get_user_authentication_method_by_id(
        &self,
        id: &str,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        let user_authentication_methods = self.user_authentication_methods.lock().await;

        let user_authentication_method = user_authentication_methods
            .iter()
            .find(|&auth_method_inner| auth_method_inner.id == id);

        if let Some(user_authentication_method) = user_authentication_method {
            Ok(user_authentication_method.to_owned())
        } else {
            return Err(errors::StorageError::ValueNotFound(format!(
                "No user authentication method found for id = {id}",
            ))
            .into());
        }
    }

    async fn list_user_authentication_methods_for_auth_id(
        &self,
        auth_id: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError> {
        let user_authentication_methods = self.user_authentication_methods.lock().await;

        let user_authentication_methods_list: Vec<_> = user_authentication_methods
            .iter()
            .filter(|auth_method_inner| auth_method_inner.auth_id == auth_id)
            .cloned()
            .collect();
        if user_authentication_methods_list.is_empty() {
            return Err(errors::StorageError::ValueNotFound(format!(
                "No user authentication method found for auth_id = {auth_id}",
            ))
            .into());
        }

        Ok(user_authentication_methods_list)
    }

    async fn list_user_authentication_methods_for_owner_id(
        &self,
        owner_id: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError> {
        let user_authentication_methods = self.user_authentication_methods.lock().await;

        let user_authentication_methods_list: Vec<_> = user_authentication_methods
            .iter()
            .filter(|auth_method_inner| auth_method_inner.owner_id == owner_id)
            .cloned()
            .collect();
        if user_authentication_methods_list.is_empty() {
            return Err(errors::StorageError::ValueNotFound(format!(
                "No user authentication method found for owner_id = {owner_id}",
            ))
            .into());
        }

        Ok(user_authentication_methods_list)
    }

    async fn update_user_authentication_method(
        &self,
        id: &str,
        user_authentication_method_update: storage::UserAuthenticationMethodUpdate,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        let mut user_authentication_methods = self.user_authentication_methods.lock().await;
        user_authentication_methods
            .iter_mut()
            .find(|auth_method_inner| auth_method_inner.id == id)
            .map(|auth_method_inner| {
                *auth_method_inner = match user_authentication_method_update {
                    storage::UserAuthenticationMethodUpdate::UpdateConfig {
                        private_config,
                        public_config,
                    } => storage::UserAuthenticationMethod {
                        private_config,
                        public_config,
                        last_modified_at: common_utils::date_time::now(),
                        ..auth_method_inner.to_owned()
                    },
                    storage::UserAuthenticationMethodUpdate::EmailDomain { email_domain } => {
                        storage::UserAuthenticationMethod {
                            email_domain: email_domain.to_owned(),
                            last_modified_at: common_utils::date_time::now(),
                            ..auth_method_inner.to_owned()
                        }
                    }
                };
                auth_method_inner.to_owned()
            })
            .ok_or(
                errors::StorageError::ValueNotFound(format!(
                    "No authentication method available for the id = {id}"
                ))
                .into(),
            )
    }

    #[instrument(skip_all)]
    async fn list_user_authentication_methods_for_email_domain(
        &self,
        email_domain: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError> {
        let user_authentication_methods = self.user_authentication_methods.lock().await;

        let user_authentication_methods_list: Vec<_> = user_authentication_methods
            .iter()
            .filter(|auth_method_inner| auth_method_inner.email_domain == email_domain)
            .cloned()
            .collect();

        Ok(user_authentication_methods_list)
    }
}


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

pub struct RefundResponse


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

// Public submodules:
pub mod transformers;


// Function: get_or_update_dispute_object
// File: crates/router/src/core/webhooks/incoming.rs
// Module: router

pub fn get_or_update_dispute_object(
    state: SessionState,
    option_dispute: Option<diesel_models::dispute::Dispute>,
    dispute_details: api::disputes::DisputePayload,
    merchant_id: &common_utils::id_type::MerchantId,
    organization_id: &common_utils::id_type::OrganizationId,
    payment_attempt: &PaymentAttempt,
    dispute_status: common_enums::enums::DisputeStatus,
    business_profile: &domain::Profile,
    connector_name: &str,
) -> CustomResult<diesel_models::dispute::Dispute, errors::ApiErrorResponse>


// Struct: ForteCaptureResponse
// File: crates/hyperswitch_connectors/src/connectors/forte/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ForteCaptureResponse


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

pub fn get_key_type(key: &str) -> Result<String, String>


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

pub mod types;

use common_utils::types::MinorUnit;

use crate::{
    backend::{self, inputs, EuclidBackend},
    frontend::ast,
};

pub struct InterpreterBackend<O> {
    program: ast::Program<O>,
}

impl<O> InterpreterBackend<O>
where
    O: Clone,
{
    fn eval_number_comparison_array(
        num: MinorUnit,
        array: &[ast::NumberComparison],
    ) -> Result<bool, types::InterpreterError> {
        for comparison in array {
            let other = comparison.number;
            let res = match comparison.comparison_type {
                ast::ComparisonType::GreaterThan => num > other,
                ast::ComparisonType::LessThan => num < other,
                ast::ComparisonType::LessThanEqual => num <= other,
                ast::ComparisonType::GreaterThanEqual => num >= other,
                ast::ComparisonType::Equal => num == other,
                ast::ComparisonType::NotEqual => num != other,
            };

            if res {
                return Ok(true);
            }
        }

        Ok(false)
    }

    fn eval_comparison(
        comparison: &ast::Comparison,
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        use ast::{ComparisonType::*, ValueType::*};

        let value = ctx
            .get(&comparison.lhs)
            .ok_or_else(|| types::InterpreterError {
                error_type: types::InterpreterErrorType::InvalidKey(comparison.lhs.clone()),
                metadata: comparison.metadata.clone(),
            })?;

        if let Some(val) = value {
            match (val, &comparison.comparison, &comparison.value) {
                (EnumVariant(e1), Equal, EnumVariant(e2)) => Ok(e1 == e2),
                (EnumVariant(e1), NotEqual, EnumVariant(e2)) => Ok(e1 != e2),
                (EnumVariant(e), Equal, EnumVariantArray(evec)) => Ok(evec.iter().any(|v| e == v)),
                (EnumVariant(e), NotEqual, EnumVariantArray(evec)) => {
                    Ok(evec.iter().all(|v| e != v))
                }
                (Number(n1), Equal, Number(n2)) => Ok(n1 == n2),
                (Number(n1), NotEqual, Number(n2)) => Ok(n1 != n2),
                (Number(n1), LessThanEqual, Number(n2)) => Ok(n1 <= n2),
                (Number(n1), GreaterThanEqual, Number(n2)) => Ok(n1 >= n2),
                (Number(n1), LessThan, Number(n2)) => Ok(n1 < n2),
                (Number(n1), GreaterThan, Number(n2)) => Ok(n1 > n2),
                (Number(n), Equal, NumberArray(nvec)) => Ok(nvec.iter().any(|v| v == n)),
                (Number(n), NotEqual, NumberArray(nvec)) => Ok(nvec.iter().all(|v| v != n)),
                (Number(n), Equal, NumberComparisonArray(ncvec)) => {
                    Self::eval_number_comparison_array(*n, ncvec)
                }
                _ => Err(types::InterpreterError {
                    error_type: types::InterpreterErrorType::InvalidComparison,
                    metadata: comparison.metadata.clone(),
                }),
            }
        } else {
            Ok(false)
        }
    }

    fn eval_if_condition(
        condition: &ast::IfCondition,
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        for comparison in condition {
            let res = Self::eval_comparison(comparison, ctx)?;

            if !res {
                return Ok(false);
            }
        }

        Ok(true)
    }

    fn eval_if_statement(
        stmt: &ast::IfStatement,
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        let cond_res = Self::eval_if_condition(&stmt.condition, ctx)?;

        if !cond_res {
            return Ok(false);
        }

        if let Some(ref nested) = stmt.nested {
            for nested_if in nested {
                let res = Self::eval_if_statement(nested_if, ctx)?;

                if res {
                    return Ok(true);
                }
            }

            return Ok(false);
        }

        Ok(true)
    }

    fn eval_rule_statements(
        statements: &[ast::IfStatement],
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        for stmt in statements {
            let res = Self::eval_if_statement(stmt, ctx)?;

            if res {
                return Ok(true);
            }
        }

        Ok(false)
    }

    #[inline]
    fn eval_rule(
        rule: &ast::Rule<O>,
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        Self::eval_rule_statements(&rule.statements, ctx)
    }

    fn eval_program(
        program: &ast::Program<O>,
        ctx: &types::Context,
    ) -> Result<backend::BackendOutput<O>, types::InterpreterError> {
        for rule in &program.rules {
            let res = Self::eval_rule(rule, ctx)?;

            if res {
                return Ok(backend::BackendOutput {
                    connector_selection: rule.connector_selection.clone(),
                    rule_name: Some(rule.name.clone()),
                });
            }
        }

        Ok(backend::BackendOutput {
            connector_selection: program.default_selection.clone(),
            rule_name: None,
        })
    }
}

impl<O> EuclidBackend<O> for InterpreterBackend<O>
where
    O: Clone,
{
    type Error = types::InterpreterError;

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

    fn execute(&self, input: inputs::BackendInput) -> Result<super::BackendOutput<O>, Self::Error> {
        let ctx: types::Context = input.into();
        Self::eval_program(&self.program, &ctx)
    }
}


// Function: get_bank_account_connector_details
// File: crates/router/src/core/payment_methods/cards.rs
// Module: router

pub fn get_bank_account_connector_details(
    pm: &domain::PaymentMethod,
) -> errors::RouterResult<Option<BankAccountTokenData>>


// Struct: AchBankTransferAdditionalData
// File: crates/common_utils/src/payout_method_utils.rs
// Module: common_utils
// Implementations: 0

pub struct AchBankTransferAdditionalData


// Function: new
// File: crates/redis_interface/src/types.rs
// Module: redis_interface

pub fn new(value: FredRedisValue) -> Self


// Struct: CheckoutThreeDS
// File: crates/hyperswitch_connectors/src/connectors/checkout/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CheckoutThreeDS


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

impl api::PaymentCapture for for Dlocal


// Function: get_blocklist_guard_key
// File: crates/common_utils/src/id_type/merchant.rs
// Module: common_utils

// Documentation: get_blocklist_enabled_key

pub fn get_blocklist_guard_key(&self) -> String


// File: crates/router/src/workflows/process_dispute.rs
// Module: router
// Public functions: 2
// Public structs: 1

use common_utils::ext_traits::{StringExt, ValueExt};
use diesel_models::process_tracker::business_status;
use error_stack::ResultExt;
use router_env::logger;
use scheduler::{
    consumer::{self, types::process_data, workflows::ProcessTrackerWorkflow},
    errors as sch_errors, utils as scheduler_utils,
};

#[cfg(feature = "v1")]
use crate::core::webhooks::incoming::get_payment_attempt_from_object_reference_id;
use crate::{
    core::disputes,
    db::StorageInterface,
    errors,
    routes::SessionState,
    types::{api, domain, storage},
};

pub struct ProcessDisputeWorkflow;

/// This workflow inserts only new dispute records into the dispute table and triggers related outgoing webhook
#[async_trait::async_trait]
impl ProcessTrackerWorkflow<SessionState> for ProcessDisputeWorkflow {
    #[cfg(feature = "v2")]
    async fn execute_workflow<'a>(
        &'a self,
        _state: &'a SessionState,
        _process: storage::ProcessTracker,
    ) -> Result<(), sch_errors::ProcessTrackerError> {
        todo!()
    }

    #[cfg(feature = "v1")]
    async fn execute_workflow<'a>(
        &'a self,
        state: &'a SessionState,
        process: storage::ProcessTracker,
    ) -> Result<(), sch_errors::ProcessTrackerError> {
        let db: &dyn StorageInterface = &*state.store;
        let tracking_data: api::ProcessDisputePTData = process
            .tracking_data
            .clone()
            .parse_value("ProcessDisputePTData")?;
        let key_manager_state = &state.into();
        let key_store = db
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &tracking_data.merchant_id,
                &db.get_master_key().to_vec().into(),
            )
            .await?;

        let merchant_account = db
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &tracking_data.merchant_id,
                &key_store,
            )
            .await?;

        let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(domain::Context(
            merchant_account.clone(),
            key_store.clone(),
        )));

        let payment_attempt = get_payment_attempt_from_object_reference_id(
            state,
            tracking_data.dispute_payload.object_reference_id.clone(),
            &merchant_context,
        )
        .await?;

        let business_profile = state
            .store
            .find_business_profile_by_profile_id(
                &(state).into(),
                merchant_context.get_merchant_key_store(),
                &payment_attempt.profile_id,
            )
            .await?;

        // Check if the dispute already exists
        let dispute = state
            .store
            .find_by_merchant_id_payment_id_connector_dispute_id(
                merchant_context.get_merchant_account().get_id(),
                &payment_attempt.payment_id,
                &tracking_data.dispute_payload.connector_dispute_id,
            )
            .await
            .ok()
            .flatten();

        if dispute.is_some() {
            // Dispute already exists — mark the process as complete
            state
                .store
                .as_scheduler()
                .finish_process_with_business_status(process, business_status::COMPLETED_BY_PT)
                .await?;
        } else {
            // Update dispute data
            let response = disputes::update_dispute_data(
                state,
                merchant_context,
                business_profile,
                dispute,
                tracking_data.dispute_payload,
                payment_attempt,
                tracking_data.connector_name.as_str(),
            )
            .await
            .map_err(|error| logger::error!("Dispute update failed: {error}"));

            match response {
                Ok(_) => {
                    state
                        .store
                        .as_scheduler()
                        .finish_process_with_business_status(
                            process,
                            business_status::COMPLETED_BY_PT,
                        )
                        .await?;
                }
                Err(_) => {
                    retry_sync_task(
                        db,
                        tracking_data.connector_name,
                        tracking_data.merchant_id,
                        process,
                    )
                    .await?;
                }
            }
        }
        Ok(())
    }

    async fn error_handler<'a>(
        &'a self,
        state: &'a SessionState,
        process: storage::ProcessTracker,
        error: sch_errors::ProcessTrackerError,
    ) -> errors::CustomResult<(), sch_errors::ProcessTrackerError> {
        consumer::consumer_error_handler(state.store.as_scheduler(), process, error).await
    }
}

pub async fn get_sync_process_schedule_time(
    db: &dyn StorageInterface,
    connector: &str,
    merchant_id: &common_utils::id_type::MerchantId,
    retry_count: i32,
) -> Result<Option<time::PrimitiveDateTime>, errors::ProcessTrackerError> {
    let mapping: common_utils::errors::CustomResult<
        process_data::ConnectorPTMapping,
        errors::StorageError,
    > = db
        .find_config_by_key(&format!("pt_mapping_{connector}"))
        .await
        .map(|value| value.config)
        .and_then(|config| {
            config
                .parse_struct("ConnectorPTMapping")
                .change_context(errors::StorageError::DeserializationFailed)
        });
    let mapping = match mapping {
        Ok(x) => x,
        Err(error) => {
            logger::info!(?error, "Redis Mapping Error");
            process_data::ConnectorPTMapping::default()
        }
    };
    let time_delta = scheduler_utils::get_schedule_time(mapping, merchant_id, retry_count);

    Ok(scheduler_utils::get_time_from_delta(time_delta))
}

/// Schedule the task for retry
///
/// Returns bool which indicates whether this was the last retry or not
pub async fn retry_sync_task(
    db: &dyn StorageInterface,
    connector: String,
    merchant_id: common_utils::id_type::MerchantId,
    pt: storage::ProcessTracker,
) -> Result<bool, sch_errors::ProcessTrackerError> {
    let schedule_time =
        get_sync_process_schedule_time(db, &connector, &merchant_id, pt.retry_count + 1).await?;

    match schedule_time {
        Some(s_time) => {
            db.as_scheduler().retry_process(pt, s_time).await?;
            Ok(false)
        }
        None => {
            db.as_scheduler()
                .finish_process_with_business_status(pt, business_status::RETRIES_EXCEEDED)
                .await?;
            Ok(true)
        }
    }
}


// Struct: FiservRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/fiserv/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FiservRefundRequest


// Struct: PayoutLinkInitiateRequest
// File: crates/api_models/src/payouts.rs
// Module: api_models
// Implementations: 0

pub struct PayoutLinkInitiateRequest


// Implementation: impl OvercaptureEnabledBool
// File: crates/common_types/src/primitive_wrappers.rs
// Module: common_types
// Methods: 1 total (1 public)

impl OvercaptureEnabledBool


// Struct: RSync
// File: crates/hyperswitch_domain_models/src/router_flow_types/refunds.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct RSync


// Function: is_off_session
// File: crates/common_enums/src/enums.rs
// Module: common_enums

// Documentation: Indicates whether the payment method should be saved for future use or not

pub fn is_off_session(self) -> bool


// File: crates/analytics/src/payments/metrics/sessionized_metrics/connector_success_rate.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, FilterTypes, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql,
        Window,
    },
    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
};

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

#[async_trait::async_trait]
impl<T> super::PaymentMetric<T> for ConnectorSuccessRate
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);
        let mut dimensions = dimensions.to_vec();

        dimensions.push(PaymentDimensions::PaymentStatus);

        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()?;

        query_builder
            .add_custom_filter_clause(PaymentDimensions::Connector, "NULL", FilterTypes::IsNotNull)
            .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),
                        None,
                        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<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>,
                crate::query::PostProcessingError,
            >>()
            .change_context(MetricsError::PostProcessingFailure)
    }
}


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

// Public submodules:
pub mod transformers;


// Struct: PaypalOrderErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaypalOrderErrorResponse


// Function: files_create
// File: crates/router/src/routes/files.rs
// Module: router

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


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

pub fn new() -> &'static Self


// Implementation: impl api::Payouts for for Cybersource
// File: crates/hyperswitch_connectors/src/connectors/cybersource.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Payouts for for Cybersource


// File: crates/router/src/core/unified_authentication_service/types.rs
// Module: router
// Public structs: 2

use api_models::payments;
use hyperswitch_domain_models::{
    errors::api_error_response::{self as errors, NotImplementedMessage},
    router_request_types::{
        authentication::MessageCategory,
        unified_authentication_service::{
            UasAuthenticationRequestData, UasPostAuthenticationRequestData,
            UasPreAuthenticationRequestData,
        },
        BrowserInformation,
    },
};

use crate::{
    core::{errors::RouterResult, payments::helpers::MerchantConnectorAccountType},
    db::domain,
    routes::SessionState,
};

pub const CTP_MASTERCARD: &str = "ctp_mastercard";

pub const UNIFIED_AUTHENTICATION_SERVICE: &str = "unified_authentication_service";

pub const IRRELEVANT_ATTEMPT_ID_IN_AUTHENTICATION_FLOW: &str =
    "irrelevant_attempt_id_in_AUTHENTICATION_flow";

pub const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_AUTHENTICATION_FLOW: &str =
    "irrelevant_connector_request_reference_id_in_AUTHENTICATION_flow";

pub struct ClickToPay;

pub struct ExternalAuthentication;

#[async_trait::async_trait]
pub trait UnifiedAuthenticationService {
    #[allow(clippy::too_many_arguments)]
    fn get_pre_authentication_request_data(
        _payment_method_data: Option<&domain::PaymentMethodData>,
        _service_details: Option<payments::CtpServiceDetails>,
        _amount: common_utils::types::MinorUnit,
        _currency: Option<common_enums::Currency>,
        _merchant_details: Option<&hyperswitch_domain_models::router_request_types::unified_authentication_service::MerchantDetails>,
        _billing_address: Option<&hyperswitch_domain_models::address::Address>,
        _acquirer_bin: Option<String>,
        _acquirer_merchant_id: Option<String>,
    ) -> RouterResult<UasPreAuthenticationRequestData> {
        Err(errors::ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason(
                "get_pre_authentication_request_data".to_string(),
            ),
        }
        .into())
    }

    #[allow(clippy::too_many_arguments)]
    async fn pre_authentication(
        _state: &SessionState,
        _merchant_id: &common_utils::id_type::MerchantId,
        _payment_id: Option<&common_utils::id_type::PaymentId>,
        _payment_method_data: Option<&domain::PaymentMethodData>,
        _merchant_connector_account: &MerchantConnectorAccountType,
        _connector_name: &str,
        _authentication_id: &common_utils::id_type::AuthenticationId,
        _payment_method: common_enums::PaymentMethod,
        _amount: common_utils::types::MinorUnit,
        _currency: Option<common_enums::Currency>,
        _service_details: Option<payments::CtpServiceDetails>,
        _merchant_details: Option<&hyperswitch_domain_models::router_request_types::unified_authentication_service::MerchantDetails>,
        _billing_address: Option<&hyperswitch_domain_models::address::Address>,
        _acquirer_bin: Option<String>,
        _acquirer_merchant_id: Option<String>,
    ) -> RouterResult<hyperswitch_domain_models::types::UasPreAuthenticationRouterData> {
        Err(errors::ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason("pre_authentication".to_string()),
        }
        .into())
    }

    #[allow(clippy::too_many_arguments)]
    fn get_authentication_request_data(
        _browser_details: Option<BrowserInformation>,
        _amount: Option<common_utils::types::MinorUnit>,
        _currency: Option<common_enums::Currency>,
        _message_category: MessageCategory,
        _device_channel: payments::DeviceChannel,
        _authentication: diesel_models::authentication::Authentication,
        _return_url: Option<String>,
        _sdk_information: Option<payments::SdkInformation>,
        _threeds_method_comp_ind: payments::ThreeDsCompletionIndicator,
        _email: Option<common_utils::pii::Email>,
        _webhook_url: String,
    ) -> RouterResult<UasAuthenticationRequestData> {
        Err(errors::ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason(
                "get_pre_authentication_request_data".to_string(),
            ),
        }
        .into())
    }

    #[allow(clippy::too_many_arguments)]
    async fn authentication(
        _state: &SessionState,
        _business_profile: &domain::Profile,
        _payment_method: &common_enums::PaymentMethod,
        _browser_details: Option<BrowserInformation>,
        _amount: Option<common_utils::types::MinorUnit>,
        _currency: Option<common_enums::Currency>,
        _message_category: MessageCategory,
        _device_channel: payments::DeviceChannel,
        _authentication_data: diesel_models::authentication::Authentication,
        _return_url: Option<String>,
        _sdk_information: Option<payments::SdkInformation>,
        _threeds_method_comp_ind: payments::ThreeDsCompletionIndicator,
        _email: Option<common_utils::pii::Email>,
        _webhook_url: String,
        _merchant_connector_account: &MerchantConnectorAccountType,
        _connector_name: &str,
        _payment_id: Option<common_utils::id_type::PaymentId>,
    ) -> RouterResult<hyperswitch_domain_models::types::UasAuthenticationRouterData> {
        Err(errors::ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason("authentication".to_string()),
        }
        .into())
    }

    fn get_post_authentication_request_data(
        _authentication: Option<diesel_models::authentication::Authentication>,
    ) -> RouterResult<UasPostAuthenticationRequestData> {
        Err(errors::ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason("post_authentication".to_string()),
        }
        .into())
    }

    #[allow(clippy::too_many_arguments)]
    async fn post_authentication(
        _state: &SessionState,
        _business_profile: &domain::Profile,
        _payment_id: Option<&common_utils::id_type::PaymentId>,
        _merchant_connector_account: &MerchantConnectorAccountType,
        _connector_name: &str,
        _authentication_id: &common_utils::id_type::AuthenticationId,
        _payment_method: common_enums::PaymentMethod,
        _merchant_id: &common_utils::id_type::MerchantId,
        _authentication: Option<&diesel_models::authentication::Authentication>,
    ) -> RouterResult<hyperswitch_domain_models::types::UasPostAuthenticationRouterData> {
        Err(errors::ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason("post_authentication".to_string()),
        }
        .into())
    }

    #[allow(clippy::too_many_arguments)]
    async fn confirmation(
        _state: &SessionState,
        _authentication_id: Option<&common_utils::id_type::AuthenticationId>,
        _currency: Option<common_enums::Currency>,
        _status: common_enums::AttemptStatus,
        _service_details: Option<payments::CtpServiceDetails>,
        _merchant_connector_account: &MerchantConnectorAccountType,
        _connector_name: &str,
        _payment_method: common_enums::PaymentMethod,
        _net_amount: common_utils::types::MinorUnit,
        _payment_id: Option<&common_utils::id_type::PaymentId>,
        _merchant_id: &common_utils::id_type::MerchantId,
    ) -> RouterResult<()> {
        Err(errors::ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason("confirmation".to_string()),
        }
        .into())
    }
}


// Struct: ProfileDefaultRoutingConfig
// File: crates/api_models/src/routing.rs
// Module: api_models
// Implementations: 0

pub struct ProfileDefaultRoutingConfig


// Function: find_by_profile_id_connector_transaction_id
// File: crates/diesel_models/src/query/payment_attempt.rs
// Module: diesel_models

pub fn find_by_profile_id_connector_transaction_id(
        conn: &PgPooledConn,
        profile_id: &common_utils::id_type::ProfileId,
        connector_txn_id: &str,
    ) -> StorageResult<Self>


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

pub struct TransactionDetails


        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<disputes::DisputePayload, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

        let amount = convert_amount(
            self.amount_converter_webhooks,
            notif.amount.value,
            notif.amount.currency,
        )?;
        Ok(disputes::DisputePayload {
            amount,
            currency: notif.amount.currency,
            dispute_stage: api_models::enums::DisputeStage::from(notif.event_code.clone()),
            connector_dispute_id: notif.psp_reference,
            connector_reason: notif.reason,
            connector_reason_code: notif.additional_data.chargeback_reason_code,
            challenge_required_by: notif.additional_data.defense_period_ends_at,
            connector_status: notif.event_code.to_string(),
            created_at: notif.event_date,
            updated_at: notif.event_date,
        })
    }

    fn get_mandate_details(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<
        Option<hyperswitch_domain_models::router_flow_types::ConnectorMandateDetails>,
        errors::ConnectorError,
    > {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
        let mandate_reference =
            notif
                .additional_data
                .recurring_detail_reference
                .map(|mandate_id| {
                    hyperswitch_domain_models::router_flow_types::ConnectorMandateDetails {
                        connector_mandate_id: mandate_id.clone(),
                    }
                });
        Ok(mandate_reference)
    }

    fn get_network_txn_id(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<
        Option<hyperswitch_domain_models::router_flow_types::ConnectorNetworkTxnId>,
        errors::ConnectorError,
    > {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
        let optional_network_txn_id =
            notif
                .additional_data
                .network_tx_reference
                .map(|network_txn_id| {
                    hyperswitch_domain_models::router_flow_types::ConnectorNetworkTxnId::new(
                        network_txn_id,
                    )
                });
        Ok(optional_network_txn_id)
    }
}

impl Dispute for Adyen {}
impl DefendDispute for Adyen {}
impl AcceptDispute for Adyen {}
impl SubmitEvidence for Adyen {}

impl ConnectorIntegration<Accept, AcceptDisputeRequestData, AcceptDisputeResponse> for Adyen {
    fn get_headers(
        &self,
        req: &AcceptDisputeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            AcceptDisputeType::get_content_type(self).to_string().into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_url(
        &self,
        req: &AcceptDisputeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let endpoint = build_env_specific_endpoint(
            connectors.adyen.dispute_base_url.as_str(),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!(
            "{endpoint}ca/services/DisputeService/v30/acceptDispute",
        ))
    }

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

    fn handle_response(
        &self,
        data: &AcceptDisputeRouterData,
        _event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<AcceptDisputeRouterData, errors::ConnectorError> {
        let response: adyen::AdyenDisputeResponse = res
            .response
            .parse_struct("AdyenDisputeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        RouterData::foreign_try_from((data, response))
            .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<Defend, DefendDisputeRequestData, DefendDisputeResponse> for Adyen {
    fn get_headers(
        &self,
        req: &DefendDisputeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            DefendDisputeType::get_content_type(self).to_string().into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_url(
        &self,
        req: &DefendDisputeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let endpoint = build_env_specific_endpoint(
            connectors.adyen.dispute_base_url.as_str(),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!(
            "{endpoint}ca/services/DisputeService/v30/defendDispute",
        ))
    }

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

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

    fn handle_response(
        &self,
        data: &DefendDisputeRouterData,
        _event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<DefendDisputeRouterData, errors::ConnectorError> {
        let response: adyen::AdyenDisputeResponse = res
            .response
            .parse_struct("AdyenDisputeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        RouterData::foreign_try_from((data, response))
            .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<Evidence, SubmitEvidenceRequestData, SubmitEvidenceResponse> for Adyen {
    fn get_headers(
        &self,
        req: &SubmitEvidenceRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            SubmitEvidenceType::get_content_type(self)
                .to_string()
                .into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_url(
        &self,
        req: &SubmitEvidenceRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let endpoint = build_env_specific_endpoint(
            connectors.adyen.dispute_base_url.as_str(),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!(
            "{endpoint}ca/services/DisputeService/v30/supplyDefenseDocument",
        ))
    }

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

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

    fn handle_response(
        &self,
        data: &SubmitEvidenceRouterData,
        _event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<SubmitEvidenceRouterData, errors::ConnectorError> {
        let response: adyen::AdyenDisputeResponse = res
            .response
            .parse_struct("AdyenDisputeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        RouterData::foreign_try_from((data, response))
            .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 UploadFile for Adyen {}
impl RetrieveFile for Adyen {}
impl ConnectorIntegration<Retrieve, RetrieveFileRequestData, RetrieveFileResponse> for Adyen {}
impl ConnectorIntegration<Upload, UploadFileRequestData, UploadFileResponse> for Adyen {}
#[async_trait::async_trait]
impl FileUpload for Adyen {
    fn validate_file_upload(
        &self,
        purpose: FilePurpose,
        file_size: i32,
        file_type: mime::Mime,
    ) -> CustomResult<(), errors::ConnectorError> {
        match purpose {
            FilePurpose::DisputeEvidence => {
                let supported_file_types =
                    ["image/jpeg", "image/jpg", "image/png", "application/pdf"];
                if !supported_file_types.contains(&file_type.to_string().as_str()) {
                    Err(errors::ConnectorError::FileValidationFailed {
                        reason: "file_type does not match JPEG, JPG, PNG, or PDF format".to_owned(),
                    })?
                }
                //10 MB
                if (file_type.to_string().as_str() == "image/jpeg"
                    || file_type.to_string().as_str() == "image/jpg"
                    || file_type.to_string().as_str() == "image/png")
                    && file_size > 10000000
                {
                    Err(errors::ConnectorError::FileValidationFailed {
                        reason: "file_size exceeded the max file size of 10MB for Image formats"
                            .to_owned(),
                    })?
                }
                //2 MB
                if file_type.to_string().as_str() == "application/pdf" && file_size > 2000000 {
                    Err(errors::ConnectorError::FileValidationFailed {
                        reason: "file_size exceeded the max file size of 2MB for PDF formats"
                            .to_owned(),
                    })?
                }
            }
        }
        Ok(())
    }
}

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

    let supported_capture_methods2 = vec![
        enums::CaptureMethod::Automatic,
        enums::CaptureMethod::Manual,
        enums::CaptureMethod::SequentialAutomatic,
    ];

    let supported_capture_methods3 = vec![
        enums::CaptureMethod::Automatic,
        enums::CaptureMethod::SequentialAutomatic,
    ];

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

    let mut adyen_supported_payment_methods = SupportedPaymentMethods::new();

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

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

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

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

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        PaymentMethodType::Paypal,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods1.clone(),
            specific_features: None,
        },
    );

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

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

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        PaymentMethodType::GoPay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        PaymentMethodType::KakaoPay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        PaymentMethodType::Gcash,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        PaymentMethodType::Momo,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

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

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

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

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

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

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

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        PaymentMethodType::Twint,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods2.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        PaymentMethodType::Vipps,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods1.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        PaymentMethodType::Dana,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

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

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        PaymentMethodType::Klarna,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods2.clone(),
            specific_features: None,
        },
    );
    adyen_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        PaymentMethodType::Affirm,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods1.clone(),
            specific_features: None,
        },
    );
    adyen_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        PaymentMethodType::AfterpayClearpay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods1.clone(),
            specific_features: None,
        },
    );
    adyen_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        PaymentMethodType::PayBright,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods1.clone(),
            specific_features: None,
        },
    );
    adyen_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        PaymentMethodType::Walley,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods2.clone(),
            specific_features: None,
        },
    );
    adyen_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        PaymentMethodType::Alma,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods2.clone(),
            specific_features: None,
        },
    );
    adyen_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        PaymentMethodType::Atome,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::BancontactCard,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::Bizum,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::Blik,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::Eps,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::Ideal,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::OnlineBankingCzechRepublic,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::OnlineBankingFinland,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::OnlineBankingPoland,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::OnlineBankingSlovakia,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::OnlineBankingFpx,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::OnlineBankingThailand,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::OpenBankingUk,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        PaymentMethodType::Trustly,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankDebit,
        PaymentMethodType::Ach,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods2.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankDebit,
        PaymentMethodType::Sepa,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods1.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankDebit,
        PaymentMethodType::Bacs,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods2.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankTransfer,
        PaymentMethodType::PermataBankTransfer,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankTransfer,
        PaymentMethodType::BcaBankTransfer,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankTransfer,
        PaymentMethodType::BniVa,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankTransfer,
        PaymentMethodType::BriVa,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankTransfer,
        PaymentMethodType::CimbVa,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankTransfer,
        PaymentMethodType::DanamonVa,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankTransfer,
        PaymentMethodType::MandiriVa,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::BankTransfer,
        PaymentMethodType::Pix,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::CardRedirect,
        PaymentMethodType::Knet,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::CardRedirect,
        PaymentMethodType::Benefit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::CardRedirect,
        PaymentMethodType::MomoAtm,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::Boleto,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::NotSupported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::Alfamart,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::Indomaret,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::Oxxo,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::NotSupported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::SevenEleven,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::NotSupported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::Lawson,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::NotSupported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::MiniStop,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::NotSupported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::FamilyMart,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::NotSupported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::Seicomart,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::NotSupported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::Voucher,
        PaymentMethodType::PayEasy,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::NotSupported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::GiftCard,
        PaymentMethodType::PaySafeCard,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods3.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods.add(
        enums::PaymentMethod::GiftCard,
        PaymentMethodType::Givex,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods2.clone(),
            specific_features: None,
        },
    );

    adyen_supported_payment_methods
});

static ADYEN_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
        display_name: "Adyen",


// Implementation: impl ResponseError for for CustomJsonError
// File: crates/router/src/utils.rs
// Module: router
// Methods: 2 total (0 public)

impl ResponseError for for CustomJsonError