// File: crates/smithy-generator/build.rs
// Module: smithy-generator
// Public functions: 1

// crates/smithy-generator/build.rs

use std::{fs, path::Path};

use regex::Regex;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("cargo:rerun-if-changed=../");
    run_build()
}

fn run_build() -> Result<(), Box<dyn std::error::Error>> {
    let workspace_root = get_workspace_root()?;

    let mut smithy_models = Vec::new();

    // Scan all crates in the workspace for SmithyModel derives
    let crates_dir = workspace_root.join("crates");
    if let Ok(entries) = fs::read_dir(&crates_dir) {
        for entry in entries.flatten() {
            if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) {
                let crate_path = entry.path();
                let crate_name = match crate_path.file_name() {
                    Some(name) => name.to_string_lossy(),
                    None => {
                        println!(
                            "cargo:warning=Skipping crate with invalid path: {}",
                            crate_path.display()
                        );
                        continue;
                    }
                };

                // Skip the smithy crate itself to avoid self-dependency
                if crate_name == "smithy"
                    || crate_name == "smithy-core"
                    || crate_name == "smithy-generator"
                {
                    continue;
                }

                if let Err(e) =
                    scan_crate_for_smithy_models(&crate_path, &crate_name, &mut smithy_models)
                {
                    println!("cargo:warning=Failed to scan crate {}: {}", crate_name, e);
                }
            }
        }
    }

    // Generate the registry file
    generate_model_registry(&smithy_models)?;

    Ok(())
}

fn get_workspace_root() -> Result<std::path::PathBuf, Box<dyn std::error::Error>> {
    let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")
        .map_err(|_| "CARGO_MANIFEST_DIR environment variable not set")?;

    let manifest_path = Path::new(&manifest_dir);

    let parent1 = manifest_path
        .parent()
        .ok_or("Cannot get parent directory of CARGO_MANIFEST_DIR")?;

    let workspace_root = parent1
        .parent()
        .ok_or("Cannot get workspace root directory")?;

    Ok(workspace_root.to_path_buf())
}

fn scan_crate_for_smithy_models(
    crate_path: &Path,
    crate_name: &str,
    models: &mut Vec<SmithyModelInfo>,
) -> Result<(), Box<dyn std::error::Error>> {
    let src_path = crate_path.join("src");
    if !src_path.exists() {
        return Ok(());
    }

    scan_directory(&src_path, crate_name, "", models)?;
    Ok(())
}

fn scan_directory(
    dir: &Path,
    crate_name: &str,
    module_path: &str,
    models: &mut Vec<SmithyModelInfo>,
) -> Result<(), Box<dyn std::error::Error>> {
    if let Ok(entries) = fs::read_dir(dir) {
        for entry in entries.flatten() {
            let path = entry.path();
            if path.is_dir() {
                let dir_name = match path.file_name() {
                    Some(name) => name.to_string_lossy(),
                    None => {
                        println!(
                            "cargo:warning=Skipping directory with invalid name: {}",
                            path.display()
                        );
                        continue;
                    }
                };
                let new_module_path = if module_path.is_empty() {
                    dir_name.to_string()
                } else {
                    format!("{}::{}", module_path, dir_name)
                };
                scan_directory(&path, crate_name, &new_module_path, models)?;
            } else if path.extension().map(|ext| ext == "rs").unwrap_or(false) {
                if let Err(e) = scan_rust_file(&path, crate_name, module_path, models) {
                    println!(
                        "cargo:warning=Failed to scan Rust file {}: {}",
                        path.display(),
                        e
                    );
                }
            }
        }
    }
    Ok(())
}

fn scan_rust_file(
    file_path: &Path,
    crate_name: &str,
    module_path: &str,
    models: &mut Vec<SmithyModelInfo>,
) -> Result<(), Box<dyn std::error::Error>> {
    if let Ok(content) = fs::read_to_string(file_path) {
        // Enhanced regex that handles comments, doc comments, and multiple attributes
        // between derive and struct/enum declarations
        let re = Regex::new(r"(?ms)^#\[derive\(([^)]*(?:\([^)]*\))*[^)]*)\)\]\s*(?:(?:#\[[^\]]*\]\s*)|(?://[^\r\n]*\s*)|(?:///[^\r\n]*\s*)|(?:/\*.*?\*/\s*))*(?:pub\s+)?(?:struct|enum)\s+([A-Z][A-Za-z0-9_]*)\s*[<\{\(]")
            .map_err(|e| format!("Failed to compile regex: {}", e))?;

        for captures in re.captures_iter(&content) {
            let derive_content = match captures.get(1) {
                Some(capture) => capture.as_str(),
                None => {
                    println!(
                        "cargo:warning=Missing derive content in regex capture for {}",
                        file_path.display()
                    );
                    continue;
                }
            };
            let item_name = match captures.get(2) {
                Some(capture) => capture.as_str(),
                None => {
                    println!(
                        "cargo:warning=Missing item name in regex capture for {}",
                        file_path.display()
                    );
                    continue;
                }
            };

            // Check if "SmithyModel" is present in the derive macro's content.
            if derive_content.contains("SmithyModel") {
                // Validate that the item name is a valid Rust identifier
                if is_valid_rust_identifier(item_name) {
                    let full_module_path = create_module_path(file_path, crate_name, module_path)?;

                    models.push(SmithyModelInfo {
                        struct_name: item_name.to_string(),
                        module_path: full_module_path,
                    });
                } else {
                    println!(
                        "cargo:warning=Skipping invalid identifier: {} in {}",
                        item_name,
                        file_path.display()
                    );
                }
            }
        }
    }
    Ok(())
}

fn is_valid_rust_identifier(name: &str) -> bool {
    if name.is_empty() {
        return false;
    }

    // Rust identifiers must start with a letter or underscore
    let first_char = match name.chars().next() {
        Some(ch) => ch,
        None => return false, // This shouldn't happen since we checked is_empty above, but being safe
    };
    if !first_char.is_ascii_alphabetic() && first_char != '_' {
        return false;
    }

    // Must not be a Rust keyword
    let keywords = [
        "as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn",
        "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref",
        "return", "self", "Self", "static", "struct", "super", "trait", "true", "type", "unsafe",
        "use", "where", "while", "async", "await", "dyn", "is", "abstract", "become", "box", "do",
        "final", "macro", "override", "priv", "typeof", "unsized", "virtual", "yield", "try",
    ];

    if keywords.contains(&name) {
        return false;
    }

    // All other characters must be alphanumeric or underscore
    name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}

fn create_module_path(
    file_path: &Path,
    crate_name: &str,
    module_path: &str,
) -> Result<String, Box<dyn std::error::Error>> {
    let file_name = file_path
        .file_stem()
        .and_then(|s| s.to_str())
        .ok_or_else(|| {
            format!(
                "Cannot extract file name from path: {}",
                file_path.display()
            )
        })?;

    let crate_name_normalized = crate_name.replace('-', "_");

    let result = if file_name == "lib" || file_name == "mod" {
        if module_path.is_empty() {
            crate_name_normalized
        } else {
            format!("{}::{}", crate_name_normalized, module_path)
        }
    } else if module_path.is_empty() {
        format!("{}::{}", crate_name_normalized, file_name)
    } else {
        format!("{}::{}::{}", crate_name_normalized, module_path, file_name)
    };

    Ok(result)
}

#[derive(Debug)]
struct SmithyModelInfo {
    struct_name: String,
    module_path: String,
}

fn generate_model_registry(models: &[SmithyModelInfo]) -> Result<(), Box<dyn std::error::Error>> {
    let out_dir = std::env::var("OUT_DIR").map_err(|_| "OUT_DIR environment variable not set")?;
    let registry_path = Path::new(&out_dir).join("model_registry.rs");

    let mut content = String::new();
    content.push_str("// Auto-generated model registry\n");
    content.push_str("// DO NOT EDIT - This file is generated by build.rs\n\n");

    if !models.is_empty() {
        content.push_str("use smithy_core::{SmithyModel, SmithyModelGenerator};\n\n");

        // Generate imports
        for model in models {
            content.push_str(&format!(
                "use {}::{};\n",
                model.module_path, model.struct_name
            ));
        }

        content.push_str("\npub fn discover_smithy_models() -> Vec<SmithyModel> {\n");
        content.push_str("    let mut models = Vec::new();\n\n");

        // Generate model collection calls
        for model in models {
            content.push_str(&format!(
                "    models.push({}::generate_smithy_model());\n",
                model.struct_name
            ));
        }

        content.push_str("\n    models\n");
        content.push_str("}\n");
    } else {
        // Generate empty function if no models found
        content.push_str("use smithy_core::SmithyModel;\n\n");
        content.push_str("pub fn discover_smithy_models() -> Vec<SmithyModel> {\n");
        content.push_str(
            "    router_env::logger::info!(\"No SmithyModel structs found in workspace\");\n",
        );
        content.push_str("    Vec::new()\n");
        content.push_str("}\n");
    }

    fs::write(&registry_path, content).map_err(|e| {
        format!(
            "Failed to write model registry to {}: {}",
            registry_path.display(),
            e
        )
    })?;

    Ok(())
}


// Struct: PaystackRouterData
// File: crates/hyperswitch_connectors/src/connectors/paystack/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaystackRouterData<T>


// Struct: Defend
// File: crates/hyperswitch_domain_models/src/router_flow_types/dispute.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct Defend


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

impl api::MandateSetup for for Square


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

pub struct SantanderWebhookBody


// Struct: NetworkRetryConfig
// File: crates/router/src/types/storage/revenue_recovery.rs
// Module: router
// Implementations: 0

pub struct NetworkRetryConfig


// Function: try_emit
// File: crates/events/src/lib.rs
// Module: events

// Documentation: Emit the event.

pub fn try_emit(self) -> Result<(), EventsError>


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

pub struct PaymentAccountInformation


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

pub struct CreateProfileDetails


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

impl api::RefundSync for for Worldpayxml


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

pub fn new() -> &'static Self


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

pub struct PaypalOrdersResponse


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

pub fn get_product_type(&self) -> Option<common_enums::MerchantProductType>


// Trait: PaymentAuthConnectorDataExt
// File: crates/router/src/core/pm_auth/helpers.rs
// Module: router

pub trait PaymentAuthConnectorDataExt


// Function: set_limit_by
// File: crates/analytics/src/query.rs
// Module: analytics

pub fn set_limit_by(&mut self, limit: u64, columns: &[impl ToSql<T>]) -> QueryResult<()>


// Struct: ThreeDSRequest
// File: crates/hyperswitch_connectors/src/connectors/worldpay/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ThreeDSRequest


// Implementation: impl api::PaymentIncrementalAuthorization for for Wellsfargo
// File: crates/hyperswitch_connectors/src/connectors/wellsfargo.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentIncrementalAuthorization for for Wellsfargo


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

impl api::RefundSync for for Flexiti


// Function: get_order_amount
// File: crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
// Module: hyperswitch_domain_models

pub fn get_order_amount(&self) -> MinorUnit


// Function: new
// File: crates/router_env/src/logger/config.rs
// Module: router_env

// Documentation: Default constructor.

pub fn new() -> Result<Self, config::ConfigError>


// Struct: PaymentUpdateIntent
// File: crates/router/src/core/payments/operations/payment_update_intent.rs
// Module: router
// Implementations: 1
// Traits: ValidateStatusForOperation

pub struct PaymentUpdateIntent


// File: crates/analytics/src/payments/metrics.rs
// Module: analytics
// Public structs: 1

use std::collections::HashSet;

use api_models::analytics::{
    payments::{PaymentDimensions, PaymentFilters, PaymentMetrics, PaymentMetricsBucketIdentifier},
    Granularity, TimeRange,
};
use diesel_models::enums as storage_enums;
use time::PrimitiveDateTime;

use crate::{
    enums::AuthInfo,
    query::{Aggregate, GroupByClause, ToSql, Window},
    types::{AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, LoadRow, MetricsResult},
};

mod avg_ticket_size;
mod connector_success_rate;
mod debit_routing;
mod payment_count;
mod payment_processed_amount;
mod payment_success_count;
mod retries_count;
mod sessionized_metrics;
mod success_rate;

use avg_ticket_size::AvgTicketSize;
use connector_success_rate::ConnectorSuccessRate;
use debit_routing::DebitRouting;
use payment_count::PaymentCount;
use payment_processed_amount::PaymentProcessedAmount;
use payment_success_count::PaymentSuccessCount;
use success_rate::PaymentSuccessRate;

use self::retries_count::RetriesCount;

#[derive(Debug, PartialEq, Eq, serde::Deserialize, Hash)]
pub struct PaymentMetricRow {
    pub currency: Option<DBEnumWrapper<storage_enums::Currency>>,
    pub status: Option<DBEnumWrapper<storage_enums::AttemptStatus>>,
    pub connector: Option<String>,
    pub authentication_type: Option<DBEnumWrapper<storage_enums::AuthenticationType>>,
    pub payment_method: Option<String>,
    pub payment_method_type: Option<String>,
    pub client_source: Option<String>,
    pub client_version: Option<String>,
    pub profile_id: Option<String>,
    pub card_network: Option<String>,
    pub merchant_id: Option<String>,
    pub card_last_4: Option<String>,
    pub card_issuer: Option<String>,
    pub error_reason: Option<String>,
    pub first_attempt: Option<bool>,
    pub total: Option<bigdecimal::BigDecimal>,
    pub count: Option<i64>,
    pub routing_approach: Option<DBEnumWrapper<storage_enums::RoutingApproach>>,
    pub signature_network: Option<String>,
    pub is_issuer_regulated: Option<bool>,
    pub is_debit_routed: Option<bool>,
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub start_bucket: Option<PrimitiveDateTime>,
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub end_bucket: Option<PrimitiveDateTime>,
}

pub trait PaymentMetricAnalytics: LoadRow<PaymentMetricRow> {}

#[async_trait::async_trait]
pub trait PaymentMetric<T>
where
    T: AnalyticsDataSource + PaymentMetricAnalytics,
{
    async fn load_metrics(
        &self,
        dimensions: &[PaymentDimensions],
        auth: &AuthInfo,
        filters: &PaymentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>>;
}

#[async_trait::async_trait]
impl<T> PaymentMetric<T> for PaymentMetrics
where
    T: AnalyticsDataSource + PaymentMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[PaymentDimensions],
        auth: &AuthInfo,
        filters: &PaymentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
        match self {
            Self::PaymentSuccessRate => {
                PaymentSuccessRate
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::PaymentCount => {
                PaymentCount
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::PaymentSuccessCount => {
                PaymentSuccessCount
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::PaymentProcessedAmount => {
                PaymentProcessedAmount
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::AvgTicketSize => {
                AvgTicketSize
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::RetriesCount => {
                RetriesCount
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::ConnectorSuccessRate => {
                ConnectorSuccessRate
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::DebitRouting => {
                DebitRouting
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::SessionizedPaymentSuccessRate => {
                sessionized_metrics::PaymentSuccessRate
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::SessionizedPaymentCount => {
                sessionized_metrics::PaymentCount
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::SessionizedPaymentSuccessCount => {
                sessionized_metrics::PaymentSuccessCount
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::SessionizedPaymentProcessedAmount => {
                sessionized_metrics::PaymentProcessedAmount
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::SessionizedAvgTicketSize => {
                sessionized_metrics::AvgTicketSize
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::SessionizedRetriesCount => {
                sessionized_metrics::RetriesCount
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::SessionizedConnectorSuccessRate => {
                sessionized_metrics::ConnectorSuccessRate
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::PaymentsDistribution => {
                sessionized_metrics::PaymentsDistribution
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::FailureReasons => {
                sessionized_metrics::FailureReasons
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
            Self::SessionizedDebitRouting => {
                sessionized_metrics::DebitRouting
                    .load_metrics(dimensions, auth, filters, granularity, time_range, pool)
                    .await
            }
        }
    }
}


// Implementation: impl State for for PmTokenUpdated
// File: crates/router/src/core/payment_methods/tokenize/payment_method_executor.rs
// Module: router
// Methods: 0 total (0 public)

impl State for for PmTokenUpdated


// Struct: AirwallexRedirectResponse
// File: crates/hyperswitch_connectors/src/connectors/airwallex/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AirwallexRedirectResponse


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

pub struct RevolutPayData


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

impl api::PaymentAuthorize for for Bankofamerica


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

impl api::PaymentCapture for for Peachpayments


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

pub struct PaypalIncrementalAuthStatusDetails


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

pub struct BamboraapacRouterData<T>


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

impl Responder


// Struct: HashiCorpVaultConfig
// File: crates/external_services/src/hashicorp_vault/core.rs
// Module: external_services
// Implementations: 1

pub struct HashiCorpVaultConfig


// Function: add_bool_filter_clause
// File: crates/analytics/src/query.rs
// Module: analytics

pub fn add_bool_filter_clause(
        &mut self,
        key: impl ToSql<T>,
        value: impl ToSql<T>,
    ) -> QueryResult<()>


// Implementation: impl RequestBuilder
// File: crates/common_utils/src/request.rs
// Module: common_utils
// Methods: 12 total (12 public)

impl RequestBuilder


// Struct: HyperswitchVaultErrorDetails
// File: crates/hyperswitch_connectors/src/connectors/hyperswitch_vault/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct HyperswitchVaultErrorDetails


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

pub fn check_payout_eligibility(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    connector_data: &api::ConnectorData,
    payout_data: &mut PayoutData,
) -> RouterResult<()>


// Function: routing_update_default_config
// File: crates/openapi/src/routes/routing.rs
// Module: openapi

pub fn routing_update_default_config()


            ),
            FiuuWebhooksResponse::FiuuWebhookRefundResponse(webhook_refund_response) => {
                Ok(Box::new(fiuu::FiuuRefundSyncResponse::Webhook(
                    webhook_refund_response,
                )))
            }
        }
    }

    fn get_mandate_details(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<
        Option<hyperswitch_domain_models::router_flow_types::ConnectorMandateDetails>,
        errors::ConnectorError,
    > {
        parse_and_log_keys_in_url_encoded_response::<transformers::FiuuWebhooksPaymentResponse>(
            request.body,
        );
        let webhook_payment_response: transformers::FiuuWebhooksPaymentResponse =
            serde_urlencoded::from_bytes::<transformers::FiuuWebhooksPaymentResponse>(request.body)
                .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?;
        let mandate_reference = webhook_payment_response.extra_parameters.as_ref().and_then(|extra_p| {
                    let mandate_token: Result<ExtraParameters, _> = serde_json::from_str(&extra_p.clone().expose());
                    match mandate_token {
                        Ok(token) => {
                            token.token.as_ref().map(|token| hyperswitch_domain_models::router_flow_types::ConnectorMandateDetails {
                                connector_mandate_id:token.clone(),
                            })
                        }
                        Err(err) => {
                            router_env::logger::warn!(
                                "Failed to convert 'extraP' from fiuu webhook response to fiuu::ExtraParameters. \
                                 Input: '{:?}', Error: {}",
                                extra_p,
                                err
                            );
                            None
                        }
                    }
                });
        Ok(mandate_reference)
    }
}

static FIUU_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> = LazyLock::new(|| {
    let supported_capture_methods = vec![
        CaptureMethod::Automatic,
        CaptureMethod::Manual,
        CaptureMethod::SequentialAutomatic,
    ];

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

    let mut fiuu_supported_payment_methods = SupportedPaymentMethods::new();

    fiuu_supported_payment_methods.add(
        PaymentMethod::RealTimePayment,
        PaymentMethodType::DuitNow,
        PaymentMethodDetails {
            mandates: common_enums::FeatureStatus::NotSupported,
            refunds: common_enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

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

    fiuu_supported_payment_methods.add(
        PaymentMethod::Wallet,
        PaymentMethodType::GooglePay,
        PaymentMethodDetails {
            mandates: common_enums::FeatureStatus::NotSupported,
            refunds: common_enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

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

    fiuu_supported_payment_methods.add(
        PaymentMethod::Card,
        PaymentMethodType::Credit,
        PaymentMethodDetails {
            mandates: common_enums::FeatureStatus::Supported,
            refunds: common_enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: Some(
                api_models::feature_matrix::PaymentMethodSpecificFeatures::Card({
                    api_models::feature_matrix::CardSpecificFeatures {
                        three_ds: common_enums::FeatureStatus::Supported,
                        no_three_ds: common_enums::FeatureStatus::Supported,
                        supported_card_networks: supported_card_network.clone(),
                    }
                }),
            ),
        },
    );

    fiuu_supported_payment_methods.add(
        PaymentMethod::Card,
        PaymentMethodType::Debit,
        PaymentMethodDetails {
            mandates: common_enums::FeatureStatus::Supported,
            refunds: common_enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: Some(
                api_models::feature_matrix::PaymentMethodSpecificFeatures::Card({
                    api_models::feature_matrix::CardSpecificFeatures {
                        three_ds: common_enums::FeatureStatus::Supported,
                        no_three_ds: common_enums::FeatureStatus::Supported,
                        supported_card_networks: supported_card_network.clone(),
                    }
                }),
            ),
        },
    );

    fiuu_supported_payment_methods
});

static FIUU_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Fiuu",
    description:
        "Fiuu, formerly known as Razer Merchant Services, is a leading online payment gateway in Southeast Asia, offering secure and seamless payment solutions for businesses of all sizes, including credit and debit cards, e-wallets, and bank transfers.",
    connector_type: common_enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: common_enums::ConnectorIntegrationStatus::Live,
};

static FIUU_SUPPORTED_WEBHOOK_FLOWS: [common_enums::EventClass; 2] = [
    common_enums::EventClass::Payments,
    common_enums::EventClass::Refunds,
];

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

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

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


// Function: payouts_create
// File: crates/router/src/routes/payouts.rs
// Module: router

pub fn payouts_create(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<payout_types::PayoutCreateRequest>,
) -> HttpResponse


// File: crates/diesel_models/src/user_key_store.rs
// Module: diesel_models
// Public structs: 2

use common_utils::encryption::Encryption;
use diesel::{Identifiable, Insertable, Queryable, Selectable};
use time::PrimitiveDateTime;

use crate::schema::user_key_store;

#[derive(
    Clone, Debug, serde::Serialize, serde::Deserialize, Identifiable, Queryable, Selectable,
)]
#[diesel(table_name = user_key_store, primary_key(user_id), check_for_backend(diesel::pg::Pg))]
pub struct UserKeyStore {
    pub user_id: String,
    pub key: Encryption,
    pub created_at: PrimitiveDateTime,
}

#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Insertable)]
#[diesel(table_name = user_key_store)]
pub struct UserKeyStoreNew {
    pub user_id: String,
    pub key: Encryption,
    pub created_at: PrimitiveDateTime,
}


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

pub struct CardsData


// Function: make_fulfillment_api_call
// File: crates/router/src/core/fraud_check.rs
// Module: router

pub fn make_fulfillment_api_call(
    db: &dyn StorageInterface,
    fraud_check: FraudCheck,
    payment_intent: PaymentIntent,
    state: SessionState,
    merchant_context: domain::MerchantContext,
    req: frm_core_types::FrmFulfillmentRequest,
) -> RouterResponse<frm_types::FraudCheckResponseData>


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

pub struct PayoutAttemptUpdateMems


// Function: add_connector_http_status_code_metrics
// File: crates/router/src/utils.rs
// Module: router

pub fn add_connector_http_status_code_metrics(option_status_code: Option<u16>)


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

impl ConnectorSpecifications for for Blackhawknetwork


// Function: customers_create
// File: crates/openapi/src/routes/customers.rs
// Module: openapi

pub fn customers_create()


// Struct: CashtocodeErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/cashtocode/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CashtocodeErrorResponse


// Struct: OpenSearchConfig
// File: crates/analytics/src/opensearch.rs
// Module: analytics
// Implementations: 2
// Traits: Default

pub struct OpenSearchConfig


// Struct: BluesnapWalletTokenResponse
// File: crates/hyperswitch_connectors/src/connectors/bluesnap/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BluesnapWalletTokenResponse


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

pub fn save_network_token_in_locker(
    _state: &SessionState,
    _merchant_context: &domain::MerchantContext,
    _card_data: &domain::Card,
    _payment_method_request: api::PaymentMethodCreate,
) -> RouterResult<(
    Option<api_models::payment_methods::PaymentMethodResponse>,
    Option<payment_methods::transformers::DataDuplicationCheck>,
    Option<String>,
)>


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

pub fn payouts_filtered_list_core(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    profile_id_list: Option<Vec<id_type::ProfileId>>,
    filters: payouts::PayoutListFilterConstraints,
) -> RouterResponse<payouts::PayoutListResponse>


// Struct: PaymentIntentData
// File: crates/hyperswitch_domain_models/src/payments.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct PaymentIntentData<F>


// Trait: RefundMetric
// File: crates/analytics/src/refunds/metrics.rs
// Module: analytics

pub trait RefundMetric<T>


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

impl api::PaymentToken for for Dlocal


// Struct: PlaidRouterData
// File: crates/hyperswitch_connectors/src/connectors/plaid/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PlaidRouterData<T>


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

pub fn find_all_by_merchant_id_payment_id_authorized_attempt_id(
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
        authorized_attempt_id: &str,
        conn: &PgPooledConn,
    ) -> StorageResult<Vec<Self>>


// Struct: AuthEventMetricRow
// File: crates/analytics/src/auth_events/metrics.rs
// Module: analytics
// Implementations: 0

pub struct AuthEventMetricRow


// Function: verify_recon_token
// File: crates/router/src/routes/recon.rs
// Module: router

pub fn verify_recon_token(state: web::Data<AppState>, http_req: HttpRequest) -> HttpResponse


// Function: get_nmi_webhook_event
// File: crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs
// Module: hyperswitch_connectors

pub fn get_nmi_webhook_event(status: NmiWebhookEventType) -> IncomingWebhookEvent


// File: crates/diesel_models/src/payout_attempt.rs
// Module: diesel_models
// Public functions: 1
// Public structs: 3

use common_utils::{
    payout_method_utils,
    types::{UnifiedCode, UnifiedMessage},
};
use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable};
use serde::{self, Deserialize, Serialize};
use time::PrimitiveDateTime;

use crate::{enums as storage_enums, schema::payout_attempt};

#[derive(
    Clone, Debug, Eq, PartialEq, Identifiable, Queryable, Selectable, Serialize, Deserialize,
)]
#[diesel(table_name = payout_attempt, primary_key(payout_attempt_id), check_for_backend(diesel::pg::Pg))]
pub struct PayoutAttempt {
    pub payout_attempt_id: String,
    pub payout_id: common_utils::id_type::PayoutId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub address_id: Option<String>,
    pub connector: Option<String>,
    pub connector_payout_id: Option<String>,
    pub payout_token: Option<String>,
    pub status: storage_enums::PayoutStatus,
    pub is_eligible: Option<bool>,
    pub error_message: Option<String>,
    pub error_code: Option<String>,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub last_modified_at: PrimitiveDateTime,
    pub profile_id: common_utils::id_type::ProfileId,
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    pub routing_info: Option<serde_json::Value>,
    pub unified_code: Option<UnifiedCode>,
    pub unified_message: Option<UnifiedMessage>,
    pub additional_payout_method_data: Option<payout_method_utils::AdditionalPayoutMethodData>,
    pub merchant_order_reference_id: Option<String>,
}

#[derive(
    Clone,
    Debug,
    Eq,
    PartialEq,
    Insertable,
    serde::Serialize,
    serde::Deserialize,
    router_derive::DebugAsDisplay,
    router_derive::Setter,
)]
#[diesel(table_name = payout_attempt)]
pub struct PayoutAttemptNew {
    pub payout_attempt_id: String,
    pub payout_id: common_utils::id_type::PayoutId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub address_id: Option<String>,
    pub connector: Option<String>,
    pub connector_payout_id: Option<String>,
    pub payout_token: Option<String>,
    pub status: storage_enums::PayoutStatus,
    pub is_eligible: Option<bool>,
    pub error_message: Option<String>,
    pub error_code: Option<String>,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub last_modified_at: PrimitiveDateTime,
    pub profile_id: common_utils::id_type::ProfileId,
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    pub routing_info: Option<serde_json::Value>,
    pub unified_code: Option<UnifiedCode>,
    pub unified_message: Option<UnifiedMessage>,
    pub additional_payout_method_data: Option<payout_method_utils::AdditionalPayoutMethodData>,
    pub merchant_order_reference_id: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PayoutAttemptUpdate {
    StatusUpdate {
        connector_payout_id: Option<String>,
        status: storage_enums::PayoutStatus,
        error_message: Option<String>,
        error_code: Option<String>,
        is_eligible: Option<bool>,
        unified_code: Option<UnifiedCode>,
        unified_message: Option<UnifiedMessage>,
    },
    PayoutTokenUpdate {
        payout_token: String,
    },
    BusinessUpdate {
        business_country: Option<storage_enums::CountryAlpha2>,
        business_label: Option<String>,
        address_id: Option<String>,
        customer_id: Option<common_utils::id_type::CustomerId>,
    },
    UpdateRouting {
        connector: String,
        routing_info: Option<serde_json::Value>,
        merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    },
    AdditionalPayoutMethodDataUpdate {
        additional_payout_method_data: Option<payout_method_utils::AdditionalPayoutMethodData>,
    },
}

#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
#[diesel(table_name = payout_attempt)]
pub struct PayoutAttemptUpdateInternal {
    pub payout_token: Option<String>,
    pub connector_payout_id: Option<String>,
    pub status: Option<storage_enums::PayoutStatus>,
    pub error_message: Option<String>,
    pub error_code: Option<String>,
    pub is_eligible: Option<bool>,
    pub business_country: Option<storage_enums::CountryAlpha2>,
    pub business_label: Option<String>,
    pub connector: Option<String>,
    pub routing_info: Option<serde_json::Value>,
    pub last_modified_at: PrimitiveDateTime,
    pub address_id: Option<String>,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    pub unified_code: Option<UnifiedCode>,
    pub unified_message: Option<UnifiedMessage>,
    pub additional_payout_method_data: Option<payout_method_utils::AdditionalPayoutMethodData>,
    pub merchant_order_reference_id: Option<String>,
}

impl Default for PayoutAttemptUpdateInternal {
    fn default() -> Self {
        Self {
            payout_token: None,
            connector_payout_id: None,
            status: None,
            error_message: None,
            error_code: None,
            is_eligible: None,
            business_country: None,
            business_label: None,
            connector: None,
            routing_info: None,
            merchant_connector_id: None,
            last_modified_at: common_utils::date_time::now(),
            address_id: None,
            customer_id: None,
            unified_code: None,
            unified_message: None,
            additional_payout_method_data: None,
            merchant_order_reference_id: None,
        }
    }
}

impl From<PayoutAttemptUpdate> for PayoutAttemptUpdateInternal {
    fn from(payout_update: PayoutAttemptUpdate) -> Self {
        match payout_update {
            PayoutAttemptUpdate::PayoutTokenUpdate { payout_token } => Self {
                payout_token: Some(payout_token),
                ..Default::default()
            },
            PayoutAttemptUpdate::StatusUpdate {
                connector_payout_id,
                status,
                error_message,
                error_code,
                is_eligible,
                unified_code,
                unified_message,
            } => Self {
                connector_payout_id,
                status: Some(status),
                error_message,
                error_code,
                is_eligible,
                unified_code,
                unified_message,
                ..Default::default()
            },
            PayoutAttemptUpdate::BusinessUpdate {
                business_country,
                business_label,
                address_id,
                customer_id,
            } => Self {
                business_country,
                business_label,
                address_id,
                customer_id,
                ..Default::default()
            },
            PayoutAttemptUpdate::UpdateRouting {
                connector,
                routing_info,
                merchant_connector_id,
            } => Self {
                connector: Some(connector),
                routing_info,
                merchant_connector_id,
                ..Default::default()
            },
            PayoutAttemptUpdate::AdditionalPayoutMethodDataUpdate {
                additional_payout_method_data,
            } => Self {
                additional_payout_method_data,
                ..Default::default()
            },
        }
    }
}

impl PayoutAttemptUpdate {
    pub fn apply_changeset(self, source: PayoutAttempt) -> PayoutAttempt {
        let PayoutAttemptUpdateInternal {
            payout_token,
            connector_payout_id,
            status,
            error_message,
            error_code,
            is_eligible,
            business_country,
            business_label,
            connector,
            routing_info,
            last_modified_at,
            address_id,
            customer_id,
            merchant_connector_id,
            unified_code,
            unified_message,
            additional_payout_method_data,
            merchant_order_reference_id,
        } = self.into();
        PayoutAttempt {
            payout_token: payout_token.or(source.payout_token),
            connector_payout_id: connector_payout_id.or(source.connector_payout_id),
            status: status.unwrap_or(source.status),
            error_message: error_message.or(source.error_message),
            error_code: error_code.or(source.error_code),
            is_eligible: is_eligible.or(source.is_eligible),
            business_country: business_country.or(source.business_country),
            business_label: business_label.or(source.business_label),
            connector: connector.or(source.connector),
            routing_info: routing_info.or(source.routing_info),
            last_modified_at,
            address_id: address_id.or(source.address_id),
            customer_id: customer_id.or(source.customer_id),
            merchant_connector_id: merchant_connector_id.or(source.merchant_connector_id),
            unified_code: unified_code.or(source.unified_code),
            unified_message: unified_message.or(source.unified_message),
            additional_payout_method_data: additional_payout_method_data
                .or(source.additional_payout_method_data),
            merchant_order_reference_id: merchant_order_reference_id
                .or(source.merchant_order_reference_id),
            ..source
        }
    }
}


// Function: create_success_based_routing
// File: crates/router/src/routes/routing.rs
// Module: router

pub fn create_success_based_routing(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<api_models::routing::CreateDynamicRoutingQuery>,
    path: web::Path<routing_types::ToggleDynamicRoutingPath>,
    success_based_config: web::Json<routing_types::SuccessBasedRoutingConfig>,
) -> impl Responder


// Function: generate_signature
// File: crates/hyperswitch_connectors/src/connectors/payone.rs
// Module: hyperswitch_connectors

pub fn generate_signature(
        &self,
        auth: payone::PayoneAuthType,
        http_method: String,
        canonicalized_path: String,
        content_type: String,
        date_header: String,
    ) -> CustomResult<String, ConnectorError>


// Module Structure
// File: crates/api_models/src/refunds.rs
// Module: api_models

// Public exports:
pub use common_utils::types::MinorUnit;


// Struct: LabelWithScoreEventResponse
// File: crates/router/src/core/payments/routing/utils.rs
// Module: router
// Implementations: 0

pub struct LabelWithScoreEventResponse


// Function: create_gsm_rule
// File: crates/router/src/core/gsm.rs
// Module: router

pub fn create_gsm_rule(
    state: SessionState,
    gsm_rule: gsm_api_types::GsmCreateRequest,
) -> RouterResponse<gsm_api_types::GsmResponse>


// Implementation: impl Authorization
// File: crates/diesel_models/src/query/authorization.rs
// Module: diesel_models
// Methods: 2 total (0 public)

impl Authorization


// Implementation: impl CardNetwork
// File: crates/common_enums/src/enums.rs
// Module: common_enums
// Methods: 2 total (2 public)

impl CardNetwork


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

pub fn call_surcharge_decision_management_for_session_flow(
    _state: &SessionState,
    _merchant_context: &domain::MerchantContext,
    _payment_attempt: &storage::PaymentAttempt,
    _payment_intent: &storage::PaymentIntent,
    _billing_address: Option<hyperswitch_domain_models::address::Address>,
    _session_connector_data: &[api::SessionConnectorData],
) -> RouterResult<Option<api::SessionSurchargeDetails>>


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

impl api::RefundSync for for Thunes


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

// Public submodules:
pub mod transformers;


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

pub fn get_description_category() -> JsResult


// Function: api_key_revoke
// File: crates/openapi/src/routes/api_keys.rs
// Module: openapi

pub fn api_key_revoke()


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

impl ConnectorSpecifications for for Xendit


// Struct: AirwallexPaymentsNextAction
// File: crates/hyperswitch_connectors/src/connectors/airwallex/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AirwallexPaymentsNextAction


// File: crates/router/tests/connectors/payone.rs
// Module: router

use masking::Secret;
use router::types::{self, domain, storage::enums};
use test_utils::connector_auth;

use crate::utils::{self, ConnectorActions};

#[derive(Clone, Copy)]
struct PayoneTest;
impl ConnectorActions for PayoneTest {}
impl utils::Connector for PayoneTest {
    fn get_data(&self) -> types::api::ConnectorData {
        use router::connector::Payone;
        utils::construct_connector_data_old(
            Box::new(Payone::new()),
            types::Connector::Payone,
            types::api::GetToken::Connector,
            None,
        )
    }

    fn get_auth_token(&self) -> types::ConnectorAuthType {
        utils::to_connector_auth_type(
            connector_auth::ConnectorAuthentication::new()
                .payone
                .expect("Missing connector authentication configuration")
                .into(),
        )
    }

    fn get_name(&self) -> String {
        "payone".to_string()
    }
}

static CONNECTOR: PayoneTest = PayoneTest {};

fn get_default_payment_info() -> Option<utils::PaymentInfo> {
    None
}

fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
    None
}

// Cards Positive Tests
// Creates a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_only_authorize_payment() {
    let response = CONNECTOR
        .authorize_payment(payment_method_details(), get_default_payment_info())
        .await
        .expect("Authorize payment response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized);
}

// Captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(payment_method_details(), None, get_default_payment_info())
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Partially captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(
            payment_method_details(),
            Some(types::PaymentsCaptureData {
                amount_to_capture: 50,
                ..utils::PaymentCaptureType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_authorized_payment() {
    let authorize_response = CONNECTOR
        .authorize_payment(payment_method_details(), get_default_payment_info())
        .await
        .expect("Authorize payment response");
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Authorized,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .expect("PSync response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
}

// Voids a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_void_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_void_payment(
            payment_method_details(),
            Some(types::PaymentsCancelData {
                connector_transaction_id: String::from(""),
                cancellation_reason: Some("requested_by_customer".to_string()),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .expect("Void payment response");
    assert_eq!(response.status, enums::AttemptStatus::Voided);
}

// Refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Synchronizes a refund using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_manually_captured_refund() {
    let refund_response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_make_payment() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_auto_captured_payment() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Charged,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                capture_method: Some(enums::CaptureMethod::Automatic),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(response.status, enums::AttemptStatus::Charged,);
}

// Refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_auto_captured_payment() {
    let response = CONNECTOR
        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_succeeded_payment() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        refund_response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_succeeded_payment_multiple_times() {
    CONNECTOR
        .make_payment_and_multiple_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await;
}

// Synchronizes a refund using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_refund() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Cards Negative scenarios
// Creates a payment with incorrect CVC.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_cvc: Secret::new("12345".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's security code is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry month.
#[actix_web::test]
async fn should_fail_payment_for_invalid_exp_month() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_exp_month: Secret::new("20".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration month is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry year.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_expiry_year() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_exp_year: Secret::new("2000".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration year is invalid.".to_string(),
    );
}

// Voids a payment using automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_fail_void_payment_for_auto_capture() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let void_response = CONNECTOR
        .void_payment(txn_id.unwrap(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        void_response.response.unwrap_err().message,
        "You cannot cancel this PaymentIntent because it has a status of succeeded."
    );
}

// Captures a payment using invalid connector payment id.
#[actix_web::test]
async fn should_fail_capture_for_invalid_payment() {
    let capture_response = CONNECTOR
        .capture_payment("123456789".to_string(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        capture_response.response.unwrap_err().message,
        String::from("No such payment_intent: '123456789'")
    );
}

// Refunds a payment with refund amount higher than payment amount.
#[actix_web::test]
async fn should_fail_for_refund_amount_higher_than_payment_amount() {
    let response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 150,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
    );
}

// Connector dependent test cases goes here

// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests


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

pub fn update_profile(
    state: SessionState,
    profile_id: &id_type::ProfileId,
    key_store: domain::MerchantKeyStore,
    request: api::ProfileUpdate,
) -> RouterResponse<api::ProfileResponse>


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

impl ConnectorCommon for for Phonepe


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

pub fn connector_delete()


// Struct: BluesnapErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/bluesnap/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BluesnapErrorResponse


// Struct: MandateId
// File: crates/api_models/src/mandates.rs
// Module: api_models
// Implementations: 0

pub struct MandateId


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

pub struct RefundResponse


// Function: is_deletable
// File: crates/router/src/services/authorization/roles.rs
// Module: router

pub fn is_deletable(&self) -> bool


// Struct: GatewayStatusMapperUpdateInternal
// File: crates/diesel_models/src/gsm.rs
// Module: diesel_models
// Implementations: 0

pub struct GatewayStatusMapperUpdateInternal


// Struct: VaultDeleteRequest
// File: crates/router/src/types/payment_methods.rs
// Module: router
// Implementations: 0

pub struct VaultDeleteRequest


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

impl Responder


// Function: check_if_profile_id_is_present_in_payment_intent
// File: crates/router/src/core/verification/utils.rs
// Module: router

pub fn check_if_profile_id_is_present_in_payment_intent(
    payment_id: PaymentId,
    state: &SessionState,
    auth_data: &AuthenticationData,
) -> CustomResult<(), errors::ApiErrorResponse>


// Implementation: impl AuthenticationConnectorData
// File: crates/router/src/types/api/authentication.rs
// Module: router
// Methods: 2 total (1 public)

impl AuthenticationConnectorData


// Struct: AirwallexCompleteRequest
// File: crates/hyperswitch_connectors/src/connectors/airwallex/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AirwallexCompleteRequest


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

impl api::PaymentSession for for Bambora


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

pub fn authenticate_pm_client_secret_and_check_expiry(
    req_client_secret: &String,
    payment_method: &domain::PaymentMethod,
) -> errors::CustomResult<bool, errors::ApiErrorResponse>


// Struct: KlarnaRefundSyncResponse
// File: crates/hyperswitch_connectors/src/connectors/klarna/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct KlarnaRefundSyncResponse


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

impl api::PaymentSync for for Tokenex