// File: crates/router/src/db/relay.rs
// Module: router

use common_utils::types::keymanager::KeyManagerState;
use diesel_models;
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::behaviour::{Conversion, ReverseConversion};
use storage_impl::MockDb;

use super::domain;
use crate::{
    connection,
    core::errors::{self, CustomResult},
    db::kafka_store::KafkaStore,
    services::Store,
};

#[async_trait::async_trait]
pub trait RelayInterface {
    async fn insert_relay(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        new: hyperswitch_domain_models::relay::Relay,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError>;

    async fn update_relay(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        current_state: hyperswitch_domain_models::relay::Relay,
        relay_update: hyperswitch_domain_models::relay::RelayUpdate,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError>;

    async fn find_relay_by_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        relay_id: &common_utils::id_type::RelayId,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError>;

    async fn find_relay_by_profile_id_connector_reference_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        profile_id: &common_utils::id_type::ProfileId,
        connector_reference_id: &str,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError>;
}

#[async_trait::async_trait]
impl RelayInterface for Store {
    async fn insert_relay(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        new: hyperswitch_domain_models::relay::Relay,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        new.construct_new()
            .await
            .change_context(errors::StorageError::EncryptionError)?
            .insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))?
            .convert(
                key_manager_state,
                merchant_key_store.key.get_inner(),
                merchant_key_store.merchant_id.clone().into(),
            )
            .await
            .change_context(errors::StorageError::DecryptionError)
    }

    async fn update_relay(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        current_state: hyperswitch_domain_models::relay::Relay,
        relay_update: hyperswitch_domain_models::relay::RelayUpdate,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        Conversion::convert(current_state)
            .await
            .change_context(errors::StorageError::EncryptionError)?
            .update(
                &conn,
                diesel_models::relay::RelayUpdateInternal::from(relay_update),
            )
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))?
            .convert(
                key_manager_state,
                merchant_key_store.key.get_inner(),
                merchant_key_store.merchant_id.clone().into(),
            )
            .await
            .change_context(errors::StorageError::DecryptionError)
    }

    async fn find_relay_by_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        relay_id: &common_utils::id_type::RelayId,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        diesel_models::relay::Relay::find_by_id(&conn, relay_id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))?
            .convert(
                key_manager_state,
                merchant_key_store.key.get_inner(),
                merchant_key_store.merchant_id.clone().into(),
            )
            .await
            .change_context(errors::StorageError::DecryptionError)
    }

    async fn find_relay_by_profile_id_connector_reference_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        profile_id: &common_utils::id_type::ProfileId,
        connector_reference_id: &str,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        diesel_models::relay::Relay::find_by_profile_id_connector_reference_id(
            &conn,
            profile_id,
            connector_reference_id,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))?
        .convert(
            key_manager_state,
            merchant_key_store.key.get_inner(),
            merchant_key_store.merchant_id.clone().into(),
        )
        .await
        .change_context(errors::StorageError::DecryptionError)
    }
}

#[async_trait::async_trait]
impl RelayInterface for MockDb {
    async fn insert_relay(
        &self,
        _key_manager_state: &KeyManagerState,
        _merchant_key_store: &domain::MerchantKeyStore,
        _new: hyperswitch_domain_models::relay::Relay,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn update_relay(
        &self,
        _key_manager_state: &KeyManagerState,
        _merchant_key_store: &domain::MerchantKeyStore,
        _current_state: hyperswitch_domain_models::relay::Relay,
        _relay_update: hyperswitch_domain_models::relay::RelayUpdate,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn find_relay_by_id(
        &self,
        _key_manager_state: &KeyManagerState,
        _merchant_key_store: &domain::MerchantKeyStore,
        _relay_id: &common_utils::id_type::RelayId,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn find_relay_by_profile_id_connector_reference_id(
        &self,
        _key_manager_state: &KeyManagerState,
        _merchant_key_store: &domain::MerchantKeyStore,
        _profile_id: &common_utils::id_type::ProfileId,
        _connector_reference_id: &str,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }
}

#[async_trait::async_trait]
impl RelayInterface for KafkaStore {
    async fn insert_relay(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        new: hyperswitch_domain_models::relay::Relay,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        self.diesel_store
            .insert_relay(key_manager_state, merchant_key_store, new)
            .await
    }

    async fn update_relay(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        current_state: hyperswitch_domain_models::relay::Relay,
        relay_update: hyperswitch_domain_models::relay::RelayUpdate,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        self.diesel_store
            .update_relay(
                key_manager_state,
                merchant_key_store,
                current_state,
                relay_update,
            )
            .await
    }

    async fn find_relay_by_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        relay_id: &common_utils::id_type::RelayId,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        self.diesel_store
            .find_relay_by_id(key_manager_state, merchant_key_store, relay_id)
            .await
    }

    async fn find_relay_by_profile_id_connector_reference_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        profile_id: &common_utils::id_type::ProfileId,
        connector_reference_id: &str,
    ) -> CustomResult<hyperswitch_domain_models::relay::Relay, errors::StorageError> {
        self.diesel_store
            .find_relay_by_profile_id_connector_reference_id(
                key_manager_state,
                merchant_key_store,
                profile_id,
                connector_reference_id,
            )
            .await
    }
}


// Struct: JWTAuth
// File: crates/router/src/services/authentication.rs
// Module: router
// Implementations: 0

pub struct JWTAuth


// Struct: TsysPaymentsSyncResponse
// File: crates/hyperswitch_connectors/src/connectors/tsys/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TsysPaymentsSyncResponse


// Struct: PaymentMethodIntentConfirm
// File: crates/api_models/src/payment_methods.rs
// Module: api_models
// Implementations: 1

pub struct PaymentMethodIntentConfirm


// Implementation: impl ConnectorCommon for for Boku
// File: crates/hyperswitch_connectors/src/connectors/boku.rs
// Module: hyperswitch_connectors
// Methods: 4 total (0 public)

impl ConnectorCommon for for Boku


// Struct: ArchipelIncrementalAuthorizationRequest
// File: crates/hyperswitch_connectors/src/connectors/archipel/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ArchipelIncrementalAuthorizationRequest


// File: crates/router/src/db/dispute.rs
// Module: router
// Public structs: 1

use std::collections::HashMap;

use error_stack::report;
use hyperswitch_domain_models::disputes;
use router_env::{instrument, tracing};

use super::{MockDb, Store};
use crate::{
    connection,
    core::errors::{self, CustomResult},
    types::storage::{self, DisputeDbExt},
};

#[async_trait::async_trait]
pub trait DisputeInterface {
    async fn insert_dispute(
        &self,
        dispute: storage::DisputeNew,
    ) -> CustomResult<storage::Dispute, errors::StorageError>;

    async fn find_by_merchant_id_payment_id_connector_dispute_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
        connector_dispute_id: &str,
    ) -> CustomResult<Option<storage::Dispute>, errors::StorageError>;

    async fn find_dispute_by_merchant_id_dispute_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        dispute_id: &str,
    ) -> CustomResult<storage::Dispute, errors::StorageError>;

    async fn find_disputes_by_constraints(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        dispute_constraints: &disputes::DisputeListConstraints,
    ) -> CustomResult<Vec<storage::Dispute>, errors::StorageError>;

    async fn find_disputes_by_merchant_id_payment_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
    ) -> CustomResult<Vec<storage::Dispute>, errors::StorageError>;

    async fn update_dispute(
        &self,
        this: storage::Dispute,
        dispute: storage::DisputeUpdate,
    ) -> CustomResult<storage::Dispute, errors::StorageError>;

    async fn get_dispute_status_with_count(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
        time_range: &common_utils::types::TimeRange,
    ) -> CustomResult<Vec<(common_enums::enums::DisputeStatus, i64)>, errors::StorageError>;
}

#[async_trait::async_trait]
impl DisputeInterface for Store {
    #[instrument(skip_all)]
    async fn insert_dispute(
        &self,
        dispute: storage::DisputeNew,
    ) -> CustomResult<storage::Dispute, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        dispute
            .insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn find_by_merchant_id_payment_id_connector_dispute_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
        connector_dispute_id: &str,
    ) -> CustomResult<Option<storage::Dispute>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::Dispute::find_by_merchant_id_payment_id_connector_dispute_id(
            &conn,
            merchant_id,
            payment_id,
            connector_dispute_id,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn find_dispute_by_merchant_id_dispute_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        dispute_id: &str,
    ) -> CustomResult<storage::Dispute, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::Dispute::find_by_merchant_id_dispute_id(&conn, merchant_id, dispute_id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn find_disputes_by_constraints(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        dispute_constraints: &disputes::DisputeListConstraints,
    ) -> CustomResult<Vec<storage::Dispute>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::Dispute::filter_by_constraints(&conn, merchant_id, dispute_constraints)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn find_disputes_by_merchant_id_payment_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
    ) -> CustomResult<Vec<storage::Dispute>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::Dispute::find_by_merchant_id_payment_id(&conn, merchant_id, payment_id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn update_dispute(
        &self,
        this: storage::Dispute,
        dispute: storage::DisputeUpdate,
    ) -> CustomResult<storage::Dispute, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        this.update(&conn, dispute)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn get_dispute_status_with_count(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
        time_range: &common_utils::types::TimeRange,
    ) -> CustomResult<Vec<(common_enums::DisputeStatus, i64)>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::Dispute::get_dispute_status_with_count(
            &conn,
            merchant_id,
            profile_id_list,
            time_range,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl DisputeInterface for MockDb {
    async fn insert_dispute(
        &self,
        dispute: storage::DisputeNew,
    ) -> CustomResult<storage::Dispute, errors::StorageError> {
        let evidence = dispute.evidence.ok_or(errors::StorageError::MockDbError)?;

        let mut locked_disputes = self.disputes.lock().await;

        if locked_disputes
            .iter()
            .any(|d| d.dispute_id == dispute.dispute_id)
        {
            Err(errors::StorageError::MockDbError)?;
        }

        let now = common_utils::date_time::now();

        let new_dispute = storage::Dispute {
            dispute_id: dispute.dispute_id,
            amount: dispute.amount,
            currency: dispute.currency,
            dispute_stage: dispute.dispute_stage,
            dispute_status: dispute.dispute_status,
            payment_id: dispute.payment_id,
            attempt_id: dispute.attempt_id,
            merchant_id: dispute.merchant_id,
            connector_status: dispute.connector_status,
            connector_dispute_id: dispute.connector_dispute_id,
            connector_reason: dispute.connector_reason,
            connector_reason_code: dispute.connector_reason_code,
            challenge_required_by: dispute.challenge_required_by,
            connector_created_at: dispute.connector_created_at,
            connector_updated_at: dispute.connector_updated_at,
            created_at: now,
            modified_at: now,
            connector: dispute.connector,
            profile_id: dispute.profile_id,
            evidence,
            merchant_connector_id: dispute.merchant_connector_id,
            dispute_amount: dispute.dispute_amount,
            organization_id: dispute.organization_id,
            dispute_currency: dispute.dispute_currency,
        };

        locked_disputes.push(new_dispute.clone());

        Ok(new_dispute)
    }
    async fn find_by_merchant_id_payment_id_connector_dispute_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
        connector_dispute_id: &str,
    ) -> CustomResult<Option<storage::Dispute>, errors::StorageError> {
        Ok(self
            .disputes
            .lock()
            .await
            .iter()
            .find(|d| {
                d.merchant_id == *merchant_id
                    && d.payment_id == *payment_id
                    && d.connector_dispute_id == connector_dispute_id
            })
            .cloned())
    }

    async fn find_dispute_by_merchant_id_dispute_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        dispute_id: &str,
    ) -> CustomResult<storage::Dispute, errors::StorageError> {
        let locked_disputes = self.disputes.lock().await;

        locked_disputes
            .iter()
            .find(|d| d.merchant_id == *merchant_id && d.dispute_id == dispute_id)
            .cloned()
            .ok_or(errors::StorageError::ValueNotFound(format!("No dispute available for merchant_id = {merchant_id:?} and dispute_id = {dispute_id}"))
            .into())
    }

    async fn find_disputes_by_constraints(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        dispute_constraints: &disputes::DisputeListConstraints,
    ) -> CustomResult<Vec<storage::Dispute>, errors::StorageError> {
        let locked_disputes = self.disputes.lock().await;
        let limit_usize = dispute_constraints
            .limit
            .unwrap_or(u32::MAX)
            .try_into()
            .unwrap_or(usize::MAX);
        let offset_usize = dispute_constraints
            .offset
            .unwrap_or(0)
            .try_into()
            .unwrap_or(usize::MIN);
        let filtered_disputes: Vec<storage::Dispute> = locked_disputes
            .iter()
            .filter(|dispute| {
                dispute.merchant_id == *merchant_id
                    && dispute_constraints
                        .dispute_id
                        .as_ref()
                        .is_none_or(|id| &dispute.dispute_id == id)
                    && dispute_constraints
                        .payment_id
                        .as_ref()
                        .is_none_or(|id| &dispute.payment_id == id)
                    && dispute_constraints
                        .profile_id
                        .as_ref()
                        .is_none_or(|profile_ids| {
                            dispute
                                .profile_id
                                .as_ref()
                                .is_none_or(|id| profile_ids.contains(id))
                        })
                    && dispute_constraints
                        .dispute_status
                        .as_ref()
                        .is_none_or(|statuses| statuses.contains(&dispute.dispute_status))
                    && dispute_constraints
                        .dispute_stage
                        .as_ref()
                        .is_none_or(|stages| stages.contains(&dispute.dispute_stage))
                    && dispute_constraints.reason.as_ref().is_none_or(|reason| {
                        dispute
                            .connector_reason
                            .as_ref()
                            .is_none_or(|d_reason| d_reason == reason)
                    })
                    && dispute_constraints
                        .connector
                        .as_ref()
                        .is_none_or(|connectors| {
                            connectors
                                .iter()
                                .any(|connector| dispute.connector.as_str() == *connector)
                        })
                    && dispute_constraints
                        .merchant_connector_id
                        .as_ref()
                        .is_none_or(|id| dispute.merchant_connector_id.as_ref() == Some(id))
                    && dispute_constraints
                        .currency
                        .as_ref()
                        .is_none_or(|currencies| {
                            currencies.iter().any(|currency| {
                                dispute
                                    .dispute_currency
                                    .map(|dispute_currency| &dispute_currency == currency)
                                    .unwrap_or(dispute.currency.as_str() == currency.to_string())
                            })
                        })
                    && dispute_constraints.time_range.as_ref().is_none_or(|range| {
                        let dispute_time = dispute.created_at;
                        dispute_time >= range.start_time
                            && range
                                .end_time
                                .is_none_or(|end_time| dispute_time <= end_time)
                    })
            })
            .skip(offset_usize)
            .take(limit_usize)
            .cloned()
            .collect();

        Ok(filtered_disputes)
    }

    async fn find_disputes_by_merchant_id_payment_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
    ) -> CustomResult<Vec<storage::Dispute>, errors::StorageError> {
        let locked_disputes = self.disputes.lock().await;

        Ok(locked_disputes
            .iter()
            .filter(|d| d.merchant_id == *merchant_id && d.payment_id == *payment_id)
            .cloned()
            .collect())
    }

    async fn update_dispute(
        &self,
        this: storage::Dispute,
        dispute: storage::DisputeUpdate,
    ) -> CustomResult<storage::Dispute, errors::StorageError> {
        let mut locked_disputes = self.disputes.lock().await;

        let dispute_to_update = locked_disputes
            .iter_mut()
            .find(|d| d.dispute_id == this.dispute_id)
            .ok_or(errors::StorageError::MockDbError)?;

        let now = common_utils::date_time::now();

        match dispute {
            storage::DisputeUpdate::Update {
                dispute_stage,
                dispute_status,
                connector_status,
                connector_reason,
                connector_reason_code,
                challenge_required_by,
                connector_updated_at,
            } => {
                if connector_reason.is_some() {
                    dispute_to_update.connector_reason = connector_reason;
                }

                if connector_reason_code.is_some() {
                    dispute_to_update.connector_reason_code = connector_reason_code;
                }

                if challenge_required_by.is_some() {
                    dispute_to_update.challenge_required_by = challenge_required_by;
                }

                if connector_updated_at.is_some() {
                    dispute_to_update.connector_updated_at = connector_updated_at;
                }

                dispute_to_update.dispute_stage = dispute_stage;
                dispute_to_update.dispute_status = dispute_status;
                dispute_to_update.connector_status = connector_status;
            }
            storage::DisputeUpdate::StatusUpdate {
                dispute_status,
                connector_status,
            } => {
                if let Some(status) = connector_status {
                    dispute_to_update.connector_status = status;
                }
                dispute_to_update.dispute_status = dispute_status;
            }
            storage::DisputeUpdate::EvidenceUpdate { evidence } => {
                dispute_to_update.evidence = evidence;
            }
        }

        dispute_to_update.modified_at = now;

        Ok(dispute_to_update.clone())
    }

    async fn get_dispute_status_with_count(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
        time_range: &common_utils::types::TimeRange,
    ) -> CustomResult<Vec<(common_enums::DisputeStatus, i64)>, errors::StorageError> {
        let locked_disputes = self.disputes.lock().await;

        let filtered_disputes_data = locked_disputes
            .iter()
            .filter(|d| {
                d.merchant_id == *merchant_id
                    && d.created_at >= time_range.start_time
                    && time_range
                        .end_time
                        .as_ref()
                        .is_none_or(|received_end_time| received_end_time >= &d.created_at)
                    && profile_id_list
                        .as_ref()
                        .zip(d.profile_id.as_ref())
                        .is_none_or(|(received_profile_list, received_profile_id)| {
                            received_profile_list.contains(received_profile_id)
                        })
            })
            .cloned()
            .collect::<Vec<storage::Dispute>>();

        Ok(filtered_disputes_data
            .into_iter()
            .fold(
                HashMap::new(),
                |mut acc: HashMap<common_enums::DisputeStatus, i64>, value| {
                    acc.entry(value.dispute_status)
                        .and_modify(|value| *value += 1)
                        .or_insert(1);
                    acc
                },
            )
            .into_iter()
            .collect::<Vec<(common_enums::DisputeStatus, i64)>>())
    }
}

#[cfg(test)]
mod tests {
    #![allow(clippy::expect_used, clippy::unwrap_used)]
    mod mockdb_dispute_interface {
        use std::borrow::Cow;

        use common_enums::enums::Currency;
        use common_utils::types::{AmountConvertor, MinorUnit, StringMinorUnitForConnector};
        use diesel_models::{
            dispute::DisputeNew,
            enums::{DisputeStage, DisputeStatus},
        };
        use hyperswitch_domain_models::disputes::DisputeListConstraints;
        use masking::Secret;
        use redis_interface::RedisSettings;
        use serde_json::Value;
        use time::macros::datetime;

        use crate::db::{dispute::DisputeInterface, MockDb};

        pub struct DisputeNewIds {
            dispute_id: String,
            payment_id: common_utils::id_type::PaymentId,
            attempt_id: String,
            merchant_id: common_utils::id_type::MerchantId,
            connector_dispute_id: String,
        }

        fn create_dispute_new(dispute_ids: DisputeNewIds) -> DisputeNew {
            DisputeNew {
                dispute_id: dispute_ids.dispute_id,
                amount: StringMinorUnitForConnector::convert(
                    &StringMinorUnitForConnector,
                    MinorUnit::new(0),
                    Currency::USD,
                )
                .expect("Amount Conversion Error"),
                currency: "currency".into(),
                dispute_stage: DisputeStage::Dispute,
                dispute_status: DisputeStatus::DisputeOpened,
                payment_id: dispute_ids.payment_id,
                attempt_id: dispute_ids.attempt_id,
                merchant_id: dispute_ids.merchant_id,
                connector_status: "connector_status".into(),
                connector_dispute_id: dispute_ids.connector_dispute_id,
                connector_reason: Some("connector_reason".into()),
                connector_reason_code: Some("connector_reason_code".into()),
                challenge_required_by: Some(datetime!(2019-01-01 0:00)),
                connector_created_at: Some(datetime!(2019-01-02 0:00)),
                connector_updated_at: Some(datetime!(2019-01-03 0:00)),
                connector: "connector".into(),
                evidence: Some(Secret::from(Value::String("evidence".into()))),
                profile_id: Some(common_utils::generate_profile_id_of_default_length()),
                merchant_connector_id: None,
                dispute_amount: MinorUnit::new(1040),
                organization_id: common_utils::id_type::OrganizationId::default(),
                dispute_currency: Some(Currency::default()),
            }
        }

        #[tokio::test]
        async fn test_insert_dispute() {
            let mockdb = MockDb::new(&RedisSettings::default())
                .await
                .expect("Failed to create a mock DB");

            let merchant_id =
                common_utils::id_type::MerchantId::try_from(Cow::from("merchant_1")).unwrap();

            let created_dispute = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_1".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: common_utils::id_type::PaymentId::try_from(Cow::Borrowed(
                        "payment_1",
                    ))
                    .unwrap(),
                    connector_dispute_id: "connector_dispute_1".into(),
                }))
                .await
                .unwrap();

            let found_dispute = mockdb
                .disputes
                .lock()
                .await
                .iter()
                .find(|d| d.dispute_id == created_dispute.dispute_id)
                .cloned();

            assert!(found_dispute.is_some());

            assert_eq!(created_dispute, found_dispute.unwrap());
        }

        #[tokio::test]
        async fn test_find_by_merchant_id_payment_id_connector_dispute_id() {
            let merchant_id =
                common_utils::id_type::MerchantId::try_from(Cow::from("merchant_1")).unwrap();

            let mockdb = MockDb::new(&RedisSettings::default())
                .await
                .expect("Failed to create Mock store");

            let created_dispute = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_1".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: common_utils::id_type::PaymentId::try_from(Cow::Borrowed(
                        "payment_1",
                    ))
                    .unwrap(),
                    connector_dispute_id: "connector_dispute_1".into(),
                }))
                .await
                .unwrap();

            let _ = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_2".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: common_utils::id_type::PaymentId::try_from(Cow::Borrowed(
                        "payment_1",
                    ))
                    .unwrap(),
                    connector_dispute_id: "connector_dispute_2".into(),
                }))
                .await
                .unwrap();

            let found_dispute = mockdb
                .find_by_merchant_id_payment_id_connector_dispute_id(
                    &merchant_id,
                    &common_utils::id_type::PaymentId::try_from(Cow::Borrowed("payment_1"))
                        .unwrap(),
                    "connector_dispute_1",
                )
                .await
                .unwrap();

            assert!(found_dispute.is_some());

            assert_eq!(created_dispute, found_dispute.unwrap());
        }

        #[tokio::test]
        async fn test_find_dispute_by_merchant_id_dispute_id() {
            let merchant_id =
                common_utils::id_type::MerchantId::try_from(Cow::from("merchant_1")).unwrap();

            let payment_id =
                common_utils::id_type::PaymentId::try_from(Cow::Borrowed("payment_1")).unwrap();

            let mockdb = MockDb::new(&RedisSettings::default())
                .await
                .expect("Failed to create Mock store");

            let created_dispute = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_1".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: payment_id.clone(),
                    connector_dispute_id: "connector_dispute_1".into(),
                }))
                .await
                .unwrap();

            let _ = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_2".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: payment_id.clone(),
                    connector_dispute_id: "connector_dispute_1".into(),
                }))
                .await
                .unwrap();

            let found_dispute = mockdb
                .find_dispute_by_merchant_id_dispute_id(&merchant_id, "dispute_1")
                .await
                .unwrap();

            assert_eq!(created_dispute, found_dispute);
        }

        #[tokio::test]
        async fn test_find_disputes_by_merchant_id() {
            let merchant_id =
                common_utils::id_type::MerchantId::try_from(Cow::from("merchant_2")).unwrap();

            let payment_id =
                common_utils::id_type::PaymentId::try_from(Cow::Borrowed("payment_1")).unwrap();

            let mockdb = MockDb::new(&RedisSettings::default())
                .await
                .expect("Failed to create Mock store");

            let created_dispute = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_1".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: payment_id.clone(),
                    connector_dispute_id: "connector_dispute_1".into(),
                }))
                .await
                .unwrap();

            let _ = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_2".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: payment_id.clone(),
                    connector_dispute_id: "connector_dispute_1".into(),
                }))
                .await
                .unwrap();

            let found_disputes = mockdb
                .find_disputes_by_constraints(
                    &merchant_id,
                    &DisputeListConstraints {
                        dispute_id: None,
                        payment_id: None,
                        profile_id: None,
                        connector: None,
                        merchant_connector_id: None,
                        currency: None,
                        limit: None,
                        offset: None,
                        dispute_status: None,
                        dispute_stage: None,
                        reason: None,
                        time_range: None,
                    },
                )
                .await
                .unwrap();

            assert_eq!(1, found_disputes.len());

            assert_eq!(created_dispute, found_disputes.first().unwrap().clone());
        }

        #[tokio::test]
        async fn test_find_disputes_by_merchant_id_payment_id() {
            let merchant_id =
                common_utils::id_type::MerchantId::try_from(Cow::from("merchant_1")).unwrap();

            let payment_id =
                common_utils::id_type::PaymentId::try_from(Cow::Borrowed("payment_1")).unwrap();

            let mockdb = MockDb::new(&RedisSettings::default())
                .await
                .expect("Failed to create Mock store");

            let created_dispute = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_1".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: payment_id.clone(),
                    connector_dispute_id: "connector_dispute_1".into(),
                }))
                .await
                .unwrap();

            let _ = mockdb
                .insert_dispute(create_dispute_new(DisputeNewIds {
                    dispute_id: "dispute_2".into(),
                    attempt_id: "attempt_1".into(),
                    merchant_id: merchant_id.clone(),
                    payment_id: payment_id.clone(),
                    connector_dispute_id: "connector_dispute_1".into(),
                }))
                .await
                .unwrap();

            let found_disputes = mockdb
                .find_disputes_by_merchant_id_payment_id(&merchant_id, &payment_id)
                .await
                .unwrap();

            assert_eq!(1, found_disputes.len());

            assert_eq!(created_dispute, found_disputes.first().unwrap().clone());
        }

        mod update_dispute {
            use std::borrow::Cow;

            use diesel_models::{
                dispute::DisputeUpdate,
                enums::{DisputeStage, DisputeStatus},
            };
            use masking::Secret;
            use serde_json::Value;
            use time::macros::datetime;

            use crate::db::{
                dispute::{
                    tests::mockdb_dispute_interface::{create_dispute_new, DisputeNewIds},
                    DisputeInterface,
                },
                MockDb,
            };

            #[tokio::test]
            async fn test_update_dispute_update() {
                let merchant_id =
                    common_utils::id_type::MerchantId::try_from(Cow::from("merchant_1")).unwrap();

                let payment_id =
                    common_utils::id_type::PaymentId::try_from(Cow::Borrowed("payment_1")).unwrap();

                let mockdb = MockDb::new(&redis_interface::RedisSettings::default())
                    .await
                    .expect("Failed to create Mock store");

                let created_dispute = mockdb
                    .insert_dispute(create_dispute_new(DisputeNewIds {
                        dispute_id: "dispute_1".into(),
                        attempt_id: "attempt_1".into(),
                        merchant_id: merchant_id.clone(),
                        payment_id: payment_id.clone(),
                        connector_dispute_id: "connector_dispute_1".into(),
                    }))
                    .await
                    .unwrap();

                let updated_dispute = mockdb
                    .update_dispute(
                        created_dispute.clone(),
                        DisputeUpdate::Update {
                            dispute_stage: DisputeStage::PreDispute,
                            dispute_status: DisputeStatus::DisputeAccepted,
                            connector_status: "updated_connector_status".into(),
                            connector_reason: Some("updated_connector_reason".into()),
                            connector_reason_code: Some("updated_connector_reason_code".into()),
                            challenge_required_by: Some(datetime!(2019-01-10 0:00)),
                            connector_updated_at: Some(datetime!(2019-01-11 0:00)),
                        },
                    )
                    .await
                    .unwrap();

                assert_eq!(created_dispute.dispute_id, updated_dispute.dispute_id);
                assert_eq!(created_dispute.amount, updated_dispute.amount);
                assert_eq!(created_dispute.currency, updated_dispute.currency);
                assert_ne!(created_dispute.dispute_stage, updated_dispute.dispute_stage);
                assert_ne!(
                    created_dispute.dispute_status,
                    updated_dispute.dispute_status
                );
                assert_eq!(created_dispute.payment_id, updated_dispute.payment_id);
                assert_eq!(created_dispute.attempt_id, updated_dispute.attempt_id);
                assert_eq!(created_dispute.merchant_id, updated_dispute.merchant_id);
                assert_ne!(
                    created_dispute.connector_status,
                    updated_dispute.connector_status
                );
                assert_eq!(
                    created_dispute.connector_dispute_id,
                    updated_dispute.connector_dispute_id
                );
                assert_ne!(
                    created_dispute.connector_reason,
                    updated_dispute.connector_reason
                );
                assert_ne!(
                    created_dispute.connector_reason_code,
                    updated_dispute.connector_reason_code
                );
                assert_ne!(
                    created_dispute.challenge_required_by,
                    updated_dispute.challenge_required_by
                );
                assert_eq!(
                    created_dispute.connector_created_at,
                    updated_dispute.connector_created_at
                );
                assert_ne!(
                    created_dispute.connector_updated_at,
                    updated_dispute.connector_updated_at
                );
                assert_eq!(created_dispute.created_at, updated_dispute.created_at);
                assert_ne!(created_dispute.modified_at, updated_dispute.modified_at);
                assert_eq!(created_dispute.connector, updated_dispute.connector);
                assert_eq!(created_dispute.evidence, updated_dispute.evidence);
            }

            #[tokio::test]
            async fn test_update_dispute_update_status() {
                let merchant_id =
                    common_utils::id_type::MerchantId::try_from(Cow::from("merchant_1")).unwrap();

                let payment_id =
                    common_utils::id_type::PaymentId::try_from(Cow::Borrowed("payment_1")).unwrap();

                let mockdb = MockDb::new(&redis_interface::RedisSettings::default())
                    .await
                    .expect("Failed to create Mock store");

                let created_dispute = mockdb
                    .insert_dispute(create_dispute_new(DisputeNewIds {
                        dispute_id: "dispute_1".into(),
                        attempt_id: "attempt_1".into(),
                        merchant_id: merchant_id.clone(),
                        payment_id: payment_id.clone(),
                        connector_dispute_id: "connector_dispute_1".into(),
                    }))
                    .await
                    .unwrap();

                let updated_dispute = mockdb
                    .update_dispute(
                        created_dispute.clone(),
                        DisputeUpdate::StatusUpdate {
                            dispute_status: DisputeStatus::DisputeExpired,
                            connector_status: Some("updated_connector_status".into()),
                        },
                    )
                    .await
                    .unwrap();

                assert_eq!(created_dispute.dispute_id, updated_dispute.dispute_id);
                assert_eq!(created_dispute.amount, updated_dispute.amount);
                assert_eq!(created_dispute.currency, updated_dispute.currency);
                assert_eq!(created_dispute.dispute_stage, updated_dispute.dispute_stage);
                assert_ne!(
                    created_dispute.dispute_status,
                    updated_dispute.dispute_status
                );
                assert_eq!(created_dispute.payment_id, updated_dispute.payment_id);
                assert_eq!(created_dispute.attempt_id, updated_dispute.attempt_id);
                assert_eq!(created_dispute.merchant_id, updated_dispute.merchant_id);
                assert_ne!(
                    created_dispute.connector_status,
                    updated_dispute.connector_status
                );
                assert_eq!(
                    created_dispute.connector_dispute_id,
                    updated_dispute.connector_dispute_id
                );
                assert_eq!(
                    created_dispute.connector_reason,
                    updated_dispute.connector_reason
                );
                assert_eq!(
                    created_dispute.connector_reason_code,
                    updated_dispute.connector_reason_code
                );
                assert_eq!(
                    created_dispute.challenge_required_by,
                    updated_dispute.challenge_required_by
                );
                assert_eq!(
                    created_dispute.connector_created_at,
                    updated_dispute.connector_created_at
                );
                assert_eq!(
                    created_dispute.connector_updated_at,
                    updated_dispute.connector_updated_at
                );
                assert_eq!(created_dispute.created_at, updated_dispute.created_at);
                assert_ne!(created_dispute.modified_at, updated_dispute.modified_at);
                assert_eq!(created_dispute.connector, updated_dispute.connector);
                assert_eq!(created_dispute.evidence, updated_dispute.evidence);
            }

            #[tokio::test]
            async fn test_update_dispute_update_evidence() {
                let merchant_id =
                    common_utils::id_type::MerchantId::try_from(Cow::from("merchant_1")).unwrap();

                let payment_id =
                    common_utils::id_type::PaymentId::try_from(Cow::Borrowed("payment_1")).unwrap();

                let mockdb = MockDb::new(&redis_interface::RedisSettings::default())
                    .await
                    .expect("Failed to create Mock store");

                let created_dispute = mockdb
                    .insert_dispute(create_dispute_new(DisputeNewIds {
                        dispute_id: "dispute_1".into(),
                        attempt_id: "attempt_1".into(),
                        merchant_id: merchant_id.clone(),
                        payment_id: payment_id.clone(),
                        connector_dispute_id: "connector_dispute_1".into(),
                    }))
                    .await
                    .unwrap();

                let updated_dispute = mockdb
                    .update_dispute(
                        created_dispute.clone(),
                        DisputeUpdate::EvidenceUpdate {
                            evidence: Secret::from(Value::String("updated_evidence".into())),
                        },
                    )
                    .await
                    .unwrap();

                assert_eq!(created_dispute.dispute_id, updated_dispute.dispute_id);
                assert_eq!(created_dispute.amount, updated_dispute.amount);
                assert_eq!(created_dispute.currency, updated_dispute.currency);
                assert_eq!(created_dispute.dispute_stage, updated_dispute.dispute_stage);
                assert_eq!(
                    created_dispute.dispute_status,
                    updated_dispute.dispute_status
                );
                assert_eq!(created_dispute.payment_id, updated_dispute.payment_id);
                assert_eq!(created_dispute.attempt_id, updated_dispute.attempt_id);
                assert_eq!(created_dispute.merchant_id, updated_dispute.merchant_id);
                assert_eq!(
                    created_dispute.connector_status,
                    updated_dispute.connector_status
                );
                assert_eq!(
                    created_dispute.connector_dispute_id,
                    updated_dispute.connector_dispute_id
                );
                assert_eq!(
                    created_dispute.connector_reason,
                    updated_dispute.connector_reason
                );
                assert_eq!(
                    created_dispute.connector_reason_code,
                    updated_dispute.connector_reason_code
                );
                assert_eq!(
                    created_dispute.challenge_required_by,
                    updated_dispute.challenge_required_by
                );
                assert_eq!(
                    created_dispute.connector_created_at,
                    updated_dispute.connector_created_at
                );
                assert_eq!(
                    created_dispute.connector_updated_at,
                    updated_dispute.connector_updated_at
                );
                assert_eq!(created_dispute.created_at, updated_dispute.created_at);
                assert_ne!(created_dispute.modified_at, updated_dispute.modified_at);
                assert_eq!(created_dispute.connector, updated_dispute.connector);
                assert_ne!(created_dispute.evidence, updated_dispute.evidence);
            }
        }
    }
}


// Implementation: impl Parse for for DieselEnumMeta
// File: crates/router_derive/src/macros/diesel.rs
// Module: router_derive
// Methods: 1 total (0 public)

impl Parse for for DieselEnumMeta


// Function: update_by_unified_code_unified_message_locale
// File: crates/diesel_models/src/query/unified_translations.rs
// Module: diesel_models

pub fn update_by_unified_code_unified_message_locale(
        conn: &PgPooledConn,
        unified_code: String,
        unified_message: String,
        locale: String,
        data: UnifiedTranslationsUpdate,
    ) -> StorageResult<Self>


// Struct: StripePaymentIntentRequest
// File: crates/router/src/compatibility/stripe/payment_intents/types.rs
// Module: router
// Implementations: 0

pub struct StripePaymentIntentRequest


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

impl IncomingWebhook for for Payu


// Function: generate_sample_data_for_user
// File: crates/router/src/core/user/sample_data.rs
// Module: router

pub fn generate_sample_data_for_user(
    state: SessionState,
    user_from_token: UserFromToken,
    req: SampleDataRequest,
    _req_state: ReqState,
) -> SampleDataApiResponse<()>


// Function: find_connector_ids
// File: crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs
// Module: hyperswitch_connectors

pub fn find_connector_ids(&self) -> Result<ChargebeeMandateDetails, errors::ConnectorError>


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

use async_bb8_diesel::AsyncRunQueryDsl;
use common_utils::errors::CustomResult;
use diesel::{associations::HasTable, ExpressionMethods, QueryDsl};
pub use diesel_models::mandate::{
    Mandate, MandateNew, MandateUpdate, MandateUpdateInternal, SingleUseMandate,
};
use diesel_models::{errors, schema::mandate::dsl};
use error_stack::ResultExt;

use crate::{connection::PgPooledConn, logger};

#[async_trait::async_trait]
pub trait MandateDbExt: Sized {
    async fn filter_by_constraints(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        mandate_list_constraints: api_models::mandates::MandateListConstraints,
    ) -> CustomResult<Vec<Self>, errors::DatabaseError>;
}

#[async_trait::async_trait]
impl MandateDbExt for Mandate {
    async fn filter_by_constraints(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        mandate_list_constraints: api_models::mandates::MandateListConstraints,
    ) -> CustomResult<Vec<Self>, errors::DatabaseError> {
        let mut filter = <Self as HasTable>::table()
            .filter(dsl::merchant_id.eq(merchant_id.to_owned()))
            .order(dsl::created_at.desc())
            .into_boxed();

        if let Some(created_time) = mandate_list_constraints.created_time {
            filter = filter.filter(dsl::created_at.eq(created_time));
        }
        if let Some(created_time_lt) = mandate_list_constraints.created_time_lt {
            filter = filter.filter(dsl::created_at.lt(created_time_lt));
        }
        if let Some(created_time_gt) = mandate_list_constraints.created_time_gt {
            filter = filter.filter(dsl::created_at.gt(created_time_gt));
        }
        if let Some(created_time_lte) = mandate_list_constraints.created_time_lte {
            filter = filter.filter(dsl::created_at.le(created_time_lte));
        }
        if let Some(created_time_gte) = mandate_list_constraints.created_time_gte {
            filter = filter.filter(dsl::created_at.ge(created_time_gte));
        }
        if let Some(connector) = mandate_list_constraints.connector {
            filter = filter.filter(dsl::connector.eq(connector));
        }
        if let Some(mandate_status) = mandate_list_constraints.mandate_status {
            filter = filter.filter(dsl::mandate_status.eq(mandate_status));
        }
        if let Some(limit) = mandate_list_constraints.limit {
            filter = filter.limit(limit);
        }
        if let Some(offset) = mandate_list_constraints.offset {
            filter = filter.offset(offset);
        }

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

        filter
            .get_results_async(conn)
            .await
            // The query built here returns an empty Vec when no records are found, and if any error does occur,
            // it would be an internal database error, due to which we are raising a DatabaseError::Unknown error
            .change_context(errors::DatabaseError::Others)
            .attach_printable("Error filtering mandates by specified constraints")
    }
}


// Struct: NexixpayPaymentsRequest
// File: crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NexixpayPaymentsRequest


// Function: is_jwt_auth
// File: crates/router/src/services/authentication.rs
// Module: router

pub fn is_jwt_auth(headers: &HeaderMap) -> bool


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

pub fn construct_public_and_private_db_configs(
    state: &SessionState,
    auth_config: &user_api::AuthConfig,
    encryption_key: &[u8],
    id: String,
) -> UserResult<(Option<Encryption>, Option<serde_json::Value>)>


// File: crates/router/src/db/customers.rs
// Module: router

pub use hyperswitch_domain_models::customer::{CustomerInterface, CustomerListConstraints};


            "cavite" | "kabite" => Ok(Self::Cavite),
            "cebu" | "sebu" => Ok(Self::Cebu),
            "centralluzon" | "rehiyonnggitnangluzon" => Ok(Self::CentralLuzon),
            "centralvisayas" | "rehiyonnggitnangbisaya" => Ok(Self::CentralVisayas),
            "cordilleraadministrativeregion" | "rehiyonngadministratibongkordilyera" => {
                Ok(Self::CordilleraAdministrativeRegion)
            }
            "cotabato" | "kotabato" => Ok(Self::Cotabato),
            "davao" | "rehiyonngdabaw" => Ok(Self::Davao),
            "davaooccidental" | "kanlurangdabaw" => Ok(Self::DavaoOccidental),
            "davaooriental" | "silangangdabaw" => Ok(Self::DavaoOriental),
            "davaodeoro" => Ok(Self::DavaoDeOro),
            "davaodelnorte" | "hilagangdabaw" => Ok(Self::DavaoDelNorte),
            "davaodelsur" | "timogdabaw" => Ok(Self::DavaoDelSur),
            "dinagatislands" | "pulongdinagat" => Ok(Self::DinagatIslands),
            "easternsamar" | "silangangsamar" => Ok(Self::EasternSamar),
            "easternvisayas" | "rehiyonngsilangangbisaya" => Ok(Self::EasternVisayas),
            "guimaras" | "gimaras" => Ok(Self::Guimaras),
            "hilagangiloko" | "ilocosnorte" => Ok(Self::HilagangIloko),
            "hilaganglanaw" | "lanaodelnorte" => Ok(Self::HilagangLanaw),
            "hilagangmagindanaw" | "maguindanaodelnorte" => Ok(Self::HilagangMagindanaw),
            "hilagangsamar" | "northernsamar" => Ok(Self::HilagangSamar),
            "hilagangsambuwangga" | "zamboangadelnorte" => Ok(Self::HilagangSambuwangga),
            "hilagangsurigaw" | "surigaodelnorte" => Ok(Self::HilagangSurigaw),
            "ifugao" | "ipugaw" => Ok(Self::Ifugao),
            "ilocos" | "rehiyonngiloko" => Ok(Self::Ilocos),
            "ilocossur" | "timogiloko" => Ok(Self::IlocosSur),
            "iloilo" | "iloylo" => Ok(Self::Iloilo),
            "isabela" => Ok(Self::Isabela),
            "kalinga" => Ok(Self::Kalinga),
            "kanlurangmindoro" | "mindorooccidental" => Ok(Self::KanlurangMindoro),
            "kanlurangmisamis" | "misamisoriental" => Ok(Self::KanlurangMisamis),
            "kanlurangnegros" | "negrosoccidental" => Ok(Self::KanlurangNegros),
            "katimogangleyte" | "southernleyte" => Ok(Self::KatimogangLeyte),
            "keson" | "quezon" => Ok(Self::Keson),
            "kirino" | "quirino" => Ok(Self::Kirino),
            "launion" => Ok(Self::LaUnion),
            "laguna" => Ok(Self::Laguna),
            "lalawigangbulubundukin" | "mountainprovince" => Ok(Self::LalawigangBulubundukin),
            "lanaodelsur" | "timoglanaw" => Ok(Self::LanaoDelSur),
            "leyte" => Ok(Self::Leyte),
            "maguidanaodelsur" | "timogmaguindanao" => Ok(Self::MaguindanaoDelSur),
            "marinduque" => Ok(Self::Marinduque),
            "masbate" => Ok(Self::Masbate),
            "mimaropa" | "rehiyonngmimaropa" => Ok(Self::Mimaropa),
            "mindorooriental" | "silingangmindoro" => Ok(Self::MindoroOriental),
            "misamisoccidental" | "silingangmisamis" => Ok(Self::MisamisOccidental),
            "nationalcapitalregion" | "pambansangpunonglungsod" => Ok(Self::NationalCapitalRegion),
            "negrosoriental" | "silingangnegros" => Ok(Self::NegrosOriental),
            "northernmindanao" | "rehiyonnghilagangmindanao" => Ok(Self::NorthernMindanao),
            "nuevaecija" | "nuwevaesiha" => Ok(Self::NuevaEcija),
            "nuevavizcaya" => Ok(Self::NuevaVizcaya),
            "palawan" => Ok(Self::Palawan),
            "pampanga" => Ok(Self::Pampanga),
            "pangasinan" => Ok(Self::Pangasinan),
            "rehiyonngkanlurangbisaya" | "westernvisayas" => Ok(Self::RehiyonNgKanlurangBisaya),
            "rehiyonngsoccsksargen" | "soccsksargen" => Ok(Self::RehiyonNgSoccsksargen),
            "rehiyonngtangwayngsambuwangga" | "zamboangapeninsula" => {
                Ok(Self::RehiyonNgTangwayNgSambuwangga)
            }
            "risal" | "rizal" => Ok(Self::Risal),
            "romblon" => Ok(Self::Romblon),
            "samar" => Ok(Self::Samar),
            "sambales" | "zambales" => Ok(Self::Sambales),
            "sambuwanggasibugay" | "zamboangasibugay" => Ok(Self::SambuwanggaSibugay),
            "sarangani" => Ok(Self::Sarangani),
            "siquijor" | "sikihor" => Ok(Self::Sikihor),
            "sorsogon" => Ok(Self::Sorsogon),
            "southcotabato" | "timogkotabato" => Ok(Self::SouthCotabato),
            "sultankudarat" => Ok(Self::SultanKudarat),
            "sulu" => Ok(Self::Sulu),
            "surigaodelsur" | "timogsurigaw" => Ok(Self::SurigaoDelSur),
            "tarlac" => Ok(Self::Tarlac),
            "tawitawi" => Ok(Self::TawiTawi),
            "timogsambuwangga" | "zamboangadelsur" => Ok(Self::TimogSambuwangga),
            _ => Err(errors::ConnectorError::InvalidDataFormat {
                field_name: "address.state",
            }
            .into()),
        }
    }
}

impl ForeignTryFrom<String> for IndiaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state = parse_state_enum::<Self>(value, "IndiaStatesAbbreviation", "address.state")?;
        match state.as_str() {
            "andamanandnicobarislands" => Ok(Self::AndamanAndNicobarIslands),
            "andhrapradesh" => Ok(Self::AndhraPradesh),
            "arunachalpradesh" => Ok(Self::ArunachalPradesh),
            "assam" => Ok(Self::Assam),
            "bihar" => Ok(Self::Bihar),
            "chandigarh" => Ok(Self::Chandigarh),
            "chhattisgarh" => Ok(Self::Chhattisgarh),
            "dadraandnagarhavelianddamananddiu" => Ok(Self::DadraAndNagarHaveliAndDamanAndDiu),
            "delhi" => Ok(Self::Delhi),
            "goa" => Ok(Self::Goa),
            "gujarat" => Ok(Self::Gujarat),
            "haryana" => Ok(Self::Haryana),
            "himachalpradesh" => Ok(Self::HimachalPradesh),
            "jammuandkashmir" => Ok(Self::JammuAndKashmir),
            "jharkhand" => Ok(Self::Jharkhand),
            "karnataka" => Ok(Self::Karnataka),
            "kerala" => Ok(Self::Kerala),
            "ladakh" => Ok(Self::Ladakh),
            "lakshadweep" => Ok(Self::Lakshadweep),
            "madhyapradesh" => Ok(Self::MadhyaPradesh),
            "maharashtra" => Ok(Self::Maharashtra),
            "manipur" => Ok(Self::Manipur),
            "meghalaya" => Ok(Self::Meghalaya),
            "mizoram" => Ok(Self::Mizoram),
            "nagaland" => Ok(Self::Nagaland),
            "odisha" => Ok(Self::Odisha),
            "puducherry" | "pondicherry" => Ok(Self::Puducherry),
            "punjab" => Ok(Self::Punjab),
            "rajasthan" => Ok(Self::Rajasthan),
            "sikkim" => Ok(Self::Sikkim),
            "tamilnadu" => Ok(Self::TamilNadu),
            "telangana" => Ok(Self::Telangana),
            "tripura" => Ok(Self::Tripura),
            "uttarpradesh" => Ok(Self::UttarPradesh),
            "uttarakhand" => Ok(Self::Uttarakhand),
            "westbengal" => Ok(Self::WestBengal),
            _ => Err(errors::ConnectorError::InvalidDataFormat {
                field_name: "address.state",
            }
            .into()),
        }
    }
}

impl ForeignTryFrom<String> for MoldovaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "MoldovaStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Anenii Noi District" => Ok(Self::AneniiNoiDistrict),
                "Basarabeasca District" => Ok(Self::BasarabeascaDistrict),
                "Bender Municipality" => Ok(Self::BenderMunicipality),
                "Briceni District" => Ok(Self::BriceniDistrict),
                "Bălți Municipality" => Ok(Self::BălțiMunicipality),
                "Cahul District" => Ok(Self::CahulDistrict),
                "Cantemir District" => Ok(Self::CantemirDistrict),
                "Chișinău Municipality" => Ok(Self::ChișinăuMunicipality),
                "Cimișlia District" => Ok(Self::CimișliaDistrict),
                "Criuleni District" => Ok(Self::CriuleniDistrict),
                "Călărași District" => Ok(Self::CălărașiDistrict),
                "Căușeni District" => Ok(Self::CăușeniDistrict),
                "Dondușeni District" => Ok(Self::DondușeniDistrict),
                "Drochia District" => Ok(Self::DrochiaDistrict),
                "Dubăsari District" => Ok(Self::DubăsariDistrict),
                "Edineț District" => Ok(Self::EdinețDistrict),
                "Florești District" => Ok(Self::FloreștiDistrict),
                "Fălești District" => Ok(Self::FăleștiDistrict),
                "Găgăuzia" => Ok(Self::Găgăuzia),
                "Glodeni District" => Ok(Self::GlodeniDistrict),
                "Hîncești District" => Ok(Self::HînceștiDistrict),
                "Ialoveni District" => Ok(Self::IaloveniDistrict),
                "Nisporeni District" => Ok(Self::NisporeniDistrict),
                "Ocnița District" => Ok(Self::OcnițaDistrict),
                "Orhei District" => Ok(Self::OrheiDistrict),
                "Rezina District" => Ok(Self::RezinaDistrict),
                "Rîșcani District" => Ok(Self::RîșcaniDistrict),
                "Soroca District" => Ok(Self::SorocaDistrict),
                "Strășeni District" => Ok(Self::StrășeniDistrict),
                "Sîngerei District" => Ok(Self::SîngereiDistrict),
                "Taraclia District" => Ok(Self::TaracliaDistrict),
                "Telenești District" => Ok(Self::TeleneștiDistrict),
                "Transnistria Autonomous Territorial Unit" => {
                    Ok(Self::TransnistriaAutonomousTerritorialUnit)
                }
                "Ungheni District" => Ok(Self::UngheniDistrict),
                "Șoldănești District" => Ok(Self::ȘoldăneștiDistrict),
                "Ștefan Vodă District" => Ok(Self::ȘtefanVodăDistrict),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for LithuaniaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "LithuaniaStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Akmenė District Municipality" => Ok(Self::AkmeneDistrictMunicipality),
                "Alytus City Municipality" => Ok(Self::AlytusCityMunicipality),
                "Alytus County" => Ok(Self::AlytusCounty),
                "Alytus District Municipality" => Ok(Self::AlytusDistrictMunicipality),
                "Birštonas Municipality" => Ok(Self::BirstonasMunicipality),
                "Biržai District Municipality" => Ok(Self::BirzaiDistrictMunicipality),
                "Druskininkai municipality" => Ok(Self::DruskininkaiMunicipality),
                "Elektrėnai municipality" => Ok(Self::ElektrenaiMunicipality),
                "Ignalina District Municipality" => Ok(Self::IgnalinaDistrictMunicipality),
                "Jonava District Municipality" => Ok(Self::JonavaDistrictMunicipality),
                "Joniškis District Municipality" => Ok(Self::JoniskisDistrictMunicipality),
                "Jurbarkas District Municipality" => Ok(Self::JurbarkasDistrictMunicipality),
                "Kaišiadorys District Municipality" => Ok(Self::KaisiadorysDistrictMunicipality),
                "Kalvarija municipality" => Ok(Self::KalvarijaMunicipality),
                "Kaunas City Municipality" => Ok(Self::KaunasCityMunicipality),
                "Kaunas County" => Ok(Self::KaunasCounty),
                "Kaunas District Municipality" => Ok(Self::KaunasDistrictMunicipality),
                "Kazlų Rūda municipality" => Ok(Self::KazluRudaMunicipality),
                "Kelmė District Municipality" => Ok(Self::KelmeDistrictMunicipality),
                "Klaipeda City Municipality" => Ok(Self::KlaipedaCityMunicipality),
                "Klaipėda County" => Ok(Self::KlaipedaCounty),
                "Klaipėda District Municipality" => Ok(Self::KlaipedaDistrictMunicipality),
                "Kretinga District Municipality" => Ok(Self::KretingaDistrictMunicipality),
                "Kupiškis District Municipality" => Ok(Self::KupiskisDistrictMunicipality),
                "Kėdainiai District Municipality" => Ok(Self::KedainiaiDistrictMunicipality),
                "Lazdijai District Municipality" => Ok(Self::LazdijaiDistrictMunicipality),
                "Marijampolė County" => Ok(Self::MarijampoleCounty),
                "Marijampolė Municipality" => Ok(Self::MarijampoleMunicipality),
                "Mažeikiai District Municipality" => Ok(Self::MazeikiaiDistrictMunicipality),
                "Molėtai District Municipality" => Ok(Self::MoletaiDistrictMunicipality),
                "Neringa Municipality" => Ok(Self::NeringaMunicipality),
                "Pagėgiai municipality" => Ok(Self::PagegiaiMunicipality),
                "Pakruojis District Municipality" => Ok(Self::PakruojisDistrictMunicipality),
                "Palanga City Municipality" => Ok(Self::PalangaCityMunicipality),
                "Panevėžys City Municipality" => Ok(Self::PanevezysCityMunicipality),
                "Panevėžys County" => Ok(Self::PanevezysCounty),
                "Panevėžys District Municipality" => Ok(Self::PanevezysDistrictMunicipality),
                "Pasvalys District Municipality" => Ok(Self::PasvalysDistrictMunicipality),
                "Plungė District Municipality" => Ok(Self::PlungeDistrictMunicipality),
                "Prienai District Municipality" => Ok(Self::PrienaiDistrictMunicipality),
                "Radviliškis District Municipality" => Ok(Self::RadviliskisDistrictMunicipality),
                "Raseiniai District Municipality" => Ok(Self::RaseiniaiDistrictMunicipality),
                "Rietavas municipality" => Ok(Self::RietavasMunicipality),
                "Rokiškis District Municipality" => Ok(Self::RokiskisDistrictMunicipality),
                "Skuodas District Municipality" => Ok(Self::SkuodasDistrictMunicipality),
                "Tauragė County" => Ok(Self::TaurageCounty),
                "Tauragė District Municipality" => Ok(Self::TaurageDistrictMunicipality),
                "Telšiai County" => Ok(Self::TelsiaiCounty),
                "Telšiai District Municipality" => Ok(Self::TelsiaiDistrictMunicipality),
                "Trakai District Municipality" => Ok(Self::TrakaiDistrictMunicipality),
                "Ukmergė District Municipality" => Ok(Self::UkmergeDistrictMunicipality),
                "Utena County" => Ok(Self::UtenaCounty),
                "Utena District Municipality" => Ok(Self::UtenaDistrictMunicipality),
                "Varėna District Municipality" => Ok(Self::VarenaDistrictMunicipality),
                "Vilkaviškis District Municipality" => Ok(Self::VilkaviskisDistrictMunicipality),
                "Vilnius City Municipality" => Ok(Self::VilniusCityMunicipality),
                "Vilnius County" => Ok(Self::VilniusCounty),
                "Vilnius District Municipality" => Ok(Self::VilniusDistrictMunicipality),
                "Visaginas Municipality" => Ok(Self::VisaginasMunicipality),
                "Zarasai District Municipality" => Ok(Self::ZarasaiDistrictMunicipality),
                "Šakiai District Municipality" => Ok(Self::SakiaiDistrictMunicipality),
                "Šalčininkai District Municipality" => Ok(Self::SalcininkaiDistrictMunicipality),
                "Šiauliai City Municipality" => Ok(Self::SiauliaiCityMunicipality),
                "Šiauliai County" => Ok(Self::SiauliaiCounty),
                "Šiauliai District Municipality" => Ok(Self::SiauliaiDistrictMunicipality),
                "Šilalė District Municipality" => Ok(Self::SilaleDistrictMunicipality),
                "Šilutė District Municipality" => Ok(Self::SiluteDistrictMunicipality),
                "Širvintos District Municipality" => Ok(Self::SirvintosDistrictMunicipality),
                "Švenčionys District Municipality" => Ok(Self::SvencionysDistrictMunicipality),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for LiechtensteinStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "LiechtensteinStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Balzers" => Ok(Self::Balzers),
                "Eschen" => Ok(Self::Eschen),
                "Gamprin" => Ok(Self::Gamprin),
                "Mauren" => Ok(Self::Mauren),
                "Planken" => Ok(Self::Planken),
                "Ruggell" => Ok(Self::Ruggell),
                "Schaan" => Ok(Self::Schaan),
                "Schellenberg" => Ok(Self::Schellenberg),
                "Triesen" => Ok(Self::Triesen),
                "Triesenberg" => Ok(Self::Triesenberg),
                "Vaduz" => Ok(Self::Vaduz),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for LatviaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "LatviaStatesAbbreviation");
        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Aglona Municipality" => Ok(Self::AglonaMunicipality),
                "Aizkraukle Municipality" => Ok(Self::AizkraukleMunicipality),
                "Aizpute Municipality" => Ok(Self::AizputeMunicipality),
                "Aknīste Municipality" => Ok(Self::AknīsteMunicipality),
                "Aloja Municipality" => Ok(Self::AlojaMunicipality),
                "Alsunga Municipality" => Ok(Self::AlsungaMunicipality),
                "Alūksne Municipality" => Ok(Self::AlūksneMunicipality),
                "Amata Municipality" => Ok(Self::AmataMunicipality),
                "Ape Municipality" => Ok(Self::ApeMunicipality),
                "Auce Municipality" => Ok(Self::AuceMunicipality),
                "Babīte Municipality" => Ok(Self::BabīteMunicipality),
                "Baldone Municipality" => Ok(Self::BaldoneMunicipality),
                "Baltinava Municipality" => Ok(Self::BaltinavaMunicipality),
                "Balvi Municipality" => Ok(Self::BalviMunicipality),
                "Bauska Municipality" => Ok(Self::BauskaMunicipality),
                "Beverīna Municipality" => Ok(Self::BeverīnaMunicipality),
                "Brocēni Municipality" => Ok(Self::BrocēniMunicipality),
                "Burtnieki Municipality" => Ok(Self::BurtniekiMunicipality),
                "Carnikava Municipality" => Ok(Self::CarnikavaMunicipality),
                "Cesvaine Municipality" => Ok(Self::CesvaineMunicipality),
                "Cibla Municipality" => Ok(Self::CiblaMunicipality),
                "Cēsis Municipality" => Ok(Self::CēsisMunicipality),
                "Dagda Municipality" => Ok(Self::DagdaMunicipality),
                "Daugavpils" => Ok(Self::Daugavpils),
                "Daugavpils Municipality" => Ok(Self::DaugavpilsMunicipality),
                "Dobele Municipality" => Ok(Self::DobeleMunicipality),
                "Dundaga Municipality" => Ok(Self::DundagaMunicipality),
                "Durbe Municipality" => Ok(Self::DurbeMunicipality),
                "Engure Municipality" => Ok(Self::EngureMunicipality),
                "Garkalne Municipality" => Ok(Self::GarkalneMunicipality),
                "Grobiņa Municipality" => Ok(Self::GrobiņaMunicipality),
                "Gulbene Municipality" => Ok(Self::GulbeneMunicipality),
                "Iecava Municipality" => Ok(Self::IecavaMunicipality),
                "Ikšķile Municipality" => Ok(Self::IkšķileMunicipality),
                "Ilūkste Municipalityy" => Ok(Self::IlūksteMunicipality),
                "Inčukalns Municipality" => Ok(Self::InčukalnsMunicipality),
                "Jaunjelgava Municipality" => Ok(Self::JaunjelgavaMunicipality),
                "Jaunpiebalga Municipality" => Ok(Self::JaunpiebalgaMunicipality),
                "Jaunpils Municipality" => Ok(Self::JaunpilsMunicipality),
                "Jelgava" => Ok(Self::Jelgava),
                "Jelgava Municipality" => Ok(Self::JelgavaMunicipality),
                "Jēkabpils" => Ok(Self::Jēkabpils),
                "Jēkabpils Municipality" => Ok(Self::JēkabpilsMunicipality),
                "Jūrmala" => Ok(Self::Jūrmala),
                "Kandava Municipality" => Ok(Self::KandavaMunicipality),
                "Kocēni Municipality" => Ok(Self::KocēniMunicipality),
                "Koknese Municipality" => Ok(Self::KokneseMunicipality),
                "Krimulda Municipality" => Ok(Self::KrimuldaMunicipality),
                "Krustpils Municipality" => Ok(Self::KrustpilsMunicipality),
                "Krāslava Municipality" => Ok(Self::KrāslavaMunicipality),
                "Kuldīga Municipality" => Ok(Self::KuldīgaMunicipality),
                "Kārsava Municipality" => Ok(Self::KārsavaMunicipality),
                "Lielvārde Municipality" => Ok(Self::LielvārdeMunicipality),
                "Liepāja" => Ok(Self::Liepāja),
                "Limbaži Municipality" => Ok(Self::LimbažiMunicipality),
                "Lubāna Municipality" => Ok(Self::LubānaMunicipality),
                "Ludza Municipality" => Ok(Self::LudzaMunicipality),
                "Līgatne Municipality" => Ok(Self::LīgatneMunicipality),
                "Līvāni Municipality" => Ok(Self::LīvāniMunicipality),
                "Madona Municipality" => Ok(Self::MadonaMunicipality),
                "Mazsalaca Municipality" => Ok(Self::MazsalacaMunicipality),
                "Mālpils Municipality" => Ok(Self::MālpilsMunicipality),
                "Mārupe Municipality" => Ok(Self::MārupeMunicipality),
                "Mērsrags Municipality" => Ok(Self::MērsragsMunicipality),
                "Naukšēni Municipality" => Ok(Self::NaukšēniMunicipality),
                "Nereta Municipality" => Ok(Self::NeretaMunicipality),
                "Nīca Municipality" => Ok(Self::NīcaMunicipality),
                "Ogre Municipality" => Ok(Self::OgreMunicipality),
                "Olaine Municipality" => Ok(Self::OlaineMunicipality),
                "Ozolnieki Municipality" => Ok(Self::OzolniekiMunicipality),
                "Preiļi Municipality" => Ok(Self::PreiļiMunicipality),
                "Priekule Municipality" => Ok(Self::PriekuleMunicipality),
                "Priekuļi Municipality" => Ok(Self::PriekuļiMunicipality),
                "Pārgauja Municipality" => Ok(Self::PārgaujaMunicipality),
                "Pāvilosta Municipality" => Ok(Self::PāvilostaMunicipality),
                "Pļaviņas Municipality" => Ok(Self::PļaviņasMunicipality),
                "Rauna Municipality" => Ok(Self::RaunaMunicipality),
                "Riebiņi Municipality" => Ok(Self::RiebiņiMunicipality),
                "Riga" => Ok(Self::Riga),
                "Roja Municipality" => Ok(Self::RojaMunicipality),
                "Ropaži Municipality" => Ok(Self::RopažiMunicipality),
                "Rucava Municipality" => Ok(Self::RucavaMunicipality),
                "Rugāji Municipality" => Ok(Self::RugājiMunicipality),
                "Rundāle Municipality" => Ok(Self::RundāleMunicipality),
                "Rēzekne" => Ok(Self::Rēzekne),
                "Rēzekne Municipality" => Ok(Self::RēzekneMunicipality),
                "Rūjiena Municipality" => Ok(Self::RūjienaMunicipality),
                "Sala Municipality" => Ok(Self::SalaMunicipality),
                "Salacgrīva Municipality" => Ok(Self::SalacgrīvaMunicipality),
                "Salaspils Municipality" => Ok(Self::SalaspilsMunicipality),
                "Saldus Municipality" => Ok(Self::SaldusMunicipality),
                "Saulkrasti Municipality" => Ok(Self::SaulkrastiMunicipality),
                "Sigulda Municipality" => Ok(Self::SiguldaMunicipality),
                "Skrunda Municipality" => Ok(Self::SkrundaMunicipality),
                "Skrīveri Municipality" => Ok(Self::SkrīveriMunicipality),
                "Smiltene Municipality" => Ok(Self::SmilteneMunicipality),
                "Stopiņi Municipality" => Ok(Self::StopiņiMunicipality),
                "Strenči Municipality" => Ok(Self::StrenčiMunicipality),
                "Sēja Municipality" => Ok(Self::SējaMunicipality),
                _ => Err(errors::ConnectorError::InvalidDataFormat {
                    field_name: "address.state",
                }
                .into()),
            },
        }
    }
}

impl ForeignTryFrom<String> for MaltaStatesAbbreviation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(value: String) -> Result<Self, Self::Error> {
        let state_abbreviation_check =
            StringExt::<Self>::parse_enum(value.clone(), "MaltaStatesAbbreviation");

        match state_abbreviation_check {
            Ok(state_abbreviation) => Ok(state_abbreviation),
            Err(_) => match value.as_str() {
                "Attard" => Ok(Self::Attard),
                "Balzan" => Ok(Self::Balzan),
                "Birgu" => Ok(Self::Birgu),
                "Birkirkara" => Ok(Self::Birkirkara),
                "Birżebbuġa" => Ok(Self::Birżebbuġa),
                "Cospicua" => Ok(Self::Cospicua),
                "Dingli" => Ok(Self::Dingli),
                "Fgura" => Ok(Self::Fgura),
                "Floriana" => Ok(Self::Floriana),
                "Fontana" => Ok(Self::Fontana),
                "Gudja" => Ok(Self::Gudja),
                "Gżira" => Ok(Self::Gżira),
                "Għajnsielem" => Ok(Self::Għajnsielem),
                "Għarb" => Ok(Self::Għarb),
                "Għargħur" => Ok(Self::Għargħur),
                "Għasri" => Ok(Self::Għasri),
                "Għaxaq" => Ok(Self::Għaxaq),
                "Ħamrun" => Ok(Self::Ħamrun),
                "Iklin" => Ok(Self::Iklin),
                "Senglea" => Ok(Self::Senglea),
                "Kalkara" => Ok(Self::Kalkara),
                "Kerċem" => Ok(Self::Kerċem),
                "Kirkop" => Ok(Self::Kirkop),
                "Lija" => Ok(Self::Lija),
                "Luqa" => Ok(Self::Luqa),
                "Marsa" => Ok(Self::Marsa),
                "Marsaskala" => Ok(Self::Marsaskala),
                "Marsaxlokk" => Ok(Self::Marsaxlokk),
                "Mdina" => Ok(Self::Mdina),
                "Mellieħa" => Ok(Self::Mellieħa),
                "Mosta" => Ok(Self::Mosta),
                "Mqabba" => Ok(Self::Mqabba),
                "Msida" => Ok(Self::Msida),
                "Mtarfa" => Ok(Self::Mtarfa),
                "Munxar" => Ok(Self::Munxar),
                "Mġarr" => Ok(Self::Mġarr),
                "Nadur" => Ok(Self::Nadur),
                "Naxxar" => Ok(Self::Naxxar),
                "Paola" => Ok(Self::Paola),
                "Pembroke" => Ok(Self::Pembroke),
                "Pietà" => Ok(Self::Pietà),
                "Qala" => Ok(Self::Qala),
                "Qormi" => Ok(Self::Qormi),
                "Qrendi" => Ok(Self::Qrendi),
                "Rabat" => Ok(Self::Rabat),
                "Saint Lawrence" => Ok(Self::SaintLawrence),
                "San Ġwann" => Ok(Self::SanĠwann),
                "Sannat" => Ok(Self::Sannat),
                "Santa Luċija" => Ok(Self::SantaLuċija),
                "Santa Venera" => Ok(Self::SantaVenera),
                "Siġġiewi" => Ok(Self::Siġġiewi),
                "Sliema" => Ok(Self::Sliema),
                "St. Julian's" => Ok(Self::StJulians),
                "St. Paul's Bay" => Ok(Self::StPaulsBay),
                "Swieqi" => Ok(Self::Swieqi),
                "Ta' Xbiex" => Ok(Self::TaXbiex),
                "Tarxien" => Ok(Self::Tarxien),
                "Valletta" => Ok(Self::Valletta),
                "Victoria" => Ok(Self::Victoria),
                "Xagħra" => Ok(Self::Xagħra),


// Struct: PaysafePaymentsSyncResponse
// File: crates/hyperswitch_connectors/src/connectors/paysafe/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaysafePaymentsSyncResponse


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

impl api::PaymentSync for for Katapult


// Struct: ListRolesQueryParams
// File: crates/api_models/src/user_role/role.rs
// Module: api_models
// Implementations: 0

pub struct ListRolesQueryParams


// Implementation: impl api::Payment for for Wellsfargopayout
// File: crates/hyperswitch_connectors/src/connectors/wellsfargopayout.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Payment for for Wellsfargopayout


// Function: get_group_authorization_info
// File: crates/router/src/services/authorization/info.rs
// Module: router

pub fn get_group_authorization_info() -> Option<Vec<GroupInfo>>


// File: crates/diesel_models/src/types.rs
// Module: diesel_models
// Public functions: 3
// Public structs: 9

#[cfg(feature = "v2")]
use common_enums::enums::PaymentConnectorTransmission;
#[cfg(feature = "v2")]
use common_utils::id_type;
use common_utils::{hashing::HashedString, pii, types::MinorUnit};
use diesel::{
    sql_types::{Json, Jsonb},
    AsExpression, FromSqlRow,
};
use masking::{Secret, WithType};
use serde::{self, Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Jsonb)]
pub struct OrderDetailsWithAmount {
    /// Name of the product that is being purchased
    pub product_name: String,
    /// The quantity of the product to be purchased
    pub quantity: u16,
    /// the amount per quantity of product
    pub amount: MinorUnit,
    // Does the order includes shipping
    pub requires_shipping: Option<bool>,
    /// The image URL of the product
    pub product_img_link: Option<String>,
    /// ID of the product that is being purchased
    pub product_id: Option<String>,
    /// Category of the product that is being purchased
    pub category: Option<String>,
    /// Sub category of the product that is being purchased
    pub sub_category: Option<String>,
    /// Brand of the product that is being purchased
    pub brand: Option<String>,
    /// Type of the product that is being purchased
    pub product_type: Option<common_enums::ProductType>,
    /// The tax code for the product
    pub product_tax_code: Option<String>,
    /// tax rate applicable to the product
    pub tax_rate: Option<f64>,
    /// total tax amount applicable to the product
    pub total_tax_amount: Option<MinorUnit>,
    /// description of the product
    pub description: Option<String>,
    /// stock keeping unit of the product
    pub sku: Option<String>,
    /// universal product code of the product
    pub upc: Option<String>,
    /// commodity code of the product
    pub commodity_code: Option<String>,
    /// unit of measure of the product
    pub unit_of_measure: Option<String>,
    /// total amount of the product
    pub total_amount: Option<MinorUnit>,
    /// discount amount on the unit
    pub unit_discount_amount: Option<MinorUnit>,
}

impl masking::SerializableSecret for OrderDetailsWithAmount {}

common_utils::impl_to_sql_from_sql_json!(OrderDetailsWithAmount);

#[cfg(feature = "v2")]
#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Json)]
pub struct FeatureMetadata {
    /// Redirection response coming in request as metadata field only for redirection scenarios
    pub redirect_response: Option<RedirectResponse>,
    /// Additional tags to be used for global search
    pub search_tags: Option<Vec<HashedString<WithType>>>,
    /// Recurring payment details required for apple pay Merchant Token
    pub apple_pay_recurring_details: Option<ApplePayRecurringDetails>,
    /// revenue recovery data for payment intent
    pub payment_revenue_recovery_metadata: Option<PaymentRevenueRecoveryMetadata>,
}

#[cfg(feature = "v2")]
impl FeatureMetadata {
    pub fn get_payment_method_sub_type(&self) -> Option<common_enums::PaymentMethodType> {
        self.payment_revenue_recovery_metadata
            .as_ref()
            .map(|rrm| rrm.payment_method_subtype)
    }

    pub fn get_payment_method_type(&self) -> Option<common_enums::PaymentMethod> {
        self.payment_revenue_recovery_metadata
            .as_ref()
            .map(|recovery_metadata| recovery_metadata.payment_method_type)
    }

    pub fn get_billing_merchant_connector_account_id(
        &self,
    ) -> Option<id_type::MerchantConnectorAccountId> {
        self.payment_revenue_recovery_metadata
            .as_ref()
            .map(|recovery_metadata| recovery_metadata.billing_connector_id.clone())
    }

    // TODO: Check search_tags for relevant payment method type
    // TODO: Check redirect_response metadata if applicable
    // TODO: Check apple_pay_recurring_details metadata if applicable
}

#[cfg(feature = "v1")]
#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Json)]
pub struct FeatureMetadata {
    /// Redirection response coming in request as metadata field only for redirection scenarios
    pub redirect_response: Option<RedirectResponse>,
    /// Additional tags to be used for global search
    pub search_tags: Option<Vec<HashedString<WithType>>>,
    /// Recurring payment details required for apple pay Merchant Token
    pub apple_pay_recurring_details: Option<ApplePayRecurringDetails>,
    /// The system that the gateway is integrated with, e.g., `Direct`(through hyperswitch), `UnifiedConnectorService`(through ucs), etc.
    pub gateway_system: Option<common_enums::GatewaySystem>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Json)]
pub struct ApplePayRecurringDetails {
    /// A description of the recurring payment that Apple Pay displays to the user in the payment sheet
    pub payment_description: String,
    /// The regular billing cycle for the recurring payment, including start and end dates, an interval, and an interval count
    pub regular_billing: ApplePayRegularBillingDetails,
    /// A localized billing agreement that the payment sheet displays to the user before the user authorizes the payment
    pub billing_agreement: Option<String>,
    /// A URL to a web page where the user can update or delete the payment method for the recurring payment
    pub management_url: common_utils::types::Url,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Json)]
pub struct ApplePayRegularBillingDetails {
    /// The label that Apple Pay displays to the user in the payment sheet with the recurring details
    pub label: String,
    /// The date of the first payment
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub recurring_payment_start_date: Option<time::PrimitiveDateTime>,
    /// The date of the final payment
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub recurring_payment_end_date: Option<time::PrimitiveDateTime>,
    /// The amount of time — in calendar units, such as day, month, or year — that represents a fraction of the total payment interval
    pub recurring_payment_interval_unit: Option<RecurringPaymentIntervalUnit>,
    /// The number of interval units that make up the total payment interval
    pub recurring_payment_interval_count: Option<i32>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Json)]
#[serde(rename_all = "snake_case")]
pub enum RecurringPaymentIntervalUnit {
    Year,
    Month,
    Day,
    Hour,
    Minute,
}

common_utils::impl_to_sql_from_sql_json!(ApplePayRecurringDetails);
common_utils::impl_to_sql_from_sql_json!(ApplePayRegularBillingDetails);
common_utils::impl_to_sql_from_sql_json!(RecurringPaymentIntervalUnit);

common_utils::impl_to_sql_from_sql_json!(FeatureMetadata);

#[derive(Default, Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
pub struct RedirectResponse {
    pub param: Option<Secret<String>>,
    pub json_payload: Option<pii::SecretSerdeValue>,
}
impl masking::SerializableSecret for RedirectResponse {}
common_utils::impl_to_sql_from_sql_json!(RedirectResponse);

#[cfg(feature = "v2")]
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct PaymentRevenueRecoveryMetadata {
    /// Total number of billing connector + recovery retries for a payment intent.
    pub total_retry_count: u16,
    /// Flag for the payment connector's call
    pub payment_connector_transmission: PaymentConnectorTransmission,
    /// Billing Connector Id to update the invoices
    pub billing_connector_id: id_type::MerchantConnectorAccountId,
    /// Payment Connector Id to retry the payments
    pub active_attempt_payment_connector_id: id_type::MerchantConnectorAccountId,
    /// Billing Connector Payment Details
    pub billing_connector_payment_details: BillingConnectorPaymentDetails,
    ///Payment Method Type
    pub payment_method_type: common_enums::enums::PaymentMethod,
    /// PaymentMethod Subtype
    pub payment_method_subtype: common_enums::enums::PaymentMethodType,
    /// The name of the payment connector through which the payment attempt was made.
    pub connector: common_enums::connector_enums::Connector,
    /// Time at which next invoice will be created
    pub invoice_next_billing_time: Option<time::PrimitiveDateTime>,
    /// Time at which invoice started
    pub invoice_billing_started_at_time: Option<time::PrimitiveDateTime>,
    /// Extra Payment Method Details that are needed to be stored
    pub billing_connector_payment_method_details: Option<BillingConnectorPaymentMethodDetails>,
    /// First Payment Attempt Payment Gateway Error Code
    pub first_payment_attempt_pg_error_code: Option<String>,
    /// First Payment Attempt Network Error Code
    pub first_payment_attempt_network_decline_code: Option<String>,
    /// First Payment Attempt Network Advice Code
    pub first_payment_attempt_network_advice_code: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[cfg(feature = "v2")]
pub struct BillingConnectorPaymentDetails {
    /// Payment Processor Token to process the Revenue Recovery Payment
    pub payment_processor_token: String,
    /// Billing Connector's Customer Id
    pub connector_customer_id: String,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
pub enum BillingConnectorPaymentMethodDetails {
    Card(BillingConnectorAdditionalCardInfo),
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct BillingConnectorAdditionalCardInfo {
    /// Card Network
    pub card_network: Option<common_enums::enums::CardNetwork>,
    /// Card Issuer
    pub card_issuer: Option<String>,
}


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

impl PaymentsPostProcessing for for Plaid


// Trait: OutgoingWebhookLogsFilterAnalytics
// File: crates/analytics/src/outgoing_webhook_event/events.rs
// Module: analytics

pub trait OutgoingWebhookLogsFilterAnalytics: LoadRow<OutgoingWebhookLogsResult>


// Implementation: impl MerchantAccount
// File: crates/diesel_models/src/query/merchant_account.rs
// Module: diesel_models
// Methods: 9 total (0 public)

impl MerchantAccount


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

impl Noon


// Module Structure
// File: crates/router/src/core/errors/user.rs
// Module: router

// Public submodules:
pub mod sample_data;


// Struct: Deutschebank
// File: crates/hyperswitch_connectors/src/connectors/deutschebank.rs
// Module: hyperswitch_connectors
// Implementations: 18
// Traits: api::Payment, api::PaymentSession, api::ConnectorAccessToken, api::MandateSetup, api::PaymentAuthorize, api::PaymentsCompleteAuthorize, api::PaymentSync, api::PaymentCapture, api::PaymentVoid, api::Refund, api::RefundExecute, api::RefundSync, api::PaymentToken, ConnectorCommon, ConnectorValidation, webhooks::IncomingWebhook, ConnectorSpecifications

pub struct Deutschebank

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