maud::html! {
                    (maud::DOCTYPE)
                    head {
                        (PreEscaped(r#""#))
                    }
                    body style="background-color: #ffffff; padding: 20px; font-family: Arial, Helvetica, Sans-Serif;" {

                        div id="loader-wrapper" {
                            div id="loader1" class="lottie" style="height: 150px; display: block; position: relative; margin-top: 150px; margin-left: auto; margin-right: auto;" { "" }

                        (PreEscaped(r#""#))

                        (PreEscaped(r#"

                            "#))

                        h3 style="text-align: center;" { "Please wait while we process your payment..." }
                        }

                        div id="threeds-wrapper" style="display: flex; width: 100%; height: 100vh; align-items: center; justify-content: center;" {""}
                    }
                    (PreEscaped(format!(""
            )))
                }
        }
        RedirectForm::Mifinity {
            initialization_token,
        } => {
            let mifinity_base_url = config.connectors.mifinity.base_url;
            maud::html! {
                        (maud::DOCTYPE)
                        head {
                            (PreEscaped(format!(r#""#)))
                        }

                        (PreEscaped(format!("

	  ")))

            }
        }
        RedirectForm::WorldpayDDCForm {
            endpoint,
            method,
            form_fields,
            collection_id,
        } => maud::html! {
            (maud::DOCTYPE)
            html {
                meta name="viewport" content="width=device-width, initial-scale=1";
                head {
                    (PreEscaped(r##"

                        "##))
                }

                body style="background-color: #ffffff; padding: 20px; font-family: Arial, Helvetica, Sans-Serif;" {
                    div id="loader1" class="lottie" style="height: 150px; display: block; position: relative; margin-left: auto; margin-right: auto;" { "" }
                    (PreEscaped(r#""#))
                    (PreEscaped(r#"

                    "#))
                    h3 style="text-align: center;" { "Please wait while we process your payment..." }

                    script {
                        (PreEscaped(format!(
                            r#"
                                var ddcProcessed = false;
                                var timeoutHandle = null;

                                function submitCollectionReference(collectionReference) {{
                                    if (ddcProcessed) {{
                                        console.log("DDC already processed, ignoring duplicate submission");
                                        return;
                                    }}
                                    ddcProcessed = true;

                                    if (timeoutHandle) {{
                                        clearTimeout(timeoutHandle);
                                        timeoutHandle = null;
                                    }}

                                    var redirectPathname = window.location.pathname.replace(/payments\/redirect\/([^\/]+)\/([^\/]+)\/[^\/]+/, "payments/$1/$2/redirect/complete/worldpay");
                                    var redirectUrl = window.location.origin + redirectPathname;
                                    try {{
                                        if (typeof collectionReference === "string" && collectionReference.length > 0) {{
                                            var form = document.createElement("form");
                                            form.action = redirectPathname;
                                            form.method = "GET";
                                            var input = document.createElement("input");
                                            input.type = "hidden";
                                            input.name = "collectionReference";
                                            input.value = collectionReference;
                                            form.appendChild(input);
                                            document.body.appendChild(form);
                                            form.submit();
                                        }} else {{
                                            window.location.replace(redirectUrl);
                                        }}
                                    }} catch (error) {{
                                        console.error("Error submitting DDC:", error);
                                        window.location.replace(redirectUrl);
                                    }}
                                }}
                                var allowedHost = "{}";
                                var collectionField = "{}";
                                window.addEventListener("message", function(event) {{
                                    if (ddcProcessed) {{
                                        console.log("DDC already processed, ignoring message event");
                                        return;
                                    }}
                                    if (event.origin === allowedHost) {{
                                        try {{
                                            var data = JSON.parse(event.data);
                                            if (collectionField.length > 0) {{
                                                var collectionReference = data[collectionField];
                                                return submitCollectionReference(collectionReference);
                                            }} else {{
                                                console.error("Collection field not found in event data (" + collectionField + ")");
                                            }}
                                        }} catch (error) {{
                                            console.error("Error parsing event data: ", error);
                                        }}
                                    }} else {{
                                        console.error("Invalid origin: " + event.origin, "Expected origin: " + allowedHost);
                                    }}

                                    submitCollectionReference("");
                                }});

                                // Timeout after 10 seconds and will submit empty collection reference
                                timeoutHandle = window.setTimeout(function() {{
                                    if (!ddcProcessed) {{
                                        console.log("DDC timeout reached, submitting empty collection reference");
                                        submitCollectionReference("");
                                    }}
                                }}, 10000);
                            "#,
                            endpoint.host_str().map_or(endpoint.as_ref().split('/').take(3).collect::<Vec<&str>>().join("/"), |host| format!("{}://{}", endpoint.scheme(), host)),
                            collection_id.clone().unwrap_or("".to_string())))
                        )
                    }

                    iframe
                        style="display: none;"
                        srcdoc=(
                            maud::html! {
                                (maud::DOCTYPE)
                                html {
                                    body {
                                        form action=(PreEscaped(endpoint.to_string())) method=(method.to_string()) #payment_form {
                                            @for (field, value) in form_fields {
                                                input type="hidden" name=(field) value=(value);
                                            }
                                        }
                                        (PreEscaped(format!(r#"

                                        "#)))
                                    }
                                }
                            }.into_string()
                        )
                        {}
                }
            }
        },
    }
}

fn build_payment_link_template(
    payment_link_data: PaymentLinkFormData,
) -> CustomResult<(Tera, Context), errors::ApiErrorResponse> {
    let mut tera = Tera::default();

    // Add modification to css template with dynamic data
    let css_template =
        include_str!("../core/payment_link/payment_link_initiate/payment_link.css").to_string();
    let _ = tera.add_raw_template("payment_link_css", &css_template);
    let mut context = Context::new();
    context.insert("css_color_scheme", &payment_link_data.css_script);

    let rendered_css = match tera.render("payment_link_css", &context) {
        Ok(rendered_css) => rendered_css,
        Err(tera_error) => {
            crate::logger::warn!("{tera_error}");
            Err(errors::ApiErrorResponse::InternalServerError)?
        }
    };

    // Add modification to js template with dynamic data
    let js_template =
        include_str!("../core/payment_link/payment_link_initiate/payment_link.js").to_string();

    let _ = tera.add_raw_template("payment_link_js", &js_template);

    context.insert("payment_details_js_script", &payment_link_data.js_script);
    let sdk_origin = payment_link_data
        .sdk_url
        .host_str()
        .ok_or_else(|| {
            logger::error!("Host missing for payment link SDK URL");
            report!(errors::ApiErrorResponse::InternalServerError)
        })
        .and_then(|host| {
            if host == "localhost" {
                let port = payment_link_data.sdk_url.port().ok_or_else(|| {
                    logger::error!("Port missing for localhost in SDK URL");
                    report!(errors::ApiErrorResponse::InternalServerError)
                })?;
                Ok(format!(
                    "{}://{}:{}",
                    payment_link_data.sdk_url.scheme(),
                    host,
                    port
                ))
            } else {
                Ok(format!("{}://{}", payment_link_data.sdk_url.scheme(), host))
            }
        })?;
    context.insert("sdk_origin", &sdk_origin);

    let rendered_js = match tera.render("payment_link_js", &context) {
        Ok(rendered_js) => rendered_js,
        Err(tera_error) => {
            crate::logger::warn!("{tera_error}");
            Err(errors::ApiErrorResponse::InternalServerError)?
        }
    };

    // Logging template
    let logging_template =
        include_str!("redirection/assets/redirect_error_logs_push.js").to_string();
    //Locale template
    let locale_template = include_str!("../core/payment_link/locale.js").to_string();

    // Modify Html template with rendered js and rendered css files
    let html_template =
        include_str!("../core/payment_link/payment_link_initiate/payment_link.html").to_string();

    let _ = tera.add_raw_template("payment_link", &html_template);

    context.insert("rendered_meta_tag_html", &payment_link_data.html_meta_tags);

    context.insert(
        "preload_link_tags",
        &get_preload_link_html_template(&payment_link_data.sdk_url),
    );

    context.insert(
        "hyperloader_sdk_link",
        &get_hyper_loader_sdk(&payment_link_data.sdk_url),
    );
    context.insert("locale_template", &locale_template);
    context.insert("rendered_css", &rendered_css);
    context.insert("rendered_js", &rendered_js);

    context.insert("logging_template", &logging_template);

    Ok((tera, context))
}

pub fn build_payment_link_html(
    payment_link_data: PaymentLinkFormData,
) -> CustomResult<String, errors::ApiErrorResponse> {
    let (tera, mut context) = build_payment_link_template(payment_link_data)
        .attach_printable("Failed to build payment link's HTML template")?;
    let payment_link_initiator =
        include_str!("../core/payment_link/payment_link_initiate/payment_link_initiator.js")
            .to_string();
    context.insert("payment_link_initiator", &payment_link_initiator);

    tera.render("payment_link", &context)
        .map_err(|tera_error: TeraError| {
            crate::logger::warn!("{tera_error}");
            report!(errors::ApiErrorResponse::InternalServerError)
        })
        .attach_printable("Error while rendering open payment link's HTML template")
}

pub fn build_secure_payment_link_html(
    payment_link_data: PaymentLinkFormData,
) -> CustomResult<String, errors::ApiErrorResponse> {
    let (tera, mut context) = build_payment_link_template(payment_link_data)


// Struct: RefundMetaData
// File: crates/hyperswitch_connectors/src/connectors/gocardless/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RefundMetaData


// Function: trigger_event
// File: crates/router/src/core/payments/routing/utils.rs
// Module: router

pub fn trigger_event<Res, F, Fut>(
        self,
        state: &SessionState,
        func: F,
    ) -> RoutingResult<RoutingEventsResponse<Res>>
    where
        F: FnOnce() -> Fut + Send,
        Res: Serialize + serde::de::DeserializeOwned + Clone,
        Fut: futures::Future<Output = RoutingResult<Option<Res>>> + Send,


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

impl api::ConnectorAccessToken for for Authipay


// Function: create_config
// File: crates/diesel_models/src/configs.rs
// Module: diesel_models

pub fn create_config(self, source: Config) -> Config


// Trait: ShouldCallConnector
// File: crates/router/src/core/payments/operations.rs
// Module: router

// Documentation: Should the connector be called for this operation

pub trait ShouldCallConnector


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

pub struct BluesnapCaptureRequest


            PaymentMethodType::GoPay => Self::Wallet,
            PaymentMethodType::Gcash => Self::Wallet,
            PaymentMethodType::Mifinity => Self::Wallet,
            PaymentMethodType::Ideal => Self::BankRedirect,
            PaymentMethodType::Klarna => Self::PayLater,
            PaymentMethodType::KakaoPay => Self::Wallet,
            PaymentMethodType::Knet => Self::CardRedirect,
            PaymentMethodType::LocalBankRedirect => Self::BankRedirect,
            PaymentMethodType::MbWay => Self::Wallet,
            PaymentMethodType::MobilePay => Self::Wallet,
            PaymentMethodType::Momo => Self::Wallet,
            PaymentMethodType::MomoAtm => Self::CardRedirect,
            PaymentMethodType::Multibanco => Self::BankTransfer,
            PaymentMethodType::MandiriVa => Self::BankTransfer,
            PaymentMethodType::Interac => Self::BankRedirect,
            PaymentMethodType::InstantBankTransfer => Self::BankTransfer,
            PaymentMethodType::InstantBankTransferFinland => Self::BankTransfer,
            PaymentMethodType::InstantBankTransferPoland => Self::BankTransfer,
            PaymentMethodType::Indomaret => Self::Voucher,
            PaymentMethodType::OnlineBankingCzechRepublic => Self::BankRedirect,
            PaymentMethodType::OnlineBankingFinland => Self::BankRedirect,
            PaymentMethodType::OnlineBankingFpx => Self::BankRedirect,
            PaymentMethodType::OnlineBankingThailand => Self::BankRedirect,
            PaymentMethodType::OnlineBankingPoland => Self::BankRedirect,
            PaymentMethodType::OnlineBankingSlovakia => Self::BankRedirect,
            PaymentMethodType::Paze => Self::Wallet,
            PaymentMethodType::PermataBankTransfer => Self::BankTransfer,
            PaymentMethodType::Pix => Self::BankTransfer,
            PaymentMethodType::Pse => Self::BankTransfer,
            PaymentMethodType::LocalBankTransfer => Self::BankTransfer,
            PaymentMethodType::PayBright => Self::PayLater,
            PaymentMethodType::Paypal => Self::Wallet,
            PaymentMethodType::PaySafeCard => Self::GiftCard,
            PaymentMethodType::Przelewy24 => Self::BankRedirect,
            PaymentMethodType::PromptPay => Self::RealTimePayment,
            PaymentMethodType::SamsungPay => Self::Wallet,
            PaymentMethodType::Sepa => Self::BankDebit,
            PaymentMethodType::SepaBankTransfer => Self::BankTransfer,
            PaymentMethodType::Sofort => Self::BankRedirect,
            PaymentMethodType::Swish => Self::BankRedirect,
            PaymentMethodType::Trustly => Self::BankRedirect,
            PaymentMethodType::Twint => Self::Wallet,
            PaymentMethodType::UpiCollect => Self::Upi,
            PaymentMethodType::UpiIntent => Self::Upi,
            PaymentMethodType::Vipps => Self::Wallet,
            PaymentMethodType::Venmo => Self::Wallet,
            PaymentMethodType::VietQr => Self::RealTimePayment,
            PaymentMethodType::Walley => Self::PayLater,
            PaymentMethodType::WeChatPay => Self::Wallet,
            PaymentMethodType::TouchNGo => Self::Wallet,
            PaymentMethodType::Atome => Self::PayLater,
            PaymentMethodType::Boleto => Self::Voucher,
            PaymentMethodType::Efecty => Self::Voucher,
            PaymentMethodType::PagoEfectivo => Self::Voucher,
            PaymentMethodType::RedCompra => Self::Voucher,
            PaymentMethodType::RedPagos => Self::Voucher,
            PaymentMethodType::Cashapp => Self::Wallet,
            PaymentMethodType::BhnCardNetwork => Self::GiftCard,
            PaymentMethodType::Givex => Self::GiftCard,
            PaymentMethodType::Oxxo => Self::Voucher,
            PaymentMethodType::OpenBankingUk => Self::BankRedirect,
            PaymentMethodType::SevenEleven => Self::Voucher,
            PaymentMethodType::Lawson => Self::Voucher,
            PaymentMethodType::MiniStop => Self::Voucher,
            PaymentMethodType::FamilyMart => Self::Voucher,
            PaymentMethodType::Seicomart => Self::Voucher,
            PaymentMethodType::PayEasy => Self::Voucher,
            PaymentMethodType::OpenBankingPIS => Self::OpenBanking,
            PaymentMethodType::DirectCarrierBilling => Self::MobilePayment,
            PaymentMethodType::RevolutPay => Self::Wallet,
            PaymentMethodType::IndonesianBankTransfer => Self::BankTransfer,
        }
    }
}

#[derive(Debug)]
pub struct NumericCountryCodeParseError;
#[allow(dead_code)]
mod custom_serde {
    use super::*;

    pub mod alpha2_country_code {
        use std::fmt;

        use serde::de::Visitor;

        use super::*;

        // `serde::Serialize` implementation needs the function to accept `&Country`
        #[allow(clippy::trivially_copy_pass_by_ref)]
        pub fn serialize<S>(code: &Country, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer,
        {
            code.to_alpha2().serialize(serializer)
        }

        struct FieldVisitor;

        impl Visitor<'_> for FieldVisitor {
            type Value = CountryAlpha2;

            fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
                formatter.write_str("CountryAlpha2 as a string")
            }
        }

        pub fn deserialize<'a, D>(deserializer: D) -> Result<Country, D::Error>
        where
            D: serde::Deserializer<'a>,
        {
            CountryAlpha2::deserialize(deserializer).map(Country::from_alpha2)
        }
    }

    pub mod alpha3_country_code {
        use std::fmt;

        use serde::de::Visitor;

        use super::*;

        // `serde::Serialize` implementation needs the function to accept `&Country`
        #[allow(clippy::trivially_copy_pass_by_ref)]
        pub fn serialize<S>(code: &Country, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer,
        {
            code.to_alpha3().serialize(serializer)
        }

        struct FieldVisitor;

        impl Visitor<'_> for FieldVisitor {
            type Value = CountryAlpha3;

            fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
                formatter.write_str("CountryAlpha3 as a string")
            }
        }

        pub fn deserialize<'a, D>(deserializer: D) -> Result<Country, D::Error>
        where
            D: serde::Deserializer<'a>,
        {
            CountryAlpha3::deserialize(deserializer).map(Country::from_alpha3)
        }
    }

    pub mod numeric_country_code {
        use std::fmt;

        use serde::de::Visitor;

        use super::*;

        // `serde::Serialize` implementation needs the function to accept `&Country`
        #[allow(clippy::trivially_copy_pass_by_ref)]
        pub fn serialize<S>(code: &Country, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer,
        {
            code.to_numeric().serialize(serializer)
        }

        struct FieldVisitor;

        impl Visitor<'_> for FieldVisitor {
            type Value = u32;

            fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
                formatter.write_str("Numeric country code passed as an u32")
            }
        }

        pub fn deserialize<'a, D>(deserializer: D) -> Result<Country, D::Error>
        where
            D: serde::Deserializer<'a>,
        {
            u32::deserialize(deserializer)
                .and_then(|value| Country::from_numeric(value).map_err(serde::de::Error::custom))
        }
    }
}

impl From<Option<bool>> for super::External3dsAuthenticationRequest {
    fn from(value: Option<bool>) -> Self {
        match value {
            Some(true) => Self::Enable,
            _ => Self::Skip,
        }
    }
}

/// Get the boolean value of the `External3dsAuthenticationRequest`.
impl super::External3dsAuthenticationRequest {
    pub fn as_bool(&self) -> bool {
        match self {
            Self::Enable => true,
            Self::Skip => false,
        }
    }
}

impl super::EnablePaymentLinkRequest {
    pub fn as_bool(&self) -> bool {
        match self {
            Self::Enable => true,
            Self::Skip => false,
        }
    }
}

impl From<Option<bool>> for super::EnablePaymentLinkRequest {
    fn from(value: Option<bool>) -> Self {
        match value {
            Some(true) => Self::Enable,
            _ => Self::Skip,
        }
    }
}

impl From<Option<bool>> for super::MitExemptionRequest {
    fn from(value: Option<bool>) -> Self {
        match value {
            Some(true) => Self::Apply,
            _ => Self::Skip,
        }
    }
}

impl super::MitExemptionRequest {
    pub fn as_bool(&self) -> bool {
        match self {
            Self::Apply => true,
            Self::Skip => false,
        }
    }
}

impl From<Option<bool>> for super::PresenceOfCustomerDuringPayment {
    fn from(value: Option<bool>) -> Self {
        match value {
            Some(false) => Self::Absent,
            _ => Self::Present,
        }
    }
}

impl super::PresenceOfCustomerDuringPayment {
    pub fn as_bool(&self) -> bool {
        match self {
            Self::Present => true,
            Self::Absent => false,
        }
    }
}

impl From<AttemptStatus> for IntentStatus {
    fn from(s: AttemptStatus) -> Self {
        match s {
            AttemptStatus::Charged | AttemptStatus::AutoRefunded => Self::Succeeded,

            AttemptStatus::ConfirmationAwaited => Self::RequiresConfirmation,
            AttemptStatus::PaymentMethodAwaited => Self::RequiresPaymentMethod,

            AttemptStatus::Authorized => Self::RequiresCapture,
            AttemptStatus::AuthenticationPending | AttemptStatus::DeviceDataCollectionPending => {
                Self::RequiresCustomerAction
            }
            AttemptStatus::Unresolved => Self::RequiresMerchantAction,
            AttemptStatus::IntegrityFailure => Self::Conflicted,
            AttemptStatus::PartialCharged => Self::PartiallyCaptured,
            AttemptStatus::PartialChargedAndChargeable => Self::PartiallyCapturedAndCapturable,
            AttemptStatus::Started
            | AttemptStatus::AuthenticationSuccessful
            | AttemptStatus::Authorizing
            | AttemptStatus::CodInitiated
            | AttemptStatus::VoidInitiated
            | AttemptStatus::CaptureInitiated
            | AttemptStatus::Pending => Self::Processing,

            AttemptStatus::AuthenticationFailed
            | AttemptStatus::AuthorizationFailed
            | AttemptStatus::VoidFailed
            | AttemptStatus::RouterDeclined
            | AttemptStatus::CaptureFailed
            | AttemptStatus::Failure => Self::Failed,
            AttemptStatus::Voided => Self::Cancelled,
            AttemptStatus::VoidedPostCharge => Self::CancelledPostCapture,
            AttemptStatus::Expired => Self::Expired,
            AttemptStatus::PartiallyAuthorized => Self::PartiallyAuthorizedAndRequiresCapture,
        }
    }
}

impl From<IntentStatus> for Option<EventType> {
    fn from(value: IntentStatus) -> Self {
        match value {
            IntentStatus::Succeeded => Some(EventType::PaymentSucceeded),
            IntentStatus::Failed => Some(EventType::PaymentFailed),
            IntentStatus::Processing => Some(EventType::PaymentProcessing),
            IntentStatus::RequiresMerchantAction
            | IntentStatus::RequiresCustomerAction
            | IntentStatus::Conflicted => Some(EventType::ActionRequired),
            IntentStatus::Cancelled => Some(EventType::PaymentCancelled),
            IntentStatus::CancelledPostCapture => Some(EventType::PaymentCancelledPostCapture),
            IntentStatus::Expired => Some(EventType::PaymentExpired),
            IntentStatus::PartiallyCaptured | IntentStatus::PartiallyCapturedAndCapturable => {
                Some(EventType::PaymentCaptured)
            }
            IntentStatus::RequiresCapture => Some(EventType::PaymentAuthorized),
            IntentStatus::RequiresPaymentMethod | IntentStatus::RequiresConfirmation => None,
            IntentStatus::PartiallyAuthorizedAndRequiresCapture => {
                Some(EventType::PaymentPartiallyAuthorized)
            }
        }
    }
}

impl From<RefundStatus> for Option<EventType> {
    fn from(value: RefundStatus) -> Self {
        match value {
            RefundStatus::Success => Some(EventType::RefundSucceeded),
            RefundStatus::Failure => Some(EventType::RefundFailed),
            RefundStatus::ManualReview
            | RefundStatus::Pending
            | RefundStatus::TransactionFailure => None,
        }
    }
}

#[cfg(feature = "payouts")]
impl From<PayoutStatus> for Option<EventType> {
    fn from(value: PayoutStatus) -> Self {
        match value {
            PayoutStatus::Success => Some(EventType::PayoutSuccess),
            PayoutStatus::Failed => Some(EventType::PayoutFailed),
            PayoutStatus::Cancelled => Some(EventType::PayoutCancelled),
            PayoutStatus::Initiated => Some(EventType::PayoutInitiated),
            PayoutStatus::Expired => Some(EventType::PayoutExpired),
            PayoutStatus::Reversed => Some(EventType::PayoutReversed),
            PayoutStatus::Ineligible
            | PayoutStatus::Pending
            | PayoutStatus::RequiresCreation
            | PayoutStatus::RequiresFulfillment
            | PayoutStatus::RequiresPayoutMethodData
            | PayoutStatus::RequiresVendorAccountCreation
            | PayoutStatus::RequiresConfirmation => None,
        }
    }
}

impl From<DisputeStatus> for EventType {
    fn from(value: DisputeStatus) -> Self {
        match value {
            DisputeStatus::DisputeOpened => Self::DisputeOpened,
            DisputeStatus::DisputeExpired => Self::DisputeExpired,
            DisputeStatus::DisputeAccepted => Self::DisputeAccepted,
            DisputeStatus::DisputeCancelled => Self::DisputeCancelled,
            DisputeStatus::DisputeChallenged => Self::DisputeChallenged,
            DisputeStatus::DisputeWon => Self::DisputeWon,
            DisputeStatus::DisputeLost => Self::DisputeLost,
        }
    }
}

impl From<MandateStatus> for Option<EventType> {
    fn from(value: MandateStatus) -> Self {
        match value {
            MandateStatus::Active => Some(EventType::MandateActive),
            MandateStatus::Revoked => Some(EventType::MandateRevoked),
            MandateStatus::Inactive | MandateStatus::Pending => None,
        }
    }
}

#[cfg(test)]
mod tests {
    #![allow(clippy::unwrap_used)]

    use super::*;

    #[derive(serde::Serialize)]
    struct Alpha2Request {
        #[serde(with = "custom_serde::alpha2_country_code")]
        pub country: Country,
    }

    #[derive(serde::Serialize)]
    struct Alpha3Request {
        #[serde(with = "custom_serde::alpha3_country_code")]
        pub country: Country,
    }

    #[derive(serde::Serialize)]
    struct NumericRequest {
        #[serde(with = "custom_serde::numeric_country_code")]
        pub country: Country,
    }

    #[derive(serde::Serialize, serde::Deserialize)]
    struct HyperswitchRequestAlpha2 {
        #[serde(with = "custom_serde::alpha2_country_code")]
        pub country: Country,
    }

    #[derive(serde::Serialize, serde::Deserialize)]
    struct HyperswitchRequestAlpha3 {
        #[serde(with = "custom_serde::alpha3_country_code")]
        pub country: Country,
    }

    #[derive(serde::Serialize, serde::Deserialize, Debug)]
    struct HyperswitchRequestNumeric {
        #[serde(with = "custom_serde::numeric_country_code")]
        pub country: Country,
    }

    #[test]
    fn test_serialize_alpha2() {
        let x_request = Alpha2Request {
            country: Country::India,
        };
        let serialized_country = serde_json::to_string(&x_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":"IN"}"#);

        let x_request = Alpha2Request {
            country: Country::MacedoniaTheFormerYugoslavRepublic,
        };
        let serialized_country = serde_json::to_string(&x_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":"MK"}"#);

        let x_request = Alpha2Request {
            country: Country::FrenchSouthernTerritories,
        };
        let serialized_country = serde_json::to_string(&x_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":"TF"}"#);
    }

    #[test]
    fn test_serialize_alpha3() {
        let y_request = Alpha3Request {
            country: Country::India,
        };
        let serialized_country = serde_json::to_string(&y_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":"IND"}"#);

        let y_request = Alpha3Request {
            country: Country::HeardIslandAndMcDonaldIslands,
        };
        let serialized_country = serde_json::to_string(&y_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":"HMD"}"#);

        let y_request = Alpha3Request {
            country: Country::Argentina,
        };
        let serialized_country = serde_json::to_string(&y_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":"ARG"}"#);
    }

    #[test]
    fn test_serialize_numeric() {
        let y_request = NumericRequest {
            country: Country::India,
        };
        let serialized_country = serde_json::to_string(&y_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":356}"#);

        let y_request = NumericRequest {
            country: Country::Bermuda,
        };
        let serialized_country = serde_json::to_string(&y_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":60}"#);

        let y_request = NumericRequest {
            country: Country::GuineaBissau,
        };
        let serialized_country = serde_json::to_string(&y_request).unwrap();
        assert_eq!(serialized_country, r#"{"country":624}"#);
    }

    #[test]
    fn test_deserialize_alpha2() {
        let request_str = r#"{"country":"IN"}"#;
        let request = serde_json::from_str::<HyperswitchRequestAlpha2>(request_str).unwrap();
        assert_eq!(request.country, Country::India);

        let request_str = r#"{"country":"GR"}"#;
        let request = serde_json::from_str::<HyperswitchRequestAlpha2>(request_str).unwrap();
        assert_eq!(request.country, Country::Greece);

        let request_str = r#"{"country":"IQ"}"#;
        let request = serde_json::from_str::<HyperswitchRequestAlpha2>(request_str).unwrap();
        assert_eq!(request.country, Country::Iraq);
    }

    #[test]
    fn test_deserialize_alpha3() {
        let request_str = r#"{"country":"IND"}"#;
        let request = serde_json::from_str::<HyperswitchRequestAlpha3>(request_str).unwrap();
        assert_eq!(request.country, Country::India);

        let request_str = r#"{"country":"LVA"}"#;
        let request = serde_json::from_str::<HyperswitchRequestAlpha3>(request_str).unwrap();
        assert_eq!(request.country, Country::Latvia);

        let request_str = r#"{"country":"PNG"}"#;
        let request = serde_json::from_str::<HyperswitchRequestAlpha3>(request_str).unwrap();
        assert_eq!(request.country, Country::PapuaNewGuinea);
    }

    #[test]
    fn test_deserialize_numeric() {
        let request_str = r#"{"country":356}"#;
        let request = serde_json::from_str::<HyperswitchRequestNumeric>(request_str).unwrap();
        assert_eq!(request.country, Country::India);

        let request_str = r#"{"country":239}"#;
        let request = serde_json::from_str::<HyperswitchRequestNumeric>(request_str).unwrap();
        assert_eq!(
            request.country,
            Country::SouthGeorgiaAndTheSouthSandwichIslands
        );

        let request_str = r#"{"country":826}"#;
        let request = serde_json::from_str::<HyperswitchRequestNumeric>(request_str).unwrap();
        assert_eq!(
            request.country,
            Country::UnitedKingdomOfGreatBritainAndNorthernIreland
        );
    }

    #[test]
    fn test_deserialize_and_serialize() {
        // Deserialize the country as alpha2 code
        // Serialize the country as alpha3 code
        let request_str = r#"{"country":"IN"}"#;
        let request = serde_json::from_str::<HyperswitchRequestAlpha2>(request_str).unwrap();
        let alpha3_request = Alpha3Request {
            country: request.country,
        };
        let response = serde_json::to_string::<Alpha3Request>(&alpha3_request).unwrap();
        assert_eq!(response, r#"{"country":"IND"}"#)
    }

    #[test]
    fn test_serialize_and_deserialize() {
        let request_str = r#"{"country":"AX"}"#;
        let request = serde_json::from_str::<HyperswitchRequestAlpha2>(request_str).unwrap();
        let alpha3_request = Alpha3Request {
            country: request.country,
        };
        let response = serde_json::to_string::<Alpha3Request>(&alpha3_request).unwrap();
        assert_eq!(response, r#"{"country":"ALA"}"#);

        let result = serde_json::from_str::<HyperswitchRequestAlpha3>(response.as_str()).unwrap();
        assert_eq!(result.country, Country::AlandIslands);
    }

    #[test]
    fn test_deserialize_invalid_country_code() {
        let request_str = r#"{"country": 123456}"#;
        let result: Result<HyperswitchRequestNumeric, _> =
            serde_json::from_str::<HyperswitchRequestNumeric>(request_str);
        assert!(result.is_err());
    }
}


// Struct: RedirectionFormData
// File: crates/hyperswitch_domain_models/src/api.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct RedirectionFormData


// Struct: TrustpaymentsFilterValue
// File: crates/hyperswitch_connectors/src/connectors/trustpayments/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TrustpaymentsFilterValue


// Function: get_card_range_if_available
// File: crates/hyperswitch_connectors/src/connectors/netcetera/transformers.rs
// Module: hyperswitch_connectors

pub fn get_card_range_if_available(&self) -> Option<CardRange>


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

impl api::PaymentsCompleteAuthorize for for Shift4


// Struct: Frequency
// File: crates/hyperswitch_connectors/src/connectors/amazonpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Frequency


// Implementation: impl Forex
// File: crates/router/src/routes/app.rs
// Module: router
// Methods: 1 total (1 public)

impl Forex


// Function: update
// File: crates/api_models/src/open_router.rs
// Module: api_models

pub fn update(&mut self, new_config: Self)


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

pub struct VaultRetrieveRequest


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

use hyperswitch_domain_models::payment_method_data::{Card, PaymentMethodData};
use masking::Secret;
use router::types::{self, api, storage::enums};
use test_utils::connector_auth;

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

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

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

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

static CONNECTOR: InespayTest = InespayTest {};

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: PaymentMethodData::Card(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: PaymentMethodData::Card(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: PaymentMethodData::Card(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


// Struct: WorldpayxmlAuthType
// File: crates/hyperswitch_connectors/src/connectors/worldpayxml/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct WorldpayxmlAuthType


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

pub struct AuthEventMetricsResponse<T>


// Struct: PayeezyPaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/payeezy/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PayeezyPaymentsResponse


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

pub fn check_permission_exists(&self, required_permission: Permission) -> bool


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

impl ConnectorCommon for for Paytm


// Struct: EncryptedDataGroup
// File: crates/common_utils/src/types/keymanager.rs
// Module: common_utils
// Implementations: 0

pub struct EncryptedDataGroup


// Struct: TrustpaymentsRouterData
// File: crates/hyperswitch_connectors/src/connectors/trustpayments/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TrustpaymentsRouterData<T>


// Function: negation
// File: crates/euclid/src/dssa/types.rs
// Module: euclid

pub fn negation(values: &'a [dir::DirValue], metadata: &'a Metadata) -> Self


// Implementation: impl api::PayoutSync for for Wise
// File: crates/hyperswitch_connectors/src/connectors/wise.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PayoutSync for for Wise


// Function: update_by_user_id_tenant_id_org_id_merchant_id_profile_id
// File: crates/diesel_models/src/query/user_role.rs
// Module: diesel_models

pub fn update_by_user_id_tenant_id_org_id_merchant_id_profile_id(
        conn: &PgPooledConn,
        user_id: String,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
        merchant_id: Option<id_type::MerchantId>,
        profile_id: Option<id_type::ProfileId>,
        update: UserRoleUpdate,
        version: UserRoleVersion,
    ) -> StorageResult<Self>


// Struct: TokenioApiWrapper
// File: crates/hyperswitch_connectors/src/connectors/tokenio/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TokenioApiWrapper


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

pub struct BankRedirectRefundResponse


// Struct: Metadata
// File: crates/hyperswitch_connectors/src/connectors/razorpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Metadata


// Implementation: impl PollConfig
// File: crates/router/src/types.rs
// Module: router
// Methods: 1 total (1 public)

impl PollConfig


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

pub struct NuveiTxnPartialApproval


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

pub fn validate_uniqueness_of_payout_id_against_merchant_id(
    db: &dyn StorageInterface,
    payout_id: &id_type::PayoutId,
    merchant_id: &id_type::MerchantId,
    storage_scheme: storage::enums::MerchantStorageScheme,
) -> RouterResult<Option<storage::Payouts>>


// Struct: NetworkTokenExpiry
// File: crates/router/src/core/payments.rs
// Module: router
// Implementations: 0

pub struct NetworkTokenExpiry


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

pub fn server(state: AppState) -> Scope


// Struct: FinixCard
// File: crates/hyperswitch_connectors/src/connectors/finix/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FinixCard


// Struct: DiscountCodes
// File: crates/hyperswitch_connectors/src/connectors/riskified/transformers/api.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DiscountCodes


// Function: diesel_error_to_data_error
// File: crates/storage_impl/src/lib.rs
// Module: storage_impl

pub fn diesel_error_to_data_error(
    diesel_error: diesel_models::errors::DatabaseError,
) -> StorageError


// Function: get_decision_based_on_params
// File: crates/router/src/core/revenue_recovery/types.rs
// Module: router

pub fn get_decision_based_on_params(
        state: &SessionState,
        intent_status: enums::IntentStatus,
        called_connector: enums::PaymentConnectorTransmission,
        active_attempt_id: Option<id_type::GlobalAttemptId>,
        revenue_recovery_data: &storage::revenue_recovery::RevenueRecoveryPaymentData,
        payment_id: &id_type::GlobalPaymentId,
    ) -> RecoveryResult<Self>


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

pub struct SdkEventFiltersResponse


// Implementation: impl std::fmt::Display for for KvOperation
// File: crates/storage_impl/src/redis/kv_store.rs
// Module: storage_impl
// Methods: 1 total (0 public)

impl std::fmt::Display for for KvOperation


// Implementation: impl PartialEq for for AuthEventMetricsBucketIdentifier
// File: crates/api_models/src/analytics/auth_events.rs
// Module: api_models
// Methods: 1 total (0 public)

impl PartialEq for for AuthEventMetricsBucketIdentifier


// Function: profile_create
// File: crates/openapi/src/routes/profile.rs
// Module: openapi

pub fn profile_create()


// Struct: BraintreeAuthType
// File: crates/hyperswitch_connectors/src/connectors/braintree/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BraintreeAuthType


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

impl Mollie


// Struct: RetryFeatureData
// File: crates/common_types/src/domain.rs
// Module: common_types
// Implementations: 1

pub struct RetryFeatureData


// Struct: FlexitiPaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/flexiti/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FlexitiPaymentsResponse


        _ => None,
    }
}

/// Concatenates a vector of strings without any separator
/// This is useful for creating verification messages for webhooks
pub fn concat_strings(strings: &[String]) -> String {
    strings.join("")
}

fn convert_to_additional_payment_method_connector_response(
    payment_option: Option<PaymentOption>,
) -> Option<AdditionalPaymentMethodConnectorResponse> {
    let card = payment_option.as_ref()?.card.as_ref()?;
    let avs_code = card.avs_code.as_ref();
    let cvv2_code = card.cvv2_reply.as_ref();

    let avs_description = avs_code.and_then(|code| get_avs_response_description(code));
    let cvv_description = cvv2_code.and_then(|code| get_cvv2_response_description(code));

    let payment_checks = serde_json::json!({
        "avs_result": avs_code,
        "avs_description": avs_description,
        "card_validation_result": cvv2_code,
        "card_validation_description": cvv_description,
    });

    let card_network = card.brand.clone();
    let three_ds_data = card
        .three_d
        .clone()
        .map(|three_d| {
            serde_json::to_value(three_d)
                .map_err(|_| errors::ConnectorError::ResponseHandlingFailed)
                .attach_printable("threeDs encoding failed Nuvei")
        })
        .transpose();

    match three_ds_data {
        Ok(authentication_data) => Some(AdditionalPaymentMethodConnectorResponse::Card {
            authentication_data,
            payment_checks: Some(payment_checks),
            card_network,
            domestic_network: None,
        }),
        Err(_) => None,
    }
}

pub fn map_notification_to_event(
    status: DmnStatus,
    transaction_type: NuveiTransactionType,
) -> Result<api_models::webhooks::IncomingWebhookEvent, error_stack::Report<errors::ConnectorError>>
{
    match (status, transaction_type) {
        (DmnStatus::Success | DmnStatus::Approved, NuveiTransactionType::Auth) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentAuthorizationSuccess)
        }
        (DmnStatus::Success | DmnStatus::Approved, NuveiTransactionType::Sale) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentSuccess)
        }
        (DmnStatus::Success | DmnStatus::Approved, NuveiTransactionType::Settle) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentCaptureSuccess)
        }
        (DmnStatus::Success | DmnStatus::Approved, NuveiTransactionType::Void) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentCancelled)
        }
        (DmnStatus::Success | DmnStatus::Approved, NuveiTransactionType::Credit) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::RefundSuccess)
        }
        (DmnStatus::Error | DmnStatus::Declined, NuveiTransactionType::Auth) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentAuthorizationFailure)
        }
        (DmnStatus::Error | DmnStatus::Declined, NuveiTransactionType::Sale) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentFailure)
        }
        (DmnStatus::Error | DmnStatus::Declined, NuveiTransactionType::Settle) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentCaptureFailure)
        }
        (DmnStatus::Error | DmnStatus::Declined, NuveiTransactionType::Void) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentCancelFailure)
        }
        (DmnStatus::Error | DmnStatus::Declined, NuveiTransactionType::Credit) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::RefundFailure)
        }
        (
            DmnStatus::Pending,
            NuveiTransactionType::Auth | NuveiTransactionType::Sale | NuveiTransactionType::Settle,
        ) => Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentProcessing),
        _ => Err(errors::ConnectorError::WebhookEventTypeNotFound.into()),
    }
}

#[cfg(feature = "payouts")]
pub fn map_notification_to_event_for_payout(
    status: DmnStatus,
    transaction_type: NuveiTransactionType,
) -> Result<api_models::webhooks::IncomingWebhookEvent, error_stack::Report<errors::ConnectorError>>
{
    match (status, transaction_type) {
        (DmnStatus::Success | DmnStatus::Approved, NuveiTransactionType::Credit) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PayoutSuccess)
        }
        (DmnStatus::Pending, _) => Ok(api_models::webhooks::IncomingWebhookEvent::PayoutProcessing),
        (DmnStatus::Declined | DmnStatus::Error, _) => {
            Ok(api_models::webhooks::IncomingWebhookEvent::PayoutFailure)
        }
        _ => Err(errors::ConnectorError::WebhookEventTypeNotFound.into()),
    }
}

pub fn map_dispute_notification_to_event(
    dispute_code: DisputeUnifiedStatusCode,
) -> Result<api_models::webhooks::IncomingWebhookEvent, error_stack::Report<errors::ConnectorError>>
{
    match dispute_code {
        DisputeUnifiedStatusCode::FirstChargebackInitiatedByIssuer
        | DisputeUnifiedStatusCode::CreditChargebackInitiatedByIssuer
        | DisputeUnifiedStatusCode::McCollaborationInitiatedByIssuer
        | DisputeUnifiedStatusCode::FirstChargebackClosedRecall
        | DisputeUnifiedStatusCode::InquiryInitiatedByIssuer => {
            Ok(api_models::webhooks::IncomingWebhookEvent::DisputeOpened)
        }
        DisputeUnifiedStatusCode::CreditChargebackAcceptedAutomatically
        | DisputeUnifiedStatusCode::FirstChargebackAcceptedAutomatically
        | DisputeUnifiedStatusCode::FirstChargebackAcceptedAutomaticallyMcoll
        | DisputeUnifiedStatusCode::FirstChargebackAcceptedByMerchant
        | DisputeUnifiedStatusCode::FirstChargebackDisputeResponseNotAllowed
        | DisputeUnifiedStatusCode::Rdr
        | DisputeUnifiedStatusCode::McCollaborationRefundedByMerchant
        | DisputeUnifiedStatusCode::McCollaborationAutomaticAccept
        | DisputeUnifiedStatusCode::InquiryAcceptedFullRefund
        | DisputeUnifiedStatusCode::PreArbitrationAcceptedByMerchant
        | DisputeUnifiedStatusCode::PreArbitrationPartiallyAcceptedByMerchant
        | DisputeUnifiedStatusCode::PreArbitrationAutomaticallyAcceptedByMerchant
        | DisputeUnifiedStatusCode::RejectedPreArbAcceptedByMerchant
        | DisputeUnifiedStatusCode::RejectedPreArbExpiredAutoAccepted => {
            Ok(api_models::webhooks::IncomingWebhookEvent::DisputeAccepted)
        }
        DisputeUnifiedStatusCode::FirstChargebackNoResponseExpired
        | DisputeUnifiedStatusCode::FirstChargebackPartiallyAcceptedByMerchant
        | DisputeUnifiedStatusCode::FirstChargebackClosedCardholderFavour
        | DisputeUnifiedStatusCode::PreArbitrationClosedCardholderFavour
        | DisputeUnifiedStatusCode::McCollaborationClosedCardholderFavour => {
            Ok(api_models::webhooks::IncomingWebhookEvent::DisputeLost)
        }
        DisputeUnifiedStatusCode::FirstChargebackRejectedByMerchant
        | DisputeUnifiedStatusCode::FirstChargebackRejectedAutomatically
        | DisputeUnifiedStatusCode::PreArbitrationInitiatedByIssuer
        | DisputeUnifiedStatusCode::MerchantPreArbitrationRejectedByIssuer
        | DisputeUnifiedStatusCode::InquiryRespondedByMerchant
        | DisputeUnifiedStatusCode::PreArbitrationRejectedByMerchant => {
            Ok(api_models::webhooks::IncomingWebhookEvent::DisputeChallenged)
        }
        DisputeUnifiedStatusCode::FirstChargebackRejectedAutomaticallyExpired
        | DisputeUnifiedStatusCode::FirstChargebackPartiallyAcceptedByMerchantExpired
        | DisputeUnifiedStatusCode::FirstChargebackRejectedByMerchantExpired
        | DisputeUnifiedStatusCode::McCollaborationExpired
        | DisputeUnifiedStatusCode::InquiryExpired
        | DisputeUnifiedStatusCode::PreArbitrationPartiallyAcceptedByMerchantExpired
        | DisputeUnifiedStatusCode::PreArbitrationRejectedByMerchantExpired => {
            Ok(api_models::webhooks::IncomingWebhookEvent::DisputeExpired)
        }
        DisputeUnifiedStatusCode::MerchantPreArbitrationAcceptedByIssuer
        | DisputeUnifiedStatusCode::MerchantPreArbitrationPartiallyAcceptedByIssuer
        | DisputeUnifiedStatusCode::FirstChargebackClosedMerchantFavour
        | DisputeUnifiedStatusCode::McCollaborationClosedMerchantFavour
        | DisputeUnifiedStatusCode::PreArbitrationClosedMerchantFavour => {
            Ok(api_models::webhooks::IncomingWebhookEvent::DisputeWon)
        }
        DisputeUnifiedStatusCode::FirstChargebackRecalledByIssuer
        | DisputeUnifiedStatusCode::InquiryCancelledAfterRefund
        | DisputeUnifiedStatusCode::PreArbitrationClosedRecall
        | DisputeUnifiedStatusCode::CreditChargebackRecalledByIssuer => {
            Ok(api_models::webhooks::IncomingWebhookEvent::DisputeCancelled)
        }

        DisputeUnifiedStatusCode::McCollaborationPreviouslyRefundedAuto
        | DisputeUnifiedStatusCode::McCollaborationRejectedByMerchant
        | DisputeUnifiedStatusCode::InquiryAutomaticallyRejected
        | DisputeUnifiedStatusCode::InquiryPartialAcceptedPartialRefund
        | DisputeUnifiedStatusCode::InquiryUpdated => {
            Err(errors::ConnectorError::WebhookEventTypeNotFound.into())
        }
    }
}

impl From<DisputeUnifiedStatusCode> for common_enums::DisputeStage {
    fn from(code: DisputeUnifiedStatusCode) -> Self {
        match code {
            // --- PreDispute ---
            DisputeUnifiedStatusCode::Rdr
            | DisputeUnifiedStatusCode::InquiryInitiatedByIssuer
            | DisputeUnifiedStatusCode::InquiryRespondedByMerchant
            | DisputeUnifiedStatusCode::InquiryExpired
            | DisputeUnifiedStatusCode::InquiryAutomaticallyRejected
            | DisputeUnifiedStatusCode::InquiryCancelledAfterRefund
            | DisputeUnifiedStatusCode::InquiryAcceptedFullRefund
            | DisputeUnifiedStatusCode::InquiryPartialAcceptedPartialRefund
            | DisputeUnifiedStatusCode::InquiryUpdated => Self::PreDispute,

            // --- Dispute ---
            DisputeUnifiedStatusCode::FirstChargebackInitiatedByIssuer
            | DisputeUnifiedStatusCode::CreditChargebackInitiatedByIssuer
            | DisputeUnifiedStatusCode::FirstChargebackNoResponseExpired
            | DisputeUnifiedStatusCode::FirstChargebackAcceptedByMerchant
            | DisputeUnifiedStatusCode::FirstChargebackAcceptedAutomatically
            | DisputeUnifiedStatusCode::FirstChargebackAcceptedAutomaticallyMcoll
            | DisputeUnifiedStatusCode::FirstChargebackPartiallyAcceptedByMerchant
            | DisputeUnifiedStatusCode::FirstChargebackPartiallyAcceptedByMerchantExpired
            | DisputeUnifiedStatusCode::FirstChargebackRejectedByMerchant
            | DisputeUnifiedStatusCode::FirstChargebackRejectedByMerchantExpired
            | DisputeUnifiedStatusCode::FirstChargebackRejectedAutomatically
            | DisputeUnifiedStatusCode::FirstChargebackRejectedAutomaticallyExpired
            | DisputeUnifiedStatusCode::FirstChargebackClosedMerchantFavour
            | DisputeUnifiedStatusCode::FirstChargebackClosedCardholderFavour
            | DisputeUnifiedStatusCode::FirstChargebackClosedRecall
            | DisputeUnifiedStatusCode::FirstChargebackRecalledByIssuer
            | DisputeUnifiedStatusCode::FirstChargebackDisputeResponseNotAllowed
            | DisputeUnifiedStatusCode::McCollaborationInitiatedByIssuer
            | DisputeUnifiedStatusCode::McCollaborationPreviouslyRefundedAuto
            | DisputeUnifiedStatusCode::McCollaborationRefundedByMerchant
            | DisputeUnifiedStatusCode::McCollaborationExpired
            | DisputeUnifiedStatusCode::McCollaborationRejectedByMerchant
            | DisputeUnifiedStatusCode::McCollaborationAutomaticAccept
            | DisputeUnifiedStatusCode::McCollaborationClosedMerchantFavour
            | DisputeUnifiedStatusCode::McCollaborationClosedCardholderFavour
            | DisputeUnifiedStatusCode::CreditChargebackAcceptedAutomatically => Self::Dispute,

            // --- PreArbitration ---
            DisputeUnifiedStatusCode::PreArbitrationInitiatedByIssuer
            | DisputeUnifiedStatusCode::MerchantPreArbitrationAcceptedByIssuer
            | DisputeUnifiedStatusCode::MerchantPreArbitrationRejectedByIssuer
            | DisputeUnifiedStatusCode::MerchantPreArbitrationPartiallyAcceptedByIssuer
            | DisputeUnifiedStatusCode::PreArbitrationClosedMerchantFavour
            | DisputeUnifiedStatusCode::PreArbitrationClosedCardholderFavour
            | DisputeUnifiedStatusCode::PreArbitrationAcceptedByMerchant
            | DisputeUnifiedStatusCode::PreArbitrationPartiallyAcceptedByMerchant
            | DisputeUnifiedStatusCode::PreArbitrationPartiallyAcceptedByMerchantExpired
            | DisputeUnifiedStatusCode::PreArbitrationRejectedByMerchant
            | DisputeUnifiedStatusCode::PreArbitrationRejectedByMerchantExpired
            | DisputeUnifiedStatusCode::PreArbitrationAutomaticallyAcceptedByMerchant
            | DisputeUnifiedStatusCode::PreArbitrationClosedRecall
            | DisputeUnifiedStatusCode::RejectedPreArbAcceptedByMerchant
            | DisputeUnifiedStatusCode::RejectedPreArbExpiredAutoAccepted => Self::PreArbitration,

            // --- DisputeReversal ---
            DisputeUnifiedStatusCode::CreditChargebackRecalledByIssuer => Self::DisputeReversal,
        }
    }
}


// Function: new
// File: crates/router/src/core/webhooks/network_tokenization_incoming.rs
// Module: router

pub fn new(header: Option<&HeaderValue>) -> Self


// File: crates/router/tests/macros.rs
// Module: router

#[cfg(test)]
mod flat_struct_test {
    #![allow(clippy::unwrap_used)]
    use std::collections::HashMap;

    use router_derive::FlatStruct;
    use serde::Serialize;

    #[test]
    fn test_flat_struct() {
        #[derive(FlatStruct, Serialize)]
        struct User {
            address: Address,
        }

        #[derive(Serialize)]
        struct Address {
            line1: String,
            zip: String,
            city: String,
        }

        let line1 = "1397".to_string();
        let zip = "Some street".to_string();
        let city = "941222".to_string();

        let address = Address {
            line1: line1.clone(),
            zip: zip.clone(),
            city: city.clone(),
        };
        let user = User { address };
        let flat_user_map = user.flat_struct();

        let mut required_map = HashMap::new();
        required_map.insert("address.line1".to_string(), line1);
        required_map.insert("address.zip".to_string(), zip);
        required_map.insert("address.city".to_string(), city);

        assert_eq!(flat_user_map, required_map);
    }
}

#[cfg(test)]
mod validate_schema_test {
    #![allow(clippy::unwrap_used)]

    use router_derive::ValidateSchema;
    use url::Url;

    #[test]
    fn test_validate_schema() {
        #[derive(ValidateSchema)]
        struct Payment {
            #[schema(min_length = 5, max_length = 12)]
            payment_id: String,

            #[schema(min_length = 10, max_length = 100)]
            description: Option<String>,

            #[schema(max_length = 255)]
            return_url: Option<Url>,
        }

        // Valid case
        let valid_payment = Payment {
            payment_id: "payment_123".to_string(),
            description: Some("This is a valid description".to_string()),
            return_url: Some("https://example.com/return".parse().unwrap()),
        };
        assert!(valid_payment.validate().is_ok());

        // Invalid: payment_id too short
        let invalid_id = Payment {
            payment_id: "pay".to_string(),
            description: Some("This is a valid description".to_string()),
            return_url: Some("https://example.com/return".parse().unwrap()),
        };
        let err = invalid_id.validate().unwrap_err();
        assert!(
            err.contains("payment_id must be at least 5 characters long. Received 3 characters")
        );

        // Invalid: payment_id too long
        let invalid_desc = Payment {
            payment_id: "payment_12345".to_string(),
            description: Some("This is a valid description".to_string()),
            return_url: Some("https://example.com/return".parse().unwrap()),
        };
        let err = invalid_desc.validate().unwrap_err();
        assert!(
            err.contains("payment_id must be at most 12 characters long. Received 13 characters")
        );

        // None values should pass validation
        let none_values = Payment {
            payment_id: "payment_123".to_string(),
            description: None,
            return_url: None,
        };
        assert!(none_values.validate().is_ok());
    }
}


// Function: get_outgoing_webhook_response_content
// File: crates/router/src/core/webhooks/types.rs
// Module: router

pub fn get_outgoing_webhook_response_content(
        self,
    ) -> webhook_events::OutgoingWebhookResponseContent


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

impl api::PaymentVoid for for Juspaythreedsserver


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

pub struct AuthorizeResponse


// Struct: StaxMetaData
// File: crates/hyperswitch_connectors/src/connectors/stax/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct StaxMetaData


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

pub fn new() -> &'static Self


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

impl ConnectorAccessToken for for Threedsecureio


            self.set_key_if_not_exists_and_get_value(key, (*value).to_owned(), ttl)
        });

        let del_result = futures::future::try_join_all(futures)
            .await
            .change_context(errors::RedisError::SetFailed)?;

        Ok(del_result)
    }

    /// Sets a value in Redis if not already present, and returns the value (either existing or newly set).
    /// This operation is atomic using Redis transactions.
    #[instrument(level = "DEBUG", skip(self))]
    pub async fn set_key_if_not_exists_and_get_value<V>(
        &self,
        key: &RedisKey,
        value: V,
        ttl: Option<i64>,
    ) -> CustomResult<SetGetReply<V>, errors::RedisError>
    where
        V: TryInto<RedisValue> + Debug + FromRedis + Send + Sync + serde::de::DeserializeOwned,
        V::Error: Into<fred::error::RedisError> + Send + Sync,
    {
        let redis_key = key.tenant_aware_key(self);
        let ttl_seconds = ttl.unwrap_or(self.config.default_ttl.into());

        // Get a client from the pool and start transaction
        let trx = self.get_transaction();

        // Try to set if not exists with expiry - queue the command
        trx.set::<(), _, _>(
            &redis_key,
            value,
            Some(Expiration::EX(ttl_seconds)),
            Some(SetOptions::NX),
            false,
        )
        .await
        .change_context(errors::RedisError::SetFailed)
        .attach_printable("Failed to queue set command")?;

        // Always get the value after the SET attempt - queue the command
        trx.get::<V, _>(&redis_key)
            .await
            .change_context(errors::RedisError::GetFailed)
            .attach_printable("Failed to queue get command")?;

        // Execute transaction
        let mut results: Vec<RedisValue> = trx
            .exec(true)
            .await
            .change_context(errors::RedisError::SetFailed)
            .attach_printable("Failed to execute the redis transaction")?;

        let msg = "Got unexpected number of results from transaction";
        let get_result = results
            .pop()
            .ok_or(errors::RedisError::SetFailed)
            .attach_printable(msg)?;
        let set_result = results
            .pop()
            .ok_or(errors::RedisError::SetFailed)
            .attach_printable(msg)?;
        // Parse the GET result to get the actual value
        let actual_value: V = FromRedis::from_value(get_result)
            .change_context(errors::RedisError::SetFailed)
            .attach_printable("Failed to convert from redis value")?;

        // Check if SET NX succeeded or failed
        match set_result {
            // SET NX returns "OK" if key was set
            RedisValue::String(_) => Ok(SetGetReply::ValueSet(actual_value)),
            // SET NX returns null if key already exists
            RedisValue::Null => Ok(SetGetReply::ValueExists(actual_value)),
            _ => Err(report!(errors::RedisError::SetFailed))
                .attach_printable("Unexpected result from SET NX operation"),
        }
    }
}

#[cfg(test)]
mod tests {
    #![allow(clippy::expect_used, clippy::unwrap_used)]

    use std::collections::HashMap;

    use crate::{errors::RedisError, RedisConnectionPool, RedisEntryId, RedisSettings};

    #[tokio::test]
    async fn test_consumer_group_create() {
        let is_invalid_redis_entry_error = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let redis_conn = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");

                // Act
                let result1 = redis_conn
                    .consumer_group_create(&"TEST1".into(), "GTEST", &RedisEntryId::AutoGeneratedID)
                    .await;

                let result2 = redis_conn
                    .consumer_group_create(
                        &"TEST3".into(),
                        "GTEST",
                        &RedisEntryId::UndeliveredEntryID,
                    )
                    .await;

                // Assert Setup
                *result1.unwrap_err().current_context() == RedisError::InvalidRedisEntryId
                    && *result2.unwrap_err().current_context() == RedisError::InvalidRedisEntryId
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_invalid_redis_entry_error);
    }

    #[tokio::test]
    async fn test_delete_existing_key_success() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");
                let _ = pool.set_key(&"key".into(), "value".to_string()).await;

                // Act
                let result = pool.delete_key(&"key".into()).await;

                // Assert setup
                result.is_ok()
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }
    #[tokio::test]
    async fn test_delete_non_existing_key_success() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");

                // Act
                let result = pool.delete_key(&"key not exists".into()).await;

                // Assert Setup
                result.is_ok()
            })
        })
        .await
        .expect("Spawn block failure");
        assert!(is_success);
    }

    #[tokio::test]
    async fn test_setting_keys_using_scripts() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");
                let lua_script = r#"
                for i = 1, #KEYS do
                    redis.call("INCRBY", KEYS[i], ARGV[i])
                end
                return
                "#;
                let mut keys_and_values = HashMap::new();
                for i in 0..10 {
                    keys_and_values.insert(format!("key{i}"), i);
                }

                let key = keys_and_values.keys().cloned().collect::<Vec<_>>();
                let values = keys_and_values
                    .values()
                    .map(|val| val.to_string())
                    .collect::<Vec<String>>();

                // Act
                let result = pool
                    .evaluate_redis_script::<_, ()>(lua_script, key, values)
                    .await;

                // Assert Setup
                result.is_ok()
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }
    #[tokio::test]
    async fn test_getting_keys_using_scripts() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");

                // First set some keys
                for i in 0..3 {
                    let key = format!("script_test_key{i}").into();
                    let _ = pool.set_key(&key, format!("value{i}")).await;
                }

                let lua_script = r#"
                local results = {}
                for i = 1, #KEYS do
                    results[i] = redis.call("GET", KEYS[i])
                end
                return results
                "#;

                let keys = vec![
                    "script_test_key0".to_string(),
                    "script_test_key1".to_string(),
                    "script_test_key2".to_string(),
                ];

                // Act
                let result = pool
                    .evaluate_redis_script::<_, Vec<String>>(lua_script, keys, vec![""])
                    .await;

                // Assert Setup
                result.is_ok()
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }

    #[tokio::test]
    async fn test_set_key_if_not_exists_and_get_value_new_key() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");
                let key = "test_new_key_string".into();
                let value = "test_value".to_string();

                // Act
                let result = pool
                    .set_key_if_not_exists_and_get_value(&key, value.clone(), Some(30))
                    .await;

                // Assert
                match result {
                    Ok(crate::types::SetGetReply::ValueSet(returned_value)) => {
                        returned_value == value
                    }
                    _ => false,
                }
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }

    #[tokio::test]
    async fn test_set_key_if_not_exists_and_get_value_existing_key() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");
                let key = "test_existing_key_string".into();
                let initial_value = "initial_value".to_string();
                let new_value = "new_value".to_string();

                // First, set an initial value using regular set_key
                let _ = pool.set_key(&key, initial_value.clone()).await;

                // Act - try to set a new value (should fail and return existing value)
                let result = pool
                    .set_key_if_not_exists_and_get_value(&key, new_value, Some(30))
                    .await;

                // Assert
                match result {
                    Ok(crate::types::SetGetReply::ValueExists(returned_value)) => {
                        returned_value == initial_value
                    }
                    _ => false,
                }
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }

    #[tokio::test]
    async fn test_set_key_if_not_exists_and_get_value_with_default_ttl() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");
                let key = "test_default_ttl_key_string".into();
                let value = "test_value".to_string();

                // Act - use None for TTL to test default behavior
                let result = pool
                    .set_key_if_not_exists_and_get_value(&key, value.clone(), None)
                    .await;

                // Assert
                match result {
                    Ok(crate::types::SetGetReply::ValueSet(returned_value)) => {
                        returned_value == value
                    }
                    _ => false,
                }
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }

    #[tokio::test]
    async fn test_set_key_if_not_exists_and_get_value_concurrent_access() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");
                let key_name = "test_concurrent_key_string";
                let value1 = "value1".to_string();
                let value2 = "value2".to_string();

                // Act - simulate concurrent access
                let pool1 = pool.clone("");
                let pool2 = pool.clone("");
                let key1 = key_name.into();
                let key2 = key_name.into();

                let (result1, result2) = tokio::join!(
                    pool1.set_key_if_not_exists_and_get_value(&key1, value1, Some(30)),
                    pool2.set_key_if_not_exists_and_get_value(&key2, value2, Some(30))
                );

                // Assert - one should succeed with ValueSet, one should fail with ValueExists
                let result1_is_set = matches!(result1, Ok(crate::types::SetGetReply::ValueSet(_)));
                let result2_is_set = matches!(result2, Ok(crate::types::SetGetReply::ValueSet(_)));
                let result1_is_exists =
                    matches!(result1, Ok(crate::types::SetGetReply::ValueExists(_)));
                let result2_is_exists =
                    matches!(result2, Ok(crate::types::SetGetReply::ValueExists(_)));

                // Exactly one should be ValueSet and one should be ValueExists
                (result1_is_set && result2_is_exists) || (result1_is_exists && result2_is_set)
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }

    #[tokio::test]
    async fn test_get_multiple_keys_success() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");

                // Set up test data
                let keys = vec![
                    "multi_test_key1".into(),
                    "multi_test_key2".into(),
                    "multi_test_key3".into(),
                ];
                let values = ["value1", "value2", "value3"];

                // Set the keys
                for (key, value) in keys.iter().zip(values.iter()) {
                    let _ = pool.set_key(key, value.to_string()).await;
                }

                // Act
                let result = pool.get_multiple_keys::<String>(&keys).await;

                // Assert
                match result {
                    Ok(retrieved_values) => {
                        retrieved_values.len() == 3
                            && retrieved_values.first() == Some(&Some("value1".to_string()))
                            && retrieved_values.get(1) == Some(&Some("value2".to_string()))
                            && retrieved_values.get(2) == Some(&Some("value3".to_string()))
                    }
                    _ => false,
                }
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }

    #[tokio::test]
    async fn test_get_multiple_keys_with_missing_keys() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");

                let keys = vec![
                    "existing_key".into(),
                    "non_existing_key".into(),
                    "another_existing_key".into(),
                ];

                // Set only some keys
                let _ = pool
                    .set_key(
                        keys.first().expect("should not be none"),
                        "value1".to_string(),
                    )
                    .await;
                let _ = pool
                    .set_key(
                        keys.get(2).expect("should not be none"),
                        "value3".to_string(),
                    )
                    .await;

                // Act
                let result = pool.get_multiple_keys::<String>(&keys).await;

                // Assert
                match result {
                    Ok(retrieved_values) => {
                        retrieved_values.len() == 3
                            && *retrieved_values.first().expect("should not be none")
                                == Some("value1".to_string())
                            && retrieved_values.get(1).is_some_and(|v| v.is_none())
                            && *retrieved_values.get(2).expect("should not be none")
                                == Some("value3".to_string())
                    }
                    _ => false,
                }
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }

    #[tokio::test]
    async fn test_get_multiple_keys_empty_input() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");

                let keys: Vec<crate::types::RedisKey> = vec![];

                // Act
                let result = pool.get_multiple_keys::<String>(&keys).await;

                // Assert
                match result {
                    Ok(retrieved_values) => retrieved_values.is_empty(),
                    _ => false,
                }
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }

    #[tokio::test]
    async fn test_get_and_deserialize_multiple_keys() {
        let is_success = tokio::task::spawn_blocking(move || {
            futures::executor::block_on(async {
                // Arrange
                let pool = RedisConnectionPool::new(&RedisSettings::default())
                    .await
                    .expect("failed to create redis connection pool");

                #[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug, Clone)]
                struct TestData {
                    id: u32,
                    name: String,
                }

                let test_data = [
                    TestData {
                        id: 1,
                        name: "test1".to_string(),
                    },
                    TestData {
                        id: 2,
                        name: "test2".to_string(),
                    },
                ];

                let keys = vec![
                    "serialize_test_key1".into(),
                    "serialize_test_key2".into(),
                    "non_existing_serialize_key".into(),
                ];

                // Set serialized data for first two keys
                for (i, data) in test_data.iter().enumerate() {
                    let _ = pool
                        .serialize_and_set_key(keys.get(i).expect("should not be none"), data)
                        .await;
                }

                // Act
                let result = pool
                    .get_and_deserialize_multiple_keys::<TestData>(&keys, "TestData")
                    .await;

                // Assert
                match result {
                    Ok(retrieved_data) => {
                        retrieved_data.len() == 3
                            && retrieved_data.first() == Some(&Some(test_data[0].clone()))
                            && retrieved_data.get(1) == Some(&Some(test_data[1].clone()))
                            && retrieved_data.get(2) == Some(&None)
                    }
                    _ => false,
                }
            })
        })
        .await
        .expect("Spawn block failure");

        assert!(is_success);
    }
}


// Function: get_frm_dimensions
// File: crates/analytics/src/utils.rs
// Module: analytics

pub fn get_frm_dimensions() -> Vec<NameDescription>


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

pub struct RedirectPurchaseUnitItem


// Struct: StripeAddressDetails
// File: crates/router/src/compatibility/stripe/customers/types.rs
// Module: router
// Implementations: 0

pub struct StripeAddressDetails


// File: crates/analytics/src/payment_intents.rs
// Module: analytics

pub mod accumulator;
mod core;
pub mod filters;
pub mod metrics;
pub mod sankey;
pub mod types;
pub use accumulator::{PaymentIntentMetricAccumulator, PaymentIntentMetricsAccumulator};

pub trait PaymentIntentAnalytics:
    metrics::PaymentIntentMetricAnalytics + filters::PaymentIntentFilterAnalytics
{
}

pub use self::core::{get_filters, get_metrics, get_sankey};


// Implementation: impl ToTokens for for SchemaParameterVariant
// File: crates/router_derive/src/macros/schema/helpers.rs
// Module: router_derive
// Methods: 1 total (0 public)

impl ToTokens for for SchemaParameterVariant


// Function: update
// File: crates/api_models/src/open_router.rs
// Module: api_models

pub fn update(&mut self, new_config: Self)


// Struct: MerchantConnectorListResponse
// File: crates/api_models/src/admin.rs
// Module: api_models
// Implementations: 2

pub struct MerchantConnectorListResponse


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

pub struct AccessTokenFlowData


// Struct: JpmorganRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct JpmorganRefundRequest


// Struct: PoCancel
// File: crates/hyperswitch_domain_models/src/router_flow_types/payouts.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct PoCancel


// Function: merchant_account_create
// File: crates/router/src/routes/admin.rs
// Module: router

pub fn merchant_account_create(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<admin::MerchantAccountCreate>,
) -> HttpResponse


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

pub struct FortePaymentsSyncResponse


// Struct: ProphetpayRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/prophetpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ProphetpayRefundRequest


// Implementation: impl behaviour::Conversion for for PaymentIntent
// File: crates/hyperswitch_domain_models/src/payments/payment_intent.rs
// Module: hyperswitch_domain_models
// Methods: 3 total (0 public)

impl behaviour::Conversion for for PaymentIntent


// Struct: PaymentMetaData
// File: crates/hyperswitch_connectors/src/connectors/gocardless/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaymentMetaData


// Function: delete_user_role
// File: crates/router/src/core/user_role.rs
// Module: router

pub fn delete_user_role(
    state: SessionState,
    user_from_token: auth::UserFromToken,
    request: user_role_api::DeleteUserRoleRequest,
    _req_state: ReqState,
) -> UserResponse<()>


// Implementation: impl utils::MultipleCaptureSyncResponse for for ActionResponse
// File: crates/hyperswitch_connectors/src/connectors/checkout/transformers.rs
// Module: hyperswitch_connectors
// Methods: 5 total (0 public)

impl utils::MultipleCaptureSyncResponse for for ActionResponse