// File: crates/diesel_models/src/query/payment_attempt.rs
// Module: diesel_models
// Public functions: 19

#[cfg(feature = "v1")]
use std::collections::HashSet;

use async_bb8_diesel::AsyncRunQueryDsl;
#[cfg(feature = "v1")]
use diesel::Table;
use diesel::{
    associations::HasTable, debug_query, pg::Pg, BoolExpressionMethods, ExpressionMethods, QueryDsl,
};
use error_stack::{report, ResultExt};

use super::generics;
#[cfg(feature = "v1")]
use crate::schema::payment_attempt::dsl;
#[cfg(feature = "v2")]
use crate::schema_v2::payment_attempt::dsl;
#[cfg(feature = "v1")]
use crate::{enums::IntentStatus, payment_attempt::PaymentAttemptUpdate, PaymentIntent};
use crate::{
    enums::{self},
    errors::DatabaseError,
    payment_attempt::{PaymentAttempt, PaymentAttemptNew, PaymentAttemptUpdateInternal},
    query::generics::db_metrics,
    PgPooledConn, StorageResult,
};

impl PaymentAttemptNew {
    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<PaymentAttempt> {
        generics::generic_insert(conn, self).await
    }
}

impl PaymentAttempt {
    #[cfg(feature = "v1")]
    pub async fn update_with_attempt_id(
        self,
        conn: &PgPooledConn,
        payment_attempt: PaymentAttemptUpdate,
    ) -> StorageResult<Self> {
        match generics::generic_update_with_unique_predicate_get_result::<
            <Self as HasTable>::Table,
            _,
            _,
            _,
        >(
            conn,
            dsl::attempt_id
                .eq(self.attempt_id.to_owned())
                .and(dsl::merchant_id.eq(self.merchant_id.to_owned())),
            PaymentAttemptUpdateInternal::from(payment_attempt).populate_derived_fields(&self),
        )
        .await
        {
            Err(error) => match error.current_context() {
                DatabaseError::NoFieldsToUpdate => Ok(self),
                _ => Err(error),
            },
            result => result,
        }
    }

    #[cfg(feature = "v2")]
    pub async fn update_with_attempt_id(
        self,
        conn: &PgPooledConn,
        payment_attempt: PaymentAttemptUpdateInternal,
    ) -> StorageResult<Self> {
        match generics::generic_update_with_unique_predicate_get_result::<
            <Self as HasTable>::Table,
            _,
            _,
            _,
        >(conn, dsl::id.eq(self.id.to_owned()), payment_attempt)
        .await
        {
            Err(error) => match error.current_context() {
                DatabaseError::NoFieldsToUpdate => Ok(self),
                _ => Err(error),
            },
            result => result,
        }
    }

    #[cfg(feature = "v1")]
    pub async fn find_optional_by_payment_id_merchant_id(
        conn: &PgPooledConn,
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> StorageResult<Option<Self>> {
        generics::generic_find_one_optional::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::payment_id.eq(payment_id.to_owned())),
        )
        .await
    }

    #[cfg(feature = "v1")]
    pub async fn find_by_connector_transaction_id_payment_id_merchant_id(
        conn: &PgPooledConn,
        connector_transaction_id: &common_utils::types::ConnectorTransactionId,
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::connector_transaction_id
                .eq(connector_transaction_id.get_id().to_owned())
                .and(dsl::payment_id.eq(payment_id.to_owned()))
                .and(dsl::merchant_id.eq(merchant_id.to_owned())),
        )
        .await
    }

    #[cfg(feature = "v1")]
    pub async fn find_last_successful_attempt_by_payment_id_merchant_id(
        conn: &PgPooledConn,
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> StorageResult<Self> {
        // perform ordering on the application level instead of database level
        generics::generic_filter::<<Self as HasTable>::Table, _, _, Self>(
            conn,
            dsl::payment_id
                .eq(payment_id.to_owned())
                .and(dsl::merchant_id.eq(merchant_id.to_owned()))
                .and(dsl::status.eq(enums::AttemptStatus::Charged)),
            Some(1),
            None,
            Some(dsl::modified_at.desc()),
        )
        .await?
        .into_iter()
        .nth(0)
        .ok_or(report!(DatabaseError::NotFound))
    }

    #[cfg(feature = "v1")]
    pub async fn find_last_successful_or_partially_captured_attempt_by_payment_id_merchant_id(
        conn: &PgPooledConn,
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> StorageResult<Self> {
        // perform ordering on the application level instead of database level
        generics::generic_filter::<<Self as HasTable>::Table, _, _, Self>(
            conn,
            dsl::payment_id
                .eq(payment_id.to_owned())
                .and(dsl::merchant_id.eq(merchant_id.to_owned()))
                .and(
                    dsl::status
                        .eq(enums::AttemptStatus::Charged)
                        .or(dsl::status.eq(enums::AttemptStatus::PartialCharged)),
                ),
            Some(1),
            None,
            Some(dsl::modified_at.desc()),
        )
        .await?
        .into_iter()
        .nth(0)
        .ok_or(report!(DatabaseError::NotFound))
    }

    #[cfg(feature = "v2")]
    pub async fn find_last_successful_or_partially_captured_attempt_by_payment_id(
        conn: &PgPooledConn,
        payment_id: &common_utils::id_type::GlobalPaymentId,
    ) -> StorageResult<Self> {
        // perform ordering on the application level instead of database level
        generics::generic_filter::<<Self as HasTable>::Table, _, _, Self>(
            conn,
            dsl::payment_id.eq(payment_id.to_owned()).and(
                dsl::status
                    .eq(enums::AttemptStatus::Charged)
                    .or(dsl::status.eq(enums::AttemptStatus::PartialCharged)),
            ),
            Some(1),
            None,
            Some(dsl::modified_at.desc()),
        )
        .await?
        .into_iter()
        .nth(0)
        .ok_or(report!(DatabaseError::NotFound))
    }

    #[cfg(feature = "v1")]
    pub async fn find_by_merchant_id_connector_txn_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_txn_id: &str,
    ) -> StorageResult<Self> {
        let (txn_id, txn_data) = common_utils::types::ConnectorTransactionId::form_id_and_data(
            connector_txn_id.to_string(),
        );
        let connector_transaction_id = txn_id
            .get_txn_id(txn_data.as_ref())
            .change_context(DatabaseError::Others)
            .attach_printable_lazy(|| {
                format!("Failed to retrieve txn_id for ({txn_id:?}, {txn_data:?})")
            })?;
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::connector_transaction_id.eq(connector_transaction_id.to_owned())),
        )
        .await
    }

    #[cfg(feature = "v2")]
    pub async fn find_by_profile_id_connector_transaction_id(
        conn: &PgPooledConn,
        profile_id: &common_utils::id_type::ProfileId,
        connector_txn_id: &str,
    ) -> StorageResult<Self> {
        let (txn_id, txn_data) = common_utils::types::ConnectorTransactionId::form_id_and_data(
            connector_txn_id.to_string(),
        );
        let connector_transaction_id = txn_id
            .get_txn_id(txn_data.as_ref())
            .change_context(DatabaseError::Others)
            .attach_printable_lazy(|| {
                format!("Failed to retrieve txn_id for ({txn_id:?}, {txn_data:?})")
            })?;
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::profile_id
                .eq(profile_id.to_owned())
                .and(dsl::connector_payment_id.eq(connector_transaction_id.to_owned())),
        )
        .await
    }

    #[cfg(feature = "v1")]
    pub async fn find_by_merchant_id_attempt_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        attempt_id: &str,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::attempt_id.eq(attempt_id.to_owned())),
        )
        .await
    }

    #[cfg(feature = "v2")]
    pub async fn find_by_id(
        conn: &PgPooledConn,
        id: &common_utils::id_type::GlobalAttemptId,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::id.eq(id.to_owned()),
        )
        .await
    }

    #[cfg(feature = "v2")]
    pub async fn find_by_payment_id(
        conn: &PgPooledConn,
        payment_id: &common_utils::id_type::GlobalPaymentId,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            dsl::payment_id.eq(payment_id.to_owned()),
            None,
            None,
            Some(dsl::created_at.asc()),
        )
        .await
    }

    #[cfg(feature = "v1")]
    pub async fn find_by_merchant_id_preprocessing_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        preprocessing_id: &str,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::preprocessing_step_id.eq(preprocessing_id.to_owned())),
        )
        .await
    }

    #[cfg(feature = "v1")]
    pub async fn find_by_payment_id_merchant_id_attempt_id(
        conn: &PgPooledConn,
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
        attempt_id: &str,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::payment_id.eq(payment_id.to_owned()).and(
                dsl::merchant_id
                    .eq(merchant_id.to_owned())
                    .and(dsl::attempt_id.eq(attempt_id.to_owned())),
            ),
        )
        .await
    }

    #[cfg(feature = "v1")]
    pub async fn find_by_merchant_id_payment_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<
            <Self as HasTable>::Table,
            _,
            <<Self as HasTable>::Table as Table>::PrimaryKey,
            _,
        >(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::payment_id.eq(payment_id.to_owned())),
            None,
            None,
            None,
        )
        .await
    }

    #[cfg(feature = "v1")]
    pub async fn get_filters_for_payments(
        conn: &PgPooledConn,
        pi: &[PaymentIntent],
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> StorageResult<(
        Vec<String>,
        Vec<enums::Currency>,
        Vec<IntentStatus>,
        Vec<enums::PaymentMethod>,
        Vec<enums::PaymentMethodType>,
        Vec<enums::AuthenticationType>,
    )> {
        let active_attempts: Vec<String> = pi
            .iter()
            .map(|payment_intent| payment_intent.clone().active_attempt_id)
            .collect();

        let filter = <Self as HasTable>::table()
            .filter(dsl::merchant_id.eq(merchant_id.to_owned()))
            .filter(dsl::attempt_id.eq_any(active_attempts));

        let intent_status: Vec<IntentStatus> = pi
            .iter()
            .map(|payment_intent| payment_intent.status)
            .collect::<HashSet<IntentStatus>>()
            .into_iter()
            .collect();

        let filter_connector = filter
            .clone()
            .select(dsl::connector)
            .distinct()
            .get_results_async::<Option<String>>(conn)
            .await
            .change_context(DatabaseError::Others)
            .attach_printable("Error filtering records by connector")?
            .into_iter()
            .flatten()
            .collect::<Vec<String>>();

        let filter_currency = filter
            .clone()
            .select(dsl::currency)
            .distinct()
            .get_results_async::<Option<enums::Currency>>(conn)
            .await
            .change_context(DatabaseError::Others)
            .attach_printable("Error filtering records by currency")?
            .into_iter()
            .flatten()
            .collect::<Vec<enums::Currency>>();

        let filter_payment_method = filter
            .clone()
            .select(dsl::payment_method)
            .distinct()
            .get_results_async::<Option<enums::PaymentMethod>>(conn)
            .await
            .change_context(DatabaseError::Others)
            .attach_printable("Error filtering records by payment method")?
            .into_iter()
            .flatten()
            .collect::<Vec<enums::PaymentMethod>>();

        let filter_payment_method_type = filter
            .clone()
            .select(dsl::payment_method_type)
            .distinct()
            .get_results_async::<Option<enums::PaymentMethodType>>(conn)
            .await
            .change_context(DatabaseError::Others)
            .attach_printable("Error filtering records by payment method type")?
            .into_iter()
            .flatten()
            .collect::<Vec<enums::PaymentMethodType>>();

        let filter_authentication_type = filter
            .clone()
            .select(dsl::authentication_type)
            .distinct()
            .get_results_async::<Option<enums::AuthenticationType>>(conn)
            .await
            .change_context(DatabaseError::Others)
            .attach_printable("Error filtering records by authentication type")?
            .into_iter()
            .flatten()
            .collect::<Vec<enums::AuthenticationType>>();

        Ok((
            filter_connector,
            filter_currency,
            intent_status,
            filter_payment_method,
            filter_payment_method_type,
            filter_authentication_type,
        ))
    }

    #[cfg(feature = "v2")]
    #[allow(clippy::too_many_arguments)]
    pub async fn get_total_count_of_attempts(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        active_attempt_ids: &[String],
        connector: Option<Vec<String>>,
        payment_method_type: Option<Vec<enums::PaymentMethod>>,
        payment_method_subtype: Option<Vec<enums::PaymentMethodType>>,
        authentication_type: Option<Vec<enums::AuthenticationType>>,
        merchant_connector_id: Option<Vec<common_utils::id_type::MerchantConnectorAccountId>>,
        card_network: Option<Vec<enums::CardNetwork>>,
    ) -> StorageResult<i64> {
        let mut filter = <Self as HasTable>::table()
            .count()
            .filter(dsl::merchant_id.eq(merchant_id.to_owned()))
            .filter(dsl::id.eq_any(active_attempt_ids.to_owned()))
            .into_boxed();

        if let Some(connectors) = connector {
            filter = filter.filter(dsl::connector.eq_any(connectors));
        }

        if let Some(payment_method_types) = payment_method_type {
            filter = filter.filter(dsl::payment_method_type_v2.eq_any(payment_method_types));
        }
        if let Some(payment_method_subtypes) = payment_method_subtype {
            filter = filter.filter(dsl::payment_method_subtype.eq_any(payment_method_subtypes));
        }
        if let Some(authentication_types) = authentication_type {
            filter = filter.filter(dsl::authentication_type.eq_any(authentication_types));
        }
        if let Some(merchant_connector_ids) = merchant_connector_id {
            filter = filter.filter(dsl::merchant_connector_id.eq_any(merchant_connector_ids));
        }
        if let Some(card_networks) = card_network {
            filter = filter.filter(dsl::card_network.eq_any(card_networks));
        }

        router_env::logger::debug!(query = %debug_query::<Pg, _>(&filter).to_string());

        // TODO: Remove these logs after debugging the issue for delay in count query
        let start_time = std::time::Instant::now();
        router_env::logger::debug!("Executing count query start_time: {:?}", start_time);
        let result = db_metrics::track_database_call::<<Self as HasTable>::Table, _, _>(
            filter.get_result_async::<i64>(conn),
            db_metrics::DatabaseOperation::Filter,
        )
        .await
        .change_context(DatabaseError::Others)
        .attach_printable("Error filtering count of payments");

        let duration = start_time.elapsed();
        router_env::logger::debug!("Completed count query in {:?}", duration);

        result
    }

    #[cfg(feature = "v1")]
    #[allow(clippy::too_many_arguments)]
    pub async fn get_total_count_of_attempts(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        active_attempt_ids: &[String],
        connector: Option<Vec<String>>,
        payment_method: Option<Vec<enums::PaymentMethod>>,
        payment_method_type: Option<Vec<enums::PaymentMethodType>>,
        authentication_type: Option<Vec<enums::AuthenticationType>>,
        merchant_connector_id: Option<Vec<common_utils::id_type::MerchantConnectorAccountId>>,
        card_network: Option<Vec<enums::CardNetwork>>,
        card_discovery: Option<Vec<enums::CardDiscovery>>,
    ) -> StorageResult<i64> {
        let mut filter = <Self as HasTable>::table()
            .count()
            .filter(dsl::merchant_id.eq(merchant_id.to_owned()))
            .filter(dsl::attempt_id.eq_any(active_attempt_ids.to_owned()))
            .into_boxed();

        if let Some(connector) = connector {
            filter = filter.filter(dsl::connector.eq_any(connector));
        }

        if let Some(payment_method) = payment_method {
            filter = filter.filter(dsl::payment_method.eq_any(payment_method));
        }
        if let Some(payment_method_type) = payment_method_type {
            filter = filter.filter(dsl::payment_method_type.eq_any(payment_method_type));
        }
        if let Some(authentication_type) = authentication_type {
            filter = filter.filter(dsl::authentication_type.eq_any(authentication_type));
        }
        if let Some(merchant_connector_id) = merchant_connector_id {
            filter = filter.filter(dsl::merchant_connector_id.eq_any(merchant_connector_id))
        }
        if let Some(card_network) = card_network {
            filter = filter.filter(dsl::card_network.eq_any(card_network))
        }
        if let Some(card_discovery) = card_discovery {
            filter = filter.filter(dsl::card_discovery.eq_any(card_discovery))
        }

        router_env::logger::debug!(query = %debug_query::<Pg, _>(&filter).to_string());

        // TODO: Remove these logs after debugging the issue for delay in count query
        let start_time = std::time::Instant::now();
        router_env::logger::debug!("Executing count query start_time: {:?}", start_time);
        let result = db_metrics::track_database_call::<<Self as HasTable>::Table, _, _>(
            filter.get_result_async::<i64>(conn),
            db_metrics::DatabaseOperation::Filter,
        )
        .await
        .change_context(DatabaseError::Others)
        .attach_printable("Error filtering count of payments");

        let duration = start_time.elapsed();
        router_env::logger::debug!("Completed count query in {:?}", duration);

        result
    }
}


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

impl ConnectorSpecifications for for Breadpay


// Implementation: impl PayoutsInterface for for KafkaStore
// File: crates/router/src/db/kafka_store.rs
// Module: router
// Methods: 0 total (0 public)

impl PayoutsInterface for for KafkaStore


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

impl api::RefundSync for for Juspaythreedsserver


// Function: insert
// File: crates/diesel_models/src/query/generic_link.rs
// Module: diesel_models

pub fn insert(self, conn: &PgPooledConn) -> StorageResult<GenericLinkState>


// Function: sort_and_minify_json
// File: crates/hyperswitch_connectors/src/connectors/bluecode/transformers.rs
// Module: hyperswitch_connectors

pub fn sort_and_minify_json(value: &Value) -> Result<String, errors::ConnectorError>


// Function: get_revenue_recovery_metadata
// File: crates/hyperswitch_domain_models/src/payments.rs
// Module: hyperswitch_domain_models

pub fn get_revenue_recovery_metadata(
        &self,
    ) -> Option<diesel_models::types::PaymentRevenueRecoveryMetadata>


// Struct: HyperwalletRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/hyperwallet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct HyperwalletRefundRequest


// Implementation: impl Nordea
// File: crates/hyperswitch_connectors/src/connectors/nordea.rs
// Module: hyperswitch_connectors
// Methods: 6 total (3 public)

impl Nordea


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

pub struct ShippingAddress


// Struct: ConnectorInfo
// File: crates/router/src/core/payments/routing/utils.rs
// Module: router
// Implementations: 1

pub struct ConnectorInfo


        sub_flow: String,
        code: String,
        message: String,
        data: hyperswitch_domain_models::gsm::GatewayStatusMappingUpdate,
    ) -> CustomResult<hyperswitch_domain_models::gsm::GatewayStatusMap, errors::StorageError> {
        self.diesel_store
            .update_gsm_rule(connector, flow, sub_flow, code, message, data)
            .await
    }

    async fn delete_gsm_rule(
        &self,
        connector: String,
        flow: String,
        sub_flow: String,
        code: String,
        message: String,
    ) -> CustomResult<bool, errors::StorageError> {
        self.diesel_store
            .delete_gsm_rule(connector, flow, sub_flow, code, message)
            .await
    }
}

#[async_trait::async_trait]
impl UnifiedTranslationsInterface for KafkaStore {
    async fn add_unfied_translation(
        &self,
        translation: storage::UnifiedTranslationsNew,
    ) -> CustomResult<storage::UnifiedTranslations, errors::StorageError> {
        self.diesel_store.add_unfied_translation(translation).await
    }

    async fn find_translation(
        &self,
        unified_code: String,
        unified_message: String,
        locale: String,
    ) -> CustomResult<String, errors::StorageError> {
        self.diesel_store
            .find_translation(unified_code, unified_message, locale)
            .await
    }

    async fn update_translation(
        &self,
        unified_code: String,
        unified_message: String,
        locale: String,
        data: storage::UnifiedTranslationsUpdate,
    ) -> CustomResult<storage::UnifiedTranslations, errors::StorageError> {
        self.diesel_store
            .update_translation(unified_code, unified_message, locale, data)
            .await
    }

    async fn delete_translation(
        &self,
        unified_code: String,
        unified_message: String,
        locale: String,
    ) -> CustomResult<bool, errors::StorageError> {
        self.diesel_store
            .delete_translation(unified_code, unified_message, locale)
            .await
    }
}

#[async_trait::async_trait]
impl StorageInterface for KafkaStore {
    fn get_scheduler_db(&self) -> Box<dyn SchedulerInterface> {
        Box::new(self.clone())
    }

    fn get_payment_methods_store(&self) -> Box<dyn PaymentMethodsStorageInterface> {
        Box::new(self.clone())
    }

    fn get_cache_store(&self) -> Box<dyn RedisConnInterface + Send + Sync + 'static> {
        Box::new(self.clone())
    }
}

impl GlobalStorageInterface for KafkaStore {
    fn get_cache_store(&self) -> Box<dyn RedisConnInterface + Send + Sync + 'static> {
        Box::new(self.clone())
    }
}
impl AccountsStorageInterface for KafkaStore {}

impl PaymentMethodsStorageInterface for KafkaStore {}

impl CommonStorageInterface for KafkaStore {
    fn get_storage_interface(&self) -> Box<dyn StorageInterface> {
        Box::new(self.clone())
    }
    fn get_global_storage_interface(&self) -> Box<dyn GlobalStorageInterface> {
        Box::new(self.clone())
    }
    fn get_accounts_storage_interface(&self) -> Box<dyn AccountsStorageInterface> {
        Box::new(self.clone())
    }
}

#[async_trait::async_trait]
impl SchedulerInterface for KafkaStore {}

impl MasterKeyInterface for KafkaStore {
    fn get_master_key(&self) -> &[u8] {
        self.diesel_store.get_master_key()
    }
}
#[async_trait::async_trait]
impl UserInterface for KafkaStore {
    async fn insert_user(
        &self,
        user_data: storage::UserNew,
    ) -> CustomResult<storage::User, errors::StorageError> {
        self.diesel_store.insert_user(user_data).await
    }

    async fn find_user_by_email(
        &self,
        user_email: &domain::UserEmail,
    ) -> CustomResult<storage::User, errors::StorageError> {
        self.diesel_store.find_user_by_email(user_email).await
    }

    async fn find_user_by_id(
        &self,
        user_id: &str,
    ) -> CustomResult<storage::User, errors::StorageError> {
        self.diesel_store.find_user_by_id(user_id).await
    }

    async fn update_user_by_user_id(
        &self,
        user_id: &str,
        user: storage::UserUpdate,
    ) -> CustomResult<storage::User, errors::StorageError> {
        self.diesel_store
            .update_user_by_user_id(user_id, user)
            .await
    }

    async fn update_user_by_email(
        &self,
        user_email: &domain::UserEmail,
        user: storage::UserUpdate,
    ) -> CustomResult<storage::User, errors::StorageError> {
        self.diesel_store
            .update_user_by_email(user_email, user)
            .await
    }

    async fn delete_user_by_user_id(
        &self,
        user_id: &str,
    ) -> CustomResult<bool, errors::StorageError> {
        self.diesel_store.delete_user_by_user_id(user_id).await
    }

    async fn find_users_by_user_ids(
        &self,
        user_ids: Vec<String>,
    ) -> CustomResult<Vec<storage::User>, errors::StorageError> {
        self.diesel_store.find_users_by_user_ids(user_ids).await
    }
}

impl RedisConnInterface for KafkaStore {
    fn get_redis_conn(&self) -> CustomResult<Arc<RedisConnectionPool>, RedisError> {
        self.diesel_store.get_redis_conn()
    }
}

#[async_trait::async_trait]
impl UserRoleInterface for KafkaStore {
    async fn insert_user_role(
        &self,
        user_role: storage::UserRoleNew,
    ) -> CustomResult<user_storage::UserRole, errors::StorageError> {
        self.diesel_store.insert_user_role(user_role).await
    }

    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> {
        self.diesel_store
            .find_user_role_by_user_id_and_lineage(
                user_id,
                tenant_id,
                org_id,
                merchant_id,
                profile_id,
                version,
            )
            .await
    }

    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: user_storage::UserRoleUpdate,
        version: enums::UserRoleVersion,
    ) -> CustomResult<storage::UserRole, errors::StorageError> {
        self.diesel_store
            .update_user_role_by_user_id_and_lineage(
                user_id,
                tenant_id,
                org_id,
                merchant_id,
                profile_id,
                update,
                version,
            )
            .await
    }

    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> {
        self.diesel_store
            .delete_user_role_by_user_id_and_lineage(
                user_id,
                tenant_id,
                org_id,
                merchant_id,
                profile_id,
                version,
            )
            .await
    }

    async fn list_user_roles_by_user_id<'a>(
        &self,
        payload: ListUserRolesByUserIdPayload<'a>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
        self.diesel_store.list_user_roles_by_user_id(payload).await
    }

    async fn list_user_roles_by_user_id_across_tenants(
        &self,
        user_id: &str,
        limit: Option<u32>,
    ) -> CustomResult<Vec<storage::UserRole>, errors::StorageError> {
        self.diesel_store
            .list_user_roles_by_user_id_across_tenants(user_id, limit)
            .await
    }

    async fn list_user_roles_by_org_id<'a>(
        &self,
        payload: ListUserRolesByOrgIdPayload<'a>,
    ) -> CustomResult<Vec<user_storage::UserRole>, errors::StorageError> {
        self.diesel_store.list_user_roles_by_org_id(payload).await
    }
}

#[async_trait::async_trait]
impl DashboardMetadataInterface for KafkaStore {
    async fn insert_metadata(
        &self,
        metadata: storage::DashboardMetadataNew,
    ) -> CustomResult<storage::DashboardMetadata, errors::StorageError> {
        self.diesel_store.insert_metadata(metadata).await
    }

    async fn update_metadata(
        &self,
        user_id: Option<String>,
        merchant_id: id_type::MerchantId,
        org_id: id_type::OrganizationId,
        data_key: enums::DashboardMetadata,
        dashboard_metadata_update: storage::DashboardMetadataUpdate,
    ) -> CustomResult<storage::DashboardMetadata, errors::StorageError> {
        self.diesel_store
            .update_metadata(
                user_id,
                merchant_id,
                org_id,
                data_key,
                dashboard_metadata_update,
            )
            .await
    }

    async fn find_user_scoped_dashboard_metadata(
        &self,
        user_id: &str,
        merchant_id: &id_type::MerchantId,
        org_id: &id_type::OrganizationId,
        data_keys: Vec<enums::DashboardMetadata>,
    ) -> CustomResult<Vec<storage::DashboardMetadata>, errors::StorageError> {
        self.diesel_store
            .find_user_scoped_dashboard_metadata(user_id, merchant_id, org_id, data_keys)
            .await
    }

    async fn find_merchant_scoped_dashboard_metadata(
        &self,
        merchant_id: &id_type::MerchantId,
        org_id: &id_type::OrganizationId,
        data_keys: Vec<enums::DashboardMetadata>,
    ) -> CustomResult<Vec<storage::DashboardMetadata>, errors::StorageError> {
        self.diesel_store
            .find_merchant_scoped_dashboard_metadata(merchant_id, org_id, data_keys)
            .await
    }

    async fn delete_all_user_scoped_dashboard_metadata_by_merchant_id(
        &self,
        user_id: &str,
        merchant_id: &id_type::MerchantId,
    ) -> CustomResult<bool, errors::StorageError> {
        self.diesel_store
            .delete_all_user_scoped_dashboard_metadata_by_merchant_id(user_id, merchant_id)
            .await
    }

    async fn delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
        &self,
        user_id: &str,
        merchant_id: &id_type::MerchantId,
        data_key: enums::DashboardMetadata,
    ) -> CustomResult<storage::DashboardMetadata, errors::StorageError> {
        self.diesel_store
            .delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
                user_id,
                merchant_id,
                data_key,
            )
            .await
    }
}

#[async_trait::async_trait]
impl BatchSampleDataInterface for KafkaStore {
    #[cfg(feature = "v1")]
    async fn insert_payment_intents_batch_for_sample_data(
        &self,
        state: &KeyManagerState,
        batch: Vec<hyperswitch_domain_models::payments::PaymentIntent>,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
    ) -> CustomResult<
        Vec<hyperswitch_domain_models::payments::PaymentIntent>,
        storage_impl::errors::StorageError,
    > {
        let payment_intents_list = self
            .diesel_store
            .insert_payment_intents_batch_for_sample_data(state, batch, key_store)
            .await?;

        for payment_intent in payment_intents_list.iter() {
            let _ = self
                .kafka_producer
                .log_payment_intent(
                    payment_intent,
                    None,
                    self.tenant_id.clone(),
                    state.infra_values.clone(),
                )
                .await;
        }
        Ok(payment_intents_list)
    }

    #[cfg(feature = "v1")]
    async fn insert_payment_attempts_batch_for_sample_data(
        &self,
        batch: Vec<diesel_models::user::sample_data::PaymentAttemptBatchNew>,
    ) -> CustomResult<
        Vec<hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt>,
        storage_impl::errors::StorageError,
    > {
        let payment_attempts_list = self
            .diesel_store
            .insert_payment_attempts_batch_for_sample_data(batch)
            .await?;

        for payment_attempt in payment_attempts_list.iter() {
            let _ = self
                .kafka_producer
                .log_payment_attempt(payment_attempt, None, self.tenant_id.clone())
                .await;
        }
        Ok(payment_attempts_list)
    }

    #[cfg(feature = "v1")]
    async fn insert_refunds_batch_for_sample_data(
        &self,
        batch: Vec<diesel_models::RefundNew>,
    ) -> CustomResult<Vec<diesel_models::Refund>, storage_impl::errors::StorageError> {
        let refunds_list = self
            .diesel_store
            .insert_refunds_batch_for_sample_data(batch)
            .await?;

        for refund in refunds_list.iter() {
            let _ = self
                .kafka_producer
                .log_refund(refund, None, self.tenant_id.clone())
                .await;
        }
        Ok(refunds_list)
    }

    #[cfg(feature = "v1")]
    async fn insert_disputes_batch_for_sample_data(
        &self,
        batch: Vec<diesel_models::DisputeNew>,
    ) -> CustomResult<Vec<diesel_models::Dispute>, storage_impl::errors::StorageError> {
        let disputes_list = self
            .diesel_store
            .insert_disputes_batch_for_sample_data(batch)
            .await?;

        for dispute in disputes_list.iter() {
            let _ = self
                .kafka_producer
                .log_dispute(dispute, None, self.tenant_id.clone())
                .await;
        }
        Ok(disputes_list)
    }

    #[cfg(feature = "v1")]
    async fn delete_payment_intents_for_sample_data(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
    ) -> CustomResult<
        Vec<hyperswitch_domain_models::payments::PaymentIntent>,
        storage_impl::errors::StorageError,
    > {
        let payment_intents_list = self
            .diesel_store
            .delete_payment_intents_for_sample_data(state, merchant_id, key_store)
            .await?;

        for payment_intent in payment_intents_list.iter() {
            let _ = self
                .kafka_producer
                .log_payment_intent_delete(
                    payment_intent,
                    self.tenant_id.clone(),
                    state.infra_values.clone(),
                )
                .await;
        }
        Ok(payment_intents_list)
    }

    #[cfg(feature = "v1")]
    async fn delete_payment_attempts_for_sample_data(
        &self,
        merchant_id: &id_type::MerchantId,
    ) -> CustomResult<
        Vec<hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt>,
        storage_impl::errors::StorageError,
    > {
        let payment_attempts_list = self
            .diesel_store
            .delete_payment_attempts_for_sample_data(merchant_id)
            .await?;

        for payment_attempt in payment_attempts_list.iter() {
            let _ = self
                .kafka_producer
                .log_payment_attempt_delete(payment_attempt, self.tenant_id.clone())
                .await;
        }

        Ok(payment_attempts_list)
    }

    #[cfg(feature = "v1")]
    async fn delete_refunds_for_sample_data(
        &self,
        merchant_id: &id_type::MerchantId,
    ) -> CustomResult<Vec<diesel_models::Refund>, storage_impl::errors::StorageError> {
        let refunds_list = self
            .diesel_store
            .delete_refunds_for_sample_data(merchant_id)
            .await?;

        for refund in refunds_list.iter() {
            let _ = self
                .kafka_producer
                .log_refund_delete(refund, self.tenant_id.clone())
                .await;
        }

        Ok(refunds_list)
    }

    #[cfg(feature = "v1")]
    async fn delete_disputes_for_sample_data(
        &self,
        merchant_id: &id_type::MerchantId,
    ) -> CustomResult<Vec<diesel_models::Dispute>, storage_impl::errors::StorageError> {
        let disputes_list = self
            .diesel_store
            .delete_disputes_for_sample_data(merchant_id)
            .await?;

        for dispute in disputes_list.iter() {
            let _ = self
                .kafka_producer
                .log_dispute_delete(dispute, self.tenant_id.clone())
                .await;
        }

        Ok(disputes_list)
    }
}

#[async_trait::async_trait]
impl AuthorizationInterface for KafkaStore {
    async fn insert_authorization(
        &self,
        authorization: storage::AuthorizationNew,
    ) -> CustomResult<storage::Authorization, errors::StorageError> {
        self.diesel_store.insert_authorization(authorization).await
    }

    async fn find_all_authorizations_by_merchant_id_payment_id(
        &self,
        merchant_id: &id_type::MerchantId,
        payment_id: &id_type::PaymentId,
    ) -> CustomResult<Vec<storage::Authorization>, errors::StorageError> {
        self.diesel_store
            .find_all_authorizations_by_merchant_id_payment_id(merchant_id, payment_id)
            .await
    }

    async fn update_authorization_by_merchant_id_authorization_id(
        &self,
        merchant_id: id_type::MerchantId,
        authorization_id: String,
        authorization: storage::AuthorizationUpdate,
    ) -> CustomResult<storage::Authorization, errors::StorageError> {
        self.diesel_store
            .update_authorization_by_merchant_id_authorization_id(
                merchant_id,
                authorization_id,
                authorization,
            )
            .await
    }
}

#[async_trait::async_trait]
impl AuthenticationInterface for KafkaStore {
    async fn insert_authentication(
        &self,
        authentication: storage::AuthenticationNew,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let auth = self
            .diesel_store
            .insert_authentication(authentication)
            .await?;

        if let Err(er) = self
            .kafka_producer
            .log_authentication(&auth, None, self.tenant_id.clone())
            .await
        {
            logger::error!(message="Failed to log analytics event for authentication {auth:?}", error_message=?er)
        }

        Ok(auth)
    }

    async fn find_authentication_by_merchant_id_authentication_id(
        &self,
        merchant_id: &id_type::MerchantId,
        authentication_id: &id_type::AuthenticationId,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        self.diesel_store
            .find_authentication_by_merchant_id_authentication_id(merchant_id, authentication_id)
            .await
    }

    async fn find_authentication_by_merchant_id_connector_authentication_id(
        &self,
        merchant_id: id_type::MerchantId,
        connector_authentication_id: String,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        self.diesel_store
            .find_authentication_by_merchant_id_connector_authentication_id(
                merchant_id,
                connector_authentication_id,
            )
            .await
    }

    async fn update_authentication_by_merchant_id_authentication_id(
        &self,
        previous_state: storage::Authentication,
        authentication_update: storage::AuthenticationUpdate,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let auth = self
            .diesel_store
            .update_authentication_by_merchant_id_authentication_id(
                previous_state.clone(),
                authentication_update,
            )
            .await?;

        if let Err(er) = self
            .kafka_producer
            .log_authentication(&auth, Some(previous_state.clone()), self.tenant_id.clone())
            .await
        {
            logger::error!(message="Failed to log analytics event for authentication {auth:?}", error_message=?er)
        }

        Ok(auth)
    }
}

#[async_trait::async_trait]
impl HealthCheckDbInterface for KafkaStore {
    async fn health_check_db(&self) -> CustomResult<(), errors::HealthCheckDBError> {
        self.diesel_store.health_check_db().await
    }
}

#[async_trait::async_trait]
impl RoleInterface for KafkaStore {
    async fn insert_role(
        &self,
        role: storage::RoleNew,
    ) -> CustomResult<storage::Role, errors::StorageError> {
        self.diesel_store.insert_role(role).await
    }

    async fn find_role_by_role_id(
        &self,
        role_id: &str,
    ) -> CustomResult<storage::Role, errors::StorageError> {
        self.diesel_store.find_role_by_role_id(role_id).await
    }

    async fn find_role_by_role_id_in_lineage(
        &self,
        role_id: &str,
        merchant_id: &id_type::MerchantId,
        org_id: &id_type::OrganizationId,
        profile_id: &id_type::ProfileId,
        tenant_id: &id_type::TenantId,
    ) -> CustomResult<storage::Role, errors::StorageError> {
        self.diesel_store
            .find_role_by_role_id_in_lineage(role_id, merchant_id, org_id, profile_id, tenant_id)
            .await
    }

    async fn find_by_role_id_org_id_tenant_id(
        &self,
        role_id: &str,
        org_id: &id_type::OrganizationId,
        tenant_id: &id_type::TenantId,
    ) -> CustomResult<storage::Role, errors::StorageError> {
        self.diesel_store
            .find_by_role_id_org_id_tenant_id(role_id, org_id, tenant_id)
            .await
    }

    async fn update_role_by_role_id(
        &self,
        role_id: &str,
        role_update: storage::RoleUpdate,
    ) -> CustomResult<storage::Role, errors::StorageError> {
        self.diesel_store
            .update_role_by_role_id(role_id, role_update)
            .await
    }

    async fn delete_role_by_role_id(
        &self,
        role_id: &str,
    ) -> CustomResult<storage::Role, errors::StorageError> {
        self.diesel_store.delete_role_by_role_id(role_id).await
    }

    //TODO: Remove once generic_list_roles_by_entity_type is stable
    async fn list_roles_for_org_by_parameters(
        &self,
        tenant_id: &id_type::TenantId,
        org_id: &id_type::OrganizationId,
        merchant_id: Option<&id_type::MerchantId>,
        entity_type: Option<enums::EntityType>,
        limit: Option<u32>,
    ) -> CustomResult<Vec<storage::Role>, errors::StorageError> {
        self.diesel_store
            .list_roles_for_org_by_parameters(tenant_id, org_id, merchant_id, entity_type, limit)
            .await
    }

    async fn generic_list_roles_by_entity_type(
        &self,
        payload: diesel_models::role::ListRolesByEntityPayload,
        is_lineage_data_required: bool,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
    ) -> CustomResult<Vec<storage::Role>, errors::StorageError> {
        self.diesel_store
            .generic_list_roles_by_entity_type(payload, is_lineage_data_required, tenant_id, org_id)
            .await
    }
}

#[async_trait::async_trait]
impl GenericLinkInterface for KafkaStore {
    async fn find_generic_link_by_link_id(
        &self,
        link_id: &str,
    ) -> CustomResult<storage::GenericLinkState, errors::StorageError> {
        self.diesel_store
            .find_generic_link_by_link_id(link_id)
            .await
    }

    async fn find_pm_collect_link_by_link_id(
        &self,
        link_id: &str,
    ) -> CustomResult<storage::PaymentMethodCollectLink, errors::StorageError> {
        self.diesel_store
            .find_pm_collect_link_by_link_id(link_id)
            .await
    }

    async fn find_payout_link_by_link_id(
        &self,
        link_id: &str,
    ) -> CustomResult<storage::PayoutLink, errors::StorageError> {
        self.diesel_store.find_payout_link_by_link_id(link_id).await
    }

    async fn insert_generic_link(
        &self,
        generic_link: storage::GenericLinkNew,
    ) -> CustomResult<storage::GenericLinkState, errors::StorageError> {
        self.diesel_store.insert_generic_link(generic_link).await
    }

    async fn insert_pm_collect_link(
        &self,
        pm_collect_link: storage::GenericLinkNew,
    ) -> CustomResult<storage::PaymentMethodCollectLink, errors::StorageError> {
        self.diesel_store
            .insert_pm_collect_link(pm_collect_link)
            .await
    }

    async fn insert_payout_link(
        &self,
        pm_collect_link: storage::GenericLinkNew,
    ) -> CustomResult<storage::PayoutLink, errors::StorageError> {
        self.diesel_store.insert_payout_link(pm_collect_link).await
    }

    async fn update_payout_link(
        &self,
        payout_link: storage::PayoutLink,
        payout_link_update: storage::PayoutLinkUpdate,
    ) -> CustomResult<storage::PayoutLink, errors::StorageError> {
        self.diesel_store
            .update_payout_link(payout_link, payout_link_update)
            .await
    }
}

#[async_trait::async_trait]
impl UserKeyStoreInterface for KafkaStore {
    async fn insert_user_key_store(
        &self,
        state: &KeyManagerState,
        user_key_store: domain::UserKeyStore,
        key: &Secret<Vec<u8>>,
    ) -> CustomResult<domain::UserKeyStore, errors::StorageError> {
        self.diesel_store
            .insert_user_key_store(state, user_key_store, key)
            .await
    }

    async fn get_user_key_store_by_user_id(
        &self,
        state: &KeyManagerState,
        user_id: &str,
        key: &Secret<Vec<u8>>,
    ) -> CustomResult<domain::UserKeyStore, errors::StorageError> {
        self.diesel_store
            .get_user_key_store_by_user_id(state, user_id, key)
            .await
    }

    async fn get_all_user_key_store(
        &self,
        state: &KeyManagerState,
        key: &Secret<Vec<u8>>,
        from: u32,
        limit: u32,
    ) -> CustomResult<Vec<domain::UserKeyStore>, errors::StorageError> {
        self.diesel_store
            .get_all_user_key_store(state, key, from, limit)
            .await
    }
}

#[async_trait::async_trait]
impl UserAuthenticationMethodInterface for KafkaStore {
    async fn insert_user_authentication_method(
        &self,
        user_authentication_method: storage::UserAuthenticationMethodNew,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        self.diesel_store
            .insert_user_authentication_method(user_authentication_method)
            .await
    }

    async fn get_user_authentication_method_by_id(
        &self,
        id: &str,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        self.diesel_store
            .get_user_authentication_method_by_id(id)
            .await
    }

    async fn list_user_authentication_methods_for_auth_id(
        &self,
        auth_id: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError> {
        self.diesel_store
            .list_user_authentication_methods_for_auth_id(auth_id)
            .await
    }

    async fn list_user_authentication_methods_for_owner_id(
        &self,
        owner_id: &str,
    ) -> CustomResult<Vec<storage::UserAuthenticationMethod>, errors::StorageError> {
        self.diesel_store
            .list_user_authentication_methods_for_owner_id(owner_id)
            .await
    }

    async fn update_user_authentication_method(
        &self,
        id: &str,
        user_authentication_method_update: storage::UserAuthenticationMethodUpdate,
    ) -> CustomResult<storage::UserAuthenticationMethod, errors::StorageError> {
        self.diesel_store
            .update_user_authentication_method(id, user_authentication_method_update)
            .await
    }

    async fn list_user_authentication_methods_for_email_domain(
        &self,
        email_domain: &str,
    ) -> CustomResult<
        Vec<diesel_models::user_authentication_method::UserAuthenticationMethod>,
        errors::StorageError,
    > {
        self.diesel_store
            .list_user_authentication_methods_for_email_domain(email_domain)
            .await
    }
}

#[async_trait::async_trait]
impl HyperswitchAiInteractionInterface for KafkaStore {
    async fn insert_hyperswitch_ai_interaction(
        &self,
        hyperswitch_ai_interaction: storage::HyperswitchAiInteractionNew,
    ) -> CustomResult<storage::HyperswitchAiInteraction, errors::StorageError> {
        self.diesel_store
            .insert_hyperswitch_ai_interaction(hyperswitch_ai_interaction)
            .await
    }

    async fn list_hyperswitch_ai_interactions(
        &self,
        merchant_id: Option<id_type::MerchantId>,
        limit: i64,
        offset: i64,
    ) -> CustomResult<Vec<storage::HyperswitchAiInteraction>, errors::StorageError> {
        self.diesel_store
            .list_hyperswitch_ai_interactions(merchant_id, limit, offset)
            .await
    }
}

#[async_trait::async_trait]
impl ThemeInterface for KafkaStore {
    async fn insert_theme(
        &self,
        theme: storage::theme::ThemeNew,
    ) -> CustomResult<storage::theme::Theme, errors::StorageError> {
        self.diesel_store.insert_theme(theme).await
    }

    async fn find_theme_by_theme_id(
        &self,
        theme_id: String,
    ) -> CustomResult<storage::theme::Theme, errors::StorageError> {
        self.diesel_store.find_theme_by_theme_id(theme_id).await
    }

    async fn find_most_specific_theme_in_lineage(
        &self,
        lineage: ThemeLineage,
    ) -> CustomResult<diesel_models::user::theme::Theme, errors::StorageError> {
        self.diesel_store
            .find_most_specific_theme_in_lineage(lineage)
            .await
    }

    async fn find_theme_by_lineage(
        &self,
        lineage: ThemeLineage,
    ) -> CustomResult<storage::theme::Theme, errors::StorageError> {
        self.diesel_store.find_theme_by_lineage(lineage).await
    }

    async fn update_theme_by_theme_id(
        &self,
        theme_id: String,
        theme_update: diesel_models::user::theme::ThemeUpdate,
    ) -> CustomResult<diesel_models::user::theme::Theme, errors::StorageError> {
        self.diesel_store
            .update_theme_by_theme_id(theme_id, theme_update)
            .await
    }

    async fn delete_theme_by_theme_id(
        &self,
        theme_id: String,
    ) -> CustomResult<storage::theme::Theme, errors::StorageError> {
        self.diesel_store.delete_theme_by_theme_id(theme_id).await
    }

    async fn list_themes_at_and_under_lineage(
        &self,
        lineage: ThemeLineage,
    ) -> CustomResult<Vec<storage::theme::Theme>, errors::StorageError> {
        self.diesel_store
            .list_themes_at_and_under_lineage(lineage)
            .await
    }
}

#[async_trait::async_trait]
#[cfg(feature = "v2")]
impl db::payment_method_session::PaymentMethodsSessionInterface for KafkaStore {
    async fn insert_payment_methods_session(
        &self,
        state: &KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        payment_methods_session: hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        validity: i64,
    ) -> CustomResult<(), errors::StorageError> {
        self.diesel_store
            .insert_payment_methods_session(state, key_store, payment_methods_session, validity)
            .await
    }

    async fn get_payment_methods_session(
        &self,
        state: &KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        id: &id_type::GlobalPaymentMethodSessionId,
    ) -> CustomResult<
        hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        errors::StorageError,
    > {
        self.diesel_store
            .get_payment_methods_session(state, key_store, id)
            .await
    }

    async fn update_payment_method_session(
        &self,
        state: &KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        id: &id_type::GlobalPaymentMethodSessionId,
        payment_methods_session: hyperswitch_domain_models::payment_methods::PaymentMethodsSessionUpdateEnum,
        current_session: hyperswitch_domain_models::payment_methods::PaymentMethodSession,
    ) -> CustomResult<
        hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        errors::StorageError,
    > {
        self.diesel_store
            .update_payment_method_session(
                state,
                key_store,
                id,
                payment_methods_session,
                current_session,
            )
            .await
    }
}

#[async_trait::async_trait]
#[cfg(feature = "v1")]
impl db::payment_method_session::PaymentMethodsSessionInterface for KafkaStore {}

#[async_trait::async_trait]
impl CallbackMapperInterface for KafkaStore {
    #[instrument(skip_all)]
    async fn insert_call_back_mapper(
        &self,
        call_back_mapper: domain::CallbackMapper,
    ) -> CustomResult<domain::CallbackMapper, errors::StorageError> {
        self.diesel_store
            .insert_call_back_mapper(call_back_mapper)
            .await
    }

    #[instrument(skip_all)]
    async fn find_call_back_mapper_by_id(
        &self,
        id: &str,
    ) -> CustomResult<domain::CallbackMapper, errors::StorageError> {
        self.diesel_store.find_call_back_mapper_by_id(id).await
    }
}

#[cfg(all(feature = "v2", feature = "tokenization_v2"))]
#[async_trait::async_trait]
impl TokenizationInterface for KafkaStore {
    async fn insert_tokenization(
        &self,
        tokenization: hyperswitch_domain_models::tokenization::Tokenization,
        merchant_key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        key_manager_state: &KeyManagerState,
    ) -> CustomResult<hyperswitch_domain_models::tokenization::Tokenization, errors::StorageError>
    {
        self.diesel_store
            .insert_tokenization(tokenization, merchant_key_store, key_manager_state)
            .await
    }

    async fn get_entity_id_vault_id_by_token_id(
        &self,
        token: &id_type::GlobalTokenId,
        merchant_key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        key_manager_state: &KeyManagerState,
    ) -> CustomResult<hyperswitch_domain_models::tokenization::Tokenization, errors::StorageError>
    {
        self.diesel_store
            .get_entity_id_vault_id_by_token_id(token, merchant_key_store, key_manager_state)
            .await
    }

    async fn update_tokenization_record(
        &self,
        tokenization: hyperswitch_domain_models::tokenization::Tokenization,
        tokenization_update: hyperswitch_domain_models::tokenization::TokenizationUpdate,
        merchant_key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        key_manager_state: &KeyManagerState,
    ) -> CustomResult<hyperswitch_domain_models::tokenization::Tokenization, errors::StorageError>
    {
        self.diesel_store
            .update_tokenization_record(
                tokenization,
                tokenization_update,
                merchant_key_store,
                key_manager_state,
            )
            .await
    }
}

#[cfg(not(all(feature = "v2", feature = "tokenization_v2")))]
impl TokenizationInterface for KafkaStore {}


// Struct: ThemeUpdateInternal
// File: crates/diesel_models/src/user/theme.rs
// Module: diesel_models
// Implementations: 0

pub struct ThemeUpdateInternal


// Function: get_evidence_request_data
// File: crates/router/src/core/disputes/transformers.rs
// Module: router

pub fn get_evidence_request_data(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    evidence_request: api_models::disputes::SubmitEvidenceRequest,
    dispute: &diesel_models::dispute::Dispute,
) -> CustomResult<SubmitEvidenceRequestData, errors::ApiErrorResponse>


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

impl api::Refund for for Itaubank


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

pub mod address;
pub mod api_keys;
pub mod authentication;
pub mod authorization;
pub mod blocklist;
pub mod blocklist_fingerprint;
pub mod blocklist_lookup;
pub mod business_profile;
pub mod callback_mapper;
pub mod capture;
pub mod cards_info;
pub mod configs;
pub mod customers;
pub mod dashboard_metadata;
pub mod dispute;
pub mod dynamic_routing_stats;
pub mod enums;
pub mod ephemeral_key;
pub mod events;
pub mod file;
pub mod fraud_check;
pub mod generic_link;
pub mod gsm;
pub mod hyperswitch_ai_interaction;
pub mod invoice;
#[cfg(feature = "kv_store")]
pub mod kv;
pub mod locker_mock_up;
pub mod mandate;
pub mod merchant_account;
pub mod merchant_connector_account;
pub mod merchant_key_store;
pub mod payment_attempt;
pub mod payment_link;
pub mod payment_method;
pub mod payout_attempt;
pub mod payouts;
pub mod refund;
#[cfg(feature = "v2")]
pub mod revenue_recovery;
#[cfg(feature = "v2")]
pub mod revenue_recovery_redis_operation;
pub mod reverse_lookup;
pub mod role;
pub mod routing_algorithm;
pub mod subscription;
pub mod unified_translations;
pub mod user;
pub mod user_authentication_method;
pub mod user_role;

pub use diesel_models::{
    process_tracker::business_status, ProcessTracker, ProcessTrackerNew, ProcessTrackerRunner,
    ProcessTrackerUpdate,
};
#[cfg(feature = "v1")]
pub use hyperswitch_domain_models::payments::payment_attempt::PaymentAttemptNew;
#[cfg(feature = "payouts")]
pub use hyperswitch_domain_models::payouts::{
    payout_attempt::{PayoutAttempt, PayoutAttemptNew, PayoutAttemptUpdate},
    payouts::{Payouts, PayoutsNew, PayoutsUpdate},
};
pub use hyperswitch_domain_models::{
    payments::{
        payment_attempt::{PaymentAttempt, PaymentAttemptUpdate},
        payment_intent::{PaymentIntentUpdate, PaymentIntentUpdateFields},
        PaymentIntent,
    },
    routing::{
        PaymentRoutingInfo, PaymentRoutingInfoInner, PreRoutingConnectorChoice, RoutingData,
    },
};
pub use scheduler::db::process_tracker;

pub use self::{
    address::*, api_keys::*, authentication::*, authorization::*, blocklist::*,
    blocklist_fingerprint::*, blocklist_lookup::*, business_profile::*, callback_mapper::*,
    capture::*, cards_info::*, configs::*, customers::*, dashboard_metadata::*, dispute::*,
    dynamic_routing_stats::*, ephemeral_key::*, events::*, file::*, fraud_check::*,
    generic_link::*, gsm::*, hyperswitch_ai_interaction::*, invoice::*, locker_mock_up::*,
    mandate::*, merchant_account::*, merchant_connector_account::*, merchant_key_store::*,
    payment_link::*, payment_method::*, process_tracker::*, refund::*, reverse_lookup::*, role::*,
    routing_algorithm::*, subscription::*, unified_translations::*, user::*,
    user_authentication_method::*, user_role::*,
};


// Struct: CardsInfoUpdateForm
// File: crates/router/src/core/cards_info.rs
// Module: router
// Implementations: 0

pub struct CardsInfoUpdateForm


// Implementation: impl Nmi
// File: crates/hyperswitch_connectors/src/connectors/nmi.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl Nmi


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

impl api::RefundSync for for Zsl


// Function: from_storage
// File: crates/router/src/services/kafka/payment_intent_event.rs
// Module: router

pub fn from_storage(intent: &'a PaymentIntent, infra_values: Option<Value>) -> Self


// Struct: BillwerkPaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/billwerk/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BillwerkPaymentsResponse


// Struct: NovalnetPaymentsRequest
// File: crates/hyperswitch_connectors/src/connectors/novalnet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NovalnetPaymentsRequest