// File: crates/connector_configs/src/response_modifier.rs
// Module: connector_configs
// Public functions: 1

use crate::common_config::{
    CardProvider, ConnectorApiIntegrationPayload, DashboardPaymentMethodPayload,
    DashboardRequestPayload, Provider,
};

impl ConnectorApiIntegrationPayload {
    pub fn get_transformed_response_payload(response: Self) -> DashboardRequestPayload {
        let mut wallet_details: Vec<Provider> = Vec::new();
        let mut bank_redirect_details: Vec<Provider> = Vec::new();
        let mut pay_later_details: Vec<Provider> = Vec::new();
        let mut debit_details: Vec<CardProvider> = Vec::new();
        let mut credit_details: Vec<CardProvider> = Vec::new();
        let mut bank_transfer_details: Vec<Provider> = Vec::new();
        let mut crypto_details: Vec<Provider> = Vec::new();
        let mut bank_debit_details: Vec<Provider> = Vec::new();
        let mut reward_details: Vec<Provider> = Vec::new();
        let mut real_time_payment_details: Vec<Provider> = Vec::new();
        let mut upi_details: Vec<Provider> = Vec::new();
        let mut voucher_details: Vec<Provider> = Vec::new();
        let mut gift_card_details: Vec<Provider> = Vec::new();
        let mut card_redirect_details: Vec<Provider> = Vec::new();
        let mut open_banking_details: Vec<Provider> = Vec::new();
        let mut mobile_payment_details: Vec<Provider> = Vec::new();

        if let Some(payment_methods_enabled) = response.payment_methods_enabled.clone() {
            for methods in payment_methods_enabled {
                match methods.payment_method {
                    api_models::enums::PaymentMethod::Card => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                match method_type.payment_method_type {
                                    api_models::enums::PaymentMethodType::Credit => {
                                        if let Some(card_networks) = method_type.card_networks {
                                            for card in card_networks {
                                                credit_details.push(CardProvider {
                                                    payment_method_type: card,
                                                    accepted_currencies: method_type
                                                        .accepted_currencies
                                                        .clone(),
                                                    accepted_countries: method_type
                                                        .accepted_countries
                                                        .clone(),
                                                })
                                            }
                                        }
                                    }
                                    api_models::enums::PaymentMethodType::Debit => {
                                        if let Some(card_networks) = method_type.card_networks {
                                            for card in card_networks {
                                                // debit_details.push(card)
                                                debit_details.push(CardProvider {
                                                    payment_method_type: card,
                                                    accepted_currencies: method_type
                                                        .accepted_currencies
                                                        .clone(),
                                                    accepted_countries: method_type
                                                        .accepted_countries
                                                        .clone(),
                                                })
                                            }
                                        }
                                    }
                                    _ => (),
                                }
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::Wallet => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                // wallet_details.push(method_type.payment_method_type)
                                wallet_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::BankRedirect => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                bank_redirect_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::PayLater => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                pay_later_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::BankTransfer => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                bank_transfer_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::Crypto => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                crypto_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::BankDebit => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                bank_debit_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::Reward => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                reward_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::RealTimePayment => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                real_time_payment_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::OpenBanking => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                open_banking_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::Upi => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                upi_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::Voucher => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                voucher_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::GiftCard => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                gift_card_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::CardRedirect => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                card_redirect_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                    api_models::enums::PaymentMethod::MobilePayment => {
                        if let Some(payment_method_types) = methods.payment_method_types {
                            for method_type in payment_method_types {
                                mobile_payment_details.push(Provider {
                                    payment_method_type: method_type.payment_method_type,
                                    accepted_currencies: method_type.accepted_currencies.clone(),
                                    accepted_countries: method_type.accepted_countries.clone(),
                                    payment_experience: method_type.payment_experience,
                                })
                            }
                        }
                    }
                }
            }
        }

        let open_banking = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::OpenBanking,
            payment_method_type: api_models::enums::PaymentMethod::OpenBanking.to_string(),
            provider: Some(open_banking_details),
            card_provider: None,
        };

        let upi = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::Upi,
            payment_method_type: api_models::enums::PaymentMethod::Upi.to_string(),
            provider: Some(upi_details),
            card_provider: None,
        };

        let voucher: DashboardPaymentMethodPayload = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::Voucher,
            payment_method_type: api_models::enums::PaymentMethod::Voucher.to_string(),
            provider: Some(voucher_details),
            card_provider: None,
        };

        let gift_card: DashboardPaymentMethodPayload = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::GiftCard,
            payment_method_type: api_models::enums::PaymentMethod::GiftCard.to_string(),
            provider: Some(gift_card_details),
            card_provider: None,
        };

        let reward = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::Reward,
            payment_method_type: api_models::enums::PaymentMethod::Reward.to_string(),
            provider: Some(reward_details),
            card_provider: None,
        };

        let real_time_payment = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::RealTimePayment,
            payment_method_type: api_models::enums::PaymentMethod::RealTimePayment.to_string(),
            provider: Some(real_time_payment_details),
            card_provider: None,
        };

        let wallet = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::Wallet,
            payment_method_type: api_models::enums::PaymentMethod::Wallet.to_string(),
            provider: Some(wallet_details),
            card_provider: None,
        };
        let bank_redirect = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::BankRedirect,
            payment_method_type: api_models::enums::PaymentMethod::BankRedirect.to_string(),
            provider: Some(bank_redirect_details),
            card_provider: None,
        };

        let bank_debit = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::BankDebit,
            payment_method_type: api_models::enums::PaymentMethod::BankDebit.to_string(),
            provider: Some(bank_debit_details),
            card_provider: None,
        };

        let bank_transfer = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::BankTransfer,
            payment_method_type: api_models::enums::PaymentMethod::BankTransfer.to_string(),
            provider: Some(bank_transfer_details),
            card_provider: None,
        };

        let crypto = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::Crypto,
            payment_method_type: api_models::enums::PaymentMethod::Crypto.to_string(),
            provider: Some(crypto_details),
            card_provider: None,
        };

        let card_redirect = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::CardRedirect,
            payment_method_type: api_models::enums::PaymentMethod::CardRedirect.to_string(),
            provider: Some(card_redirect_details),
            card_provider: None,
        };
        let pay_later = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::PayLater,
            payment_method_type: api_models::enums::PaymentMethod::PayLater.to_string(),
            provider: Some(pay_later_details),
            card_provider: None,
        };
        let debit_details = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::Card,
            payment_method_type: api_models::enums::PaymentMethodType::Debit.to_string(),
            provider: None,
            card_provider: Some(debit_details),
        };
        let credit_details = DashboardPaymentMethodPayload {
            payment_method: api_models::enums::PaymentMethod::Card,
            payment_method_type: api_models::enums::PaymentMethodType::Credit.to_string(),
            provider: None,
            card_provider: Some(credit_details),
        };

        DashboardRequestPayload {
            connector: response.connector_name,
            payment_methods_enabled: Some(vec![
                open_banking,
                upi,
                voucher,
                reward,
                real_time_payment,
                wallet,
                bank_redirect,
                bank_debit,
                bank_transfer,
                crypto,
                card_redirect,
                pay_later,
                debit_details,
                credit_details,
                gift_card,
            ]),
            metadata: response.metadata,
        }
    }
}


// Struct: CardholderAuthentication
// File: crates/hyperswitch_connectors/src/connectors/worldpayvantiv/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CardholderAuthentication


// File: crates/router/src/db/user_role.rs
// Module: router
// Public structs: 2

use common_utils::id_type;
use diesel_models::{
    enums::{self, UserStatus},
    user_role as storage,
};
use error_stack::{report, ResultExt};
use router_env::{instrument, tracing};

use super::MockDb;
use crate::{
    connection,
    core::errors::{self, CustomResult},
    services::Store,
};

pub struct ListUserRolesByOrgIdPayload<'a> {
    pub user_id: Option<&'a String>,
    pub tenant_id: &'a id_type::TenantId,
    pub org_id: &'a id_type::OrganizationId,
    pub merchant_id: Option<&'a id_type::MerchantId>,
    pub profile_id: Option<&'a id_type::ProfileId>,
    pub version: Option<enums::UserRoleVersion>,
    pub limit: Option<u32>,
}

pub struct ListUserRolesByUserIdPayload<'a> {
    pub user_id: &'a str,
    pub tenant_id: &'a id_type::TenantId,
    pub org_id: Option<&'a id_type::OrganizationId>,
    pub merchant_id: Option<&'a id_type::MerchantId>,
    pub profile_id: Option<&'a id_type::ProfileId>,
    pub entity_id: Option<&'a String>,
    pub version: Option<enums::UserRoleVersion>,
    pub status: Option<UserStatus>,
    pub limit: Option<u32>,
}

#[async_trait::async_trait]
pub trait UserRoleInterface {
    async fn insert_user_role(
        &self,
        user_role: storage::UserRoleNew,
    ) -> CustomResult<storage::UserRole, errors::StorageError>;

    async fn find_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: &id_type::MerchantId,
        profile_id: &id_type::ProfileId,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError>;

    #[allow(clippy::too_many_arguments)]
    async fn update_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: Option<&id_type::MerchantId>,
        profile_id: Option<&id_type::ProfileId>,
        update: storage::UserRoleUpdate,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError>;

    async fn delete_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: &id_type::MerchantId,
        profile_id: &id_type::ProfileId,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError>;

    async fn list_user_roles_by_user_id<'a>(
        &self,
        payload: ListUserRolesByUserIdPayload<'a>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError>;

    async fn list_user_roles_by_user_id_across_tenants(
        &self,
        user_id: &str,
        limit: Option<u32>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError>;

    async fn list_user_roles_by_org_id<'a>(
        &self,
        payload: ListUserRolesByOrgIdPayload<'a>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError>;
}

#[async_trait::async_trait]
impl UserRoleInterface for Store {
    #[instrument(skip_all)]
    async fn insert_user_role(
        &self,
        user_role: storage::UserRoleNew,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;

        user_role
            .insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn find_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: &id_type::MerchantId,
        profile_id: &id_type::ProfileId,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::UserRole::find_by_user_id_tenant_id_org_id_merchant_id_profile_id(
            &conn,
            user_id.to_owned(),
            tenant_id.to_owned(),
            org_id.to_owned(),
            merchant_id.to_owned(),
            profile_id.to_owned(),
            version,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn update_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: Option<&id_type::MerchantId>,
        profile_id: Option<&id_type::ProfileId>,
        update: storage::UserRoleUpdate,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::UserRole::update_by_user_id_tenant_id_org_id_merchant_id_profile_id(
            &conn,
            user_id.to_owned(),
            tenant_id.to_owned(),
            org_id.to_owned(),
            merchant_id.cloned(),
            profile_id.cloned(),
            update,
            version,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn delete_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: &id_type::MerchantId,
        profile_id: &id_type::ProfileId,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::UserRole::delete_by_user_id_tenant_id_org_id_merchant_id_profile_id(
            &conn,
            user_id.to_owned(),
            tenant_id.to_owned(),
            org_id.to_owned(),
            merchant_id.to_owned(),
            profile_id.to_owned(),
            version,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn list_user_roles_by_user_id<'a>(
        &self,
        payload: ListUserRolesByUserIdPayload<'a>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::UserRole::generic_user_roles_list_for_user(
            &conn,
            payload.user_id.to_owned(),
            payload.tenant_id.to_owned(),
            payload.org_id.cloned(),
            payload.merchant_id.cloned(),
            payload.profile_id.cloned(),
            payload.entity_id.cloned(),
            payload.status,
            payload.version,
            payload.limit,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn list_user_roles_by_user_id_across_tenants(
        &self,
        user_id: &str,
        limit: Option<u32>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::UserRole::list_user_roles_by_user_id_across_tenants(
            &conn,
            user_id.to_owned(),
            limit,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn list_user_roles_by_org_id<'a>(
        &self,
        payload: ListUserRolesByOrgIdPayload<'a>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::UserRole::generic_user_roles_list_for_org_and_extra(
            &conn,
            payload.user_id.cloned(),
            payload.tenant_id.to_owned(),
            payload.org_id.to_owned(),
            payload.merchant_id.cloned(),
            payload.profile_id.cloned(),
            payload.version,
            payload.limit,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl UserRoleInterface for MockDb {
    async fn insert_user_role(
        &self,
        user_role: storage::UserRoleNew,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        let mut db_user_roles = self.user_roles.lock().await;

        if db_user_roles
            .iter()
            .any(|user_role_inner| user_role_inner.user_id == user_role.user_id)
        {
            Err(errors::StorageError::DuplicateValue {
                entity: "user_id",
                key: None,
            })?
        }
        let user_role = storage::UserRole {
            id: i32::try_from(db_user_roles.len())
                .change_context(errors::StorageError::MockDbError)?,
            user_id: user_role.user_id,
            merchant_id: user_role.merchant_id,
            role_id: user_role.role_id,
            status: user_role.status,
            created_by: user_role.created_by,
            created_at: user_role.created_at,
            last_modified: user_role.last_modified,
            last_modified_by: user_role.last_modified_by,
            org_id: user_role.org_id,
            profile_id: None,
            entity_id: None,
            entity_type: None,
            version: enums::UserRoleVersion::V1,
            tenant_id: user_role.tenant_id,
        };
        db_user_roles.push(user_role.clone());
        Ok(user_role)
    }

    async fn find_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: &id_type::MerchantId,
        profile_id: &id_type::ProfileId,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        let user_roles = self.user_roles.lock().await;

        for user_role in user_roles.iter() {
            let tenant_level_check = user_role.tenant_id == *tenant_id
                && user_role.org_id.is_none()
                && user_role.merchant_id.is_none()
                && user_role.profile_id.is_none();

            let org_level_check = user_role.tenant_id == *tenant_id
                && user_role.org_id.as_ref() == Some(org_id)
                && user_role.merchant_id.is_none()
                && user_role.profile_id.is_none();

            let merchant_level_check = user_role.tenant_id == *tenant_id
                && user_role.org_id.as_ref() == Some(org_id)
                && user_role.merchant_id.as_ref() == Some(merchant_id)
                && user_role.profile_id.is_none();

            let profile_level_check = user_role.tenant_id == *tenant_id
                && user_role.org_id.as_ref() == Some(org_id)
                && user_role.merchant_id.as_ref() == Some(merchant_id)
                && user_role.profile_id.as_ref() == Some(profile_id);

            // Check if any condition matches and the version matches
            if user_role.user_id == user_id
                && (tenant_level_check
                    || org_level_check
                    || merchant_level_check
                    || profile_level_check)
                && user_role.version == version
            {
                return Ok(user_role.clone());
            }
        }

        Err(errors::StorageError::ValueNotFound(format!(
            "No user role available for user_id = {user_id} in the current token hierarchy",
        ))
        .into())
    }

    async fn update_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: Option<&id_type::MerchantId>,
        profile_id: Option<&id_type::ProfileId>,
        update: storage::UserRoleUpdate,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        let mut user_roles = self.user_roles.lock().await;

        for user_role in user_roles.iter_mut() {
            let tenant_level_check = user_role.tenant_id == *tenant_id
                && user_role.org_id.is_none()
                && user_role.merchant_id.is_none()
                && user_role.profile_id.is_none();

            let org_level_check = user_role.tenant_id == *tenant_id
                && user_role.org_id.as_ref() == Some(org_id)
                && user_role.merchant_id.is_none()
                && user_role.profile_id.is_none();

            let merchant_level_check = user_role.tenant_id == *tenant_id
                && user_role.org_id.as_ref() == Some(org_id)
                && user_role.merchant_id.as_ref() == merchant_id
                && user_role.profile_id.is_none();

            let profile_level_check = user_role.tenant_id == *tenant_id
                && user_role.org_id.as_ref() == Some(org_id)
                && user_role.merchant_id.as_ref() == merchant_id
                && user_role.profile_id.as_ref() == profile_id;

            // Check if any condition matches and the version matches
            if user_role.user_id == user_id
                && (tenant_level_check
                    || org_level_check
                    || merchant_level_check
                    || profile_level_check)
                && user_role.version == version
            {
                match &update {
                    storage::UserRoleUpdate::UpdateRole {
                        role_id,
                        modified_by,
                    } => {
                        user_role.role_id = role_id.to_string();
                        user_role.last_modified_by = modified_by.to_string();
                    }
                    storage::UserRoleUpdate::UpdateStatus {
                        status,
                        modified_by,
                    } => {
                        user_role.status = *status;
                        user_role.last_modified_by = modified_by.to_string();
                    }
                }
                return Ok(user_role.clone());
            }
        }
        Err(
            errors::StorageError::ValueNotFound("Cannot find user role to update".to_string())
                .into(),
        )
    }

    async fn delete_user_role_by_user_id_and_lineage(
        &self,
        user_id: &str,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: &id_type::MerchantId,
        profile_id: &id_type::ProfileId,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        let mut user_roles = self.user_roles.lock().await;

        // Find the position of the user role to delete
        let index = user_roles.iter().position(|role| {
            let tenant_level_check = role.tenant_id == *tenant_id
                && role.org_id.is_none()
                && role.merchant_id.is_none()
                && role.profile_id.is_none();

            let org_level_check = role.tenant_id == *tenant_id
                && role.org_id.as_ref() == Some(org_id)
                && role.merchant_id.is_none()
                && role.profile_id.is_none();

            let merchant_level_check = role.tenant_id == *tenant_id
                && role.org_id.as_ref() == Some(org_id)
                && role.merchant_id.as_ref() == Some(merchant_id)
                && role.profile_id.is_none();

            let profile_level_check = role.tenant_id == *tenant_id
                && role.org_id.as_ref() == Some(org_id)
                && role.merchant_id.as_ref() == Some(merchant_id)
                && role.profile_id.as_ref() == Some(profile_id);

            // Check if the user role matches the conditions and the version matches
            role.user_id == user_id
                && (tenant_level_check
                    || org_level_check
                    || merchant_level_check
                    || profile_level_check)
                && role.version == version
        });

        // Remove and return the user role if found
        match index {
            Some(idx) => Ok(user_roles.remove(idx)),
            None => Err(errors::StorageError::ValueNotFound(
                "Cannot find user role to delete".to_string(),
            )
            .into()),
        }
    }

    async fn list_user_roles_by_user_id<'a>(
        &self,
        payload: ListUserRolesByUserIdPayload<'a>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
        let user_roles = self.user_roles.lock().await;

        let mut filtered_roles: Vec<_> = user_roles
            .iter()
            .filter_map(|role| {
                let mut filter_condition = role.user_id == payload.user_id;

                role.org_id
                    .as_ref()
                    .zip(payload.org_id)
                    .inspect(|(role_org_id, org_id)| {
                        filter_condition = filter_condition && role_org_id == org_id
                    });
                role.merchant_id.as_ref().zip(payload.merchant_id).inspect(
                    |(role_merchant_id, merchant_id)| {
                        filter_condition = filter_condition && role_merchant_id == merchant_id
                    },
                );
                role.profile_id.as_ref().zip(payload.profile_id).inspect(
                    |(role_profile_id, profile_id)| {
                        filter_condition = filter_condition && role_profile_id == profile_id
                    },
                );
                role.entity_id.as_ref().zip(payload.entity_id).inspect(
                    |(role_entity_id, entity_id)| {
                        filter_condition = filter_condition && role_entity_id == entity_id
                    },
                );
                payload
                    .version
                    .inspect(|ver| filter_condition = filter_condition && ver == &role.version);
                payload.status.inspect(|status| {
                    filter_condition = filter_condition && status == &role.status
                });

                filter_condition.then(|| role.to_owned())
            })
            .collect();

        if let Some(Ok(limit)) = payload.limit.map(|val| val.try_into()) {
            filtered_roles = filtered_roles.into_iter().take(limit).collect();
        }
        Ok(filtered_roles)
    }

    async fn list_user_roles_by_user_id_across_tenants(
        &self,
        user_id: &str,
        limit: Option<u32>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
        let user_roles = self.user_roles.lock().await;

        let filtered_roles: Vec<_> = user_roles
            .iter()
            .filter(|role| role.user_id == user_id)
            .cloned()
            .collect();

        if let Some(Ok(limit)) = limit.map(|val| val.try_into()) {
            return Ok(filtered_roles.into_iter().take(limit).collect());
        }

        Ok(filtered_roles)
    }

    async fn list_user_roles_by_org_id<'a>(
        &self,
        payload: ListUserRolesByOrgIdPayload<'a>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
        let user_roles = self.user_roles.lock().await;

        let mut filtered_roles = Vec::new();

        for role in user_roles.iter() {
            let role_org_id = role
                .org_id
                .as_ref()
                .ok_or(report!(errors::StorageError::MockDbError))?;

            let mut filter_condition = role_org_id == payload.org_id;

            if let Some(user_id) = payload.user_id {
                filter_condition = filter_condition && user_id == &role.user_id
            }

            role.merchant_id.as_ref().zip(payload.merchant_id).inspect(
                |(role_merchant_id, merchant_id)| {
                    filter_condition = filter_condition && role_merchant_id == merchant_id
                },
            );

            role.profile_id.as_ref().zip(payload.profile_id).inspect(
                |(role_profile_id, profile_id)| {
                    filter_condition = filter_condition && role_profile_id == profile_id
                },
            );

            payload
                .version
                .inspect(|ver| filter_condition = filter_condition && ver == &role.version);

            if filter_condition {
                filtered_roles.push(role.clone())
            }
        }

        Ok(filtered_roles)
    }
}


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

pub fn new() -> &'static Self


// Struct: Keys
// File: crates/hyperswitch_constraint_graph/src/dense_map.rs
// Module: hyperswitch_constraint_graph
// Implementations: 2
// Traits: Iterator

pub struct Keys<K>


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

pub struct TwoFactorAuthStatusResponse


// Function: validate
// File: crates/external_services/src/email.rs
// Module: external_services

// Documentation: Validation for the Email client specific configurations

pub fn validate(&self) -> Result<(), &'static str>


// File: crates/api_models/src/subscription.rs
// Module: api_models
// Public functions: 3
// Public structs: 7

use common_types::payments::CustomerAcceptance;
use common_utils::{errors::ValidationError, events::ApiEventMetric, types::MinorUnit};
use masking::Secret;
use utoipa::ToSchema;

use crate::{
    enums as api_enums,
    payments::{Address, PaymentMethodDataRequest},
};

// use crate::{
//     customers::{CustomerRequest, CustomerResponse},
//     payments::CustomerDetailsResponse,
// };

/// Request payload for creating a subscription.
///
/// This struct captures details required to create a subscription,
/// including plan, profile, merchant connector, and optional customer info.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct CreateSubscriptionRequest {
    /// Merchant specific Unique identifier.
    pub merchant_reference_id: Option<String>,

    /// Identifier for the subscription plan.
    pub plan_id: Option<String>,

    /// Optional coupon code applied to the subscription.
    pub coupon_code: Option<String>,

    /// customer ID associated with this subscription.
    pub customer_id: common_utils::id_type::CustomerId,
}

/// Response payload returned after successfully creating a subscription.
///
/// Includes details such as subscription ID, status, plan, merchant, and customer info.
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
pub struct CreateSubscriptionResponse {
    /// Unique identifier for the subscription.
    pub id: common_utils::id_type::SubscriptionId,

    /// Merchant specific Unique identifier.
    pub merchant_reference_id: Option<String>,

    /// Current status of the subscription.
    pub status: SubscriptionStatus,

    /// Identifier for the associated subscription plan.
    pub plan_id: Option<String>,

    /// Associated profile ID.
    pub profile_id: common_utils::id_type::ProfileId,

    /// Optional client secret used for secure client-side interactions.
    pub client_secret: Option<Secret<String>>,

    /// Merchant identifier owning this subscription.
    pub merchant_id: common_utils::id_type::MerchantId,

    /// Optional coupon code applied to this subscription.
    pub coupon_code: Option<String>,

    /// Optional customer ID associated with this subscription.
    pub customer_id: common_utils::id_type::CustomerId,
}

/// Possible states of a subscription lifecycle.
///
/// - `Created`: Subscription was created but not yet activated.
/// - `Active`: Subscription is currently active.
/// - `InActive`: Subscription is inactive.
/// - `Pending`: Subscription is pending activation.
/// - `Trial`: Subscription is in a trial period.
/// - `Paused`: Subscription is paused.
/// - `Unpaid`: Subscription is unpaid.
/// - `Onetime`: Subscription is a one-time payment.
/// - `Cancelled`: Subscription has been cancelled.
/// - `Failed`: Subscription has failed.
#[derive(Debug, Clone, serde::Serialize, strum::EnumString, strum::Display, ToSchema)]
pub enum SubscriptionStatus {
    /// Subscription is active.
    Active,
    /// Subscription is created but not yet active.
    Created,
    /// Subscription is inactive.
    InActive,
    /// Subscription is in pending state.
    Pending,
    /// Subscription is in trial state.
    Trial,
    /// Subscription is paused.
    Paused,
    /// Subscription is unpaid.
    Unpaid,
    /// Subscription is a one-time payment.
    Onetime,
    /// Subscription is cancelled.
    Cancelled,
    /// Subscription has failed.
    Failed,
}

impl CreateSubscriptionResponse {
    /// Creates a new [`CreateSubscriptionResponse`] with the given identifiers.
    ///
    /// By default, `client_secret`, `coupon_code`, and `customer` fields are `None`.
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        id: common_utils::id_type::SubscriptionId,
        merchant_reference_id: Option<String>,
        status: SubscriptionStatus,
        plan_id: Option<String>,
        profile_id: common_utils::id_type::ProfileId,
        merchant_id: common_utils::id_type::MerchantId,
        client_secret: Option<Secret<String>>,
        customer_id: common_utils::id_type::CustomerId,
    ) -> Self {
        Self {
            id,
            merchant_reference_id,
            status,
            plan_id,
            profile_id,
            client_secret,
            merchant_id,
            coupon_code: None,
            customer_id,
        }
    }
}

impl ApiEventMetric for CreateSubscriptionResponse {}
impl ApiEventMetric for CreateSubscriptionRequest {}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct PaymentDetails {
    pub payment_method: api_enums::PaymentMethod,
    pub payment_method_type: Option<api_enums::PaymentMethodType>,
    pub payment_method_data: PaymentMethodDataRequest,
    pub setup_future_usage: Option<api_enums::FutureUsage>,
    pub customer_acceptance: Option<CustomerAcceptance>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct PaymentResponseData {
    pub payment_id: common_utils::id_type::PaymentId,
    pub status: api_enums::IntentStatus,
    pub amount: MinorUnit,
    pub currency: api_enums::Currency,
    pub connector: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ConfirmSubscriptionRequest {
    /// Client secret for SDK based interaction.
    pub client_secret: Option<String>,

    /// Amount to be charged for the invoice.
    pub amount: MinorUnit,

    /// Currency for the amount.
    pub currency: api_enums::Currency,

    /// Identifier for the associated plan_id.
    pub plan_id: Option<String>,

    /// Identifier for the associated item_price_id for the subscription.
    pub item_price_id: Option<String>,

    /// Idenctifier for the coupon code for the subscription.
    pub coupon_code: Option<String>,

    /// Identifier for customer.
    pub customer_id: common_utils::id_type::CustomerId,

    /// Billing address for the subscription.
    pub billing_address: Option<Address>,

    /// Payment details for the invoice.
    pub payment_details: PaymentDetails,
}

impl ConfirmSubscriptionRequest {
    pub fn get_item_price_id(&self) -> Result<String, error_stack::Report<ValidationError>> {
        self.item_price_id.clone().ok_or(error_stack::report!(
            ValidationError::MissingRequiredField {
                field_name: "item_price_id".to_string()
            }
        ))
    }

    pub fn get_billing_address(&self) -> Result<Address, error_stack::Report<ValidationError>> {
        self.billing_address.clone().ok_or(error_stack::report!(
            ValidationError::MissingRequiredField {
                field_name: "billing_address".to_string()
            }
        ))
    }
}

impl ApiEventMetric for ConfirmSubscriptionRequest {}

#[derive(Debug, Clone, serde::Serialize, ToSchema)]
pub struct ConfirmSubscriptionResponse {
    /// Unique identifier for the subscription.
    pub id: common_utils::id_type::SubscriptionId,

    /// Merchant specific Unique identifier.
    pub merchant_reference_id: Option<String>,

    /// Current status of the subscription.
    pub status: SubscriptionStatus,

    /// Identifier for the associated subscription plan.
    pub plan_id: Option<String>,

    /// Identifier for the associated item_price_id for the subscription.
    pub price_id: Option<String>,

    /// Optional coupon code applied to this subscription.
    pub coupon: Option<String>,

    /// Associated profile ID.
    pub profile_id: common_utils::id_type::ProfileId,

    /// Payment details for the invoice.
    pub payment: Option<PaymentResponseData>,

    /// Customer ID associated with this subscription.
    pub customer_id: Option<common_utils::id_type::CustomerId>,

    /// Invoice Details for the subscription.
    pub invoice: Option<Invoice>,
}

#[derive(Debug, Clone, serde::Serialize, ToSchema)]
pub struct Invoice {
    /// Unique identifier for the invoice.
    pub id: common_utils::id_type::InvoiceId,

    /// Unique identifier for the subscription.
    pub subscription_id: common_utils::id_type::SubscriptionId,

    /// Identifier for the merchant.
    pub merchant_id: common_utils::id_type::MerchantId,

    /// Identifier for the profile.
    pub profile_id: common_utils::id_type::ProfileId,

    /// Identifier for the merchant connector account.
    pub merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,

    /// Identifier for the Payment.
    pub payment_intent_id: Option<common_utils::id_type::PaymentId>,

    /// Identifier for the Payment method.
    pub payment_method_id: Option<String>,

    /// Identifier for the Customer.
    pub customer_id: common_utils::id_type::CustomerId,

    /// Invoice amount.
    pub amount: MinorUnit,

    /// Currency for the invoice payment.
    pub currency: api_enums::Currency,

    /// Status of the invoice.
    pub status: String,
}

impl ApiEventMetric for ConfirmSubscriptionResponse {}


// Function: get_theme_using_optional_theme_id
// File: crates/router/src/utils/user/theme.rs
// Module: router

pub fn get_theme_using_optional_theme_id(
    state: &SessionState,
    theme_id: Option<String>,
) -> UserResult<Option<Theme>>


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

impl api::PaymentCapture for for Payload


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

use std::marker::PhantomData;

use api_models::{enums::FrmSuggestion, payments::PaymentsAttemptRecordRequest};
use async_trait::async_trait;
use common_utils::{
    errors::CustomResult,
    ext_traits::{AsyncExt, Encode, ValueExt},
    types::keymanager::ToEncryptable,
};
use error_stack::ResultExt;
use hyperswitch_domain_models::payments::PaymentAttemptRecordData;
use masking::PeekInterface;
use router_env::{instrument, tracing};

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

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

type PaymentsAttemptRecordOperation<'b, F> =
    BoxedOperation<'b, F, PaymentsAttemptRecordRequest, PaymentAttemptRecordData<F>>;

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

impl ValidateStatusForOperation for PaymentAttemptRecord {
    fn validate_status_for_operation(
        &self,
        intent_status: common_enums::IntentStatus,
    ) -> Result<(), errors::ApiErrorResponse> {
        // need to verify this?
        match intent_status {
            // Payment attempt can be recorded for failed payment as well in revenue recovery flow.
            common_enums::IntentStatus::RequiresPaymentMethod
            | common_enums::IntentStatus::Failed => Ok(()),
            common_enums::IntentStatus::Succeeded
            | common_enums::IntentStatus::Cancelled
            | common_enums::IntentStatus::CancelledPostCapture
            | common_enums::IntentStatus::Processing
            | common_enums::IntentStatus::Conflicted
            | 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: [
                        common_enums::IntentStatus::RequiresPaymentMethod,
                        common_enums::IntentStatus::Failed,
                    ]
                    .map(|enum_value| enum_value.to_string())
                    .join(", "),
                })
            }
        }
    }
}

#[async_trait]
impl<F: Send + Clone + Sync>
    GetTracker<F, PaymentAttemptRecordData<F>, PaymentsAttemptRecordRequest>
    for PaymentAttemptRecord
{
    #[instrument(skip_all)]
    async fn get_trackers<'a>(
        &'a self,
        state: &'a SessionState,
        payment_id: &common_utils::id_type::GlobalPaymentId,
        request: &PaymentsAttemptRecordRequest,
        merchant_context: &domain::MerchantContext,
        _profile: &domain::Profile,
        _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
    ) -> RouterResult<operations::GetTrackerResponse<PaymentAttemptRecordData<F>>> {
        let db = &*state.store;
        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 payment_method_billing_address = request
            .payment_method_data
            .as_ref()
            .and_then(|data| {
                data.billing
                    .as_ref()
                    .map(|address| address.clone().encode_to_value())
            })
            .transpose()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to encode payment_method_billing address")?
            .map(masking::Secret::new);

        let batch_encrypted_data = domain_types::crypto_operation(
                key_manager_state,
                common_utils::type_name!(hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt),
                domain_types::CryptoOperation::BatchEncrypt(
                    hyperswitch_domain_models::payments::payment_attempt::FromRequestEncryptablePaymentAttempt::to_encryptable(
                        hyperswitch_domain_models::payments::payment_attempt::FromRequestEncryptablePaymentAttempt {
                            payment_method_billing_address,
                        },
                    ),
                ),
                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 encrypted_data =
                 hyperswitch_domain_models::payments::payment_attempt::FromRequestEncryptablePaymentAttempt::from_encryptable(batch_encrypted_data)
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed while encrypting payment intent details")?;
        let cell_id = state.conf.cell_information.id.clone();

        let payment_attempt_domain_model =
            hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt::create_domain_model_using_record_request(
                &payment_intent,
                cell_id,
                storage_scheme,
                request,
                encrypted_data,
            )
            .await?;

        let payment_attempt = db
            .insert_payment_attempt(
                key_manager_state,
                merchant_context.get_merchant_key_store(),
                payment_attempt_domain_model,
                storage_scheme,
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Could not insert payment attempt")?;
        let revenue_recovery_data = hyperswitch_domain_models::payments::RevenueRecoveryData {
            billing_connector_id: request.billing_connector_id.clone(),
            processor_payment_method_token: request.processor_payment_method_token.clone(),
            connector_customer_id: request.connector_customer_id.clone(),
            retry_count: request.retry_count,
            invoice_next_billing_time: request.invoice_next_billing_time,
            triggered_by: request.triggered_by,
            card_network: request.card_network.clone(),
            card_issuer: request.card_issuer.clone(),
        };
        let payment_address = hyperswitch_domain_models::payment_address::PaymentAddress::new(
            payment_intent
                .shipping_address
                .clone()
                .map(|address| address.into_inner()),
            payment_intent
                .billing_address
                .clone()
                .map(|address| address.into_inner()),
            payment_attempt
                .payment_method_billing_address
                .clone()
                .map(|address| address.into_inner()),
            Some(true),
        );

        let payment_data = PaymentAttemptRecordData {
            flow: PhantomData,
            payment_intent,
            payment_attempt,
            payment_address,
            revenue_recovery_data,
        };

        let get_trackers_response = operations::GetTrackerResponse { payment_data };

        Ok(get_trackers_response)
    }
}

#[async_trait]
impl<F: Clone + Sync> UpdateTracker<F, PaymentAttemptRecordData<F>, PaymentsAttemptRecordRequest>
    for PaymentAttemptRecord
{
    #[instrument(skip_all)]
    async fn update_trackers<'b>(
        &'b self,
        state: &'b SessionState,
        _req_state: ReqState,
        mut payment_data: PaymentAttemptRecordData<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<(
        PaymentsAttemptRecordOperation<'b, F>,
        PaymentAttemptRecordData<F>,
    )>
    where
        F: 'b + Send,
    {
        let feature_metadata = payment_data.get_updated_feature_metadata()?;
        let active_attempt_id = match payment_data.revenue_recovery_data.triggered_by {
            common_enums::TriggeredBy::Internal => Some(payment_data.payment_attempt.id.clone()),
            common_enums::TriggeredBy::External => None,
        };
        let payment_intent_update =

    hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::RecordUpdate
        {
            status: common_enums::IntentStatus::from(payment_data.payment_attempt.status),
            feature_metadata: Box::new(feature_metadata),
            updated_by: storage_scheme.to_string(),
            active_attempt_id
        }
    ;
        payment_data.payment_intent = state
            .store
            .update_payment_intent(
                &state.into(),
                payment_data.payment_intent,
                payment_intent_update,
                key_store,
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
        Ok((Box::new(self), payment_data))
    }
}

impl<F: Send + Clone> ValidateRequest<F, PaymentsAttemptRecordRequest, PaymentAttemptRecordData<F>>
    for PaymentAttemptRecord
{
    #[instrument(skip_all)]
    fn validate_request<'a, 'b>(
        &'b self,
        _request: &PaymentsAttemptRecordRequest,
        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 + Sync> Domain<F, PaymentsAttemptRecordRequest, PaymentAttemptRecordData<F>>
    for PaymentAttemptRecord
{
    #[instrument(skip_all)]
    async fn get_customer_details<'a>(
        &'a self,
        _state: &SessionState,
        _payment_data: &mut PaymentAttemptRecordData<F>,
        _merchant_key_store: &domain::MerchantKeyStore,
        _storage_scheme: enums::MerchantStorageScheme,
    ) -> CustomResult<
        (
            BoxedOperation<'a, F, PaymentsAttemptRecordRequest, PaymentAttemptRecordData<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 PaymentAttemptRecordData<F>,
        _storage_scheme: enums::MerchantStorageScheme,
        _merchant_key_store: &domain::MerchantKeyStore,
        _customer: &Option<domain::Customer>,
        _business_profile: &domain::Profile,
        _should_retry_with_pan: bool,
    ) -> RouterResult<(
        PaymentsAttemptRecordOperation<'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 PaymentAttemptRecordData<F>,
    ) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
        Ok(api::ConnectorCallType::Skip)
    }
}


// Implementation: impl EmailToken
// File: crates/router/src/services/email/types.rs
// Module: router
// Methods: 4 total (3 public)

impl EmailToken


// Implementation: impl api::ConnectorCustomer for for HyperswitchVault
// File: crates/hyperswitch_connectors/src/connectors/hyperswitch_vault.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ConnectorCustomer for for HyperswitchVault


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

pub struct NuveiWebhookTransactionId


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

pub struct FiuuWebhookStatus


// Implementation: impl api::ConnectorValidation for for Adyenplatform
// File: crates/hyperswitch_connectors/src/connectors/adyenplatform.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ConnectorValidation for for Adyenplatform


// Function: get_refund_filter_for_dimension
// File: crates/analytics/src/refunds/filters.rs
// Module: analytics

pub fn get_refund_filter_for_dimension<T>(
    dimension: RefundDimensions,
    auth: &AuthInfo,
    time_range: &TimeRange,
    pool: &T,
) -> FiltersResult<Vec<RefundFilterRow>>
where
    T: AnalyticsDataSource + RefundFilterAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,


// Function: authorize_preprocessing_steps
// File: crates/router/src/core/payments/flows/authorize_flow.rs
// Module: router

pub fn authorize_preprocessing_steps<F: Clone>(
    state: &SessionState,
    router_data: &types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
    confirm: bool,
    connector: &api::ConnectorData,
) -> RouterResult<types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>>


// Function: get_payment_status
// File: crates/hyperswitch_connectors/src/connectors/trustpayments/transformers.rs
// Module: hyperswitch_connectors

pub fn get_payment_status(&self) -> common_enums::AttemptStatus


// Implementation: impl Multitenancy
// File: crates/drainer/src/settings.rs
// Module: drainer
// Methods: 3 total (3 public)

impl Multitenancy


// Implementation: impl api::PaymentsPreProcessing for for Cybersource
// File: crates/hyperswitch_connectors/src/connectors/cybersource.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentsPreProcessing for for Cybersource


// Implementation: impl PaymentIntent
// File: crates/hyperswitch_domain_models/src/payments.rs
// Module: hyperswitch_domain_models
// Methods: 13 total (9 public)

impl PaymentIntent


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

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


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

pub fn new(name: Secret<String>) -> UserResult<Self>


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

impl api::PaymentSync for for Zen


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

impl Responder