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

pub struct Xendit

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


// Function: payments_status_with_gateway_creds
// File: crates/router/src/routes/payments.rs
// Module: router

pub fn payments_status_with_gateway_creds(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    payload: web::Json<api_models::payments::PaymentsRetrieveRequest>,
    path: web::Path<common_utils::id_type::GlobalPaymentId>,
) -> impl Responder


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

pub fn convert_forex_value(amount: i64, from_currency: JsValue, to_currency: JsValue) -> JsResult


// File: crates/hyperswitch_interfaces/src/secrets_interface/secret_handler.rs
// Module: hyperswitch_interfaces

//! Module containing trait for raw secret retrieval

use common_utils::errors::CustomResult;

use crate::secrets_interface::{
    secret_state::{RawSecret, SecretStateContainer, SecuredSecret},
    SecretManagementInterface, SecretsManagementError,
};

/// Trait defining the interface for retrieving a raw secret value, given a secured value
#[async_trait::async_trait]
pub trait SecretsHandler
where
    Self: Sized,
{
    /// Construct `Self` with raw secret value and transitions its type from `SecuredSecret` to `RawSecret`
    async fn convert_to_raw_secret(
        value: SecretStateContainer<Self, SecuredSecret>,
        kms_client: &dyn SecretManagementInterface,
    ) -> CustomResult<SecretStateContainer<Self, RawSecret>, SecretsManagementError>;
}


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

pub struct WebhookRefundEntity


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

pub struct DataAuthResponse


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

pub struct RefundsRetrieveBody


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

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

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

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

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

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

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

impl TryFrom<&MpgsRouterData<&PaymentsAuthorizeRouterData>> for MpgsPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &MpgsRouterData<&PaymentsAuthorizeRouterData>) -> Result<Self, Self::Error> {
        match item.router_data.request.payment_method_data.clone() {
            PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotImplemented(
                "Card payment method not implemented".to_string(),
            )
            .into()),
            _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()),
        }
    }
}

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

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

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

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

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

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

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

// Type definition for Refund Response

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

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

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

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

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

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


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

pub fn add_custom_filter_clause(
        &mut self,
        lhs: impl ToSql<T>,
        rhs: impl ToSql<T>,
        comparison: FilterTypes,
    ) -> QueryResult<()>


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

impl PaymentToken for for Plaid


// Struct: StripebillingInvoiceBody
// File: crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 1

pub struct StripebillingInvoiceBody


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

impl ConnectorSpecifications for for Payme


// Trait: SchedulerAppState
// File: crates/scheduler/src/scheduler.rs
// Module: scheduler

pub trait SchedulerAppState: Send + Sync + Clone


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

pub struct WorldpayXmlErrorResponse


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

pub struct JpmorganCancelResponse


// Function: parse_routing_algorithm
// File: crates/api_models/src/admin.rs
// Module: api_models

pub fn parse_routing_algorithm(&self) -> CustomResult<(), errors::ParsingError>


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

pub struct ItaubankRouterData<T>


// Function: create_tokenize
// File: crates/router/src/core/payment_methods/vault.rs
// Module: router

pub fn create_tokenize(
    state: &routes::SessionState,
    value1: String,
    value2: Option<String>,
    lookup_key: String,
    encryption_key: &masking::Secret<Vec<u8>>,
) -> RouterResult<String>


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

pub fn list_connectors_for_a_profile(
    state: SessionState,
    key_store: domain::MerchantKeyStore,
    profile_id: id_type::ProfileId,
) -> RouterResponse<Vec<api_models::admin::MerchantConnectorListResponse>>


// File: crates/hyperswitch_connectors/src/connectors/nordea/transformers.rs
// Module: hyperswitch_connectors
// Public functions: 1
// Public structs: 2

use std::collections::HashMap;

use common_utils::{pii, request::Method, types::StringMajorUnit};
use error_stack::ResultExt;
use hyperswitch_domain_models::{
    payment_method_data::{BankDebitData, PaymentMethodData},
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{Authorize, PreProcessing},
    router_request_types::{PaymentsAuthorizeData, PaymentsPreProcessingData, ResponseId},
    router_response_types::{PaymentsResponseData, RedirectForm},
    types::{
        self, AccessTokenAuthenticationRouterData, PaymentsAuthorizeRouterData,
        PaymentsPreProcessingRouterData, PaymentsSyncRouterData,
    },
};
use hyperswitch_interfaces::errors;
use masking::Secret;
use rand::distributions::DistString;
use serde::{Deserialize, Deserializer, Serialize};

use crate::{
    connectors::nordea::{
        requests::{
            AccessScope, AccountNumber, AccountType, CreditorAccount, CreditorBank, DebitorAccount,
            GrantType, NordeaOAuthExchangeRequest, NordeaOAuthRequest,
            NordeaPaymentsConfirmRequest, NordeaPaymentsRequest, NordeaRouterData, PaymentsUrgency,
        },
        responses::{
            NordeaErrorBody, NordeaFailures, NordeaOAuthExchangeResponse, NordeaPaymentStatus,
            NordeaPaymentsConfirmResponse, NordeaPaymentsInitiateResponse,
        },
    },
    types::{PaymentsSyncResponseRouterData, ResponseRouterData},
    utils::{self, get_unimplemented_payment_method_error_message, RouterData as _},
};

type Error = error_stack::Report<errors::ConnectorError>;

impl<T> From<(StringMajorUnit, T)> for NordeaRouterData<T> {
    fn from((amount, item): (StringMajorUnit, T)) -> Self {
        Self {
            amount,
            router_data: item,
        }
    }
}

// Auth Struct
#[derive(Debug)]
pub struct NordeaAuthType {
    pub(super) client_id: Secret<String>,
    pub(super) client_secret: Secret<String>,
    /// PEM format private key for eIDAS signing
    /// Should be base64 encoded
    pub(super) eidas_private_key: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for NordeaAuthType {
    type Error = Error;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::SignatureKey {
                api_key,
                key1,
                api_secret,
            } => Ok(Self {
                client_id: key1.to_owned(),
                client_secret: api_key.to_owned(),
                eidas_private_key: api_secret.to_owned(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct NordeaConnectorMetadataObject {
    /// Account number of the beneficiary (merchant)
    pub destination_account_number: Secret<String>,
    /// Account type (example: IBAN, BBAN_SE, BBAN_DK, BBAN_NO, BGNR, PGNR, GIRO_DK, BBAN_OTHER)
    pub account_type: String,
    /// Name of the beneficiary (merchant)
    pub merchant_name: Secret<String>,
}

impl TryFrom<&Option<pii::SecretSerdeValue>> for NordeaConnectorMetadataObject {
    type Error = Error;
    fn try_from(meta_data: &Option<pii::SecretSerdeValue>) -> Result<Self, Self::Error> {
        let metadata: Self = utils::to_connector_meta_from_secret::<Self>(meta_data.clone())
            .change_context(errors::ConnectorError::InvalidConnectorConfig {
                config: "merchant_connector_account.metadata",
            })?;
        Ok(metadata)
    }
}

impl TryFrom<&AccessTokenAuthenticationRouterData> for NordeaOAuthRequest {
    type Error = Error;
    fn try_from(item: &AccessTokenAuthenticationRouterData) -> Result<Self, Self::Error> {
        let country = item.get_billing_country()?;

        // Set refresh_token maximum expiry duration to 180 days (259200 / 60 = 180)
        // Minimum is 1 minute
        let duration = Some(259200);
        let maximum_transaction_history = Some(18);
        let redirect_uri = "https://hyperswitch.io".to_string();
        let scope = [
            AccessScope::AccountsBasic,
            AccessScope::AccountsDetails,
            AccessScope::AccountsBalances,
            AccessScope::AccountsTransactions,
            AccessScope::PaymentsMultiple,
        ]
        .to_vec();
        let state = rand::distributions::Alphanumeric.sample_string(&mut rand::thread_rng(), 15);

        Ok(Self {
            country,
            duration,
            maximum_transaction_history,
            redirect_uri,
            scope,
            state: state.into(),
        })
    }
}

impl TryFrom<&types::RefreshTokenRouterData> for NordeaOAuthExchangeRequest {
    type Error = Error;
    fn try_from(item: &types::RefreshTokenRouterData) -> Result<Self, Self::Error> {
        let code = item
            .request
            .authentication_token
            .as_ref()
            .ok_or(errors::ConnectorError::MissingRequiredField {
                field_name: "authorization_code",
            })?
            .code
            .clone();
        let grant_type = GrantType::AuthorizationCode;
        let redirect_uri = Some("https://hyperswitch.io".to_string());

        Ok(Self {
            code: Some(code),
            grant_type,
            redirect_uri,
            refresh_token: None, // We're not using refresh_token to generate new access_token
        })
    }
}

impl<F, T> TryFrom<ResponseRouterData<F, NordeaOAuthExchangeResponse, T, AccessToken>>
    for RouterData<F, T, AccessToken>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<F, NordeaOAuthExchangeResponse, T, AccessToken>,
    ) -> Result<Self, Self::Error> {
        let access_token =
            item.response
                .access_token
                .ok_or(errors::ConnectorError::MissingRequiredField {
                    field_name: "access_token",
                })?;

        let expires_in = item.response.expires_in.unwrap_or(3600); // Default to 1 hour if not provided

        Ok(Self {
            status: common_enums::AttemptStatus::AuthenticationSuccessful,
            response: Ok(AccessToken {
                token: access_token.clone(),
                expires: expires_in,
            }),
            ..item.data
        })
    }
}

impl TryFrom<&str> for AccountType {
    type Error = Error;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        match value.to_uppercase().as_str() {
            "IBAN" => Ok(Self::Iban),
            "BBAN_SE" => Ok(Self::BbanSe),
            "BBAN_DK" => Ok(Self::BbanDk),
            "BBAN_NO" => Ok(Self::BbanNo),
            "BGNR" => Ok(Self::Bgnr),
            "PGNR" => Ok(Self::Pgnr),
            "GIRO_DK" => Ok(Self::GiroDk),
            "BBAN_OTHER" => Ok(Self::BbanOther),
            _ => Err(errors::ConnectorError::InvalidConnectorConfig {
                config: "account_type",
            }
            .into()),
        }
    }
}

impl<'de> Deserialize<'de> for PaymentsUrgency {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?.to_lowercase();
        match s.as_str() {
            "standard" => Ok(Self::Standard),
            "express" => Ok(Self::Express),
            "sameday" => Ok(Self::Sameday),
            _ => Err(serde::de::Error::unknown_variant(
                &s,
                &["standard", "express", "sameday"],
            )),
        }
    }
}

fn get_creditor_account_from_metadata(
    router_data: &PaymentsPreProcessingRouterData,
) -> Result<CreditorAccount, Error> {
    let metadata: NordeaConnectorMetadataObject =
        utils::to_connector_meta_from_secret(router_data.connector_meta_data.clone())
            .change_context(errors::ConnectorError::InvalidConnectorConfig {
                config: "merchant_connector_account.metadata",
            })?;
    let creditor_account = CreditorAccount {
        account: AccountNumber {
            account_type: AccountType::try_from(metadata.account_type.as_str())
                .unwrap_or(AccountType::Iban),
            currency: router_data.request.currency,
            value: metadata.destination_account_number,
        },
        country: router_data.get_optional_billing_country(),
        // Merchant is the beneficiary in this case
        name: Some(metadata.merchant_name),
        message: router_data
            .description
            .as_ref()
            .map(|desc| desc.chars().take(20).collect::<String>()),
        bank: Some(CreditorBank {
            address: None,
            bank_code: None,
            bank_name: None,
            business_identifier_code: None,
            country: router_data.get_billing_country()?,
        }),
        creditor_address: None,
        // Either Reference or Message must be supplied in the request
        reference: None,
    };
    Ok(creditor_account)
}

impl TryFrom<&NordeaRouterData<&PaymentsPreProcessingRouterData>> for NordeaPaymentsRequest {
    type Error = Error;
    fn try_from(
        item: &NordeaRouterData<&PaymentsPreProcessingRouterData>,
    ) -> Result<Self, Self::Error> {
        match item.router_data.request.payment_method_data.clone() {
            Some(PaymentMethodData::BankDebit(bank_debit_data)) => match bank_debit_data {
                BankDebitData::SepaBankDebit { iban, .. } => {
                    let creditor_account = get_creditor_account_from_metadata(item.router_data)?;
                    let debitor_account = DebitorAccount {
                        account: AccountNumber {
                            account_type: AccountType::Iban,
                            currency: item.router_data.request.currency,
                            value: iban,
                        },
                        message: item
                            .router_data
                            .description
                            .as_ref()
                            .map(|desc| desc.chars().take(20).collect::<String>()),
                    };

                    let instructed_amount = super::requests::InstructedAmount {
                        amount: item.amount.clone(),
                        currency: item.router_data.request.currency.ok_or(
                            errors::ConnectorError::MissingRequiredField {
                                field_name: "amount",
                            },
                        )?,
                    };

                    Ok(Self {
                        creditor_account,
                        debitor_account,
                        end_to_end_identification: None,
                        external_id: Some(item.router_data.connector_request_reference_id.clone()),
                        instructed_amount,
                        recurring: None,
                        request_availability_of_funds: None,
                        requested_execution_date: None,
                        tpp_messages: None,
                        urgency: None,
                    })
                }
                BankDebitData::AchBankDebit { .. }
                | BankDebitData::BacsBankDebit { .. }
                | BankDebitData::BecsBankDebit { .. } => {
                    Err(errors::ConnectorError::NotImplemented(
                        get_unimplemented_payment_method_error_message("Nordea"),
                    )
                    .into())
                }
            },
            Some(PaymentMethodData::CardRedirect(_))
            | Some(PaymentMethodData::CardDetailsForNetworkTransactionId(_))
            | Some(PaymentMethodData::Wallet(_))
            | Some(PaymentMethodData::PayLater(_))
            | Some(PaymentMethodData::BankRedirect(_))
            | Some(PaymentMethodData::BankTransfer(_))
            | Some(PaymentMethodData::Crypto(_))
            | Some(PaymentMethodData::MandatePayment)
            | Some(PaymentMethodData::Reward)
            | Some(PaymentMethodData::RealTimePayment(_))
            | Some(PaymentMethodData::MobilePayment(_))
            | Some(PaymentMethodData::Upi(_))
            | Some(PaymentMethodData::Voucher(_))
            | Some(PaymentMethodData::GiftCard(_))
            | Some(PaymentMethodData::OpenBanking(_))
            | Some(PaymentMethodData::CardToken(_))
            | Some(PaymentMethodData::NetworkToken(_))
            | Some(PaymentMethodData::Card(_))
            | None => {
                Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into())
            }
        }
    }
}

impl TryFrom<&NordeaRouterData<&PaymentsAuthorizeRouterData>> for NordeaPaymentsConfirmRequest {
    type Error = Error;
    fn try_from(
        item: &NordeaRouterData<&PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        let payment_ids = match &item.router_data.response {
            Ok(response_data) => response_data
                .get_connector_transaction_id()
                .map_err(|_| errors::ConnectorError::MissingConnectorTransactionID)?,
            Err(_) => return Err(errors::ConnectorError::ResponseDeserializationFailed.into()),
        };

        Ok(Self {
            authentication_method: None,
            language: None,
            payments_ids: vec![payment_ids],
            redirect_url: None,
            state: None,
        })
    }
}

impl From<NordeaPaymentStatus> for common_enums::AttemptStatus {
    fn from(item: NordeaPaymentStatus) -> Self {
        match item {
            NordeaPaymentStatus::Confirmed | NordeaPaymentStatus::Paid => Self::Charged,

            NordeaPaymentStatus::PendingConfirmation
            | NordeaPaymentStatus::PendingSecondConfirmation => Self::ConfirmationAwaited,
            NordeaPaymentStatus::PendingUserApproval => Self::AuthenticationPending,

            NordeaPaymentStatus::OnHold | NordeaPaymentStatus::Unknown => Self::Pending,

            NordeaPaymentStatus::Rejected
            | NordeaPaymentStatus::InsufficientFunds
            | NordeaPaymentStatus::LimitExceeded
            | NordeaPaymentStatus::UserApprovalFailed
            | NordeaPaymentStatus::UserApprovalTimeout
            | NordeaPaymentStatus::UserApprovalCancelled => Self::Failure,
        }
    }
}

pub fn get_error_data(error_response: Option<&NordeaErrorBody>) -> Option<&NordeaFailures> {
    error_response
        .and_then(|error| error.nordea_failures.as_ref())
        .and_then(|failures| failures.first())
}

// Helper function to convert NordeaPaymentsInitiateResponse to common response data
fn convert_nordea_payment_response(
    response: &NordeaPaymentsInitiateResponse,
) -> Result<(PaymentsResponseData, common_enums::AttemptStatus), Error> {
    let payment_response = response
        .payments_response
        .as_ref()
        .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;

    let resource_id = ResponseId::ConnectorTransactionId(payment_response.payment_id.clone());

    let response_data = PaymentsResponseData::TransactionResponse {
        resource_id,
        redirection_data: Box::new(None),
        mandate_reference: Box::new(None),
        connector_metadata: None,
        network_txn_id: None,
        connector_response_reference_id: payment_response.external_id.clone(),
        incremental_authorization_allowed: None,
        charges: None,
    };

    let status = common_enums::AttemptStatus::from(payment_response.payment_status.clone());

    Ok((response_data, status))
}

impl
    TryFrom<
        ResponseRouterData<
            PreProcessing,
            NordeaPaymentsInitiateResponse,
            PaymentsPreProcessingData,
            PaymentsResponseData,
        >,
    > for RouterData<PreProcessing, PaymentsPreProcessingData, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<
            PreProcessing,
            NordeaPaymentsInitiateResponse,
            PaymentsPreProcessingData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        let (response, status) = convert_nordea_payment_response(&item.response)?;
        Ok(Self {
            status,
            response: Ok(response),
            ..item.data
        })
    }
}

impl
    TryFrom<
        ResponseRouterData<
            Authorize,
            NordeaPaymentsConfirmResponse,
            PaymentsAuthorizeData,
            PaymentsResponseData,
        >,
    > for RouterData<Authorize, PaymentsAuthorizeData, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<
            Authorize,
            NordeaPaymentsConfirmResponse,
            PaymentsAuthorizeData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        // First check if there are any errors in the response
        if let Some(errors) = &item.response.errors {
            if !errors.is_empty() {
                // Get the first error for the error response
                let first_error = errors
                    .first()
                    .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;

                return Ok(Self {
                    status: common_enums::AttemptStatus::Failure,
                    response: Err(ErrorResponse {
                        code: first_error
                            .error
                            .clone()
                            .unwrap_or_else(|| "UNKNOWN_ERROR".to_string()),
                        message: first_error
                            .error_description
                            .clone()
                            .unwrap_or_else(|| "Payment confirmation failed".to_string()),
                        reason: first_error.error_description.clone(),
                        status_code: item.http_code,
                        attempt_status: Some(common_enums::AttemptStatus::Failure),
                        connector_transaction_id: first_error.payment_id.clone(),
                        network_advice_code: None,
                        network_decline_code: None,
                        network_error_message: None,
                        connector_metadata: None,
                    }),
                    ..item.data
                });
            }
        }

        // If no errors, proceed with normal response handling
        // Check if there's a redirect link at the top level only
        let redirection_data = item
            .response
            .links
            .as_ref()
            .and_then(|links| {
                links.iter().find(|link| {
                    link.rel
                        .as_ref()
                        .map(|rel| rel == "signing")
                        .unwrap_or(false)
                })
            })
            .and_then(|link| link.href.clone())
            .map(|redirect_url| RedirectForm::Form {
                endpoint: redirect_url,
                method: Method::Get,
                form_fields: HashMap::new(),
            });

        let (response, status) = match &item.response.nordea_payments_response {
            Some(payment_response_wrapper) => {
                // Get the first payment from the payments array
                let payment = payment_response_wrapper
                    .payments
                    .first()
                    .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;

                let resource_id = ResponseId::ConnectorTransactionId(payment.payment_id.clone());

                let response = Ok(PaymentsResponseData::TransactionResponse {
                    resource_id,
                    redirection_data: Box::new(redirection_data),
                    mandate_reference: Box::new(None),
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: payment.external_id.clone(),
                    incremental_authorization_allowed: None,
                    charges: None,
                });

                let status = common_enums::AttemptStatus::from(payment.payment_status.clone());

                (response, status)
            }
            None => {
                // No payment response, but we might still have a redirect link
                if let Some(redirect) = redirection_data {
                    let response = Ok(PaymentsResponseData::TransactionResponse {
                        resource_id: ResponseId::NoResponseId,
                        redirection_data: Box::new(Some(redirect)),
                        mandate_reference: Box::new(None),
                        connector_metadata: None,
                        network_txn_id: None,
                        connector_response_reference_id: None,
                        incremental_authorization_allowed: None,
                        charges: None,
                    });
                    (response, common_enums::AttemptStatus::AuthenticationPending)
                } else {
                    return Err(errors::ConnectorError::ResponseHandlingFailed.into());
                }
            }
        };

        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}

impl TryFrom<PaymentsSyncResponseRouterData<NordeaPaymentsInitiateResponse>>
    for PaymentsSyncRouterData
{
    type Error = Error;
    fn try_from(
        item: PaymentsSyncResponseRouterData<NordeaPaymentsInitiateResponse>,
    ) -> Result<Self, Self::Error> {
        let (response, status) = convert_nordea_payment_response(&item.response)?;
        Ok(Self {
            status,
            response: Ok(response),
            ..item.data
        })
    }
}


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

pub struct StaxPaymentsRequestMetaData


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

impl api::ConnectorAccessToken for for Celero


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

// Public submodules:
pub mod role;


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

impl api::PaymentSync for for Itaubank


// Function: increment_blocked_count_in_cache
// File: crates/router/src/core/card_testing_guard/utils.rs
// Module: router

pub fn increment_blocked_count_in_cache(
    state: &SessionState,
    card_testing_guard_data: Option<CardTestingGuardData>,
) -> RouterResult<()>


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

pub fn payment_method_session_retrieve()


// Function: set_payment_method
// File: crates/router/src/core/payment_methods/tokenize/payment_method_executor.rs
// Module: router

pub fn set_payment_method(
        self,
        payment_method: &domain::PaymentMethod,
    ) -> NetworkTokenizationBuilder<'a, PmFetched>


// File: crates/hyperswitch_connectors/src/connectors/wise/transformers.rs
// Module: hyperswitch_connectors
// Public functions: 2
// Public structs: 19

#[cfg(feature = "payouts")]
use api_models::payouts::Bank;
#[cfg(feature = "payouts")]
use api_models::payouts::PayoutMethodData;
#[cfg(feature = "payouts")]
use common_enums::PayoutEntityType;
#[cfg(feature = "payouts")]
use common_enums::{CountryAlpha2, PayoutStatus, PayoutType};
#[cfg(feature = "payouts")]
use common_utils::pii::Email;
use common_utils::types::FloatMajorUnit;
use hyperswitch_domain_models::router_data::ConnectorAuthType;
#[cfg(feature = "payouts")]
use hyperswitch_domain_models::types::{PayoutsResponseData, PayoutsRouterData};
use hyperswitch_interfaces::errors::ConnectorError;
use masking::Secret;
use serde::{Deserialize, Serialize};

#[cfg(feature = "payouts")]
use crate::types::PayoutsResponseRouterData;
#[cfg(feature = "payouts")]
use crate::utils::get_unimplemented_payment_method_error_message;
#[cfg(feature = "payouts")]
use crate::utils::{PayoutsData as _, RouterData as _};

type Error = error_stack::Report<ConnectorError>;

#[derive(Debug, Serialize)]
pub struct WiseRouterData<T> {
    pub amount: FloatMajorUnit,
    pub router_data: T,
}

impl<T> From<(FloatMajorUnit, T)> for WiseRouterData<T> {
    fn from((amount, router_data): (FloatMajorUnit, T)) -> Self {
        Self {
            amount,
            router_data,
        }
    }
}

pub struct WiseAuthType {
    pub(super) api_key: Secret<String>,
    #[allow(dead_code)]
    pub(super) profile_id: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for WiseAuthType {
    type Error = Error;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self {
                api_key: api_key.to_owned(),
                profile_id: key1.to_owned(),
            }),
            _ => Err(ConnectorError::FailedToObtainAuthType)?,
        }
    }
}

// Wise error response
#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorResponse {
    pub timestamp: Option<String>,
    pub errors: Option<Vec<SubError>>,
    pub status: Option<WiseHttpStatus>,
    pub error: Option<String>,
    pub error_description: Option<String>,
    pub message: Option<String>,
    pub path: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum WiseHttpStatus {
    String(String),
    Number(u16),
}

impl Default for WiseHttpStatus {
    fn default() -> Self {
        Self::String("".to_string())
    }
}

impl WiseHttpStatus {
    pub fn get_status(&self) -> String {
        match self {
            Self::String(val) => val.clone(),
            Self::Number(val) => val.to_string(),
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct SubError {
    pub code: String,
    pub message: String,
    pub path: Option<String>,
    pub field: Option<String>,
}

// Payouts
#[cfg(feature = "payouts")]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WiseRecipientCreateRequest {
    currency: String,
    #[serde(rename = "type")]
    recipient_type: RecipientType,
    profile: Secret<String>,
    account_holder_name: Secret<String>,
    details: WiseBankDetails,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
#[allow(dead_code)]
pub enum RecipientType {
    Aba,
    Iban,
    SortCode,
    SwiftCode,
}
#[cfg(feature = "payouts")]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum AccountType {
    Checking,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WiseBankDetails {
    legal_type: LegalType,
    account_type: Option<AccountType>,
    address: Option<WiseAddressDetails>,
    post_code: Option<String>,
    nationality: Option<String>,
    account_holder_name: Option<Secret<String>>,
    email: Option<Email>,
    account_number: Option<Secret<String>>,
    city: Option<String>,
    sort_code: Option<Secret<String>>,
    iban: Option<Secret<String>>,
    bic: Option<Secret<String>>,
    transit_number: Option<Secret<String>>,
    routing_number: Option<Secret<String>>,
    abartn: Option<Secret<String>>,
    swift_code: Option<Secret<String>>,
    payin_reference: Option<String>,
    psp_reference: Option<String>,
    tax_id: Option<String>,
    order_id: Option<String>,
    job: Option<String>,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum LegalType {
    Business,
    #[default]
    Private,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WiseAddressDetails {
    country: Option<CountryAlpha2>,
    country_code: Option<CountryAlpha2>,
    first_line: Option<Secret<String>>,
    post_code: Option<Secret<String>>,
    city: Option<String>,
    state: Option<Secret<String>>,
}

#[allow(dead_code)]
#[cfg(feature = "payouts")]
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WiseRecipientCreateResponse {
    id: i64,
    business: Option<i64>,
    profile: Option<i64>,
    account_holder_name: Secret<String>,
    currency: String,
    country: String,
    #[serde(rename = "type")]
    request_type: String,
    details: Option<WiseBankDetails>,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WisePayoutQuoteRequest {
    source_currency: String,
    target_currency: String,
    source_amount: Option<FloatMajorUnit>,
    target_amount: Option<FloatMajorUnit>,
    pay_out: WisePayOutOption,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum WisePayOutOption {
    Balance,
    #[default]
    BankTransfer,
    Swift,
    SwiftOur,
    Interac,
}

#[allow(dead_code)]
#[cfg(feature = "payouts")]
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WisePayoutQuoteResponse {
    source_amount: f64,
    client_id: String,
    id: String,
    status: WiseStatus,
    profile: i64,
    rate: Option<i8>,
    source_currency: Option<String>,
    target_currency: Option<String>,
    user: Option<i64>,
    rate_type: Option<WiseRateType>,
    pay_out: Option<WisePayOutOption>,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum WiseRateType {
    #[default]
    Fixed,
    Floating,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WisePayoutCreateRequest {
    target_account: i64,
    quote_uuid: String,
    customer_transaction_id: String,
    details: WiseTransferDetails,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WiseTransferDetails {
    transfer_purpose: Option<String>,
    source_of_funds: Option<String>,
    transfer_purpose_sub_transfer_purpose: Option<String>,
}

#[allow(dead_code)]
#[cfg(feature = "payouts")]
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WisePayoutResponse {
    id: i64,
    user: i64,
    target_account: i64,
    source_account: Option<i64>,
    quote_uuid: String,
    status: WiseStatus,
    reference: Option<String>,
    rate: Option<f32>,
    business: Option<i64>,
    details: Option<WiseTransferDetails>,
    has_active_issues: Option<bool>,
    source_currency: Option<String>,
    source_value: Option<f64>,
    target_currency: Option<String>,
    target_value: Option<f64>,
    customer_transaction_id: Option<String>,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WisePayoutFulfillRequest {
    #[serde(rename = "type")]
    fund_type: FundType,
}

// NOTE - Only balance is allowed as time of incorporating this field - https://api-docs.transferwise.com/api-reference/transfer#fund
#[cfg(feature = "payouts")]
#[derive(Debug, Default, Serialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum FundType {
    #[default]
    Balance,
}

#[allow(dead_code)]
#[cfg(feature = "payouts")]
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WiseFulfillResponse {
    status: WiseStatus,
    error_code: Option<String>,
    error_message: Option<String>,
    balance_transaction_id: Option<i64>,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum WiseStatus {
    Completed,
    Pending,
    Rejected,

    #[serde(rename = "cancelled")]
    Cancelled,

    #[serde(rename = "processing")]
    #[default]
    Processing,

    #[serde(rename = "incoming_payment_waiting")]
    IncomingPaymentWaiting,
}

#[cfg(feature = "payouts")]
fn get_payout_address_details(
    address: Option<&hyperswitch_domain_models::address::Address>,
) -> Option<WiseAddressDetails> {
    address.and_then(|add| {
        add.address.as_ref().map(|a| WiseAddressDetails {
            country: a.country,
            country_code: a.country,
            first_line: a.line1.clone(),
            post_code: a.zip.clone(),
            city: a.city.clone(),
            state: a.state.clone(),
        })
    })
}

#[cfg(feature = "payouts")]
fn get_payout_bank_details(
    payout_method_data: PayoutMethodData,
    address: Option<&hyperswitch_domain_models::address::Address>,
    entity_type: PayoutEntityType,
) -> Result<WiseBankDetails, ConnectorError> {
    let wise_address_details = match get_payout_address_details(address) {
        Some(a) => Ok(a),
        None => Err(ConnectorError::MissingRequiredField {
            field_name: "address",
        }),
    }?;
    match payout_method_data {
        PayoutMethodData::Bank(Bank::Ach(b)) => Ok(WiseBankDetails {
            legal_type: LegalType::from(entity_type),
            address: Some(wise_address_details),
            account_number: Some(b.bank_account_number.to_owned()),
            abartn: Some(b.bank_routing_number),
            account_type: Some(AccountType::Checking),
            ..WiseBankDetails::default()
        }),
        PayoutMethodData::Bank(Bank::Bacs(b)) => Ok(WiseBankDetails {
            legal_type: LegalType::from(entity_type),
            address: Some(wise_address_details),
            account_number: Some(b.bank_account_number.to_owned()),
            sort_code: Some(b.bank_sort_code),
            ..WiseBankDetails::default()
        }),
        PayoutMethodData::Bank(Bank::Sepa(b)) => Ok(WiseBankDetails {
            legal_type: LegalType::from(entity_type),
            address: Some(wise_address_details),
            iban: Some(b.iban.to_owned()),
            bic: b.bic,
            ..WiseBankDetails::default()
        }),
        _ => Err(ConnectorError::NotImplemented(
            get_unimplemented_payment_method_error_message("Wise"),
        ))?,
    }
}

// Payouts recipient create request transform
#[cfg(feature = "payouts")]
impl<F> TryFrom<&WiseRouterData<&PayoutsRouterData<F>>> for WiseRecipientCreateRequest {
    type Error = Error;
    fn try_from(item_data: &WiseRouterData<&PayoutsRouterData<F>>) -> Result<Self, Self::Error> {
        let item = item_data.router_data;
        let request = item.request.to_owned();
        let customer_details = request.customer_details.to_owned();
        let payout_method_data = item.get_payout_method_data()?;
        let bank_details = get_payout_bank_details(
            payout_method_data.to_owned(),
            item.get_optional_billing(),
            item.request.entity_type,
        )?;
        let source_id = match item.connector_auth_type.to_owned() {
            ConnectorAuthType::BodyKey { api_key: _, key1 } => Ok(key1),
            _ => Err(ConnectorError::MissingRequiredField {
                field_name: "source_id for PayoutRecipient creation",
            }),
        }?;
        let payout_type = request.get_payout_type()?;
        match payout_type {
            PayoutType::Card | PayoutType::Wallet => Err(ConnectorError::NotImplemented(
                get_unimplemented_payment_method_error_message("Wise"),
            ))?,
            PayoutType::Bank => {
                let account_holder_name = customer_details
                    .ok_or(ConnectorError::MissingRequiredField {
                        field_name: "customer_details for PayoutRecipient creation",
                    })?
                    .name
                    .ok_or(ConnectorError::MissingRequiredField {
                        field_name: "customer_details.name for PayoutRecipient creation",
                    })?;
                Ok(Self {
                    profile: source_id,
                    currency: request.destination_currency.to_string(),
                    recipient_type: RecipientType::try_from(payout_method_data)?,
                    account_holder_name,
                    details: bank_details,
                })
            }
        }
    }
}

// Payouts recipient fulfill response transform
#[cfg(feature = "payouts")]
impl<F> TryFrom<PayoutsResponseRouterData<F, WiseRecipientCreateResponse>>
    for PayoutsRouterData<F>
{
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, WiseRecipientCreateResponse>,
    ) -> Result<Self, Self::Error> {
        let response: WiseRecipientCreateResponse = item.response;

        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(PayoutStatus::RequiresCreation),
                connector_payout_id: Some(response.id.to_string()),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

// Payouts quote request transform
#[cfg(feature = "payouts")]
impl<F> TryFrom<&WiseRouterData<&PayoutsRouterData<F>>> for WisePayoutQuoteRequest {
    type Error = Error;
    fn try_from(item_data: &WiseRouterData<&PayoutsRouterData<F>>) -> Result<Self, Self::Error> {
        let item = item_data.router_data;
        let request = item.request.to_owned();
        let payout_type = request.get_payout_type()?;
        match payout_type {
            PayoutType::Bank => Ok(Self {
                source_amount: Some(item_data.amount),
                source_currency: request.source_currency.to_string(),
                target_amount: None,
                target_currency: request.destination_currency.to_string(),
                pay_out: WisePayOutOption::default(),
            }),
            PayoutType::Card | PayoutType::Wallet => Err(ConnectorError::NotImplemented(
                get_unimplemented_payment_method_error_message("Wise"),
            ))?,
        }
    }
}

// Payouts quote response transform
#[cfg(feature = "payouts")]
impl<F> TryFrom<PayoutsResponseRouterData<F, WisePayoutQuoteResponse>> for PayoutsRouterData<F> {
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, WisePayoutQuoteResponse>,
    ) -> Result<Self, Self::Error> {
        let response: WisePayoutQuoteResponse = item.response;

        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(PayoutStatus::RequiresCreation),
                connector_payout_id: Some(response.id),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

// Payouts transfer creation request
#[cfg(feature = "payouts")]
impl<F> TryFrom<&PayoutsRouterData<F>> for WisePayoutCreateRequest {
    type Error = Error;
    fn try_from(item: &PayoutsRouterData<F>) -> Result<Self, Self::Error> {
        let request = item.request.to_owned();
        let payout_type = request.get_payout_type()?;
        match payout_type {
            PayoutType::Bank => {
                let connector_customer_id = item.get_connector_customer_id()?;
                let quote_uuid = item.get_quote_id()?;
                let wise_transfer_details = WiseTransferDetails {
                    transfer_purpose: None,
                    source_of_funds: None,
                    transfer_purpose_sub_transfer_purpose: None,
                };
                let target_account: i64 = connector_customer_id.trim().parse().map_err(|_| {
                    ConnectorError::MissingRequiredField {
                        field_name: "profile",
                    }
                })?;
                Ok(Self {
                    target_account,
                    quote_uuid,
                    customer_transaction_id: uuid::Uuid::new_v4().to_string(),
                    details: wise_transfer_details,
                })
            }
            PayoutType::Card | PayoutType::Wallet => Err(ConnectorError::NotImplemented(
                get_unimplemented_payment_method_error_message("Wise"),
            ))?,
        }
    }
}

// Payouts transfer creation response
#[cfg(feature = "payouts")]
impl<F> TryFrom<PayoutsResponseRouterData<F, WisePayoutResponse>> for PayoutsRouterData<F> {
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, WisePayoutResponse>,
    ) -> Result<Self, Self::Error> {
        let response: WisePayoutResponse = item.response;
        let status = match PayoutStatus::from(response.status) {
            PayoutStatus::Cancelled => PayoutStatus::Cancelled,
            _ => PayoutStatus::RequiresFulfillment,
        };

        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(status),
                connector_payout_id: Some(response.id.to_string()),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

// Payouts fulfill request transform
#[cfg(feature = "payouts")]
impl<F> TryFrom<&PayoutsRouterData<F>> for WisePayoutFulfillRequest {
    type Error = Error;
    fn try_from(item: &PayoutsRouterData<F>) -> Result<Self, Self::Error> {
        let payout_type = item.request.get_payout_type()?;
        match payout_type {
            PayoutType::Bank => Ok(Self {
                fund_type: FundType::default(),
            }),
            PayoutType::Card | PayoutType::Wallet => Err(ConnectorError::NotImplemented(
                get_unimplemented_payment_method_error_message("Wise"),
            ))?,
        }
    }
}

// Payouts fulfill response transform
#[cfg(feature = "payouts")]
impl<F> TryFrom<PayoutsResponseRouterData<F, WiseFulfillResponse>> for PayoutsRouterData<F> {
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, WiseFulfillResponse>,
    ) -> Result<Self, Self::Error> {
        let response: WiseFulfillResponse = item.response;

        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(PayoutStatus::from(response.status)),
                connector_payout_id: Some(
                    item.data
                        .request
                        .connector_payout_id
                        .clone()
                        .ok_or(ConnectorError::MissingConnectorTransactionID)?,
                ),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

#[cfg(feature = "payouts")]
impl From<WiseStatus> for PayoutStatus {
    fn from(wise_status: WiseStatus) -> Self {
        match wise_status {
            WiseStatus::Completed => Self::Initiated,
            WiseStatus::Rejected => Self::Failed,
            WiseStatus::Cancelled => Self::Cancelled,
            WiseStatus::Pending | WiseStatus::Processing | WiseStatus::IncomingPaymentWaiting => {
                Self::Pending
            }
        }
    }
}

#[cfg(feature = "payouts")]
impl From<PayoutEntityType> for LegalType {
    fn from(entity_type: PayoutEntityType) -> Self {
        match entity_type {
            PayoutEntityType::Individual
            | PayoutEntityType::Personal
            | PayoutEntityType::NonProfit
            | PayoutEntityType::NaturalPerson => Self::Private,
            PayoutEntityType::Company
            | PayoutEntityType::PublicSector
            | PayoutEntityType::Business => Self::Business,
        }
    }
}

#[cfg(feature = "payouts")]
impl TryFrom<PayoutMethodData> for RecipientType {
    type Error = error_stack::Report<ConnectorError>;
    fn try_from(payout_method_type: PayoutMethodData) -> Result<Self, Self::Error> {
        match payout_method_type {
            PayoutMethodData::Bank(Bank::Ach(_)) => Ok(Self::Aba),
            PayoutMethodData::Bank(Bank::Bacs(_)) => Ok(Self::SortCode),
            PayoutMethodData::Bank(Bank::Sepa(_)) => Ok(Self::Iban),
            _ => Err(ConnectorError::NotImplemented(
                get_unimplemented_payment_method_error_message("Wise"),
            )
            .into()),
        }
    }
}

#[cfg(feature = "payouts")]
#[derive(Debug, Deserialize, Serialize)]
pub struct WisePayoutSyncResponse {
    id: u64,
    status: WiseSyncStatus,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum WiseSyncStatus {
    IncomingPaymentWaiting,
    IncomingPaymentInitiated,
    Processing,
    FundsConverted,
    OutgoingPaymentSent,
    Cancelled,
    FundsRefunded,
    BouncedBack,
    ChargedBack,
    Unknown,
}

#[cfg(feature = "payouts")]
impl<F> TryFrom<PayoutsResponseRouterData<F, WisePayoutSyncResponse>> for PayoutsRouterData<F> {
    type Error = Error;
    fn try_from(
        item: PayoutsResponseRouterData<F, WisePayoutSyncResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(PayoutsResponseData {
                status: Some(PayoutStatus::from(item.response.status)),
                connector_payout_id: Some(item.response.id.to_string()),
                payout_eligible: None,
                should_add_next_step_to_process_tracker: false,
                error_code: None,
                error_message: None,
            }),
            ..item.data
        })
    }
}

#[cfg(feature = "payouts")]
impl From<WiseSyncStatus> for PayoutStatus {
    fn from(status: WiseSyncStatus) -> Self {
        match status {
            WiseSyncStatus::IncomingPaymentWaiting => Self::Pending,
            WiseSyncStatus::IncomingPaymentInitiated => Self::Pending,
            WiseSyncStatus::Processing => Self::Pending,
            WiseSyncStatus::FundsConverted => Self::Pending,
            WiseSyncStatus::OutgoingPaymentSent => Self::Success,
            WiseSyncStatus::Cancelled => Self::Cancelled,
            WiseSyncStatus::FundsRefunded => Self::Reversed,
            WiseSyncStatus::BouncedBack => Self::Pending,
            WiseSyncStatus::ChargedBack => Self::Reversed,
            WiseSyncStatus::Unknown => Self::Ineligible,
        }
    }
}

#[cfg(feature = "payouts")]
#[derive(Debug, Deserialize, Serialize)]
pub struct WisePayoutsWebhookBody {
    pub data: WisePayoutsWebhookData,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Deserialize, Serialize)]
pub struct WisePayoutsWebhookData {
    pub resource: WisePayoutsWebhookResource,
    pub current_state: WiseSyncStatus,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Deserialize, Serialize)]
pub struct WisePayoutsWebhookResource {
    pub id: u64,
}

#[cfg(feature = "payouts")]
impl From<WisePayoutsWebhookData> for WisePayoutSyncResponse {
    fn from(data: WisePayoutsWebhookData) -> Self {
        Self {
            id: data.resource.id,
            status: data.current_state,
        }
    }
}

#[cfg(feature = "payouts")]
pub fn get_wise_webhooks_event(
    state: WiseSyncStatus,
) -> api_models::webhooks::IncomingWebhookEvent {
    match state {
        WiseSyncStatus::IncomingPaymentWaiting => {
            api_models::webhooks::IncomingWebhookEvent::PayoutProcessing
        }
        WiseSyncStatus::IncomingPaymentInitiated => {
            api_models::webhooks::IncomingWebhookEvent::PayoutProcessing
        }
        WiseSyncStatus::Processing => api_models::webhooks::IncomingWebhookEvent::PayoutProcessing,
        WiseSyncStatus::FundsConverted => {
            api_models::webhooks::IncomingWebhookEvent::PayoutProcessing
        }
        WiseSyncStatus::OutgoingPaymentSent => {
            api_models::webhooks::IncomingWebhookEvent::PayoutSuccess
        }
        WiseSyncStatus::Cancelled => api_models::webhooks::IncomingWebhookEvent::PayoutCancelled,
        WiseSyncStatus::FundsRefunded => api_models::webhooks::IncomingWebhookEvent::PayoutReversed,
        WiseSyncStatus::BouncedBack => api_models::webhooks::IncomingWebhookEvent::PayoutProcessing,
        WiseSyncStatus::ChargedBack => api_models::webhooks::IncomingWebhookEvent::PayoutReversed,
        WiseSyncStatus::Unknown => api_models::webhooks::IncomingWebhookEvent::EventNotSupported,
    }
}


// Struct: BluecodePaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/bluecode/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BluecodePaymentsResponse


// Implementation: impl ConnectorRedirectResponse for for Bluesnap
// File: crates/hyperswitch_connectors/src/connectors/bluesnap.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl ConnectorRedirectResponse for for Bluesnap


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

pub struct DisputeResponsePaymentsRetrieve


// Function: payments_cancel
// File: crates/router/src/routes/payments.rs
// Module: router

pub fn payments_cancel(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<payment_types::PaymentsCancelRequest>,
    path: web::Path<common_utils::id_type::GlobalPaymentId>,
) -> impl Responder


// Function: get_resource
// File: crates/storage_impl/src/mock_db.rs
// Module: storage_impl

// Documentation: Throws errors when the requested resource is not found

pub fn get_resource<D, R>(
        &self,
        state: &KeyManagerState,
        key_store: &MerchantKeyStore,
        resources: MutexGuard<'_, Vec<D>>,
        filter_fn: impl Fn(&&D) -> bool,
        error_message: String,
    ) -> CustomResult<R, StorageError>
    where
        D: Sync + ReverseConversion<R> + Clone,
        R: Conversion,


// File: crates/router/src/types/storage/payout_attempt.rs
// Module: router

pub use diesel_models::payout_attempt::{
    PayoutAttempt, PayoutAttemptNew, PayoutAttemptUpdate, PayoutAttemptUpdateInternal,
};


// Struct: SchedulerSettings
// File: crates/scheduler/src/configs/settings.rs
// Module: scheduler
// Implementations: 0

pub struct SchedulerSettings


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

impl api::MandateSetup for for Digitalvirgo


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

impl api::ConnectorAccessToken for for Checkbook


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

pub struct RazorpayRefundRequest


// Function: mk_card_value1
// File: crates/router/src/core/payment_methods/transformers.rs
// Module: router

pub fn mk_card_value1(
    card_number: cards::CardNumber,
    exp_year: String,
    exp_month: String,
    name_on_card: Option<String>,
    nickname: Option<String>,
    card_last_four: Option<String>,
    card_token: Option<String>,
) -> CustomResult<String, errors::VaultError>


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

impl CustomerNew


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

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


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

pub struct PaymentsSuccessRate


// Struct: CommonPaymentMethodData
// File: crates/hyperswitch_connectors/src/connectors/globalpay/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CommonPaymentMethodData


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

pub struct PhoneNumber