// File: crates/api_models/src/profile_acquirer.rs
// Module: api_models
// Public structs: 3

use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct ProfileAcquirerCreate {
    /// The merchant id assigned by the acquirer
    #[schema(value_type= String,example = "M123456789")]
    pub acquirer_assigned_merchant_id: String,
    /// merchant name
    #[schema(value_type= String,example = "NewAge Retailer")]
    pub merchant_name: String,
    /// Network provider
    #[schema(value_type= String,example = "VISA")]
    pub network: common_enums::enums::CardNetwork,
    /// Acquirer bin
    #[schema(value_type= String,example = "456789")]
    pub acquirer_bin: String,
    /// Acquirer ica provided by acquirer
    #[schema(value_type= Option<String>,example = "401288")]
    pub acquirer_ica: Option<String>,
    /// Fraud rate for the particular acquirer configuration
    #[schema(value_type= f64,example = 0.01)]
    pub acquirer_fraud_rate: f64,
    /// Parent profile id to link the acquirer account with
    #[schema(value_type= String,example = "pro_ky0yNyOXXlA5hF8JzE5q")]
    pub profile_id: common_utils::id_type::ProfileId,
}

#[derive(Debug, Serialize, Deserialize, ToSchema, Clone)]
pub struct ProfileAcquirerResponse {
    /// The unique identifier of the profile acquirer
    #[schema(value_type= String,example = "pro_acq_LCRdERuylQvNQ4qh3QE0")]
    pub profile_acquirer_id: common_utils::id_type::ProfileAcquirerId,
    /// The merchant id assigned by the acquirer
    #[schema(value_type= String,example = "M123456789")]
    pub acquirer_assigned_merchant_id: String,
    /// Merchant name
    #[schema(value_type= String,example = "NewAge Retailer")]
    pub merchant_name: String,
    /// Network provider
    #[schema(value_type= String,example = "VISA")]
    pub network: common_enums::enums::CardNetwork,
    /// Acquirer bin
    #[schema(value_type= String,example = "456789")]
    pub acquirer_bin: String,
    /// Acquirer ica provided by acquirer
    #[schema(value_type= Option<String>,example = "401288")]
    pub acquirer_ica: Option<String>,
    /// Fraud rate for the particular acquirer configuration
    #[schema(value_type= f64,example = 0.01)]
    pub acquirer_fraud_rate: f64,
    /// Parent profile id to link the acquirer account with
    #[schema(value_type= String,example = "pro_ky0yNyOXXlA5hF8JzE5q")]
    pub profile_id: common_utils::id_type::ProfileId,
}

impl common_utils::events::ApiEventMetric for ProfileAcquirerCreate {}
impl common_utils::events::ApiEventMetric for ProfileAcquirerResponse {}

impl
    From<(
        common_utils::id_type::ProfileAcquirerId,
        &common_utils::id_type::ProfileId,
        &common_types::domain::AcquirerConfig,
    )> for ProfileAcquirerResponse
{
    fn from(
        (profile_acquirer_id, profile_id, acquirer_config): (
            common_utils::id_type::ProfileAcquirerId,
            &common_utils::id_type::ProfileId,
            &common_types::domain::AcquirerConfig,
        ),
    ) -> Self {
        Self {
            profile_acquirer_id,
            profile_id: profile_id.clone(),
            acquirer_assigned_merchant_id: acquirer_config.acquirer_assigned_merchant_id.clone(),
            merchant_name: acquirer_config.merchant_name.clone(),
            network: acquirer_config.network.clone(),
            acquirer_bin: acquirer_config.acquirer_bin.clone(),
            acquirer_ica: acquirer_config.acquirer_ica.clone(),
            acquirer_fraud_rate: acquirer_config.acquirer_fraud_rate,
        }
    }
}

#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct ProfileAcquirerUpdate {
    #[schema(value_type = Option<String>, example = "M987654321")]
    pub acquirer_assigned_merchant_id: Option<String>,
    #[schema(value_type = Option<String>, example = "Updated Retailer Name")]
    pub merchant_name: Option<String>,
    #[schema(value_type = Option<String>, example = "MASTERCARD")]
    pub network: Option<common_enums::enums::CardNetwork>,
    #[schema(value_type = Option<String>, example = "987654")]
    pub acquirer_bin: Option<String>,
    #[schema(value_type = Option<String>, example = "501299")]
    pub acquirer_ica: Option<String>,
    #[schema(value_type = Option<f64>, example = "0.02")]
    pub acquirer_fraud_rate: Option<f64>,
}

impl common_utils::events::ApiEventMetric for ProfileAcquirerUpdate {}


// Struct: ReverseLookup
// File: crates/diesel_models/src/reverse_lookup.rs
// Module: diesel_models
// Implementations: 0

pub struct ReverseLookup


// Implementation: impl NovalnetPaymentsResponseTransactionData
// File: crates/hyperswitch_connectors/src/connectors/novalnet/transformers.rs
// Module: hyperswitch_connectors
// Methods: 1 total (1 public)

impl NovalnetPaymentsResponseTransactionData


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

impl Responder


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

impl AttemptStatus


// Implementation: impl Fiservemea
// File: crates/hyperswitch_connectors/src/connectors/fiservemea.rs
// Module: hyperswitch_connectors
// Methods: 2 total (2 public)

impl Fiservemea


// File: crates/router/src/types/storage/payment_method.rs
// Module: router
// Public functions: 6
// Public structs: 7

use api_models::payment_methods;
use diesel_models::enums;
pub use diesel_models::payment_method::{
    PaymentMethod, PaymentMethodNew, PaymentMethodUpdate, PaymentMethodUpdateInternal,
    TokenizeCoreWorkflow,
};

use crate::types::{api, domain};

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PaymentTokenKind {
    Temporary,
    Permanent,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CardTokenData {
    pub payment_method_id: Option<String>,
    pub locker_id: Option<String>,
    pub token: String,
    pub network_token_locker_id: Option<String>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CardTokenData {
    pub payment_method_id: common_utils::id_type::GlobalPaymentMethodId,
    pub locker_id: Option<String>,
    pub token: String,
}

#[derive(Debug, Clone, serde::Serialize, Default, serde::Deserialize)]
pub struct PaymentMethodDataWithId {
    pub payment_method: Option<enums::PaymentMethod>,
    pub payment_method_data: Option<domain::PaymentMethodData>,
    pub payment_method_id: Option<String>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GenericTokenData {
    pub token: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct WalletTokenData {
    pub payment_method_id: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
#[cfg(feature = "v1")]
pub enum PaymentTokenData {
    // The variants 'Temporary' and 'Permanent' are added for backwards compatibility
    // with any tokenized data present in Redis at the time of deployment of this change
    Temporary(GenericTokenData),
    TemporaryGeneric(GenericTokenData),
    Permanent(CardTokenData),
    PermanentCard(CardTokenData),
    AuthBankDebit(payment_methods::BankAccountTokenData),
    WalletToken(WalletTokenData),
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
#[cfg(feature = "v2")]
pub enum PaymentTokenData {
    TemporaryGeneric(GenericTokenData),
    PermanentCard(CardTokenData),
    AuthBankDebit(payment_methods::BankAccountTokenData),
}

impl PaymentTokenData {
    #[cfg(feature = "v1")]
    pub fn permanent_card(
        payment_method_id: Option<String>,
        locker_id: Option<String>,
        token: String,
        network_token_locker_id: Option<String>,
    ) -> Self {
        Self::PermanentCard(CardTokenData {
            payment_method_id,
            locker_id,
            token,
            network_token_locker_id,
        })
    }

    #[cfg(feature = "v2")]
    pub fn permanent_card(
        payment_method_id: common_utils::id_type::GlobalPaymentMethodId,
        locker_id: Option<String>,
        token: String,
    ) -> Self {
        Self::PermanentCard(CardTokenData {
            payment_method_id,
            locker_id,
            token,
        })
    }

    pub fn temporary_generic(token: String) -> Self {
        Self::TemporaryGeneric(GenericTokenData { token })
    }

    #[cfg(feature = "v1")]
    pub fn wallet_token(payment_method_id: String) -> Self {
        Self::WalletToken(WalletTokenData { payment_method_id })
    }

    #[cfg(feature = "v1")]
    pub fn is_permanent_card(&self) -> bool {
        matches!(self, Self::PermanentCard(_) | Self::Permanent(_))
    }

    #[cfg(feature = "v2")]
    pub fn is_permanent_card(&self) -> bool {
        matches!(self, Self::PermanentCard(_))
    }
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaymentMethodListContext {
    pub card_details: Option<api::CardDetailFromLocker>,
    pub hyperswitch_token_data: Option<PaymentTokenData>,
    #[cfg(feature = "payouts")]
    pub bank_transfer_details: Option<api::BankPayout>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum PaymentMethodListContext {
    Card {
        card_details: api::CardDetailFromLocker,
        // TODO: Why can't these fields be mandatory?
        token_data: Option<PaymentTokenData>,
    },
    Bank {
        token_data: Option<PaymentTokenData>,
    },
    #[cfg(feature = "payouts")]
    BankTransfer {
        bank_transfer_details: api::BankPayout,
        token_data: Option<PaymentTokenData>,
    },
    TemporaryToken {
        token_data: Option<PaymentTokenData>,
    },
}

#[cfg(feature = "v2")]
impl PaymentMethodListContext {
    pub(crate) fn get_token_data(&self) -> Option<PaymentTokenData> {
        match self {
            Self::Card { token_data, .. }
            | Self::Bank { token_data }
            | Self::BankTransfer { token_data, .. }
            | Self::TemporaryToken { token_data } => token_data.clone(),
        }
    }
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct PaymentMethodStatusTrackingData {
    pub payment_method_id: String,
    pub prev_status: enums::PaymentMethodStatus,
    pub curr_status: enums::PaymentMethodStatus,
    pub merchant_id: common_utils::id_type::MerchantId,
}


// Function: link_token_create
// File: crates/router/src/routes/pm_auth.rs
// Module: router

pub fn link_token_create(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<api_types::pm_auth::LinkTokenCreateRequest>,
) -> impl Responder


// Implementation: impl SmtpServerConfig
// File: crates/external_services/src/email/smtp.rs
// Module: external_services
// Methods: 1 total (1 public)

impl SmtpServerConfig


// Function: create_routing_algorithm_under_profile
// File: crates/router/src/core/routing.rs
// Module: router

pub fn create_routing_algorithm_under_profile(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    authentication_profile_id: Option<common_utils::id_type::ProfileId>,
    request: routing_types::RoutingConfigRequest,
    transaction_type: enums::TransactionType,
) -> RouterResponse<routing_types::RoutingDictionaryRecord>


// Struct: ErrorResponse
// File: crates/api_models/src/open_router.rs
// Module: api_models
// Implementations: 0

pub struct ErrorResponse


// Struct: KafkaPaymentAttempt
// File: crates/router/src/services/kafka/payment_attempt.rs
// Module: router
// Implementations: 3
// Traits: super::KafkaMessage

pub struct KafkaPaymentAttempt<'a>


// Struct: AwsFileStorageConfig
// File: crates/external_services/src/file_storage/aws_s3.rs
// Module: external_services
// Implementations: 1

pub struct AwsFileStorageConfig


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

pub struct KlarnaConnectorMetadataObject


// Implementation: impl super::behaviour::Conversion for for MerchantAccount
// File: crates/hyperswitch_domain_models/src/merchant_account.rs
// Module: hyperswitch_domain_models
// Methods: 3 total (0 public)

impl super::behaviour::Conversion for for MerchantAccount


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

pub struct AuthorizedotnetTransactionResponseError


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

pub struct RoutingPayloadWrapper


// Function: delete_from_stream
// File: crates/drainer/src/stream.rs
// Module: drainer

pub fn delete_from_stream(
        &self,
        stream_name: &str,
        entry_id: &str,
    ) -> errors::DrainerResult<()>


// Implementation: impl Keys
// File: crates/hyperswitch_constraint_graph/src/dense_map.rs
// Module: hyperswitch_constraint_graph
// Methods: 1 total (0 public)

impl Keys


// Implementation: impl Default for for NetworkTokenizationBuilder
// File: crates/router/src/core/payment_methods/tokenize/card_executor.rs
// Module: router
// Methods: 1 total (0 public)

impl Default for for NetworkTokenizationBuilder


// Function: push_metrics_with_update_window_for_success_based_routing
// File: crates/router/src/core/routing/helpers.rs
// Module: router

pub fn push_metrics_with_update_window_for_success_based_routing(
    state: &SessionState,
    payment_attempt: &storage::PaymentAttempt,
    routable_connectors: Vec<routing_types::RoutableConnectorChoice>,
    profile_id: &id_type::ProfileId,
    dynamic_routing_algo_ref: routing_types::DynamicRoutingAlgorithmRef,
    dynamic_routing_config_params_interpolator: DynamicRoutingConfigParamsInterpolator,
) -> RouterResult<()>


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

impl Responder


// Implementation: impl EuclidDirFilter for for ThreeDSDecisionRule
// File: crates/common_types/src/three_ds_decision_rule_engine.rs
// Module: common_types
// Methods: 0 total (0 public)

impl EuclidDirFilter for for ThreeDSDecisionRule


// Function: build_unified_connector_service_payment_method_for_external_proxy
// File: crates/router/src/core/unified_connector_service.rs
// Module: router

pub fn build_unified_connector_service_payment_method_for_external_proxy(
    payment_method_data: hyperswitch_domain_models::payment_method_data::ExternalVaultPaymentMethodData,
    payment_method_type: PaymentMethodType,
) -> CustomResult<payments_grpc::PaymentMethod, UnifiedConnectorServiceError>


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

pub fn new_from_sync_response(
        amount: Option<i64>,
        is_post_capture_void: bool,
        payment_method: enums::PaymentMethod,
        response: &NuveiTransactionSyncResponse,
    ) -> Self


// Function: add_refund_execute_task
// File: crates/router/src/core/refunds_v2.rs
// Module: router

pub fn add_refund_execute_task(
    db: &dyn db::StorageInterface,
    refund: &diesel_refund::Refund,
    runner: storage::ProcessTrackerRunner,
) -> errors::RouterResult<storage::ProcessTracker>


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

pub struct ApplePayHeader


// File: crates/hyperswitch_connectors/src/connectors/fiservemea/transformers.rs
// Module: hyperswitch_connectors
// Public structs: 20

use common_enums::enums;
use common_utils::types::StringMajorUnit;
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, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        RefundsRouterData,
    },
};
use hyperswitch_interfaces::errors;
use masking::Secret;
use serde::{Deserialize, Serialize};

use crate::{
    types::{RefundsResponseRouterData, ResponseRouterData},
    utils::CardData as _,
};

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

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

#[derive(Debug, Serialize)]
pub struct FiservemeaTransactionAmount {
    total: StringMajorUnit,
    currency: common_enums::Currency,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaOrder {
    order_id: String,
}

#[derive(Debug, Serialize)]
pub enum FiservemeaRequestType {
    PaymentCardSaleTransaction,
    PaymentCardPreAuthTransaction,
    PostAuthTransaction,
    VoidPreAuthTransactions,
    ReturnTransaction,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaExpiryDate {
    month: Secret<String>,
    year: Secret<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaPaymentCard {
    number: cards::CardNumber,
    expiry_date: FiservemeaExpiryDate,
    security_code: Secret<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum FiservemeaPaymentMethods {
    PaymentCard(FiservemeaPaymentCard),
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaPaymentsRequest {
    request_type: FiservemeaRequestType,
    merchant_transaction_id: String,
    transaction_amount: FiservemeaTransactionAmount,
    order: FiservemeaOrder,
    payment_method: FiservemeaPaymentMethods,
}

impl TryFrom<&FiservemeaRouterData<&PaymentsAuthorizeRouterData>> for FiservemeaPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &FiservemeaRouterData<&PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        match item.router_data.request.payment_method_data.clone() {
            PaymentMethodData::Card(req_card) => {
                let card = FiservemeaPaymentCard {
                    number: req_card.card_number.clone(),
                    expiry_date: FiservemeaExpiryDate {
                        month: req_card.card_exp_month.clone(),
                        year: req_card.get_card_expiry_year_2_digit()?,
                    },
                    security_code: req_card.card_cvc,
                };
                let request_type = if matches!(
                    item.router_data.request.capture_method,
                    Some(enums::CaptureMethod::Automatic)
                        | Some(enums::CaptureMethod::SequentialAutomatic)
                ) {
                    FiservemeaRequestType::PaymentCardSaleTransaction
                } else {
                    FiservemeaRequestType::PaymentCardPreAuthTransaction
                };

                Ok(Self {
                    request_type,
                    merchant_transaction_id: item
                        .router_data
                        .request
                        .merchant_order_reference_id
                        .clone()
                        .unwrap_or(item.router_data.connector_request_reference_id.clone()),
                    transaction_amount: FiservemeaTransactionAmount {
                        total: item.amount.clone(),
                        currency: item.router_data.request.currency,
                    },
                    order: FiservemeaOrder {
                        order_id: item.router_data.connector_request_reference_id.clone(),
                    },
                    payment_method: FiservemeaPaymentMethods::PaymentCard(card),
                })
            }
            _ => Err(errors::ConnectorError::NotImplemented(
                "Selected payment method through fiservemea".to_string(),
            )
            .into()),
        }
    }
}

// Auth Struct
#[derive(Clone)]
pub struct FiservemeaAuthType {
    pub(super) api_key: Secret<String>,
    pub(super) secret_key: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for FiservemeaAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    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(),
                secret_key: key1.to_owned(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}

// PaymentsResponse
#[derive(Debug, Serialize, Deserialize)]
pub enum ResponseType {
    BadRequest,
    Unauthenticated,
    Unauthorized,
    NotFound,
    GatewayDeclined,
    EndpointDeclined,
    ServerError,
    EndpointCommunicationError,
    UnsupportedMediaType,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum FiservemeaTransactionType {
    Sale,
    Preauth,
    Credit,
    ForcedTicket,
    Void,
    Return,
    Postauth,
    PayerAuth,
    Disbursement,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum FiservemeaTransactionOrigin {
    Ecom,
    Moto,
    Mail,
    Phone,
    Retail,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum FiservemeaPaymentStatus {
    Approved,
    Waiting,
    Partial,
    ValidationFailed,
    ProcessingFailed,
    Declined,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum FiservemeaPaymentResult {
    Approved,
    Declined,
    Failed,
    Waiting,
    Partial,
    Fraud,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaPaymentCardResponse {
    expiry_date: Option<FiservemeaExpiryDate>,
    bin: Option<String>,
    last4: Option<String>,
    brand: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaPaymentMethodDetails {
    payment_card: Option<FiservemeaPaymentCardResponse>,
    payment_method_type: Option<String>,
    payment_method_brand: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Components {
    subtotal: Option<f64>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AmountDetails {
    total: Option<f64>,
    currency: Option<common_enums::Currency>,
    components: Option<Components>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AvsResponse {
    street_match: Option<String>,
    postal_code_match: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Processor {
    reference_number: Option<String>,
    authorization_code: Option<String>,
    response_code: Option<String>,
    response_message: Option<String>,
    avs_response: Option<AvsResponse>,
    security_code_response: Option<String>,
}

fn map_status(
    fiservemea_status: Option<FiservemeaPaymentStatus>,
    fiservemea_result: Option<FiservemeaPaymentResult>,
    transaction_type: FiservemeaTransactionType,
) -> common_enums::AttemptStatus {
    match fiservemea_status {
        Some(status) => match status {
            FiservemeaPaymentStatus::Approved => match transaction_type {
                FiservemeaTransactionType::Preauth => common_enums::AttemptStatus::Authorized,
                FiservemeaTransactionType::Void => common_enums::AttemptStatus::Voided,
                FiservemeaTransactionType::Sale | FiservemeaTransactionType::Postauth => {
                    common_enums::AttemptStatus::Charged
                }
                FiservemeaTransactionType::Credit
                | FiservemeaTransactionType::ForcedTicket
                | FiservemeaTransactionType::Return
                | FiservemeaTransactionType::PayerAuth
                | FiservemeaTransactionType::Disbursement => common_enums::AttemptStatus::Failure,
            },
            FiservemeaPaymentStatus::Waiting => common_enums::AttemptStatus::Pending,
            FiservemeaPaymentStatus::Partial => common_enums::AttemptStatus::PartialCharged,
            FiservemeaPaymentStatus::ValidationFailed
            | FiservemeaPaymentStatus::ProcessingFailed
            | FiservemeaPaymentStatus::Declined => common_enums::AttemptStatus::Failure,
        },
        None => match fiservemea_result {
            Some(result) => match result {
                FiservemeaPaymentResult::Approved => match transaction_type {
                    FiservemeaTransactionType::Preauth => common_enums::AttemptStatus::Authorized,
                    FiservemeaTransactionType::Void => common_enums::AttemptStatus::Voided,
                    FiservemeaTransactionType::Sale | FiservemeaTransactionType::Postauth => {
                        common_enums::AttemptStatus::Charged
                    }
                    FiservemeaTransactionType::Credit
                    | FiservemeaTransactionType::ForcedTicket
                    | FiservemeaTransactionType::Return
                    | FiservemeaTransactionType::PayerAuth
                    | FiservemeaTransactionType::Disbursement => {
                        common_enums::AttemptStatus::Failure
                    }
                },
                FiservemeaPaymentResult::Waiting => common_enums::AttemptStatus::Pending,
                FiservemeaPaymentResult::Partial => common_enums::AttemptStatus::PartialCharged,
                FiservemeaPaymentResult::Declined
                | FiservemeaPaymentResult::Failed
                | FiservemeaPaymentResult::Fraud => common_enums::AttemptStatus::Failure,
            },
            None => common_enums::AttemptStatus::Pending,
        },
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaPaymentsResponse {
    response_type: Option<ResponseType>,
    #[serde(rename = "type")]
    fiservemea_type: Option<String>,
    client_request_id: Option<String>,
    api_trace_id: Option<String>,
    ipg_transaction_id: String,
    order_id: Option<String>,
    transaction_type: FiservemeaTransactionType,
    transaction_origin: Option<FiservemeaTransactionOrigin>,
    payment_method_details: Option<FiservemeaPaymentMethodDetails>,
    country: Option<Secret<String>>,
    terminal_id: Option<String>,
    merchant_id: Option<String>,
    merchant_transaction_id: Option<String>,
    transaction_time: Option<i64>,
    approved_amount: Option<AmountDetails>,
    transaction_amount: Option<AmountDetails>,
    transaction_status: Option<FiservemeaPaymentStatus>, // FiservEMEA Docs mention that this field is deprecated. We are using it for now because transaction_result is not present in the response.
    transaction_result: Option<FiservemeaPaymentResult>,
    approval_code: Option<String>,
    error_message: Option<String>,
    transaction_state: Option<String>,
    scheme_transaction_id: Option<String>,
    processor: Option<Processor>,
}

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

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaCaptureRequest {
    request_type: FiservemeaRequestType,
    transaction_amount: FiservemeaTransactionAmount,
}

impl TryFrom<&FiservemeaRouterData<&PaymentsCaptureRouterData>> for FiservemeaCaptureRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &FiservemeaRouterData<&PaymentsCaptureRouterData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            request_type: FiservemeaRequestType::PostAuthTransaction,
            transaction_amount: FiservemeaTransactionAmount {
                total: item.amount.clone(),
                currency: item.router_data.request.currency,
            },
        })
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaVoidRequest {
    request_type: FiservemeaRequestType,
}

impl TryFrom<&PaymentsCancelRouterData> for FiservemeaVoidRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(_item: &PaymentsCancelRouterData) -> Result<Self, Self::Error> {
        Ok(Self {
            request_type: FiservemeaRequestType::VoidPreAuthTransactions,
        })
    }
}

// REFUND :
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FiservemeaRefundRequest {
    request_type: FiservemeaRequestType,
    transaction_amount: FiservemeaTransactionAmount,
}

impl<F> TryFrom<&FiservemeaRouterData<&RefundsRouterData<F>>> for FiservemeaRefundRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &FiservemeaRouterData<&RefundsRouterData<F>>) -> Result<Self, Self::Error> {
        Ok(Self {
            request_type: FiservemeaRequestType::ReturnTransaction,
            transaction_amount: FiservemeaTransactionAmount {
                total: item.amount.clone(),
                currency: item.router_data.request.currency,
            },
        })
    }
}

fn map_refund_status(
    fiservemea_status: Option<FiservemeaPaymentStatus>,
    fiservemea_result: Option<FiservemeaPaymentResult>,
) -> Result<enums::RefundStatus, errors::ConnectorError> {
    match fiservemea_status {
        Some(status) => match status {
            FiservemeaPaymentStatus::Approved => Ok(enums::RefundStatus::Success),
            FiservemeaPaymentStatus::Partial | FiservemeaPaymentStatus::Waiting => {
                Ok(enums::RefundStatus::Pending)
            }
            FiservemeaPaymentStatus::ValidationFailed
            | FiservemeaPaymentStatus::ProcessingFailed
            | FiservemeaPaymentStatus::Declined => Ok(enums::RefundStatus::Failure),
        },
        None => match fiservemea_result {
            Some(result) => match result {
                FiservemeaPaymentResult::Approved => Ok(enums::RefundStatus::Success),
                FiservemeaPaymentResult::Partial | FiservemeaPaymentResult::Waiting => {
                    Ok(enums::RefundStatus::Pending)
                }
                FiservemeaPaymentResult::Declined
                | FiservemeaPaymentResult::Failed
                | FiservemeaPaymentResult::Fraud => Ok(enums::RefundStatus::Failure),
            },
            None => Err(errors::ConnectorError::MissingRequiredField {
                field_name: "transactionResult",
            }),
        },
    }
}

impl TryFrom<RefundsResponseRouterData<Execute, FiservemeaPaymentsResponse>>
    for RefundsRouterData<Execute>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<Execute, FiservemeaPaymentsResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.ipg_transaction_id,
                refund_status: map_refund_status(
                    item.response.transaction_status,
                    item.response.transaction_result,
                )?,
            }),
            ..item.data
        })
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, FiservemeaPaymentsResponse>>
    for RefundsRouterData<RSync>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<RSync, FiservemeaPaymentsResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.ipg_transaction_id,
                refund_status: map_refund_status(
                    item.response.transaction_status,
                    item.response.transaction_result,
                )?,
            }),
            ..item.data
        })
    }
}

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

#[derive(Debug, Serialize, Deserialize)]
pub struct FiservemeaError {
    pub code: Option<String>,
    pub message: Option<String>,
    pub details: Option<Vec<ErrorDetails>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct FiservemeaErrorResponse {
    #[serde(rename = "type")]
    fiservemea_type: Option<String>,
    client_request_id: Option<String>,
    api_trace_id: Option<String>,
    pub response_type: Option<String>,
    pub error: Option<FiservemeaError>,
}


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

pub fn should_call_connector_create_customer<'a>(
    connector: &api::ConnectorData,
    customer: &'a Option<domain::Customer>,
    payment_attempt: &hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt,
    merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
) -> (bool, Option<&'a str>)


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

pub fn list_customer_payment_method_api()


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

impl api::RefundExecute for for Bluesnap


// Function: find_by_payment_id_merchant_id
// File: crates/diesel_models/src/query/refund.rs
// Module: diesel_models

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


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

impl api::PaymentSession for for Ebanx


// Implementation: impl api::RefundExecute for for Payu
// File: crates/hyperswitch_connectors/src/connectors/payu.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundExecute for for Payu


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

pub struct NetworkTransactionIdAndCardDetails


// Implementation: impl Default for for StrongSecret
// File: crates/masking/src/strong_secret.rs
// Module: masking
// Methods: 1 total (0 public)

impl Default for for StrongSecret


// File: crates/router/src/core/payments/operations/payment_update_intent.rs
// Module: router
// Public structs: 1

use std::marker::PhantomData;

use api_models::{
    enums::{FrmSuggestion, UpdateActiveAttempt},
    payments::PaymentsUpdateIntentRequest,
};
use async_trait::async_trait;
use common_utils::{
    errors::CustomResult,
    ext_traits::{Encode, ValueExt},
    types::keymanager::ToEncryptable,
};
use diesel_models::types::FeatureMetadata;
use error_stack::ResultExt;
use hyperswitch_domain_models::{
    payments::payment_intent::{PaymentIntentUpdate, PaymentIntentUpdateFields},
    ApiModelToDieselModelConvertor,
};
use masking::PeekInterface;
use router_env::{instrument, tracing};

use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest};
use crate::{
    core::{
        errors::{self, RouterResult},
        payments::{
            self, helpers,
            operations::{self, ValidateStatusForOperation},
        },
    },
    db::errors::StorageErrorExt,
    routes::{app::ReqState, SessionState},
    types::{
        api,
        domain::{self, types as domain_types},
        storage::{self, enums},
    },
};

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

impl ValidateStatusForOperation for PaymentUpdateIntent {
    /// Validate if the current operation can be performed on the current status of the payment intent
    fn validate_status_for_operation(
        &self,
        intent_status: common_enums::IntentStatus,
    ) -> Result<(), errors::ApiErrorResponse> {
        match intent_status {
            // if the status is `Failed`` we would want to Update few intent fields to perform a Revenue Recovery retry
            common_enums::IntentStatus::RequiresPaymentMethod
            | common_enums::IntentStatus::Failed
            | common_enums::IntentStatus::Conflicted => Ok(()),
            common_enums::IntentStatus::Succeeded
            | common_enums::IntentStatus::Cancelled
            | common_enums::IntentStatus::CancelledPostCapture
            | common_enums::IntentStatus::Processing
            | common_enums::IntentStatus::RequiresCustomerAction
            | common_enums::IntentStatus::RequiresMerchantAction
            | common_enums::IntentStatus::RequiresCapture
            | common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture
            | common_enums::IntentStatus::PartiallyCaptured
            | common_enums::IntentStatus::RequiresConfirmation
            | common_enums::IntentStatus::PartiallyCapturedAndCapturable
            | common_enums::IntentStatus::Expired => {
                Err(errors::ApiErrorResponse::PaymentUnexpectedState {
                    current_flow: format!("{self:?}"),
                    field_name: "status".to_string(),
                    current_value: intent_status.to_string(),
                    states: ["requires_payment_method".to_string()].join(", "),
                })
            }
        }
    }
}

impl<F: Send + Clone> Operation<F, PaymentsUpdateIntentRequest> for &PaymentUpdateIntent {
    type Data = payments::PaymentIntentData<F>;
    fn to_validate_request(
        &self,
    ) -> RouterResult<
        &(dyn ValidateRequest<F, PaymentsUpdateIntentRequest, Self::Data> + Send + Sync),
    > {
        Ok(*self)
    }
    fn to_get_tracker(
        &self,
    ) -> RouterResult<&(dyn GetTracker<F, Self::Data, PaymentsUpdateIntentRequest> + Send + Sync)>
    {
        Ok(*self)
    }
    fn to_domain(&self) -> RouterResult<&(dyn Domain<F, PaymentsUpdateIntentRequest, Self::Data>)> {
        Ok(*self)
    }
    fn to_update_tracker(
        &self,
    ) -> RouterResult<&(dyn UpdateTracker<F, Self::Data, PaymentsUpdateIntentRequest> + Send + Sync)>
    {
        Ok(*self)
    }
}

impl<F: Send + Clone> Operation<F, PaymentsUpdateIntentRequest> for PaymentUpdateIntent {
    type Data = payments::PaymentIntentData<F>;
    fn to_validate_request(
        &self,
    ) -> RouterResult<
        &(dyn ValidateRequest<F, PaymentsUpdateIntentRequest, Self::Data> + Send + Sync),
    > {
        Ok(self)
    }
    fn to_get_tracker(
        &self,
    ) -> RouterResult<&(dyn GetTracker<F, Self::Data, PaymentsUpdateIntentRequest> + Send + Sync)>
    {
        Ok(self)
    }
    fn to_domain(&self) -> RouterResult<&dyn Domain<F, PaymentsUpdateIntentRequest, Self::Data>> {
        Ok(self)
    }
    fn to_update_tracker(
        &self,
    ) -> RouterResult<&(dyn UpdateTracker<F, Self::Data, PaymentsUpdateIntentRequest> + Send + Sync)>
    {
        Ok(self)
    }
}

type PaymentsUpdateIntentOperation<'b, F> =
    BoxedOperation<'b, F, PaymentsUpdateIntentRequest, payments::PaymentIntentData<F>>;

#[async_trait]
impl<F: Send + Clone> GetTracker<F, payments::PaymentIntentData<F>, PaymentsUpdateIntentRequest>
    for PaymentUpdateIntent
{
    #[instrument(skip_all)]
    async fn get_trackers<'a>(
        &'a self,
        state: &'a SessionState,
        payment_id: &common_utils::id_type::GlobalPaymentId,
        request: &PaymentsUpdateIntentRequest,
        merchant_context: &domain::MerchantContext,
        profile: &domain::Profile,
        _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
    ) -> RouterResult<operations::GetTrackerResponse<payments::PaymentIntentData<F>>> {
        let db = &*state.store;
        if let Some(routing_algorithm_id) = request.routing_algorithm_id.as_ref() {
            helpers::validate_routing_id_with_profile_id(
                db,
                routing_algorithm_id,
                profile.get_id(),
            )
            .await?;
        }
        let key_manager_state = &state.into();
        let storage_scheme = merchant_context.get_merchant_account().storage_scheme;
        let payment_intent = db
            .find_payment_intent_by_id(
                key_manager_state,
                payment_id,
                merchant_context.get_merchant_key_store(),
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

        self.validate_status_for_operation(payment_intent.status)?;

        let PaymentsUpdateIntentRequest {
            amount_details,
            routing_algorithm_id,
            capture_method,
            authentication_type,
            billing,
            shipping,
            customer_present,
            description,
            return_url,
            setup_future_usage,
            apply_mit_exemption,
            statement_descriptor,
            order_details,
            allowed_payment_method_types,
            metadata,
            connector_metadata,
            feature_metadata,
            payment_link_config,
            request_incremental_authorization,
            session_expiry,
            frm_metadata,
            request_external_three_ds_authentication,
            set_active_attempt_id,
            enable_partial_authorization,
        } = request.clone();

        let batch_encrypted_data = domain_types::crypto_operation(
            key_manager_state,
            common_utils::type_name!(hyperswitch_domain_models::payments::PaymentIntent),
            domain_types::CryptoOperation::BatchEncrypt(
                hyperswitch_domain_models::payments::FromRequestEncryptablePaymentIntent::to_encryptable(
                    hyperswitch_domain_models::payments::FromRequestEncryptablePaymentIntent {
                        shipping_address: shipping.map(|address| address.encode_to_value()).transpose().change_context(errors::ApiErrorResponse::InternalServerError).attach_printable("Failed to encode shipping address")?.map(masking::Secret::new),
                        billing_address: billing.map(|address| address.encode_to_value()).transpose().change_context(errors::ApiErrorResponse::InternalServerError).attach_printable("Failed to encode billing address")?.map(masking::Secret::new),
                        customer_details: None,
                    },
                ),
            ),
            common_utils::types::keymanager::Identifier::Merchant(merchant_context.get_merchant_account().get_id().to_owned()),
            merchant_context.get_merchant_key_store().key.peek(),
        )
        .await
        .and_then(|val| val.try_into_batchoperation())
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed while encrypting payment intent details".to_string())?;

        let decrypted_payment_intent =
             hyperswitch_domain_models::payments::FromRequestEncryptablePaymentIntent::from_encryptable(batch_encrypted_data)
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed while encrypting payment intent details")?;

        let order_details = order_details.clone().map(|order_details| {
            order_details
                .into_iter()
                .map(|order_detail| {
                    masking::Secret::new(
                        diesel_models::types::OrderDetailsWithAmount::convert_from(order_detail),
                    )
                })
                .collect()
        });

        let session_expiry = session_expiry.map(|expiry| {
            payment_intent
                .created_at
                .saturating_add(time::Duration::seconds(i64::from(expiry)))
        });

        let updated_amount_details = match amount_details {
            Some(details) => payment_intent.amount_details.update_from_request(&details),
            None => payment_intent.amount_details,
        };

        let active_attempt_id = set_active_attempt_id
            .map(|active_attempt_req| match active_attempt_req {
                UpdateActiveAttempt::Set(global_attempt_id) => Some(global_attempt_id),
                UpdateActiveAttempt::Unset => None,
            })
            .unwrap_or(payment_intent.active_attempt_id);

        let payment_intent = hyperswitch_domain_models::payments::PaymentIntent {
            amount_details: updated_amount_details,
            description: description.or(payment_intent.description),
            return_url: return_url.or(payment_intent.return_url),
            metadata: metadata.or(payment_intent.metadata),
            statement_descriptor: statement_descriptor.or(payment_intent.statement_descriptor),
            modified_at: common_utils::date_time::now(),
            order_details,
            connector_metadata: connector_metadata.or(payment_intent.connector_metadata),
            feature_metadata: (feature_metadata
                .map(FeatureMetadata::convert_from)
                .or(payment_intent.feature_metadata)),
            updated_by: storage_scheme.to_string(),
            request_incremental_authorization: request_incremental_authorization
                .unwrap_or(payment_intent.request_incremental_authorization),
            session_expiry: session_expiry.unwrap_or(payment_intent.session_expiry),
            request_external_three_ds_authentication: request_external_three_ds_authentication
                .unwrap_or(payment_intent.request_external_three_ds_authentication),
            frm_metadata: frm_metadata.or(payment_intent.frm_metadata),
            billing_address: decrypted_payment_intent
                .billing_address
                .as_ref()
                .map(|data| {
                    data.clone()
                        .deserialize_inner_value(|value| value.parse_value("Address"))
                })
                .transpose()
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Unable to decode billing address")?,
            shipping_address: decrypted_payment_intent
                .shipping_address
                .as_ref()
                .map(|data| {
                    data.clone()
                        .deserialize_inner_value(|value| value.parse_value("Address"))
                })
                .transpose()
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Unable to decode shipping address")?,
            capture_method: capture_method.unwrap_or(payment_intent.capture_method),
            authentication_type: authentication_type.or(payment_intent.authentication_type),
            payment_link_config: payment_link_config
                .map(ApiModelToDieselModelConvertor::convert_from)
                .or(payment_intent.payment_link_config),
            apply_mit_exemption: apply_mit_exemption.unwrap_or(payment_intent.apply_mit_exemption),
            customer_present: customer_present.unwrap_or(payment_intent.customer_present),
            routing_algorithm_id: routing_algorithm_id.or(payment_intent.routing_algorithm_id),
            allowed_payment_method_types: allowed_payment_method_types
                .or(payment_intent.allowed_payment_method_types),
            active_attempt_id,
            enable_partial_authorization: enable_partial_authorization
                .or(payment_intent.enable_partial_authorization),
            ..payment_intent
        };

        let payment_data = payments::PaymentIntentData {
            flow: PhantomData,
            payment_intent,
            client_secret: None,
            sessions_token: vec![],
            vault_session_details: None,
            connector_customer_id: None,
        };

        let get_trackers_response = operations::GetTrackerResponse { payment_data };

        Ok(get_trackers_response)
    }
}

#[async_trait]
impl<F: Clone> UpdateTracker<F, payments::PaymentIntentData<F>, PaymentsUpdateIntentRequest>
    for PaymentUpdateIntent
{
    #[instrument(skip_all)]
    async fn update_trackers<'b>(
        &'b self,
        state: &'b SessionState,
        _req_state: ReqState,
        mut payment_data: payments::PaymentIntentData<F>,
        _customer: Option<domain::Customer>,
        storage_scheme: enums::MerchantStorageScheme,
        _updated_customer: Option<storage::CustomerUpdate>,
        key_store: &domain::MerchantKeyStore,
        _frm_suggestion: Option<FrmSuggestion>,
        _header_payload: hyperswitch_domain_models::payments::HeaderPayload,
    ) -> RouterResult<(
        PaymentsUpdateIntentOperation<'b, F>,
        payments::PaymentIntentData<F>,
    )>
    where
        F: 'b + Send,
    {
        let db = &*state.store;
        let key_manager_state = &state.into();

        let intent = payment_data.payment_intent.clone();

        let payment_intent_update =
            PaymentIntentUpdate::UpdateIntent(Box::new(PaymentIntentUpdateFields {
                amount: Some(intent.amount_details.order_amount),
                currency: Some(intent.amount_details.currency),
                shipping_cost: intent.amount_details.shipping_cost,
                skip_external_tax_calculation: Some(
                    intent.amount_details.skip_external_tax_calculation,
                ),
                skip_surcharge_calculation: Some(intent.amount_details.skip_surcharge_calculation),
                surcharge_amount: intent.amount_details.surcharge_amount,
                tax_on_surcharge: intent.amount_details.tax_on_surcharge,
                routing_algorithm_id: intent.routing_algorithm_id,
                capture_method: Some(intent.capture_method),
                authentication_type: intent.authentication_type,
                billing_address: intent.billing_address,
                shipping_address: intent.shipping_address,
                customer_present: Some(intent.customer_present),
                description: intent.description,
                return_url: intent.return_url,
                setup_future_usage: Some(intent.setup_future_usage),
                apply_mit_exemption: Some(intent.apply_mit_exemption),
                statement_descriptor: intent.statement_descriptor,
                order_details: intent.order_details,
                allowed_payment_method_types: intent.allowed_payment_method_types,
                metadata: intent.metadata,
                connector_metadata: intent.connector_metadata,
                feature_metadata: intent.feature_metadata,
                payment_link_config: intent.payment_link_config,
                request_incremental_authorization: Some(intent.request_incremental_authorization),
                session_expiry: Some(intent.session_expiry),
                frm_metadata: intent.frm_metadata,
                request_external_three_ds_authentication: Some(
                    intent.request_external_three_ds_authentication,
                ),
                updated_by: intent.updated_by,
                tax_details: intent.amount_details.tax_details,
                active_attempt_id: Some(intent.active_attempt_id),
                force_3ds_challenge: intent.force_3ds_challenge,
                is_iframe_redirection_enabled: intent.is_iframe_redirection_enabled,
                enable_partial_authorization: intent.enable_partial_authorization,
            }));

        let new_payment_intent = db
            .update_payment_intent(
                key_manager_state,
                payment_data.payment_intent,
                payment_intent_update,
                key_store,
                storage_scheme,
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Could not update Intent")?;

        payment_data.payment_intent = new_payment_intent;

        Ok((Box::new(self), payment_data))
    }
}

impl<F: Send + Clone>
    ValidateRequest<F, PaymentsUpdateIntentRequest, payments::PaymentIntentData<F>>
    for PaymentUpdateIntent
{
    #[instrument(skip_all)]
    fn validate_request<'a, 'b>(
        &'b self,
        _request: &PaymentsUpdateIntentRequest,
        merchant_context: &'a domain::MerchantContext,
    ) -> RouterResult<operations::ValidateResult> {
        Ok(operations::ValidateResult {
            merchant_id: merchant_context.get_merchant_account().get_id().to_owned(),
            storage_scheme: merchant_context.get_merchant_account().storage_scheme,
            requeue: false,
        })
    }
}

#[async_trait]
impl<F: Clone + Send> Domain<F, PaymentsUpdateIntentRequest, payments::PaymentIntentData<F>>
    for PaymentUpdateIntent
{
    #[instrument(skip_all)]
    async fn get_customer_details<'a>(
        &'a self,
        _state: &SessionState,
        _payment_data: &mut payments::PaymentIntentData<F>,
        _merchant_key_store: &domain::MerchantKeyStore,
        _storage_scheme: enums::MerchantStorageScheme,
    ) -> CustomResult<
        (
            BoxedOperation<'a, F, PaymentsUpdateIntentRequest, payments::PaymentIntentData<F>>,
            Option<domain::Customer>,
        ),
        errors::StorageError,
    > {
        Ok((Box::new(self), None))
    }

    #[instrument(skip_all)]
    async fn make_pm_data<'a>(
        &'a self,
        _state: &'a SessionState,
        _payment_data: &mut payments::PaymentIntentData<F>,
        _storage_scheme: enums::MerchantStorageScheme,
        _merchant_key_store: &domain::MerchantKeyStore,
        _customer: &Option<domain::Customer>,
        _business_profile: &domain::Profile,
        _should_retry_with_pan: bool,
    ) -> RouterResult<(
        PaymentsUpdateIntentOperation<'a, F>,
        Option<domain::PaymentMethodData>,
        Option<String>,
    )> {
        Ok((Box::new(self), None, None))
    }

    #[instrument(skip_all)]
    async fn perform_routing<'a>(
        &'a self,
        _merchant_context: &domain::MerchantContext,
        _business_profile: &domain::Profile,
        _state: &SessionState,
        _payment_data: &mut payments::PaymentIntentData<F>,
    ) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
        Ok(api::ConnectorCallType::Skip)
    }

    #[instrument(skip_all)]
    async fn guard_payment_against_blocklist<'a>(
        &'a self,
        _state: &SessionState,
        _merchant_context: &domain::MerchantContext,
        _payment_data: &mut payments::PaymentIntentData<F>,
    ) -> CustomResult<bool, errors::ApiErrorResponse> {
        Ok(false)
    }
}


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

impl ConnectorTransactionId for for Nexinets


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

pub fn check_existence_and_add_domain_to_db(
    state: &SessionState,
    merchant_id: common_utils::id_type::MerchantId,
    profile_id_from_auth_layer: Option<common_utils::id_type::ProfileId>,
    merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
    domain_from_req: Vec<String>,
) -> CustomResult<Vec<String>, errors::ApiErrorResponse>


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

impl api::MandateSetup for for Bluesnap


// Implementation: impl Iterator for for Iter
// File: crates/hyperswitch_constraint_graph/src/dense_map.rs
// Module: hyperswitch_constraint_graph
// Methods: 1 total (0 public)

impl Iterator for for Iter


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

impl api::PaymentAuthorize for for Getnet


// Implementation: impl PaymentMethodSession
// File: crates/diesel_models/src/payment_methods_session.rs
// Module: diesel_models
// Methods: 1 total (1 public)

impl PaymentMethodSession


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

pub struct TrustpayAccessTokenErrorResponse


// Implementation: impl ConnectorValidation for for Braintree
// File: crates/hyperswitch_connectors/src/connectors/braintree.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl ConnectorValidation for for Braintree


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

pub struct BacsBankTransfer


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

pub fn construct_router_data_to_update_calculated_tax<'a, F, T>(
    state: &'a SessionState,
    payment_data: PaymentData<F>,
    connector_id: &str,
    merchant_context: &domain::MerchantContext,
    customer: &'a Option<domain::Customer>,
    merchant_connector_account: &helpers::MerchantConnectorAccountType,
) -> RouterResult<types::RouterData<F, T, types::PaymentsResponseData>>
where
    T: TryFrom<PaymentAdditionalData<'a, F>>,
    types::RouterData<F, T, types::PaymentsResponseData>: Feature<F, T>,
    F: Clone,
    error_stack::Report<errors::ApiErrorResponse>:
        From<<T as TryFrom<PaymentAdditionalData<'a, F>>>::Error>,