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

use api_models::analytics::payment_intents::PaymentIntentMetricsBucketValue;
use bigdecimal::ToPrimitive;
use diesel_models::enums as storage_enums;

use super::metrics::PaymentIntentMetricRow;

#[derive(Debug, Default)]
pub struct PaymentIntentMetricsAccumulator {
    pub successful_smart_retries: CountAccumulator,
    pub total_smart_retries: CountAccumulator,
    pub smart_retried_amount: SmartRetriedAmountAccumulator,
    pub payment_intent_count: CountAccumulator,
    pub payments_success_rate: PaymentsSuccessRateAccumulator,
    pub payment_processed_amount: ProcessedAmountAccumulator,
    pub payments_distribution: PaymentsDistributionAccumulator,
}

#[derive(Debug, Default)]
pub struct ErrorDistributionRow {
    pub count: i64,
    pub total: i64,
    pub error_message: String,
}

#[derive(Debug, Default)]
pub struct ErrorDistributionAccumulator {
    pub error_vec: Vec<ErrorDistributionRow>,
}

#[derive(Debug, Default)]
#[repr(transparent)]
pub struct CountAccumulator {
    pub count: Option<i64>,
}

pub trait PaymentIntentMetricAccumulator {
    type MetricOutput;

    fn add_metrics_bucket(&mut self, metrics: &PaymentIntentMetricRow);

    fn collect(self) -> Self::MetricOutput;
}

#[derive(Debug, Default)]
pub struct SmartRetriedAmountAccumulator {
    pub amount: Option<i64>,
    pub amount_without_retries: Option<i64>,
}

#[derive(Debug, Default)]
pub struct PaymentsSuccessRateAccumulator {
    pub success: u32,
    pub success_without_retries: u32,
    pub total: u32,
}

#[derive(Debug, Default)]
pub struct ProcessedAmountAccumulator {
    pub count_with_retries: Option<i64>,
    pub total_with_retries: Option<i64>,
    pub count_without_retries: Option<i64>,
    pub total_without_retries: Option<i64>,
}

#[derive(Debug, Default)]
pub struct PaymentsDistributionAccumulator {
    pub success_without_retries: u32,
    pub failed_without_retries: u32,
    pub total: u32,
}

impl PaymentIntentMetricAccumulator for CountAccumulator {
    type MetricOutput = Option<u64>;
    #[inline]
    fn add_metrics_bucket(&mut self, metrics: &PaymentIntentMetricRow) {
        self.count = match (self.count, metrics.count) {
            (None, None) => None,
            (None, i @ Some(_)) | (i @ Some(_), None) => i,
            (Some(a), Some(b)) => Some(a + b),
        }
    }
    #[inline]
    fn collect(self) -> Self::MetricOutput {
        self.count.and_then(|i| u64::try_from(i).ok())
    }
}

impl PaymentIntentMetricAccumulator for SmartRetriedAmountAccumulator {
    type MetricOutput = (Option<u64>, Option<u64>, Option<u64>, Option<u64>);
    #[inline]
    fn add_metrics_bucket(&mut self, metrics: &PaymentIntentMetricRow) {
        self.amount = match (
            self.amount,
            metrics.total.as_ref().and_then(ToPrimitive::to_i64),
        ) {
            (None, None) => None,
            (None, i @ Some(_)) | (i @ Some(_), None) => i,
            (Some(a), Some(b)) => Some(a + b),
        };
        if metrics.first_attempt.unwrap_or(0) == 1 {
            self.amount_without_retries = match (
                self.amount_without_retries,
                metrics.total.as_ref().and_then(ToPrimitive::to_i64),
            ) {
                (None, None) => None,
                (None, i @ Some(_)) | (i @ Some(_), None) => i,
                (Some(a), Some(b)) => Some(a + b),
            }
        } else {
            self.amount_without_retries = Some(0);
        }
    }
    #[inline]
    fn collect(self) -> Self::MetricOutput {
        let with_retries = self.amount.and_then(|i| u64::try_from(i).ok()).or(Some(0));
        let without_retries = self
            .amount_without_retries
            .and_then(|i| u64::try_from(i).ok())
            .or(Some(0));
        (with_retries, without_retries, Some(0), Some(0))
    }
}

impl PaymentIntentMetricAccumulator for PaymentsSuccessRateAccumulator {
    type MetricOutput = (
        Option<u32>,
        Option<u32>,
        Option<u32>,
        Option<f64>,
        Option<f64>,
    );

    fn add_metrics_bucket(&mut self, metrics: &PaymentIntentMetricRow) {
        if let Some(ref status) = metrics.status {
            if status.as_ref() == &storage_enums::IntentStatus::Succeeded {
                if let Some(success) = metrics
                    .count
                    .and_then(|success| u32::try_from(success).ok())
                {
                    self.success += success;
                    if metrics.first_attempt.unwrap_or(0) == 1 {
                        self.success_without_retries += success;
                    }
                }
            }
            if status.as_ref() != &storage_enums::IntentStatus::RequiresCustomerAction
                && status.as_ref() != &storage_enums::IntentStatus::RequiresPaymentMethod
                && status.as_ref() != &storage_enums::IntentStatus::RequiresMerchantAction
                && status.as_ref() != &storage_enums::IntentStatus::RequiresConfirmation
            {
                if let Some(total) = metrics.count.and_then(|total| u32::try_from(total).ok()) {
                    self.total += total;
                }
            }
        }
    }

    fn collect(self) -> Self::MetricOutput {
        if self.total == 0 {
            (None, None, None, None, None)
        } else {
            let success = Some(self.success);
            let success_without_retries = Some(self.success_without_retries);
            let total = Some(self.total);

            let success_rate = match (success, total) {
                (Some(s), Some(t)) if t > 0 => Some(f64::from(s) * 100.0 / f64::from(t)),
                _ => None,
            };

            let success_without_retries_rate = match (success_without_retries, total) {
                (Some(s), Some(t)) if t > 0 => Some(f64::from(s) * 100.0 / f64::from(t)),
                _ => None,
            };

            (
                success,
                success_without_retries,
                total,
                success_rate,
                success_without_retries_rate,
            )
        }
    }
}

impl PaymentIntentMetricAccumulator for ProcessedAmountAccumulator {
    type MetricOutput = (
        Option<u64>,
        Option<u64>,
        Option<u64>,
        Option<u64>,
        Option<u64>,
        Option<u64>,
    );
    #[inline]
    fn add_metrics_bucket(&mut self, metrics: &PaymentIntentMetricRow) {
        self.total_with_retries = match (
            self.total_with_retries,
            metrics.total.as_ref().and_then(ToPrimitive::to_i64),
        ) {
            (None, None) => None,
            (None, i @ Some(_)) | (i @ Some(_), None) => i,
            (Some(a), Some(b)) => Some(a + b),
        };

        self.count_with_retries = match (self.count_with_retries, metrics.count) {
            (None, None) => None,
            (None, i @ Some(_)) | (i @ Some(_), None) => i,
            (Some(a), Some(b)) => Some(a + b),
        };

        if metrics.first_attempt.unwrap_or(0) == 1 {
            self.total_without_retries = match (
                self.total_without_retries,
                metrics.total.as_ref().and_then(ToPrimitive::to_i64),
            ) {
                (None, None) => None,
                (None, i @ Some(_)) | (i @ Some(_), None) => i,
                (Some(a), Some(b)) => Some(a + b),
            };

            self.count_without_retries = match (self.count_without_retries, metrics.count) {
                (None, None) => None,
                (None, i @ Some(_)) | (i @ Some(_), None) => i,
                (Some(a), Some(b)) => Some(a + b),
            };
        }
    }
    #[inline]
    fn collect(self) -> Self::MetricOutput {
        let total_with_retries = u64::try_from(self.total_with_retries.unwrap_or(0)).ok();
        let count_with_retries = self.count_with_retries.and_then(|i| u64::try_from(i).ok());

        let total_without_retries = u64::try_from(self.total_without_retries.unwrap_or(0)).ok();
        let count_without_retries = self
            .count_without_retries
            .and_then(|i| u64::try_from(i).ok());

        (
            total_with_retries,
            count_with_retries,
            total_without_retries,
            count_without_retries,
            Some(0),
            Some(0),
        )
    }
}

impl PaymentIntentMetricAccumulator for PaymentsDistributionAccumulator {
    type MetricOutput = (Option<f64>, Option<f64>);

    fn add_metrics_bucket(&mut self, metrics: &PaymentIntentMetricRow) {
        let first_attempt = metrics.first_attempt.unwrap_or(0);
        if let Some(ref status) = metrics.status {
            if status.as_ref() == &storage_enums::IntentStatus::Succeeded {
                if let Some(success) = metrics
                    .count
                    .and_then(|success| u32::try_from(success).ok())
                {
                    if first_attempt == 1 {
                        self.success_without_retries += success;
                    }
                }
            }
            if let Some(failed) = metrics.count.and_then(|failed| u32::try_from(failed).ok()) {
                if first_attempt == 0
                    || (first_attempt == 1
                        && status.as_ref() == &storage_enums::IntentStatus::Failed)
                {
                    self.failed_without_retries += failed;
                }
            }

            if status.as_ref() != &storage_enums::IntentStatus::RequiresCustomerAction
                && status.as_ref() != &storage_enums::IntentStatus::RequiresPaymentMethod
                && status.as_ref() != &storage_enums::IntentStatus::RequiresMerchantAction
                && status.as_ref() != &storage_enums::IntentStatus::RequiresConfirmation
            {
                if let Some(total) = metrics.count.and_then(|total| u32::try_from(total).ok()) {
                    self.total += total;
                }
            }
        }
    }

    fn collect(self) -> Self::MetricOutput {
        if self.total == 0 {
            (None, None)
        } else {
            let success_without_retries = Some(self.success_without_retries);
            let failed_without_retries = Some(self.failed_without_retries);
            let total = Some(self.total);

            let success_rate_without_retries = match (success_without_retries, total) {
                (Some(s), Some(t)) if t > 0 => Some(f64::from(s) * 100.0 / f64::from(t)),
                _ => None,
            };

            let failed_rate_without_retries = match (failed_without_retries, total) {
                (Some(s), Some(t)) if t > 0 => Some(f64::from(s) * 100.0 / f64::from(t)),
                _ => None,
            };
            (success_rate_without_retries, failed_rate_without_retries)
        }
    }
}

impl PaymentIntentMetricsAccumulator {
    pub fn collect(self) -> PaymentIntentMetricsBucketValue {
        let (
            successful_payments,
            successful_payments_without_smart_retries,
            total_payments,
            payments_success_rate,
            payments_success_rate_without_smart_retries,
        ) = self.payments_success_rate.collect();
        let (
            smart_retried_amount,
            smart_retried_amount_without_smart_retries,
            smart_retried_amount_in_usd,
            smart_retried_amount_without_smart_retries_in_usd,
        ) = self.smart_retried_amount.collect();
        let (
            payment_processed_amount,
            payment_processed_count,
            payment_processed_amount_without_smart_retries,
            payment_processed_count_without_smart_retries,
            payment_processed_amount_in_usd,
            payment_processed_amount_without_smart_retries_in_usd,
        ) = self.payment_processed_amount.collect();
        let (
            payments_success_rate_distribution_without_smart_retries,
            payments_failure_rate_distribution_without_smart_retries,
        ) = self.payments_distribution.collect();
        PaymentIntentMetricsBucketValue {
            successful_smart_retries: self.successful_smart_retries.collect(),
            total_smart_retries: self.total_smart_retries.collect(),
            smart_retried_amount,
            smart_retried_amount_in_usd,
            smart_retried_amount_without_smart_retries,
            smart_retried_amount_without_smart_retries_in_usd,
            payment_intent_count: self.payment_intent_count.collect(),
            successful_payments,
            successful_payments_without_smart_retries,
            total_payments,
            payments_success_rate,
            payments_success_rate_without_smart_retries,
            payment_processed_amount,
            payment_processed_count,
            payment_processed_amount_without_smart_retries,
            payment_processed_count_without_smart_retries,
            payments_success_rate_distribution_without_smart_retries,
            payments_failure_rate_distribution_without_smart_retries,
            payment_processed_amount_in_usd,
            payment_processed_amount_without_smart_retries_in_usd,
        }
    }
}


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

impl api::Refund for for Nexinets


// Struct: NoonSubscriptionObject
// File: crates/hyperswitch_connectors/src/connectors/noon/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NoonSubscriptionObject


// Function: number_comparison_array_value
// File: crates/euclid/src/frontend/ast/parser.rs
// Module: euclid

pub fn number_comparison_array_value(input: &str) -> ParseResult<&str, ast::ValueType>


// File: crates/common_utils/tests/percentage.rs
// Module: common_utils

#![allow(clippy::panic_in_result_fn)]
use common_utils::{errors::PercentageError, types::Percentage};
const PRECISION_2: u8 = 2;
const PRECISION_0: u8 = 0;

#[test]
fn invalid_range_more_than_100() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let percentage = Percentage::<PRECISION_2>::from_string("100.01".to_string());
    assert!(percentage.is_err());
    if let Err(err) = percentage {
        assert_eq!(
            *err.current_context(),
            PercentageError::InvalidPercentageValue
        )
    }
    Ok(())
}
#[test]
fn invalid_range_less_than_0() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let percentage = Percentage::<PRECISION_2>::from_string("-0.01".to_string());
    assert!(percentage.is_err());
    if let Err(err) = percentage {
        assert_eq!(
            *err.current_context(),
            PercentageError::InvalidPercentageValue
        )
    }
    Ok(())
}

#[test]
fn invalid_string() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let percentage = Percentage::<PRECISION_2>::from_string("-0.01ed".to_string());
    assert!(percentage.is_err());
    if let Err(err) = percentage {
        assert_eq!(
            *err.current_context(),
            PercentageError::InvalidPercentageValue
        )
    }
    Ok(())
}

#[test]
fn valid_range() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let percentage = Percentage::<PRECISION_2>::from_string("2.22".to_string());
    assert!(percentage.is_ok());
    if let Ok(percentage) = percentage {
        assert_eq!(percentage.get_percentage(), 2.22)
    }

    let percentage = Percentage::<PRECISION_2>::from_string("0.05".to_string());
    assert!(percentage.is_ok());
    if let Ok(percentage) = percentage {
        assert_eq!(percentage.get_percentage(), 0.05)
    }

    let percentage = Percentage::<PRECISION_2>::from_string("100.0".to_string());
    assert!(percentage.is_ok());
    if let Ok(percentage) = percentage {
        assert_eq!(percentage.get_percentage(), 100.0)
    }
    Ok(())
}
#[test]
fn valid_precision() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let percentage = Percentage::<PRECISION_2>::from_string("2.2".to_string());
    assert!(percentage.is_ok());
    if let Ok(percentage) = percentage {
        assert_eq!(percentage.get_percentage(), 2.2)
    }

    let percentage = Percentage::<PRECISION_2>::from_string("2.20000".to_string());
    assert!(percentage.is_ok());
    if let Ok(percentage) = percentage {
        assert_eq!(percentage.get_percentage(), 2.2)
    }

    let percentage = Percentage::<PRECISION_0>::from_string("2.0".to_string());
    assert!(percentage.is_ok());
    if let Ok(percentage) = percentage {
        assert_eq!(percentage.get_percentage(), 2.0)
    }

    Ok(())
}

#[test]
fn invalid_precision() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let percentage = Percentage::<PRECISION_2>::from_string("2.221".to_string());
    assert!(percentage.is_err());
    if let Err(err) = percentage {
        assert_eq!(
            *err.current_context(),
            PercentageError::InvalidPercentageValue
        )
    }
    Ok(())
}

#[test]
fn deserialization_test_ok() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let mut decimal = 0;
    let mut integer = 0;
    // check for all percentage values from 0 to 100
    while integer <= 100 {
        let json_string = format!(
            r#"
            {{
                "percentage" : {integer}.{decimal}
            }}
        "#,
        );
        let percentage = serde_json::from_str::<Percentage<PRECISION_2>>(&json_string);
        assert!(percentage.is_ok());
        if let Ok(percentage) = percentage {
            assert_eq!(
                percentage.get_percentage(),
                format!("{integer}.{decimal}")
                    .parse::<f32>()
                    .unwrap_or_default()
            )
        }
        if integer == 100 {
            break;
        }
        decimal += 1;
        if decimal == 100 {
            decimal = 0;
            integer += 1;
        }
    }

    let json_string = r#"
        {
            "percentage" : 18.7
        }
    "#;
    let percentage = serde_json::from_str::<Percentage<PRECISION_2>>(json_string);
    assert!(percentage.is_ok());
    if let Ok(percentage) = percentage {
        assert_eq!(percentage.get_percentage(), 18.7)
    }

    let json_string = r#"
        {
            "percentage" : 12.0
        }
    "#;
    let percentage = serde_json::from_str::<Percentage<PRECISION_0>>(json_string);
    assert!(percentage.is_ok());
    if let Ok(percentage) = percentage {
        assert_eq!(percentage.get_percentage(), 12.0)
    }
    Ok(())
}

#[test]
fn deserialization_test_err() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    // invalid percentage precision
    let json_string = r#"
        {
            "percentage" : 12.4
        }
    "#;
    let percentage = serde_json::from_str::<Percentage<PRECISION_0>>(json_string);
    assert!(percentage.is_err());
    if let Err(err) = percentage {
        assert_eq!(err.to_string(), "invalid value: percentage value 12.4, expected value should be a float between 0 to 100 and precise to only upto 0 decimal digits at line 4 column 9".to_string())
    }

    // invalid percentage value
    let json_string = r#"
        {
            "percentage" : 123.42
        }
    "#;
    let percentage = serde_json::from_str::<Percentage<PRECISION_2>>(json_string);
    assert!(percentage.is_err());
    if let Err(err) = percentage {
        assert_eq!(err.to_string(), "invalid value: percentage value 123.42, expected value should be a float between 0 to 100 and precise to only upto 2 decimal digits at line 4 column 9".to_string())
    }

    // missing percentage field
    let json_string = r#"
        {
            "percent": 22.0
        }
    "#;
    let percentage = serde_json::from_str::<Percentage<PRECISION_2>>(json_string);
    assert!(percentage.is_err());
    if let Err(err) = percentage {
        assert_eq!(
            err.to_string(),
            "missing field `percentage` at line 4 column 9".to_string()
        )
    }
    Ok(())
}


// Implementation: impl RedisStore
// File: crates/storage_impl/src/redis.rs
// Module: storage_impl
// Methods: 2 total (1 public)

impl RedisStore


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

pub struct AlfamartVoucherData


// Struct: ReasonsResult
// File: crates/api_models/src/analytics/refunds.rs
// Module: api_models
// Implementations: 0

pub struct ReasonsResult


// Function: default_payment_method_set_api
// File: crates/openapi/src/routes/payment_method.rs
// Module: openapi

pub fn default_payment_method_set_api()


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

pub struct AciRefundResponse


// Struct: ChargebeeCustomerCreateRequest
// File: crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ChargebeeCustomerCreateRequest


// Implementation: impl ConnectorTypeAndConnectorName
// File: crates/router/src/core/admin.rs
// Module: router
// Methods: 1 total (0 public)

impl ConnectorTypeAndConnectorName


// File: crates/hyperswitch_domain_models/src/router_flow_types/vault.rs
// Module: hyperswitch_domain_models
// Public structs: 4

#[derive(Debug, Clone)]
pub struct ExternalVaultInsertFlow;

#[derive(Debug, Clone)]
pub struct ExternalVaultRetrieveFlow;

#[derive(Debug, Clone)]
pub struct ExternalVaultDeleteFlow;

#[derive(Debug, Clone)]
pub struct ExternalVaultCreateFlow;


// Struct: UserMerchantCreate
// File: crates/api_models/src/user.rs
// Module: api_models
// Implementations: 0

pub struct UserMerchantCreate


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

pub fn mk_app(
    state: AppState,
    request_body_limit: usize,
) -> actix_web::App<
    impl ServiceFactory<
        ServiceRequest,
        Config = (),
        Response = actix_web::dev::ServiceResponse<impl MessageBody>,
        Error = actix_web::Error,
        InitError = (),
    >,
>


// Implementation: impl Responder
// File: crates/router/src/analytics.rs
// Module: router
// Methods: 0 total (0 public)

impl Responder


// Struct: PaymentFlowData
// File: crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct PaymentFlowData


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

pub struct PaymentReceipt


// Function: get_id
// File: crates/diesel_models/src/merchant_connector_account.rs
// Module: diesel_models

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


// Struct: SubmitSinglePaymentResult
// File: crates/hyperswitch_connectors/src/connectors/bamboraapac/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct SubmitSinglePaymentResult


// Implementation: impl TransactionType
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl TransactionType


// Struct: DeleteEvidenceRequest
// File: crates/api_models/src/disputes.rs
// Module: api_models
// Implementations: 0

pub struct DeleteEvidenceRequest


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

impl api::MandateSetup for for Nexixpay


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

impl RequestPaymentMethodTypes


// Implementation: impl PaymentMetricAccumulator for for RetriesAmountAccumulator
// File: crates/analytics/src/payments/accumulator.rs
// Module: analytics
// Methods: 2 total (0 public)

impl PaymentMetricAccumulator for for RetriesAmountAccumulator


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

pub struct CryptoRequest


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

pub fn external_authentication_update_trackers<F: Clone, Req>(
    state: &SessionState,
    router_data: RouterData<F, Req, UasAuthenticationResponseData>,
    authentication: diesel_models::authentication::Authentication,
    acquirer_details: Option<
        hyperswitch_domain_models::router_request_types::authentication::AcquirerDetails,
    >,
    merchant_key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
    billing_address: Option<common_utils::encryption::Encryption>,
    shipping_address: Option<common_utils::encryption::Encryption>,
    email: Option<common_utils::encryption::Encryption>,
    browser_info: Option<serde_json::Value>,
) -> RouterResult<diesel_models::authentication::Authentication>


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

pub struct AdyenTransferResponse


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

impl Bankofamerica


// Function: save_card_and_network_token_in_locker
// File: crates/router/src/core/payments/tokenization.rs
// Module: router

pub fn save_card_and_network_token_in_locker(
    state: &SessionState,
    customer_id: id_type::CustomerId,
    payment_method_status: common_enums::PaymentMethodStatus,
    payment_method_data: domain::PaymentMethodData,
    vault_operation: Option<hyperswitch_domain_models::payments::VaultOperation>,
    payment_method_info: Option<domain::PaymentMethod>,
    merchant_context: &domain::MerchantContext,
    payment_method_create_request: api::PaymentMethodCreate,
    is_network_tokenization_enabled: bool,
    business_profile: &domain::Profile,
) -> RouterResult<(
    (
        api_models::payment_methods::PaymentMethodResponse,
        Option<payment_methods::transformers::DataDuplicationCheck>,
        Option<String>,
    ),
    Option<api_models::payment_methods::PaymentMethodResponse>,
)>


// Struct: MpgsRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/mpgs/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MpgsRefundRequest


// Struct: TesouroRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/tesouro/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TesouroRefundRequest


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

pub fn get_all_connectors() -> JsResult


// Struct: NoParams
// File: crates/hyperswitch_domain_models/src/connector_endpoints.rs
// Module: hyperswitch_domain_models
// Implementations: 1

pub struct NoParams


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

pub struct TrustpayRefundRequestCards


// Implementation: impl api::ConnectorAccessToken for for Fiservemea
// File: crates/hyperswitch_connectors/src/connectors/fiservemea.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ConnectorAccessToken for for Fiservemea


// File: crates/scheduler/src/lib.rs
// Module: scheduler

pub mod configs;
pub mod consumer;
pub mod db;
pub mod env;
pub mod errors;
pub mod flow;
pub mod metrics;
pub mod producer;
pub mod scheduler;
pub mod settings;
pub mod utils;

pub use self::{consumer::types, flow::*, scheduler::*};


// Struct: BamboraapacRefundsResponse
// File: crates/hyperswitch_connectors/src/connectors/bamboraapac/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BamboraapacRefundsResponse


// Implementation: impl api::PaymentSync for for Juspaythreedsserver
// File: crates/hyperswitch_connectors/src/connectors/juspaythreedsserver.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSync for for Juspaythreedsserver


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

pub struct CybersourcePaymentsRequest


// Trait: PaymentDistributionAnalytics
// File: crates/analytics/src/payments/distribution.rs
// Module: analytics

pub trait PaymentDistributionAnalytics: LoadRow<PaymentDistributionRow>


// Struct: FiuuRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/fiuu/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FiuuRefundRequest


// Struct: SdkEventsResult
// File: crates/analytics/src/sdk_events/events.rs
// Module: analytics
// Implementations: 0

pub struct SdkEventsResult


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

impl api::PaymentCapture for for Paypal


// Struct: ElavonRouterData
// File: crates/hyperswitch_connectors/src/connectors/elavon/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ElavonRouterData<T>


// File: crates/common_utils/src/payout_method_utils.rs
// Module: common_utils
// Public structs: 7

//! This module has common utilities for payout method data in HyperSwitch

use common_enums;
use diesel::{sql_types::Jsonb, AsExpression, FromSqlRow};
use masking::Secret;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use crate::new_type::{
    MaskedBankAccount, MaskedBic, MaskedEmail, MaskedIban, MaskedPhoneNumber, MaskedRoutingNumber,
    MaskedSortCode,
};

/// Masked payout method details for storing in db
#[derive(
    Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
pub enum AdditionalPayoutMethodData {
    /// Additional data for card payout method
    Card(Box<CardAdditionalData>),
    /// Additional data for bank payout method
    Bank(Box<BankAdditionalData>),
    /// Additional data for wallet payout method
    Wallet(Box<WalletAdditionalData>),
}

crate::impl_to_sql_from_sql_json!(AdditionalPayoutMethodData);

/// Masked payout method details for card payout method
#[derive(
    Eq, PartialEq, Clone, Debug, Serialize, Deserialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
pub struct CardAdditionalData {
    /// Issuer of the card
    pub card_issuer: Option<String>,

    /// Card network of the card
    #[schema(value_type = Option<CardNetwork>)]
    pub card_network: Option<common_enums::CardNetwork>,

    /// Card type, can be either `credit` or `debit`
    pub card_type: Option<String>,

    /// Card issuing country
    pub card_issuing_country: Option<String>,

    /// Code for Card issuing bank
    pub bank_code: Option<String>,

    /// Last 4 digits of the card number
    pub last4: Option<String>,

    /// The ISIN of the card
    pub card_isin: Option<String>,

    /// Extended bin of card, contains the first 8 digits of card number
    pub card_extended_bin: Option<String>,

    /// Card expiry month
    #[schema(value_type = String, example = "01")]
    pub card_exp_month: Option<Secret<String>>,

    /// Card expiry year
    #[schema(value_type = String, example = "2026")]
    pub card_exp_year: Option<Secret<String>>,

    /// Card holder name
    #[schema(value_type = String, example = "John Doe")]
    pub card_holder_name: Option<Secret<String>>,
}

/// Masked payout method details for bank payout method
#[derive(
    Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
#[serde(untagged)]
pub enum BankAdditionalData {
    /// Additional data for ach bank transfer payout method
    Ach(Box<AchBankTransferAdditionalData>),
    /// Additional data for bacs bank transfer payout method
    Bacs(Box<BacsBankTransferAdditionalData>),
    /// Additional data for sepa bank transfer payout method
    Sepa(Box<SepaBankTransferAdditionalData>),
    /// Additional data for pix bank transfer payout method
    Pix(Box<PixBankTransferAdditionalData>),
}

/// Masked payout method details for ach bank transfer payout method
#[derive(
    Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
pub struct AchBankTransferAdditionalData {
    /// Partially masked account number for ach bank debit payment
    #[schema(value_type = String, example = "0001****3456")]
    pub bank_account_number: MaskedBankAccount,

    /// Partially masked routing number for ach bank debit payment
    #[schema(value_type = String, example = "110***000")]
    pub bank_routing_number: MaskedRoutingNumber,

    /// Name of the bank
    #[schema(value_type = Option<BankNames>, example = "Deutsche Bank")]
    pub bank_name: Option<String>,

    /// Bank country code
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub bank_country_code: Option<common_enums::CountryAlpha2>,

    /// Bank city
    #[schema(value_type = Option<String>, example = "California")]
    pub bank_city: Option<String>,
}

/// Masked payout method details for bacs bank transfer payout method
#[derive(
    Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
pub struct BacsBankTransferAdditionalData {
    /// Partially masked sort code for Bacs payment method
    #[schema(value_type = String, example = "108800")]
    pub bank_sort_code: MaskedSortCode,

    /// Bank account's owner name
    #[schema(value_type = String, example = "0001****3456")]
    pub bank_account_number: MaskedBankAccount,

    /// Bank name
    #[schema(value_type = Option<String>, example = "Deutsche Bank")]
    pub bank_name: Option<String>,

    /// Bank country code
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub bank_country_code: Option<common_enums::CountryAlpha2>,

    /// Bank city
    #[schema(value_type = Option<String>, example = "California")]
    pub bank_city: Option<String>,
}

/// Masked payout method details for sepa bank transfer payout method
#[derive(
    Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
pub struct SepaBankTransferAdditionalData {
    /// Partially masked international bank account number (iban) for SEPA
    #[schema(value_type = String, example = "DE8937******013000")]
    pub iban: MaskedIban,

    /// Bank name
    #[schema(value_type = Option<String>, example = "Deutsche Bank")]
    pub bank_name: Option<String>,

    /// Bank country code
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub bank_country_code: Option<common_enums::CountryAlpha2>,

    /// Bank city
    #[schema(value_type = Option<String>, example = "California")]
    pub bank_city: Option<String>,

    /// [8 / 11 digits] Bank Identifier Code (bic) / Swift Code - used in many countries for identifying a bank and it's branches
    #[schema(value_type = Option<String>, example = "HSBCGB2LXXX")]
    pub bic: Option<MaskedBic>,
}

/// Masked payout method details for pix bank transfer payout method
#[derive(
    Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
pub struct PixBankTransferAdditionalData {
    /// Partially masked unique key for pix transfer
    #[schema(value_type = String, example = "a1f4102e ****** 6fa48899c1d1")]
    pub pix_key: MaskedBankAccount,

    /// Partially masked CPF - CPF is a Brazilian tax identification number
    #[schema(value_type = Option<String>, example = "**** 124689")]
    pub tax_id: Option<MaskedBankAccount>,

    /// Bank account number is an unique identifier assigned by a bank to a customer.
    #[schema(value_type = String, example = "**** 23456")]
    pub bank_account_number: MaskedBankAccount,

    /// Bank name
    #[schema(value_type = Option<String>, example = "Deutsche Bank")]
    pub bank_name: Option<String>,

    /// Bank branch
    #[schema(value_type = Option<String>, example = "3707")]
    pub bank_branch: Option<String>,
}

/// Masked payout method details for wallet payout method
#[derive(
    Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
#[serde(untagged)]
pub enum WalletAdditionalData {
    /// Additional data for paypal wallet payout method
    Paypal(Box<PaypalAdditionalData>),
    /// Additional data for venmo wallet payout method
    Venmo(Box<VenmoAdditionalData>),
}

/// Masked payout method details for paypal wallet payout method
#[derive(
    Default, Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
pub struct PaypalAdditionalData {
    /// Email linked with paypal account
    #[schema(value_type = Option<String>, example = "john.doe@example.com")]
    pub email: Option<MaskedEmail>,

    /// mobile number linked to paypal account
    #[schema(value_type = Option<String>, example = "******* 3349")]
    pub telephone_number: Option<MaskedPhoneNumber>,

    /// id of the paypal account
    #[schema(value_type = Option<String>, example = "G83K ***** HCQ2")]
    pub paypal_id: Option<MaskedBankAccount>,
}

/// Masked payout method details for venmo wallet payout method
#[derive(
    Default, Eq, PartialEq, Clone, Debug, Deserialize, Serialize, FromSqlRow, AsExpression, ToSchema,
)]
#[diesel(sql_type = Jsonb)]
pub struct VenmoAdditionalData {
    /// mobile number linked to venmo account
    #[schema(value_type = Option<String>, example = "******* 3349")]
    pub telephone_number: Option<MaskedPhoneNumber>,
}


// Struct: OutgoingWebhookLogsResult
// File: crates/analytics/src/outgoing_webhook_event/events.rs
// Module: analytics
// Implementations: 0

pub struct OutgoingWebhookLogsResult


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

pub fn signin_token_only_flow(
    state: SessionState,
    request: user_api::SignInRequest,
) -> UserResponse<user_api::TokenResponse>


// Struct: FrmRouterData
// File: crates/router/src/types/fraud_check.rs
// Module: router
// Implementations: 0

pub struct FrmRouterData


// Struct: Worldpay
// File: crates/hyperswitch_connectors/src/connectors/worldpay.rs
// Module: hyperswitch_connectors
// Implementations: 19
// Traits: ConnectorCommon, ConnectorValidation, api::Payment, api::MandateSetup, api::PaymentToken, api::PaymentVoid, api::ConnectorAccessToken, api::PaymentSync, api::PaymentCapture, api::PaymentSession, api::PaymentAuthorize, api::PaymentsCompleteAuthorize, api::Refund, api::RefundExecute, api::RefundSync, IncomingWebhook, ConnectorRedirectResponse, ConnectorSpecifications

pub struct Worldpay

ConnectorCommon ConnectorValidation api::Payment api::MandateSetup api::PaymentToken api::PaymentVoid api::ConnectorAccessToken api::PaymentSync api::PaymentCapture api::PaymentSession api::PaymentAuthorize api::PaymentsCompleteAuthorize api::Refund api::RefundExecute api::RefundSync IncomingWebhook ConnectorRedirectResponse ConnectorSpecifications


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

impl ConnectorSpecifications for for Juspaythreedsserver


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

impl api::ConnectorAccessToken for for Bamboraapac


// File: crates/diesel_models/src/query/user_key_store.rs
// Module: diesel_models
// Public functions: 3

use diesel::{associations::HasTable, ExpressionMethods};

use super::generics;
use crate::{
    schema::user_key_store::dsl,
    user_key_store::{UserKeyStore, UserKeyStoreNew},
    PgPooledConn, StorageResult,
};

impl UserKeyStoreNew {
    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<UserKeyStore> {
        generics::generic_insert(conn, self).await
    }
}

impl UserKeyStore {
    pub async fn get_all_user_key_stores(
        conn: &PgPooledConn,
        from: u32,
        limit: u32,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<
            <Self as HasTable>::Table,
            _,
            <<Self as HasTable>::Table as diesel::Table>::PrimaryKey,
            _,
        >(
            conn,
            dsl::user_id.ne_all(vec!["".to_string()]),
            Some(limit.into()),
            Some(from.into()),
            None,
        )
        .await
    }

    pub async fn find_by_user_id(conn: &PgPooledConn, user_id: &str) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::user_id.eq(user_id.to_owned()),
        )
        .await
    }
}


// Implementation: impl api::PaymentSync for for Payme
// File: crates/hyperswitch_connectors/src/connectors/payme.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSync for for Payme


// Function: connector_retrieve
// File: crates/openapi/src/routes/merchant_connector_account.rs
// Module: openapi

pub fn connector_retrieve()


// Implementation: impl FrmMetricsAccumulator
// File: crates/analytics/src/frm/accumulator.rs
// Module: analytics
// Methods: 1 total (1 public)

impl FrmMetricsAccumulator


// Struct: NetceteraAuthenticationFailureResponse
// File: crates/hyperswitch_connectors/src/connectors/netcetera/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NetceteraAuthenticationFailureResponse


// Struct: CardTransactionRequest
// File: crates/hyperswitch_connectors/src/connectors/facilitapay/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CardTransactionRequest


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

pub fn is_key_not_deleted(&self) -> bool


// Struct: CsvParsingResult
// File: crates/api_models/src/revenue_recovery_data_backfill.rs
// Module: api_models
// Implementations: 1
// Traits: ApiEventMetric

pub struct CsvParsingResult


// File: crates/hyperswitch_connectors/src/connectors/juspaythreedsserver/transformers.rs
// Module: hyperswitch_connectors
// Public structs: 8

use common_enums::enums;
use common_utils::types::StringMinorUnit;
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{ConnectorAuthType, RouterData},
    router_flow_types::refunds::{Execute, RSync},
    router_request_types::ResponseId,
    router_response_types::{PaymentsResponseData, RefundsResponseData},
    types::{PaymentsAuthorizeRouterData, RefundsRouterData},
};
use hyperswitch_interfaces::errors;
use masking::Secret;
use serde::{Deserialize, Serialize};

use crate::{
    types::{RefundsResponseRouterData, ResponseRouterData},
    utils::PaymentsAuthorizeRequestData,
};

//TODO: Fill the struct with respective fields
pub struct JuspaythreedsserverRouterData<T> {
    pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
    pub router_data: T,
}

impl<T> From<(StringMinorUnit, T)> for JuspaythreedsserverRouterData<T> {
    fn from((amount, item): (StringMinorUnit, T)) -> Self {
        //Todo :  use utils to convert the amount to the type of amount that a connector accepts
        Self {
            amount,
            router_data: item,
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, PartialEq)]
pub struct JuspaythreedsserverPaymentsRequest {
    amount: StringMinorUnit,
    card: JuspaythreedsserverCard,
}

#[derive(Default, Debug, Serialize, Eq, PartialEq)]
pub struct JuspaythreedsserverCard {
    number: cards::CardNumber,
    expiry_month: Secret<String>,
    expiry_year: Secret<String>,
    cvc: Secret<String>,
    complete: bool,
}

impl TryFrom<&JuspaythreedsserverRouterData<&PaymentsAuthorizeRouterData>>
    for JuspaythreedsserverPaymentsRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &JuspaythreedsserverRouterData<&PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        match item.router_data.request.payment_method_data.clone() {
            PaymentMethodData::Card(req_card) => {
                let card = JuspaythreedsserverCard {
                    number: req_card.card_number,
                    expiry_month: req_card.card_exp_month,
                    expiry_year: req_card.card_exp_year,
                    cvc: req_card.card_cvc,
                    complete: item.router_data.request.is_auto_capture()?,
                };
                Ok(Self {
                    amount: item.amount.clone(),
                    card,
                })
            }
            _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()),
        }
    }
}

//TODO: Fill the struct with respective fields
// Auth Struct
pub struct JuspaythreedsserverAuthType {
    pub(super) api_key: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for JuspaythreedsserverAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
                api_key: api_key.to_owned(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}
// PaymentsResponse
//TODO: Append the remaining status flags
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum JuspaythreedsserverPaymentStatus {
    Succeeded,
    Failed,
    #[default]
    Processing,
}

impl From<JuspaythreedsserverPaymentStatus> for common_enums::AttemptStatus {
    fn from(item: JuspaythreedsserverPaymentStatus) -> Self {
        match item {
            JuspaythreedsserverPaymentStatus::Succeeded => Self::Charged,
            JuspaythreedsserverPaymentStatus::Failed => Self::Failure,
            JuspaythreedsserverPaymentStatus::Processing => Self::Authorizing,
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct JuspaythreedsserverPaymentsResponse {
    status: JuspaythreedsserverPaymentStatus,
    id: String,
}

impl<F, T>
    TryFrom<ResponseRouterData<F, JuspaythreedsserverPaymentsResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, JuspaythreedsserverPaymentsResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            status: common_enums::AttemptStatus::from(item.response.status),
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(item.response.id),
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: None,
                incremental_authorization_allowed: None,
                charges: None,
            }),
            ..item.data
        })
    }
}

//TODO: Fill the struct with respective fields
// REFUND :
// Type definition for RefundRequest
#[derive(Default, Debug, Serialize)]
pub struct JuspaythreedsserverRefundRequest {
    pub amount: StringMinorUnit,
}

impl<F> TryFrom<&JuspaythreedsserverRouterData<&RefundsRouterData<F>>>
    for JuspaythreedsserverRefundRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &JuspaythreedsserverRouterData<&RefundsRouterData<F>>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            amount: item.amount.to_owned(),
        })
    }
}

// Type definition for Refund Response

#[allow(dead_code)]
#[derive(Debug, Serialize, Default, Deserialize, Clone)]
pub enum RefundStatus {
    Succeeded,
    Failed,
    #[default]
    Processing,
}

impl From<RefundStatus> for enums::RefundStatus {
    fn from(item: RefundStatus) -> Self {
        match item {
            RefundStatus::Succeeded => Self::Success,
            RefundStatus::Failed => Self::Failure,
            RefundStatus::Processing => Self::Pending,
            //TODO: Review mapping
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct RefundResponse {
    id: String,
    status: RefundStatus,
}

impl TryFrom<RefundsResponseRouterData<Execute, RefundResponse>> for RefundsRouterData<Execute> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<Execute, RefundResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.id.to_string(),
                refund_status: enums::RefundStatus::from(item.response.status),
            }),
            ..item.data
        })
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, RefundResponse>> for RefundsRouterData<RSync> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<RSync, RefundResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.id.to_string(),
                refund_status: enums::RefundStatus::from(item.response.status),
            }),
            ..item.data
        })
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct JuspaythreedsserverErrorResponse {
    pub status_code: u16,
    pub code: String,
    pub message: String,
    pub reason: Option<String>,
}


// Implementation: impl ConnectorPreAuthenticationVersionCall for for Netcetera
// File: crates/hyperswitch_connectors/src/connectors/netcetera.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl ConnectorPreAuthenticationVersionCall for for Netcetera


// Struct: FacilitapayAuthRequest
// File: crates/hyperswitch_connectors/src/connectors/facilitapay/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FacilitapayAuthRequest


// Struct: CardTestingGuardConfig
// File: crates/api_models/src/admin.rs
// Module: api_models
// Implementations: 0

pub struct CardTestingGuardConfig


// Struct: ConfigNew
// File: crates/diesel_models/src/configs.rs
// Module: diesel_models
// Implementations: 0

pub struct ConfigNew


// Struct: MollieCardTokenResponse
// File: crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MollieCardTokenResponse


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

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


            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
        }

        let key_manager_state = &(&state.session_state()).into();

        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;

        let auth = AuthenticationDataWithoutProfile {
            merchant_account: merchant,
            key_store,
        };

        Ok((
            auth,
            AuthenticationType::MerchantJwt {
                merchant_id: payload.merchant_id,
                user_id: Some(payload.user_id),
            },
        ))
    }
}

#[async_trait]
impl<A> AuthenticateAndFetch<(), A> for JWTAuthMerchantFromRoute
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<((), AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.required_permission, &role_info)?;

        // Check if token has access to MerchantId that has been requested through query param
        if payload.merchant_id != self.merchant_id {
            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
        }
        Ok((
            (),
            AuthenticationType::MerchantJwt {
                merchant_id: payload.merchant_id,
                user_id: Some(payload.user_id),
            },
        ))
    }
}

#[cfg(feature = "v1")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationData, A> for JWTAuthMerchantFromRoute
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        if payload.merchant_id != self.merchant_id {
            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
        }

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.required_permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;

        let auth = AuthenticationData {
            merchant_account: merchant,
            platform_merchant_account: None,
            key_store,
            profile_id: Some(payload.profile_id),
        };
        Ok((
            auth.clone(),
            AuthenticationType::MerchantJwt {
                merchant_id: auth.merchant_account.get_id().clone(),
                user_id: Some(payload.user_id),
            },
        ))
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationData, A> for JWTAuthMerchantFromRoute
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        let profile_id =
            get_id_type_by_key_from_headers(headers::X_PROFILE_ID.to_string(), request_headers)?
                .get_required_value(headers::X_PROFILE_ID)?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }

        if payload.merchant_id != self.merchant_id {
            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
        }

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.required_permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;
        let profile = state
            .store()
            .find_business_profile_by_merchant_id_profile_id(
                key_manager_state,
                &key_store,
                &payload.merchant_id,
                &profile_id,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;

        let auth = AuthenticationData {
            merchant_account: merchant,
            key_store,
            profile,
            platform_merchant_account: None,
        };
        Ok((
            auth.clone(),
            AuthenticationType::MerchantJwt {
                merchant_id: auth.merchant_account.get_id().clone(),
                user_id: Some(payload.user_id),
            },
        ))
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationDataWithoutProfile, A> for JWTAuthMerchantFromRoute
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationDataWithoutProfile, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;

        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }

        if payload.merchant_id != self.merchant_id {
            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
        }

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.required_permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;

        let auth = AuthenticationDataWithoutProfile {
            merchant_account: merchant,
            key_store,
        };
        Ok((
            auth.clone(),
            AuthenticationType::MerchantJwt {
                merchant_id: auth.merchant_account.get_id().clone(),
                user_id: Some(payload.user_id),
            },
        ))
    }
}

pub struct JWTAuthMerchantAndProfileFromRoute {
    pub merchant_id: id_type::MerchantId,
    pub profile_id: id_type::ProfileId,
    pub required_permission: Permission,
}

#[cfg(feature = "v1")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationData, A> for JWTAuthMerchantAndProfileFromRoute
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        if payload.merchant_id != self.merchant_id {
            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
        }

        if payload.profile_id != self.profile_id {
            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
        }

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.required_permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;

        let auth = AuthenticationData {
            merchant_account: merchant,
            platform_merchant_account: None,
            key_store,
            profile_id: Some(payload.profile_id),
        };
        Ok((
            auth.clone(),
            AuthenticationType::MerchantJwtWithProfileId {
                merchant_id: auth.merchant_account.get_id().clone(),
                profile_id: auth.profile_id.clone(),
                user_id: payload.user_id,
            },
        ))
    }
}

pub struct JWTAuthProfileFromRoute {
    pub profile_id: id_type::ProfileId,
    pub required_permission: Permission,
}

#[cfg(feature = "v1")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationData, A> for JWTAuthProfileFromRoute
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.required_permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;

        if payload.profile_id != self.profile_id {
            return Err(report!(errors::ApiErrorResponse::InvalidJwtToken));
        } else {
            // if both of them are same then proceed with the profile id present in the request
            let auth = AuthenticationData {
                merchant_account: merchant,
                platform_merchant_account: None,
                key_store,
                profile_id: Some(self.profile_id.clone()),
            };
            Ok((
                auth.clone(),
                AuthenticationType::MerchantJwt {
                    merchant_id: auth.merchant_account.get_id().clone(),
                    user_id: Some(payload.user_id),
                },
            ))
        }
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationData, A> for JWTAuthProfileFromRoute
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        let profile_id =
            get_id_type_by_key_from_headers(headers::X_PROFILE_ID.to_string(), request_headers)?
                .get_required_value(headers::X_PROFILE_ID)?;

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.required_permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let profile = state
            .store()
            .find_business_profile_by_merchant_id_profile_id(
                key_manager_state,
                &key_store,
                &payload.merchant_id,
                &profile_id,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;

        let auth = AuthenticationData {
            merchant_account: merchant,
            key_store,
            profile,
            platform_merchant_account: None,
        };
        Ok((
            auth.clone(),
            AuthenticationType::MerchantJwt {
                merchant_id: auth.merchant_account.get_id().clone(),
                user_id: Some(payload.user_id),
            },
        ))
    }
}

pub async fn parse_jwt_payload<A, T>(headers: &HeaderMap, state: &A) -> RouterResult<T>
where
    T: serde::de::DeserializeOwned,
    A: SessionStateInfo + Sync,
{
    let cookie_token_result =
        get_cookie_from_header(headers).and_then(cookies::get_jwt_from_cookies);
    let auth_header_token_result = get_jwt_from_authorization_header(headers);
    let force_cookie = state.conf().user.force_cookies;

    logger::info!(
        user_agent = ?headers.get(headers::USER_AGENT),
        header_names = ?headers.keys().collect::<Vec<_>>(),
        is_token_equal =
            auth_header_token_result.as_deref().ok() == cookie_token_result.as_deref().ok(),
        cookie_error = ?cookie_token_result.as_ref().err(),
        token_error = ?auth_header_token_result.as_ref().err(),
        force_cookie,
    );

    let final_token = if force_cookie {
        cookie_token_result?
    } else {
        auth_header_token_result?.to_owned()
    };

    decode_jwt(&final_token, state).await
}

#[cfg(feature = "v1")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationData, A> for JWTAuth
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;
        let merchant_id = merchant.get_id().clone();
        let auth = AuthenticationData {
            merchant_account: merchant,
            platform_merchant_account: None,
            key_store,
            profile_id: Some(payload.profile_id),
        };
        Ok((
            auth,
            AuthenticationType::MerchantJwt {
                merchant_id,
                user_id: Some(payload.user_id),
            },
        ))
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationData, A> for JWTAuth
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        let profile_id = HeaderMapStruct::new(request_headers)
            .get_id_type_from_header::<id_type::ProfileId>(headers::X_PROFILE_ID)?;

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let profile = state
            .store()
            .find_business_profile_by_merchant_id_profile_id(
                key_manager_state,
                &key_store,
                &payload.merchant_id,
                &profile_id,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant account for the merchant id")?;
        let merchant_id = merchant.get_id().clone();
        let auth = AuthenticationData {
            merchant_account: merchant,
            key_store,
            profile,
            platform_merchant_account: None,
        };
        Ok((
            auth,
            AuthenticationType::MerchantJwt {
                merchant_id,
                user_id: Some(payload.user_id),
            },
        ))
    }
}

pub type AuthenticationDataWithUserId = (AuthenticationData, String);

#[cfg(feature = "v1")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationDataWithUserId, A> for JWTAuth
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationDataWithUserId, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        let role_info = authorization::get_role_info(state, &payload).await?;
        authorization::check_permission(self.permission, &role_info)?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .change_context(errors::ApiErrorResponse::InvalidJwtToken)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .change_context(errors::ApiErrorResponse::InvalidJwtToken)?;

        let auth = AuthenticationData {
            merchant_account: merchant,
            platform_merchant_account: None,
            key_store,
            profile_id: Some(payload.profile_id),
        };
        Ok((
            (auth.clone(), payload.user_id.clone()),
            AuthenticationType::MerchantJwt {
                merchant_id: auth.merchant_account.get_id().clone(),
                user_id: None,
            },
        ))
    }
}

pub struct DashboardNoPermissionAuth;

#[cfg(feature = "olap")]
#[async_trait]
impl<A> AuthenticateAndFetch<UserFromToken, A> for DashboardNoPermissionAuth
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(UserFromToken, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }

        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        Ok((
            UserFromToken {
                user_id: payload.user_id.clone(),
                merchant_id: payload.merchant_id.clone(),
                org_id: payload.org_id,
                role_id: payload.role_id,
                profile_id: payload.profile_id,
                tenant_id: payload.tenant_id,
            },
            AuthenticationType::MerchantJwt {
                merchant_id: payload.merchant_id,
                user_id: Some(payload.user_id),
            },
        ))
    }
}

#[cfg(feature = "olap")]
#[async_trait]
impl<A> AuthenticateAndFetch<(), A> for DashboardNoPermissionAuth
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<((), AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        if payload.check_in_blacklist(state).await? {
            return Err(errors::ApiErrorResponse::InvalidJwtToken.into());
        }
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        Ok(((), AuthenticationType::NoAuth))
    }
}

#[cfg(feature = "v1")]
#[async_trait]
impl<A> AuthenticateAndFetch<AuthenticationData, A> for DashboardNoPermissionAuth
where
    A: SessionStateInfo + Sync,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let payload = parse_jwt_payload::<A, AuthToken>(request_headers, state).await?;
        authorization::check_tenant(
            payload.tenant_id.clone(),
            &state.session_state().tenant.tenant_id,
        )?;

        let key_manager_state = &(&state.session_state()).into();
        let key_store = state
            .store()
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &state.store().get_master_key().to_vec().into(),
            )
            .await
            .change_context(errors::ApiErrorResponse::Unauthorized)
            .attach_printable("Failed to fetch merchant key store for the merchant id")?;

        let merchant = state
            .store()
            .find_merchant_account_by_merchant_id(
                key_manager_state,
                &payload.merchant_id,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;

        let auth = AuthenticationData {
            merchant_account: merchant,
            platform_merchant_account: None,
            key_store,
            profile_id: Some(payload.profile_id),
        };
        Ok((
            auth.clone(),
            AuthenticationType::MerchantJwt {
                merchant_id: auth.merchant_account.get_id().clone(),
                user_id: Some(payload.user_id),
            },
        ))
    }
}

pub trait ClientSecretFetch {
    fn get_client_secret(&self) -> Option<&String>;
}
#[cfg(feature = "payouts")]
impl ClientSecretFetch for payouts::PayoutCreateRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

#[cfg(feature = "v1")]
impl ClientSecretFetch for payments::PaymentsRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

#[cfg(feature = "v1")]
impl ClientSecretFetch for api_models::blocklist::ListBlocklistQuery {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

#[cfg(feature = "v1")]
impl ClientSecretFetch for payments::PaymentsRetrieveRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

#[cfg(feature = "v1")]
impl ClientSecretFetch for PaymentMethodListRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

impl ClientSecretFetch for payments::PaymentsPostSessionTokensRequest {
    fn get_client_secret(&self) -> Option<&String> {
        Some(self.client_secret.peek())
    }
}

#[cfg(feature = "v1")]
impl ClientSecretFetch for PaymentMethodCreate {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

impl ClientSecretFetch for api_models::cards_info::CardsInfoRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

impl ClientSecretFetch for payments::RetrievePaymentLinkRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

impl ClientSecretFetch for api_models::pm_auth::LinkTokenCreateRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

impl ClientSecretFetch for api_models::pm_auth::ExchangeTokenCreateRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

#[cfg(feature = "v1")]
impl ClientSecretFetch for api_models::payment_methods::PaymentMethodUpdate {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

#[cfg(feature = "v1")]
impl ClientSecretFetch for api_models::authentication::AuthenticationEligibilityRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret
            .as_ref()
            .map(|client_secret| client_secret.peek())
    }
}

impl ClientSecretFetch for api_models::authentication::AuthenticationAuthenticateRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret
            .as_ref()
            .map(|client_secret| client_secret.peek())
    }
}

impl ClientSecretFetch for api_models::authentication::AuthenticationSyncRequest {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret
            .as_ref()
            .map(|client_secret| client_secret.peek())
    }
}

pub fn get_auth_type_and_flow<A: SessionStateInfo + Sync + Send>(
    headers: &HeaderMap,
    api_auth: ApiKeyAuth,
) -> RouterResult<(
    Box<dyn AuthenticateAndFetch<AuthenticationData, A>>,
    api::AuthFlow,
)> {
    let api_key = get_api_key(headers)?;

    if api_key.starts_with("pk_") {
        return Ok((
            Box::new(HeaderAuth(PublishableKeyAuth)),
            api::AuthFlow::Client,
        ));
    }
    Ok((Box::new(HeaderAuth(api_auth)), api::AuthFlow::Merchant))
}

pub fn check_client_secret_and_get_auth<T>(
    headers: &HeaderMap,
    payload: &impl ClientSecretFetch,
    api_auth: ApiKeyAuth,
) -> RouterResult<(
    Box<dyn AuthenticateAndFetch<AuthenticationData, T>>,
    api::AuthFlow,
)>
where
    T: SessionStateInfo + Sync + Send,
    ApiKeyAuth: AuthenticateAndFetch<AuthenticationData, T>,
    PublishableKeyAuth: AuthenticateAndFetch<AuthenticationData, T>,
{
    let api_key = get_api_key(headers)?;
    if api_key.starts_with("pk_") {
        payload
            .get_client_secret()
            .check_value_present("client_secret")
            .map_err(|_| errors::ApiErrorResponse::MissingRequiredField {
                field_name: "client_secret",
            })?;
        return Ok((
            Box::new(HeaderAuth(PublishableKeyAuth)),
            api::AuthFlow::Client,
        ));
    }

    if payload.get_client_secret().is_some() {
        return Err(errors::ApiErrorResponse::InvalidRequestData {
            message: "client_secret is not a valid parameter".to_owned(),
        }
        .into());
    }
    Ok((Box::new(HeaderAuth(api_auth)), api::AuthFlow::Merchant))
}

pub async fn get_ephemeral_or_other_auth<T>(
    headers: &HeaderMap,
    is_merchant_flow: bool,
    payload: Option<&impl ClientSecretFetch>,
    api_auth: ApiKeyAuth,
) -> RouterResult<(
    Box<dyn AuthenticateAndFetch<AuthenticationData, T>>,
    api::AuthFlow,
    bool,
)>
where
    T: SessionStateInfo + Sync + Send,
    ApiKeyAuth: AuthenticateAndFetch<AuthenticationData, T>,
    PublishableKeyAuth: AuthenticateAndFetch<AuthenticationData, T>,
    EphemeralKeyAuth: AuthenticateAndFetch<AuthenticationData, T>,
{
    let api_key = get_api_key(headers)?;

    if api_key.starts_with("epk") {
        Ok((Box::new(EphemeralKeyAuth), api::AuthFlow::Client, true))
    } else if is_merchant_flow {
        Ok((
            Box::new(HeaderAuth(api_auth)),
            api::AuthFlow::Merchant,
            false,
        ))
    } else {
        let payload = payload.get_required_value("ClientSecretFetch")?;
        let (auth, auth_flow) = check_client_secret_and_get_auth(headers, payload, api_auth)?;
        Ok((auth, auth_flow, false))
    }
}

#[cfg(feature = "v1")]
pub fn is_ephemeral_auth<A: SessionStateInfo + Sync + Send>(
    headers: &HeaderMap,
    api_auth: ApiKeyAuth,
) -> RouterResult<Box<dyn AuthenticateAndFetch<AuthenticationData, A>>> {
    let api_key = get_api_key(headers)?;

    if !api_key.starts_with("epk") {
        Ok(Box::new(HeaderAuth(api_auth)))
    } else {
        Ok(Box::new(EphemeralKeyAuth))
    }
}

pub fn is_jwt_auth(headers: &HeaderMap) -> bool {
    let header_map_struct = HeaderMapStruct::new(headers);
    match header_map_struct.get_auth_string_from_header() {
        Ok(auth_str) => auth_str.starts_with("Bearer"),
        Err(_) => get_cookie_from_header(headers)
            .and_then(cookies::get_jwt_from_cookies)
            .is_ok(),
    }
}

pub fn is_internal_api_key_merchant_id_profile_id_auth(
    headers: &HeaderMap,
    internal_api_key_auth: settings::InternalMerchantIdProfileIdAuthSettings,
) -> bool {
    internal_api_key_auth.enabled
        && headers.contains_key(headers::X_INTERNAL_API_KEY)
        && headers.contains_key(headers::X_MERCHANT_ID)
        && headers.contains_key(headers::X_PROFILE_ID)
}

#[cfg(feature = "v1")]
pub fn check_internal_api_key_auth<T>(
    headers: &HeaderMap,
    payload: &impl ClientSecretFetch,
    api_auth: ApiKeyAuth,
    internal_api_key_auth: settings::InternalMerchantIdProfileIdAuthSettings,
) -> RouterResult<(
    Box<dyn AuthenticateAndFetch<AuthenticationData, T>>,
    api::AuthFlow,
)>
where
    T: SessionStateInfo + Sync + Send,
    ApiKeyAuth: AuthenticateAndFetch<AuthenticationData, T>,
{
    if is_internal_api_key_merchant_id_profile_id_auth(headers, internal_api_key_auth) {
        Ok((
            // HeaderAuth(api_auth) will never be called in this case as the internal auth will be checked first
            Box::new(InternalMerchantIdProfileIdAuth(HeaderAuth(api_auth))),
            api::AuthFlow::Merchant,
        ))
    } else {
        check_client_secret_and_get_auth(headers, payload, api_auth)
    }
}

pub async fn decode_jwt<T>(token: &str, state: &impl SessionStateInfo) -> RouterResult<T>
where
    T: serde::de::DeserializeOwned,
{
    let conf = state.conf();
    let secret = conf.secrets.get_inner().jwt_secret.peek().as_bytes();

    let key = DecodingKey::from_secret(secret);
    decode::<T>(token, &key, &Validation::new(Algorithm::HS256))
        .map(|decoded| decoded.claims)
        .change_context(errors::ApiErrorResponse::InvalidJwtToken)
}

pub fn get_api_key(headers: &HeaderMap) -> RouterResult<&str> {
    get_header_value_by_key("api-key".into(), headers)?.get_required_value("api_key")
}

pub fn get_header_value_by_key(key: String, headers: &HeaderMap) -> RouterResult<Option<&str>> {
    headers
        .get(&key)
        .map(|source_str| {
            source_str
                .to_str()
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable(format!(
                    "Failed to convert header value to string for header key: {key}",
                ))
        })
        .transpose()
}
pub fn get_id_type_by_key_from_headers<T: FromStr>(
    key: String,
    headers: &HeaderMap,
) -> RouterResult<Option<T>> {
    get_header_value_by_key(key.clone(), headers)?
        .map(|str_value| T::from_str(str_value))
        .transpose()
        .map_err(|_err| {


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

pub struct Details


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

impl api::PaymentSession for for Prophetpay


// File: crates/router/src/types/fraud_check.rs
// Module: router
// Public structs: 1

pub use hyperswitch_domain_models::{
    router_request_types::fraud_check::{
        FraudCheckCheckoutData, FraudCheckFulfillmentData, FraudCheckRecordReturnData,
        FraudCheckSaleData, FraudCheckTransactionData, RefundMethod,
    },
    router_response_types::fraud_check::FraudCheckResponseData,
};

use crate::{
    services,
    types::{api, ErrorResponse, RouterData},
};

pub type FrmSaleRouterData = RouterData<api::Sale, FraudCheckSaleData, FraudCheckResponseData>;

pub type FrmSaleType =
    dyn services::ConnectorIntegration<api::Sale, FraudCheckSaleData, FraudCheckResponseData>;

#[derive(Debug, Clone)]
pub struct FrmRouterData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub connector: String,
    // TODO: change this to PaymentId type
    pub payment_id: String,
    pub attempt_id: String,
    pub request: FrmRequest,
    pub response: FrmResponse,
}
#[derive(Debug, Clone)]
pub enum FrmRequest {
    Sale(FraudCheckSaleData),
    Checkout(Box<FraudCheckCheckoutData>),
    Transaction(FraudCheckTransactionData),
    Fulfillment(FraudCheckFulfillmentData),
    RecordReturn(FraudCheckRecordReturnData),
}
#[derive(Debug, Clone)]
pub enum FrmResponse {
    Sale(Result<FraudCheckResponseData, ErrorResponse>),
    Checkout(Result<FraudCheckResponseData, ErrorResponse>),
    Transaction(Result<FraudCheckResponseData, ErrorResponse>),
    Fulfillment(Result<FraudCheckResponseData, ErrorResponse>),
    RecordReturn(Result<FraudCheckResponseData, ErrorResponse>),
}

pub type FrmCheckoutRouterData =
    RouterData<api::Checkout, FraudCheckCheckoutData, FraudCheckResponseData>;

pub type FrmCheckoutType = dyn services::ConnectorIntegration<
    api::Checkout,
    FraudCheckCheckoutData,
    FraudCheckResponseData,
>;

pub type FrmTransactionRouterData =
    RouterData<api::Transaction, FraudCheckTransactionData, FraudCheckResponseData>;

pub type FrmTransactionType = dyn services::ConnectorIntegration<
    api::Transaction,
    FraudCheckTransactionData,
    FraudCheckResponseData,
>;

pub type FrmFulfillmentRouterData =
    RouterData<api::Fulfillment, FraudCheckFulfillmentData, FraudCheckResponseData>;

pub type FrmFulfillmentType = dyn services::ConnectorIntegration<
    api::Fulfillment,
    FraudCheckFulfillmentData,
    FraudCheckResponseData,
>;
pub type FrmRecordReturnRouterData =
    RouterData<api::RecordReturn, FraudCheckRecordReturnData, FraudCheckResponseData>;

pub type FrmRecordReturnType = dyn services::ConnectorIntegration<
    api::RecordReturn,
    FraudCheckRecordReturnData,
    FraudCheckResponseData,
>;


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

pub struct RefundResponse


// Struct: ThreedsecureioAuthenticationSuccessResponse
// File: crates/hyperswitch_connectors/src/connectors/threedsecureio/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ThreedsecureioAuthenticationSuccessResponse


// Implementation: impl DisputeSync for for Worldpayvantiv
// File: crates/hyperswitch_connectors/src/connectors/worldpayvantiv.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl DisputeSync for for Worldpayvantiv


// Implementation: impl api::PaymentAuthorize for for Stripe
// File: crates/hyperswitch_connectors/src/connectors/stripe.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentAuthorize for for Stripe


// Function: get_connector_name
// File: crates/hyperswitch_domain_models/src/merchant_connector_account.rs
// Module: hyperswitch_domain_models

pub fn get_connector_name(&self) -> common_enums::connector_enums::Connector


// Struct: ApplePayDetails
// File: crates/hyperswitch_connectors/src/connectors/nexinets/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ApplePayDetails