// File: crates/common_utils/src/link_utils.rs

//! This module has common utilities for links in HyperSwitch

use std::{collections::HashSet, primitive::i64};

use common_enums::{enums, UIWidgetFormLayout};
use diesel::{
    backend::Backend,
    deserialize,
    deserialize::FromSql,
    serialize::{Output, ToSql},
    sql_types::Jsonb,
    AsExpression, FromSqlRow,
};
use error_stack::{report, ResultExt};
use masking::Secret;
use regex::Regex;
#[cfg(feature = "logs")]
use router_env::logger;
use serde::Serialize;
use utoipa::ToSchema;

use crate::{consts, errors::ParsingError, id_type, types::MinorUnit};

#[derive(
    Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq, FromSqlRow, AsExpression, ToSchema,
)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
#[diesel(sql_type = Jsonb)]
/// Link status enum
pub enum GenericLinkStatus {
    /// Status variants for payment method collect link
    PaymentMethodCollect(PaymentMethodCollectStatus),
    /// Status variants for payout link
    PayoutLink(PayoutLinkStatus),
}

impl Default for GenericLinkStatus {
    fn default() -> Self {
        Self::PaymentMethodCollect(PaymentMethodCollectStatus::Initiated)
    }
}

crate::impl_to_sql_from_sql_json!(GenericLinkStatus);

#[derive(
    Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq, FromSqlRow, AsExpression, ToSchema,
)]
#[serde(rename_all = "snake_case")]
#[diesel(sql_type = Jsonb)]
/// Status variants for payment method collect links
pub enum PaymentMethodCollectStatus {
    /// Link was initialized
    Initiated,
    /// Link was expired or invalidated
    Invalidated,
    /// Payment method details were submitted
    Submitted,
}

impl<DB: Backend> FromSql<Jsonb, DB> for PaymentMethodCollectStatus
where
    serde_json::Value: FromSql<Jsonb, DB>,
{
    fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
        let value = <serde_json::Value as FromSql<Jsonb, DB>>::from_sql(bytes)?;
        let generic_status: GenericLinkStatus = serde_json::from_value(value)?;
        match generic_status {
            GenericLinkStatus::PaymentMethodCollect(status) => Ok(status),
            GenericLinkStatus::PayoutLink(_) => Err(report!(ParsingError::EnumParseFailure(
                "PaymentMethodCollectStatus"
            )))
            .attach_printable("Invalid status for PaymentMethodCollect")?,
        }
    }
}

impl ToSql<Jsonb, diesel::pg::Pg> for PaymentMethodCollectStatus
where
    serde_json::Value: ToSql<Jsonb, diesel::pg::Pg>,
{
    // This wraps PaymentMethodCollectStatus with GenericLinkStatus
    // Required for storing the status in required format in DB (GenericLinkStatus)
    // This type is used in PaymentMethodCollectLink (a variant of GenericLink, used in the application for avoiding conversion of data and status)
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, diesel::pg::Pg>) -> diesel::serialize::Result {
        let value = serde_json::to_value(GenericLinkStatus::PaymentMethodCollect(self.clone()))?;

        // the function `reborrow` only works in case of `Pg` backend. But, in case of other backends
        // please refer to the diesel migration blog:
        // https://github.com/Diesel-rs/Diesel/blob/master/guide_drafts/migration_guide.md#changed-tosql-implementations
        <serde_json::Value as ToSql<Jsonb, diesel::pg::Pg>>::to_sql(&value, &mut out.reborrow())
    }
}

#[derive(
    Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq, FromSqlRow, AsExpression, ToSchema,
)]
#[serde(rename_all = "snake_case")]
#[diesel(sql_type = Jsonb)]
/// Status variants for payout links
pub enum PayoutLinkStatus {
    /// Link was initialized
    Initiated,
    /// Link was expired or invalidated
    Invalidated,
    /// Payout details were submitted
    Submitted,
}

impl<DB: Backend> FromSql<Jsonb, DB> for PayoutLinkStatus
where
    serde_json::Value: FromSql<Jsonb, DB>,
{
    fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
        let value = <serde_json::Value as FromSql<Jsonb, DB>>::from_sql(bytes)?;
        let generic_status: GenericLinkStatus = serde_json::from_value(value)?;
        match generic_status {
            GenericLinkStatus::PayoutLink(status) => Ok(status),
            GenericLinkStatus::PaymentMethodCollect(_) => {
                Err(report!(ParsingError::EnumParseFailure("PayoutLinkStatus")))
                    .attach_printable("Invalid status for PayoutLink")?
            }
        }
    }
}

impl ToSql<Jsonb, diesel::pg::Pg> for PayoutLinkStatus
where
    serde_json::Value: ToSql<Jsonb, diesel::pg::Pg>,
{
    // This wraps PayoutLinkStatus with GenericLinkStatus
    // Required for storing the status in required format in DB (GenericLinkStatus)
    // This type is used in PayoutLink (a variant of GenericLink, used in the application for avoiding conversion of data and status)
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, diesel::pg::Pg>) -> diesel::serialize::Result {
        let value = serde_json::to_value(GenericLinkStatus::PayoutLink(self.clone()))?;

        // the function `reborrow` only works in case of `Pg` backend. But, in case of other backends
        // please refer to the diesel migration blog:
        // https://github.com/Diesel-rs/Diesel/blob/master/guide_drafts/migration_guide.md#changed-tosql-implementations
        <serde_json::Value as ToSql<Jsonb, diesel::pg::Pg>>::to_sql(&value, &mut out.reborrow())
    }
}

#[derive(Serialize, serde::Deserialize, Debug, Clone, FromSqlRow, AsExpression, ToSchema)]
#[diesel(sql_type = Jsonb)]
/// Payout link object
pub struct PayoutLinkData {
    /// Identifier for the payout link
    pub payout_link_id: String,
    /// Identifier for the customer
    pub customer_id: id_type::CustomerId,
    /// Identifier for the payouts resource
    pub payout_id: id_type::PayoutId,
    /// Link to render the payout link
    pub link: url::Url,
    /// Client secret generated for authenticating frontend APIs
    pub client_secret: Secret<String>,
    /// Expiry in seconds from the time it was created
    pub session_expiry: u32,
    #[serde(flatten)]
    /// Payout link's UI configurations
    pub ui_config: GenericLinkUiConfig,
    /// List of enabled payment methods
    pub enabled_payment_methods: Option<Vec<EnabledPaymentMethod>>,
    /// Payout amount
    pub amount: MinorUnit,
    /// Payout currency
    pub currency: enums::Currency,
    /// A list of allowed domains (glob patterns) where this link can be embedded / opened from
    pub allowed_domains: HashSet<String>,
    /// Form layout of the payout link
    pub form_layout: Option<UIWidgetFormLayout>,
    /// `test_mode` can be used for testing payout links without any restrictions
    pub test_mode: Option<bool>,
}

crate::impl_to_sql_from_sql_json!(PayoutLinkData);

/// Object for GenericLinkUiConfig
#[derive(Clone, Debug, serde::Deserialize, Serialize, ToSchema)]
pub struct GenericLinkUiConfig {
    /// Merchant's display logo
    #[schema(value_type = Option<String>, max_length = 255, example = "https://hyperswitch.io/favicon.ico")]
    pub logo: Option<url::Url>,

    /// Custom merchant name for the link
    #[schema(value_type = Option<String>, max_length = 255, example = "Hyperswitch")]
    pub merchant_name: Option<Secret<String>>,

    /// Primary color to be used in the form represented in hex format
    #[schema(value_type = Option<String>, max_length = 255, example = "#4285F4")]
    pub theme: Option<String>,
}

/// Object for GenericLinkUiConfigFormData
#[derive(Clone, Debug, serde::Deserialize, Serialize, ToSchema)]
pub struct GenericLinkUiConfigFormData {
    /// Merchant's display logo
    #[schema(value_type = String, max_length = 255, example = "https://hyperswitch.io/favicon.ico")]
    pub logo: url::Url,

    /// Custom merchant name for the link
    #[schema(value_type = String, max_length = 255, example = "Hyperswitch")]
    pub merchant_name: Secret<String>,

    /// Primary color to be used in the form represented in hex format
    #[schema(value_type = String, max_length = 255, example = "#4285F4")]
    pub theme: String,
}

/// Object for EnabledPaymentMethod
#[derive(Clone, Debug, Serialize, serde::Deserialize, ToSchema)]
pub struct EnabledPaymentMethod {
    /// Payment method (banks, cards, wallets) enabled for the operation
    #[schema(value_type = PaymentMethod)]
    pub payment_method: enums::PaymentMethod,

    /// An array of associated payment method types
    #[schema(value_type = HashSet<PaymentMethodType>)]
    pub payment_method_types: HashSet<enums::PaymentMethodType>,
}

/// Util function for validating a domain without any wildcard characters.
pub fn validate_strict_domain(domain: &str) -> bool {
    Regex::new(consts::STRICT_DOMAIN_REGEX)
        .map(|regex| regex.is_match(domain))
        .map_err(|err| {
            let err_msg = format!("Invalid strict domain regex: {err:?}");
            #[cfg(feature = "logs")]
            logger::error!(err_msg);
            err_msg
        })
        .unwrap_or(false)
}

/// Util function for validating a domain with "*" wildcard characters.
pub fn validate_wildcard_domain(domain: &str) -> bool {
    Regex::new(consts::WILDCARD_DOMAIN_REGEX)
        .map(|regex| regex.is_match(domain))
        .map_err(|err| {
            let err_msg = format!("Invalid strict domain regex: {err:?}");
            #[cfg(feature = "logs")]
            logger::error!(err_msg);
            err_msg
        })
        .unwrap_or(false)
}

#[cfg(test)]
mod domain_tests {
    use regex::Regex;

    use super::*;

    #[test]
    fn test_validate_strict_domain_regex() {
        assert!(
            Regex::new(consts::STRICT_DOMAIN_REGEX).is_ok(),
            "Strict domain regex is invalid"
        );
    }

    #[test]
    fn test_validate_wildcard_domain_regex() {
        assert!(
            Regex::new(consts::WILDCARD_DOMAIN_REGEX).is_ok(),
            "Wildcard domain regex is invalid"
        );
    }

    #[test]
    fn test_validate_strict_domain() {
        let valid_domains = vec![
            "example.com",
            "example.subdomain.com",
            "https://example.com:8080",
            "http://example.com",
            "example.com:8080",
            "example.com:443",
            "localhost:443",
            "127.0.0.1:443",
        ];

        for domain in valid_domains {
            assert!(
                validate_strict_domain(domain),
                "Could not validate strict domain: {domain}",
            );
        }

        let invalid_domains = vec![
            "",
            "invalid.domain.",
            "not_a_domain",
            "http://example.com/path?query=1#fragment",
            "127.0.0.1.2:443",
        ];

        for domain in invalid_domains {
            assert!(
                !validate_strict_domain(domain),
                "Could not validate invalid strict domain: {domain}",
            );
        }
    }

    #[test]
    fn test_validate_wildcard_domain() {
        let valid_domains = vec![
            "example.com",
            "example.subdomain.com",
            "https://example.com:8080",
            "http://example.com",
            "example.com:8080",
            "example.com:443",
            "localhost:443",
            "127.0.0.1:443",
            "*.com",
            "example.*.com",
            "example.com:*",
            "*:443",
            "localhost:*",
            "127.0.0.*:*",
            "*:*",
        ];

        for domain in valid_domains {
            assert!(
                validate_wildcard_domain(domain),
                "Could not validate wildcard domain: {domain}",
            );
        }

        let invalid_domains = vec![
            "",
            "invalid.domain.",
            "not_a_domain",
            "http://example.com/path?query=1#fragment",
            "*.",
            ".*",
            "example.com:*:",
            "*:443:",
            ":localhost:*",
            "127.00.*:*",
        ];

        for domain in invalid_domains {
            assert!(
                !validate_wildcard_domain(domain),
                "Could not validate invalid wildcard domain: {domain}",
            );
        }
    }
}


// File: crates/common_utils/src/crypto.rs

//! Utilities for cryptographic algorithms
use std::ops::Deref;

use base64::Engine;
use error_stack::ResultExt;
use masking::{ExposeInterface, Secret};
use ring::{
    aead::{self, BoundKey, OpeningKey, SealingKey, UnboundKey},
    hmac, rand as ring_rand,
    signature::{RsaKeyPair, RSA_PSS_SHA256},
};
#[cfg(feature = "logs")]
use router_env::logger;
use rsa::{pkcs8::DecodePublicKey, signature::Verifier};

use crate::{
    consts::BASE64_ENGINE,
    errors::{self, CustomResult},
    pii::{self, EncryptionStrategy},
};

#[derive(Clone, Debug)]
struct NonceSequence(u128);

impl NonceSequence {
    /// Byte index at which sequence number starts in a 16-byte (128-bit) sequence.
    /// This byte index considers the big endian order used while encoding and decoding the nonce
    /// to/from a 128-bit unsigned integer.
    const SEQUENCE_NUMBER_START_INDEX: usize = 4;

    /// Generate a random nonce sequence.
    fn new() -> Result<Self, ring::error::Unspecified> {
        use ring::rand::{SecureRandom, SystemRandom};

        let rng = SystemRandom::new();

        // 96-bit sequence number, stored in a 128-bit unsigned integer in big-endian order
        let mut sequence_number = [0_u8; 128 / 8];
        rng.fill(&mut sequence_number[Self::SEQUENCE_NUMBER_START_INDEX..])?;
        let sequence_number = u128::from_be_bytes(sequence_number);

        Ok(Self(sequence_number))
    }

    /// Returns the current nonce value as bytes.
    fn current(&self) -> [u8; aead::NONCE_LEN] {
        let mut nonce = [0_u8; aead::NONCE_LEN];
        nonce.copy_from_slice(&self.0.to_be_bytes()[Self::SEQUENCE_NUMBER_START_INDEX..]);
        nonce
    }

    /// Constructs a nonce sequence from bytes
    fn from_bytes(bytes: [u8; aead::NONCE_LEN]) -> Self {
        let mut sequence_number = [0_u8; 128 / 8];
        sequence_number[Self::SEQUENCE_NUMBER_START_INDEX..].copy_from_slice(&bytes);
        let sequence_number = u128::from_be_bytes(sequence_number);
        Self(sequence_number)
    }
}

impl aead::NonceSequence for NonceSequence {
    fn advance(&mut self) -> Result<aead::Nonce, ring::error::Unspecified> {
        let mut nonce = [0_u8; aead::NONCE_LEN];
        nonce.copy_from_slice(&self.0.to_be_bytes()[Self::SEQUENCE_NUMBER_START_INDEX..]);

        // Increment sequence number
        self.0 = self.0.wrapping_add(1);

        // Return previous sequence number as bytes
        Ok(aead::Nonce::assume_unique_for_key(nonce))
    }
}

/// Trait for cryptographically signing messages
pub trait SignMessage {
    /// Takes in a secret and a message and returns the calculated signature as bytes
    fn sign_message(
        &self,
        _secret: &[u8],
        _msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError>;
}

/// Trait for cryptographically verifying a message against a signature
pub trait VerifySignature {
    /// Takes in a secret, the signature and the message and verifies the message
    /// against the signature
    fn verify_signature(
        &self,
        _secret: &[u8],
        _signature: &[u8],
        _msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError>;
}

/// Trait for cryptographically encoding a message
pub trait EncodeMessage {
    /// Takes in a secret and the message and encodes it, returning bytes
    fn encode_message(
        &self,
        _secret: &[u8],
        _msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError>;
}

/// Trait for cryptographically decoding a message
pub trait DecodeMessage {
    /// Takes in a secret, an encoded messages and attempts to decode it, returning bytes
    fn decode_message(
        &self,
        _secret: &[u8],
        _msg: Secret<Vec<u8>, EncryptionStrategy>,
    ) -> CustomResult<Vec<u8>, errors::CryptoError>;
}

/// Represents no cryptographic algorithm.
/// Implements all crypto traits and acts like a Nop
#[derive(Debug)]
pub struct NoAlgorithm;

impl SignMessage for NoAlgorithm {
    fn sign_message(
        &self,
        _secret: &[u8],
        _msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        Ok(Vec::new())
    }
}

impl VerifySignature for NoAlgorithm {
    fn verify_signature(
        &self,
        _secret: &[u8],
        _signature: &[u8],
        _msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        Ok(true)
    }
}

impl EncodeMessage for NoAlgorithm {
    fn encode_message(
        &self,
        _secret: &[u8],
        msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        Ok(msg.to_vec())
    }
}

impl DecodeMessage for NoAlgorithm {
    fn decode_message(
        &self,
        _secret: &[u8],
        msg: Secret<Vec<u8>, EncryptionStrategy>,
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        Ok(msg.expose())
    }
}

/// Represents the HMAC-SHA-1 algorithm
#[derive(Debug)]
pub struct HmacSha1;

impl SignMessage for HmacSha1 {
    fn sign_message(
        &self,
        secret: &[u8],
        msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let key = hmac::Key::new(hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY, secret);
        Ok(hmac::sign(&key, msg).as_ref().to_vec())
    }
}

impl VerifySignature for HmacSha1 {
    fn verify_signature(
        &self,
        secret: &[u8],
        signature: &[u8],
        msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        let key = hmac::Key::new(hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY, secret);

        Ok(hmac::verify(&key, msg, signature).is_ok())
    }
}

/// Represents the HMAC-SHA-256 algorithm
#[derive(Debug)]
pub struct HmacSha256;

impl SignMessage for HmacSha256 {
    fn sign_message(
        &self,
        secret: &[u8],
        msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let key = hmac::Key::new(hmac::HMAC_SHA256, secret);
        Ok(hmac::sign(&key, msg).as_ref().to_vec())
    }
}

impl VerifySignature for HmacSha256 {
    fn verify_signature(
        &self,
        secret: &[u8],
        signature: &[u8],
        msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        let key = hmac::Key::new(hmac::HMAC_SHA256, secret);

        Ok(hmac::verify(&key, msg, signature).is_ok())
    }
}

/// Represents the HMAC-SHA-512 algorithm
#[derive(Debug)]
pub struct HmacSha512;

impl SignMessage for HmacSha512 {
    fn sign_message(
        &self,
        secret: &[u8],
        msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let key = hmac::Key::new(hmac::HMAC_SHA512, secret);
        Ok(hmac::sign(&key, msg).as_ref().to_vec())
    }
}

impl VerifySignature for HmacSha512 {
    fn verify_signature(
        &self,
        secret: &[u8],
        signature: &[u8],
        msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        let key = hmac::Key::new(hmac::HMAC_SHA512, secret);

        Ok(hmac::verify(&key, msg, signature).is_ok())
    }
}

/// Blake3
#[derive(Debug)]
pub struct Blake3(String);

impl Blake3 {
    /// Create a new instance of Blake3 with a key
    pub fn new(key: impl Into<String>) -> Self {
        Self(key.into())
    }
}

impl SignMessage for Blake3 {
    fn sign_message(
        &self,
        secret: &[u8],
        msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let key = blake3::derive_key(&self.0, secret);
        let output = blake3::keyed_hash(&key, msg).as_bytes().to_vec();
        Ok(output)
    }
}

impl VerifySignature for Blake3 {
    fn verify_signature(
        &self,
        secret: &[u8],
        signature: &[u8],
        msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        let key = blake3::derive_key(&self.0, secret);
        let output = blake3::keyed_hash(&key, msg);
        Ok(output.as_bytes() == signature)
    }
}

/// Represents the GCM-AES-256 algorithm
#[derive(Debug)]
pub struct GcmAes256;

impl EncodeMessage for GcmAes256 {
    fn encode_message(
        &self,
        secret: &[u8],
        msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let nonce_sequence =
            NonceSequence::new().change_context(errors::CryptoError::EncodingFailed)?;
        let current_nonce = nonce_sequence.current();
        let key = UnboundKey::new(&aead::AES_256_GCM, secret)
            .change_context(errors::CryptoError::EncodingFailed)?;
        let mut key = SealingKey::new(key, nonce_sequence);
        let mut in_out = msg.to_vec();

        key.seal_in_place_append_tag(aead::Aad::empty(), &mut in_out)
            .change_context(errors::CryptoError::EncodingFailed)?;
        in_out.splice(0..0, current_nonce);

        Ok(in_out)
    }
}

impl DecodeMessage for GcmAes256 {
    fn decode_message(
        &self,
        secret: &[u8],
        msg: Secret<Vec<u8>, EncryptionStrategy>,
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let msg = msg.expose();
        let key = UnboundKey::new(&aead::AES_256_GCM, secret)
            .change_context(errors::CryptoError::DecodingFailed)?;

        let nonce_sequence = NonceSequence::from_bytes(
            <[u8; aead::NONCE_LEN]>::try_from(
                msg.get(..aead::NONCE_LEN)
                    .ok_or(errors::CryptoError::DecodingFailed)
                    .attach_printable("Failed to read the nonce form the encrypted ciphertext")?,
            )
            .change_context(errors::CryptoError::DecodingFailed)?,
        );

        let mut key = OpeningKey::new(key, nonce_sequence);
        let mut binding = msg;
        let output = binding.as_mut_slice();

        let result = key
            .open_within(aead::Aad::empty(), output, aead::NONCE_LEN..)
            .change_context(errors::CryptoError::DecodingFailed)?;

        Ok(result.to_vec())
    }
}
/// Represents the ED25519 signature verification algorithm
#[derive(Debug)]
pub struct Ed25519;

impl Ed25519 {
    /// ED25519 algorithm constants
    const ED25519_PUBLIC_KEY_LEN: usize = 32;
    const ED25519_SIGNATURE_LEN: usize = 64;
    /// Validates ED25519 inputs (public key and signature lengths)
    fn validate_inputs(
        public_key: &[u8],
        signature: &[u8],
    ) -> CustomResult<(), errors::CryptoError> {
        // Validate public key length
        if public_key.len() != Self::ED25519_PUBLIC_KEY_LEN {
            return Err(errors::CryptoError::InvalidKeyLength).attach_printable(format!(
                "Invalid ED25519 public key length: expected {} bytes, got {}",
                Self::ED25519_PUBLIC_KEY_LEN,
                public_key.len()
            ));
        }

        // Validate signature length
        if signature.len() != Self::ED25519_SIGNATURE_LEN {
            return Err(errors::CryptoError::InvalidKeyLength).attach_printable(format!(
                "Invalid ED25519 signature length: expected {} bytes, got {}",
                Self::ED25519_SIGNATURE_LEN,
                signature.len()
            ));
        }

        Ok(())
    }
}

impl VerifySignature for Ed25519 {
    fn verify_signature(
        &self,
        public_key: &[u8],
        signature: &[u8], // ED25519 signature bytes (must be 64 bytes)
        msg: &[u8],       // Message that was signed
    ) -> CustomResult<bool, errors::CryptoError> {
        // Validate inputs first
        Self::validate_inputs(public_key, signature)?;

        // Create unparsed public key
        let ring_public_key =
            ring::signature::UnparsedPublicKey::new(&ring::signature::ED25519, public_key);

        // Perform verification
        match ring_public_key.verify(msg, signature) {
            Ok(()) => Ok(true),
            Err(_err) => {
                #[cfg(feature = "logs")]
                logger::error!("ED25519 signature verification failed: {:?}", _err);
                Err(errors::CryptoError::SignatureVerificationFailed)
                    .attach_printable("ED25519 signature verification failed")
            }
        }
    }
}

impl SignMessage for Ed25519 {
    fn sign_message(
        &self,
        secret: &[u8],
        msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        if secret.len() != 32 {
            return Err(errors::CryptoError::InvalidKeyLength).attach_printable(format!(
                "Invalid ED25519 private key length: expected 32 bytes, got {}",
                secret.len()
            ));
        }
        let key_pair = ring::signature::Ed25519KeyPair::from_seed_unchecked(secret)
            .change_context(errors::CryptoError::MessageSigningFailed)
            .attach_printable("Failed to create ED25519 key pair from seed")?;

        let signature = key_pair.sign(msg);
        Ok(signature.as_ref().to_vec())
    }
}
/// Secure Hash Algorithm 512
#[derive(Debug)]
pub struct Sha512;

/// Secure Hash Algorithm 256
#[derive(Debug)]
pub struct Sha256;

/// Trait for generating a digest for SHA
pub trait GenerateDigest {
    /// takes a message and creates a digest for it
    fn generate_digest(&self, message: &[u8]) -> CustomResult<Vec<u8>, errors::CryptoError>;
}

impl GenerateDigest for Sha512 {
    fn generate_digest(&self, message: &[u8]) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let digest = ring::digest::digest(&ring::digest::SHA512, message);
        Ok(digest.as_ref().to_vec())
    }
}
impl VerifySignature for Sha512 {
    fn verify_signature(
        &self,
        _secret: &[u8],
        signature: &[u8],
        msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        let msg_str = std::str::from_utf8(msg)
            .change_context(errors::CryptoError::EncodingFailed)?
            .to_owned();
        let hashed_digest = hex::encode(
            Self.generate_digest(msg_str.as_bytes())
                .change_context(errors::CryptoError::SignatureVerificationFailed)?,
        );
        let hashed_digest_into_bytes = hashed_digest.into_bytes();
        Ok(hashed_digest_into_bytes == signature)
    }
}
/// MD5 hash function
#[derive(Debug)]
pub struct Md5;

impl GenerateDigest for Md5 {
    fn generate_digest(&self, message: &[u8]) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let digest = md5::compute(message);
        Ok(digest.as_ref().to_vec())
    }
}

impl VerifySignature for Md5 {
    fn verify_signature(
        &self,
        _secret: &[u8],
        signature: &[u8],
        msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        let hashed_digest = Self
            .generate_digest(msg)
            .change_context(errors::CryptoError::SignatureVerificationFailed)?;
        Ok(hashed_digest == signature)
    }
}

impl GenerateDigest for Sha256 {
    fn generate_digest(&self, message: &[u8]) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let digest = ring::digest::digest(&ring::digest::SHA256, message);
        Ok(digest.as_ref().to_vec())
    }
}

impl VerifySignature for Sha256 {
    fn verify_signature(
        &self,
        _secret: &[u8],
        signature: &[u8],
        msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        let hashed_digest = Self
            .generate_digest(msg)
            .change_context(errors::CryptoError::SignatureVerificationFailed)?;
        let hashed_digest_into_bytes = hashed_digest.as_slice();
        Ok(hashed_digest_into_bytes == signature)
    }
}

/// Secure Hash Algorithm 256 with RSA public-key cryptosystem
#[derive(Debug)]
pub struct RsaSha256;

impl VerifySignature for RsaSha256 {
    fn verify_signature(
        &self,
        secret: &[u8],
        signature: &[u8],
        msg: &[u8],
    ) -> CustomResult<bool, errors::CryptoError> {
        // create verifying key
        let decoded_public_key = BASE64_ENGINE
            .decode(secret)
            .change_context(errors::CryptoError::SignatureVerificationFailed)
            .attach_printable("base64 decoding failed")?;

        let string_public_key = String::from_utf8(decoded_public_key)
            .change_context(errors::CryptoError::SignatureVerificationFailed)
            .attach_printable("utf8 to string parsing failed")?;

        let rsa_public_key = rsa::RsaPublicKey::from_public_key_pem(&string_public_key)
            .change_context(errors::CryptoError::SignatureVerificationFailed)
            .attach_printable("rsa public key transformation failed")?;

        let verifying_key = rsa::pkcs1v15::VerifyingKey::<rsa::sha2::Sha256>::new(rsa_public_key);

        // transfrom the signature
        let decoded_signature = BASE64_ENGINE
            .decode(signature)
            .change_context(errors::CryptoError::SignatureVerificationFailed)
            .attach_printable("base64 decoding failed")?;

        let rsa_signature = rsa::pkcs1v15::Signature::try_from(&decoded_signature[..])
            .change_context(errors::CryptoError::SignatureVerificationFailed)
            .attach_printable("rsa signature transformation failed")?;

        // signature verification
        verifying_key
            .verify(msg, &rsa_signature)
            .map(|_| true)
            .change_context(errors::CryptoError::SignatureVerificationFailed)
            .attach_printable("signature verification step failed")
    }
}

/// TripleDesEde3 hash function
#[derive(Debug)]
#[cfg(feature = "crypto_openssl")]
pub struct TripleDesEde3CBC {
    padding: common_enums::CryptoPadding,
    iv: Vec<u8>,
}

#[cfg(feature = "crypto_openssl")]
impl TripleDesEde3CBC {
    const TRIPLE_DES_KEY_LENGTH: usize = 24;
    /// Initialization Vector (IV) length for TripleDesEde3
    pub const TRIPLE_DES_IV_LENGTH: usize = 8;

    /// Constructor function to be used by the encryptor and decryptor to generate the data type
    pub fn new(
        padding: Option<common_enums::CryptoPadding>,
        iv: Vec<u8>,
    ) -> Result<Self, errors::CryptoError> {
        if iv.len() != Self::TRIPLE_DES_IV_LENGTH {
            Err(errors::CryptoError::InvalidIvLength)?
        };
        let padding = padding.unwrap_or(common_enums::CryptoPadding::PKCS7);
        Ok(Self { iv, padding })
    }
}

#[cfg(feature = "crypto_openssl")]
impl EncodeMessage for TripleDesEde3CBC {
    fn encode_message(
        &self,
        secret: &[u8],
        msg: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        if secret.len() != Self::TRIPLE_DES_KEY_LENGTH {
            Err(errors::CryptoError::InvalidKeyLength)?
        }
        let mut buffer = msg.to_vec();

        if let common_enums::CryptoPadding::ZeroPadding = self.padding {
            let pad_len = Self::TRIPLE_DES_IV_LENGTH - (buffer.len() % Self::TRIPLE_DES_IV_LENGTH);
            if pad_len != Self::TRIPLE_DES_IV_LENGTH {
                buffer.extend(vec![0u8; pad_len]);
            }
        };
        let cipher = openssl::symm::Cipher::des_ede3_cbc();
        openssl::symm::encrypt(cipher, secret, Some(&self.iv), &buffer)
            .change_context(errors::CryptoError::EncodingFailed)
    }
}

/// Generate a random string using a cryptographically secure pseudo-random number generator
/// (CSPRNG). Typically used for generating (readable) keys and passwords.
#[inline]
pub fn generate_cryptographically_secure_random_string(length: usize) -> String {
    use rand::distributions::DistString;

    rand::distributions::Alphanumeric.sample_string(&mut rand::rngs::OsRng, length)
}

/// Generate an array of random bytes using a cryptographically secure pseudo-random number
/// generator (CSPRNG). Typically used for generating keys.
#[inline]
pub fn generate_cryptographically_secure_random_bytes<const N: usize>() -> [u8; N] {
    use rand::RngCore;

    let mut bytes = [0; N];
    rand::rngs::OsRng.fill_bytes(&mut bytes);
    bytes
}

/// A wrapper type to store the encrypted data for sensitive pii domain data types
#[derive(Debug, Clone)]
pub struct Encryptable<T: Clone> {
    inner: T,
    encrypted: Secret<Vec<u8>, EncryptionStrategy>,
}

impl<T: Clone, S: masking::Strategy<T>> Encryptable<Secret<T, S>> {
    /// constructor function to be used by the encryptor and decryptor to generate the data type
    pub fn new(
        masked_data: Secret<T, S>,
        encrypted_data: Secret<Vec<u8>, EncryptionStrategy>,
    ) -> Self {
        Self {
            inner: masked_data,
            encrypted: encrypted_data,
        }
    }
}

impl<T: Clone> Encryptable<T> {
    /// Get the inner data while consuming self
    #[inline]
    pub fn into_inner(self) -> T {
        self.inner
    }

    /// Get the reference to inner value
    #[inline]
    pub fn get_inner(&self) -> &T {
        &self.inner
    }

    /// Get the inner encrypted data while consuming self
    #[inline]
    pub fn into_encrypted(self) -> Secret<Vec<u8>, EncryptionStrategy> {
        self.encrypted
    }

    /// Deserialize inner value and return new Encryptable object
    pub fn deserialize_inner_value<U, F>(
        self,
        f: F,
    ) -> CustomResult<Encryptable<U>, errors::ParsingError>
    where
        F: FnOnce(T) -> CustomResult<U, errors::ParsingError>,
        U: Clone,
    {
        let inner = self.inner;
        let encrypted = self.encrypted;
        let inner = f(inner)?;
        Ok(Encryptable { inner, encrypted })
    }

    /// consume self and modify the inner value
    pub fn map<U: Clone>(self, f: impl FnOnce(T) -> U) -> Encryptable<U> {
        let encrypted_data = self.encrypted;
        let masked_data = f(self.inner);
        Encryptable {
            inner: masked_data,
            encrypted: encrypted_data,
        }
    }
}

impl<T: Clone> Deref for Encryptable<Secret<T>> {
    type Target = Secret<T>;
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<T: Clone> masking::Serialize for Encryptable<T>
where
    T: masking::Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.inner.serialize(serializer)
    }
}

impl<T: Clone> PartialEq for Encryptable<T>
where
    T: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.inner.eq(&other.inner)
    }
}

/// Type alias for `Option<Encryptable<Secret<String>>>`
pub type OptionalEncryptableSecretString = Option<Encryptable<Secret<String>>>;
/// Type alias for `Option<Encryptable<Secret<String>>>` used for `name` field
pub type OptionalEncryptableName = Option<Encryptable<Secret<String>>>;
/// Type alias for `Option<Encryptable<Secret<String>>>` used for `email` field
pub type OptionalEncryptableEmail = Option<Encryptable<Secret<String, pii::EmailStrategy>>>;
/// Type alias for `Option<Encryptable<Secret<String>>>` used for `phone` field
pub type OptionalEncryptablePhone = Option<Encryptable<Secret<String>>>;
/// Type alias for `Option<Encryptable<Secret<serde_json::Value>>>`
pub type OptionalEncryptableValue = Option<Encryptable<Secret<serde_json::Value>>>;
/// Type alias for `Option<Secret<serde_json::Value>>`
pub type OptionalSecretValue = Option<Secret<serde_json::Value>>;
/// Type alias for `Encryptable<Secret<String>>` used for `name` field
pub type EncryptableName = Encryptable<Secret<String>>;
/// Type alias for `Encryptable<Secret<String>>` used for `email` field
pub type EncryptableEmail = Encryptable<Secret<String, pii::EmailStrategy>>;

/// Represents the RSA-PSS-SHA256 signing algorithm
#[derive(Debug)]
pub struct RsaPssSha256;

impl SignMessage for RsaPssSha256 {
    fn sign_message(
        &self,
        private_key_pem_bytes: &[u8],
        msg_to_sign: &[u8],
    ) -> CustomResult<Vec<u8>, errors::CryptoError> {
        let parsed_pem = pem::parse(private_key_pem_bytes)
            .change_context(errors::CryptoError::EncodingFailed)
            .attach_printable("Failed to parse PEM string")?;
        let key_pair = match parsed_pem.tag() {
            "PRIVATE KEY" => RsaKeyPair::from_pkcs8(parsed_pem.contents())
                .change_context(errors::CryptoError::InvalidKeyLength)
                .attach_printable("Failed to parse PKCS#8 DER with ring"),
            "RSA PRIVATE KEY" => RsaKeyPair::from_der(parsed_pem.contents())
                .change_context(errors::CryptoError::InvalidKeyLength)
                .attach_printable("Failed to parse PKCS#1 DER (using from_der) with ring"),
            tag => Err(errors::CryptoError::InvalidKeyLength).attach_printable(format!(
                "Unexpected PEM tag: {tag}. Expected 'PRIVATE KEY' or 'RSA PRIVATE KEY'",
            )),
        }?;
        let rng = ring_rand::SystemRandom::new();
        let signature_len = key_pair.public().modulus_len();
        let mut signature_bytes = vec![0; signature_len];
        key_pair
            .sign(&RSA_PSS_SHA256, &rng, msg_to_sign, &mut signature_bytes)
            .change_context(errors::CryptoError::EncodingFailed)
            .attach_printable("Failed to sign data with ring")?;

        Ok(signature_bytes)
    }
}

#[cfg(test)]
mod crypto_tests {
    use super::{DecodeMessage, EncodeMessage, SignMessage, VerifySignature};
    use crate::crypto::GenerateDigest;

    #[test]
    fn test_hmac_sha256_sign_message() {
        let message = r#"{"type":"payment_intent"}"#.as_bytes();
        let secret = "hmac_secret_1234".as_bytes();
        let right_signature =
            hex::decode("d5550730377011948f12cc28889bee590d2a5434d6f54b87562f2dbc2657823e")
                .expect("Right signature decoding");

        let signature = super::HmacSha256
            .sign_message(secret, message)
            .expect("Signature");

        assert_eq!(signature, right_signature);
    }

    #[test]
    fn test_hmac_sha256_verify_signature() {
        let right_signature =
            hex::decode("d5550730377011948f12cc28889bee590d2a5434d6f54b87562f2dbc2657823e")
                .expect("Right signature decoding");
        let wrong_signature =
            hex::decode("d5550730377011948f12cc28889bee590d2a5434d6f54b87562f2dbc2657823f")
                .expect("Wrong signature decoding");
        let secret = "hmac_secret_1234".as_bytes();
        let data = r#"{"type":"payment_intent"}"#.as_bytes();

        let right_verified = super::HmacSha256
            .verify_signature(secret, &right_signature, data)
            .expect("Right signature verification result");

        assert!(right_verified);

        let wrong_verified = super::HmacSha256
            .verify_signature(secret, &wrong_signature, data)
            .expect("Wrong signature verification result");

        assert!(!wrong_verified);
    }

    #[test]
    fn test_sha256_verify_signature() {
        let right_signature =
            hex::decode("123250a72f4e961f31661dbcee0fec0f4714715dc5ae1b573f908a0a5381ddba")
                .expect("Right signature decoding");
        let wrong_signature =
            hex::decode("123250a72f4e961f31661dbcee0fec0f4714715dc5ae1b573f908a0a5381ddbb")
                .expect("Wrong signature decoding");
        let secret = "".as_bytes();
        let data = r#"AJHFH9349JASFJHADJ9834115USD2020-11-13.13:22:34711000000021406655APPROVED12345product_id"#.as_bytes();

        let right_verified = super::Sha256
            .verify_signature(secret, &right_signature, data)
            .expect("Right signature verification result");

        assert!(right_verified);

        let wrong_verified = super::Sha256
            .verify_signature(secret, &wrong_signature, data)
            .expect("Wrong signature verification result");

        assert!(!wrong_verified);
    }

    #[test]
    fn test_hmac_sha512_sign_message() {
        let message = r#"{"type":"payment_intent"}"#.as_bytes();
        let secret = "hmac_secret_1234".as_bytes();
        let right_signature = hex::decode("38b0bc1ea66b14793e39cd58e93d37b799a507442d0dd8d37443fa95dec58e57da6db4742636fea31201c48e57a66e73a308a2e5a5c6bb831e4e39fe2227c00f")
            .expect("signature decoding");

        let signature = super::HmacSha512
            .sign_message(secret, message)
            .expect("Signature");

        assert_eq!(signature, right_signature);
    }

    #[test]
    fn test_hmac_sha512_verify_signature() {
        let right_signature = hex::decode("38b0bc1ea66b14793e39cd58e93d37b799a507442d0dd8d37443fa95dec58e57da6db4742636fea31201c48e57a66e73a308a2e5a5c6bb831e4e39fe2227c00f")
            .expect("signature decoding");
        let wrong_signature =
            hex::decode("d5550730377011948f12cc28889bee590d2a5434d6f54b87562f2dbc2657823f")
                .expect("Wrong signature decoding");
        let secret = "hmac_secret_1234".as_bytes();
        let data = r#"{"type":"payment_intent"}"#.as_bytes();

        let right_verified = super::HmacSha512
            .verify_signature(secret, &right_signature, data)
            .expect("Right signature verification result");

        assert!(right_verified);

        let wrong_verified = super::HmacSha256
            .verify_signature(secret, &wrong_signature, data)
            .expect("Wrong signature verification result");

        assert!(!wrong_verified);
    }

    #[test]
    fn test_gcm_aes_256_encode_message() {
        let message = r#"{"type":"PAYMENT"}"#.as_bytes();
        let secret =
            hex::decode("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f")
                .expect("Secret decoding");
        let algorithm = super::GcmAes256;

        let encoded_message = algorithm
            .encode_message(&secret, message)
            .expect("Encoded message and tag");

        assert_eq!(
            algorithm
                .decode_message(&secret, encoded_message.into())
                .expect("Decode Failed"),
            message
        );
    }

    #[test]
    fn test_gcm_aes_256_decode_message() {
        // Inputs taken from AES GCM test vectors provided by NIST
        // https://github.com/briansmith/ring/blob/95948b3977013aed16db92ae32e6b8384496a740/tests/aead_aes_256_gcm_tests.txt#L447-L452

        let right_secret =
            hex::decode("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308")
                .expect("Secret decoding");
        let wrong_secret =
            hex::decode("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308309")
                .expect("Secret decoding");
        let message =
            // The three parts of the message are the nonce, ciphertext and tag from the test vector
            hex::decode(
                "cafebabefacedbaddecaf888\
                 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad\
                 b094dac5d93471bdec1a502270e3cc6c"
            ).expect("Message decoding");

        let algorithm = super::GcmAes256;

        let decoded = algorithm
            .decode_message(&right_secret, message.clone().into())
            .expect("Decoded message");

        assert_eq!(
            decoded,
            hex::decode("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255")
                .expect("Decoded plaintext message")
        );

        let err_decoded = algorithm.decode_message(&wrong_secret, message.into());

        assert!(err_decoded.is_err());
    }

    #[test]
    fn test_md5_digest() {
        let message = "abcdefghijklmnopqrstuvwxyz".as_bytes();
        assert_eq!(
            format!(
                "{}",
                hex::encode(super::Md5.generate_digest(message).expect("Digest"))
            ),
            "c3fcd3d76192e4007dfb496cca67e13b"
        );
    }

    #[test]
    fn test_md5_verify_signature() {
        let right_signature =
            hex::decode("c3fcd3d76192e4007dfb496cca67e13b").expect("signature decoding");
        let wrong_signature =
            hex::decode("d5550730377011948f12cc28889bee590d2a5434d6f54b87562f2dbc2657823f")
                .expect("Wrong signature decoding");
        let secret = "".as_bytes();
        let data = "abcdefghijklmnopqrstuvwxyz".as_bytes();

        let right_verified = super::Md5
            .verify_signature(secret, &right_signature, data)
            .expect("Right signature verification result");

        assert!(right_verified);

        let wrong_verified = super::Md5
            .verify_signature(secret, &wrong_signature, data)
            .expect("Wrong signature verification result");

        assert!(!wrong_verified);
    }

    use ring::signature::{UnparsedPublicKey, RSA_PSS_2048_8192_SHA256};

    #[test]
    fn test_rsa_pss_sha256_verify_signature() {
        let signer = crate::crypto::RsaPssSha256;
        let message = b"abcdefghijklmnopqrstuvwxyz";

        let private_key_pem_bytes =
            std::fs::read("../../private_key.pem").expect("Failed to read private key");
        let parsed_pem = pem::parse(&private_key_pem_bytes).expect("Failed to parse PEM");
        let private_key_der = parsed_pem.contents();

        let signature = signer
            .sign_message(&private_key_pem_bytes, message)
            .expect("Signing failed");

        let key_pair = crate::crypto::RsaKeyPair::from_pkcs8(private_key_der)
            .expect("Failed to parse DER key");
        let public_key_der = key_pair.public().as_ref().to_vec();

        let public_key = UnparsedPublicKey::new(&RSA_PSS_2048_8192_SHA256, &public_key_der);
        assert!(
            public_key.verify(message, &signature).is_ok(),
            "Right signature should verify"
        );

        let mut wrong_signature = signature.clone();
        if let Some(byte) = wrong_signature.first_mut() {
            *byte ^= 0xFF;
        }

        assert!(
            public_key.verify(message, &wrong_signature).is_err(),
            "Wrong signature should not verify"
        );
    }

    #[test]
    fn test_rsasha256_verify_signature() {
        use base64::Engine;
        use rand::rngs::OsRng;
        use rsa::{
            pkcs8::EncodePublicKey,
            signature::{RandomizedSigner, SignatureEncoding},
        };

        use crate::consts::BASE64_ENGINE;

        let mut rng = OsRng;

        let bits = 2048;
        let private_key = rsa::RsaPrivateKey::new(&mut rng, bits).expect("keygen failed");
        let signing_key = rsa::pkcs1v15::SigningKey::<rsa::sha2::Sha256>::new(private_key.clone());

        let message = "{ This is a test message :) }".as_bytes();

        let signature = signing_key.sign_with_rng(&mut rng, message);
        let encoded_signature = BASE64_ENGINE.encode(signature.to_bytes());

        let rsa_public_key = private_key.to_public_key();
        let pem_format_public_key = rsa_public_key
            .to_public_key_pem(rsa::pkcs8::LineEnding::LF)
            .expect("transformation failed");
        let encoded_pub_key = BASE64_ENGINE.encode(&pem_format_public_key[..]);

        let right_verified = super::RsaSha256
            .verify_signature(
                encoded_pub_key.as_bytes(),
                encoded_signature.as_bytes(),
                message,
            )
            .expect("Right signature verification result");

        assert!(right_verified);
    }
}


// File: crates/common_utils/src/custom_serde.rs

//! Custom serialization/deserialization implementations.

/// Use the well-known ISO 8601 format when serializing and deserializing an
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod iso8601 {
    use std::num::NonZeroU8;

    use serde::{ser::Error as _, Deserializer, Serialize, Serializer};
    use time::{
        format_description::well_known::{
            iso8601::{Config, EncodedConfig, TimePrecision},
            Iso8601,
        },
        serde::iso8601,
        PrimitiveDateTime, UtcOffset,
    };

    const FORMAT_CONFIG: EncodedConfig = Config::DEFAULT
        .set_time_precision(TimePrecision::Second {
            decimal_digits: NonZeroU8::new(3),
        })
        .encode();

    /// Serialize a [`PrimitiveDateTime`] using the well-known ISO 8601 format.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .format(&Iso8601::<FORMAT_CONFIG>)
            .map_err(S::Error::custom)?
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from its ISO 8601 representation.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        iso8601::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }

    /// Use the well-known ISO 8601 format when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option {
        use serde::Serialize;
        use time::format_description::well_known::Iso8601;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] using the well-known ISO 8601 format.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| date_time.assume_utc().format(&Iso8601::<FORMAT_CONFIG>))
                .transpose()
                .map_err(S::Error::custom)?
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from its ISO 8601 representation.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            iso8601::option::deserialize(deserializer).map(|option_offset_date_time| {
                option_offset_date_time.map(|offset_date_time| {
                    let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
                    PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
                })
            })
        }
    }
    /// Use the well-known ISO 8601 format which is without timezone when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option_without_timezone {
        use serde::{de, Deserialize, Serialize};
        use time::macros::format_description;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] using the well-known ISO 8601 format which is without timezone.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| {
                    let format =
                        format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]");
                    date_time.assume_utc().format(format)
                })
                .transpose()
                .map_err(S::Error::custom)?
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from its ISO 8601 representation.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            Option::deserialize(deserializer)?
                .map(|time_string| {
                    let format =
                        format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]");
                    PrimitiveDateTime::parse(time_string, format).map_err(|_| {
                        de::Error::custom(format!(
                            "Failed to parse PrimitiveDateTime from {time_string}"
                        ))
                    })
                })
                .transpose()
        }
    }
}

/// Use the UNIX timestamp when serializing and deserializing an
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod timestamp {

    use serde::{Deserializer, Serialize, Serializer};
    use time::{serde::timestamp, PrimitiveDateTime, UtcOffset};

    /// Serialize a [`PrimitiveDateTime`] using UNIX timestamp.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .unix_timestamp()
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from UNIX timestamp.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        timestamp::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }

    /// Use the UNIX timestamp when serializing and deserializing an
    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
    ///
    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
    pub mod option {
        use serde::Serialize;

        use super::*;

        /// Serialize an [`Option<PrimitiveDateTime>`] from UNIX timestamp.
        pub fn serialize<S>(
            date_time: &Option<PrimitiveDateTime>,
            serializer: S,
        ) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            date_time
                .map(|date_time| date_time.assume_utc().unix_timestamp())
                .serialize(serializer)
        }

        /// Deserialize an [`Option<PrimitiveDateTime>`] from UNIX timestamp.
        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
        where
            D: Deserializer<'a>,
        {
            timestamp::option::deserialize(deserializer).map(|option_offset_date_time| {
                option_offset_date_time.map(|offset_date_time| {
                    let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
                    PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
                })
            })
        }
    }
}

/// <https://github.com/serde-rs/serde/issues/994#issuecomment-316895860>
pub mod json_string {
    use serde::{
        de::{self, Deserialize, DeserializeOwned, Deserializer},
        ser::{self, Serialize, Serializer},
    };

    /// Serialize a type to json_string format
    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where
        T: Serialize,
        S: Serializer,
    {
        let j = serde_json::to_string(value).map_err(ser::Error::custom)?;
        j.serialize(serializer)
    }

    /// Deserialize a string which is in json format
    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
    where
        T: DeserializeOwned,
        D: Deserializer<'de>,
    {
        let j = String::deserialize(deserializer)?;
        serde_json::from_str(&j).map_err(de::Error::custom)
    }
}

/// Use a custom ISO 8601 format when serializing and deserializing
/// [`PrimitiveDateTime`][PrimitiveDateTime].
///
/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
pub mod iso8601custom {

    use serde::{ser::Error as _, Deserializer, Serialize, Serializer};
    use time::{
        format_description::well_known::{
            iso8601::{Config, EncodedConfig, TimePrecision},
            Iso8601,
        },
        serde::iso8601,
        PrimitiveDateTime, UtcOffset,
    };

    const FORMAT_CONFIG: EncodedConfig = Config::DEFAULT
        .set_time_precision(TimePrecision::Second {
            decimal_digits: None,
        })
        .encode();

    /// Serialize a [`PrimitiveDateTime`] using the well-known ISO 8601 format.
    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        date_time
            .assume_utc()
            .format(&Iso8601::<FORMAT_CONFIG>)
            .map_err(S::Error::custom)?
            .replace('T', " ")
            .replace('Z', "")
            .serialize(serializer)
    }

    /// Deserialize an [`PrimitiveDateTime`] from its ISO 8601 representation.
    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
    where
        D: Deserializer<'a>,
    {
        iso8601::deserialize(deserializer).map(|offset_date_time| {
            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
        })
    }
}

#[cfg(test)]
mod tests {
    use serde::{Deserialize, Serialize};
    use serde_json::json;

    #[test]
    fn test_leap_second_parse() {
        #[derive(Serialize, Deserialize)]
        struct Try {
            #[serde(with = "crate::custom_serde::iso8601")]
            f: time::PrimitiveDateTime,
        }
        let leap_second_date_time = json!({"f": "2023-12-31T23:59:60.000Z"});
        let deser = serde_json::from_value::<Try>(leap_second_date_time);

        assert!(deser.is_ok())
    }
}


// File: crates/common_utils/src/metrics/utils.rs

//! metric utility functions

use std::time;

use router_env::opentelemetry;

/// Record the time taken by the future to execute
#[inline]
pub async fn time_future<F, R>(future: F) -> (R, time::Duration)
where
    F: futures::Future<Output = R>,
{
    let start = time::Instant::now();
    let result = future.await;
    let time_spent = start.elapsed();
    (result, time_spent)
}

/// Record the time taken (in seconds) by the operation for the given context
#[inline]
pub async fn record_operation_time<F, R>(
    future: F,
    metric: &opentelemetry::metrics::Histogram<f64>,
    key_value: &[opentelemetry::KeyValue],
) -> R
where
    F: futures::Future<Output = R>,
{
    let (result, time) = time_future(future).await;
    metric.record(time.as_secs_f64(), key_value);
    result
}


// File: crates/common_utils/src/types/primitive_wrappers.rs

pub(crate) mod bool_wrappers {
    use serde::{Deserialize, Serialize};

    /// Bool that represents if Extended Authorization is Applied or not
    #[derive(
        Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, diesel::expression::AsExpression,
    )]
    #[diesel(sql_type = diesel::sql_types::Bool)]
    pub struct ExtendedAuthorizationAppliedBool(bool);
    impl From<bool> for ExtendedAuthorizationAppliedBool {
        fn from(value: bool) -> Self {
            Self(value)
        }
    }
    impl<DB> diesel::serialize::ToSql<diesel::sql_types::Bool, DB> for ExtendedAuthorizationAppliedBool
    where
        DB: diesel::backend::Backend,
        bool: diesel::serialize::ToSql<diesel::sql_types::Bool, DB>,
    {
        fn to_sql<'b>(
            &'b self,
            out: &mut diesel::serialize::Output<'b, '_, DB>,
        ) -> diesel::serialize::Result {
            self.0.to_sql(out)
        }
    }
    impl<DB> diesel::deserialize::FromSql<diesel::sql_types::Bool, DB>
        for ExtendedAuthorizationAppliedBool
    where
        DB: diesel::backend::Backend,
        bool: diesel::deserialize::FromSql<diesel::sql_types::Bool, DB>,
    {
        fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
            bool::from_sql(value).map(Self)
        }
    }

    /// Bool that represents if Extended Authorization is Requested or not
    #[derive(
        Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, diesel::expression::AsExpression,
    )]
    #[diesel(sql_type = diesel::sql_types::Bool)]
    pub struct RequestExtendedAuthorizationBool(bool);
    impl From<bool> for RequestExtendedAuthorizationBool {
        fn from(value: bool) -> Self {
            Self(value)
        }
    }
    impl RequestExtendedAuthorizationBool {
        /// returns the inner bool value
        pub fn is_true(&self) -> bool {
            self.0
        }
    }
    impl<DB> diesel::serialize::ToSql<diesel::sql_types::Bool, DB> for RequestExtendedAuthorizationBool
    where
        DB: diesel::backend::Backend,
        bool: diesel::serialize::ToSql<diesel::sql_types::Bool, DB>,
    {
        fn to_sql<'b>(
            &'b self,
            out: &mut diesel::serialize::Output<'b, '_, DB>,
        ) -> diesel::serialize::Result {
            self.0.to_sql(out)
        }
    }
    impl<DB> diesel::deserialize::FromSql<diesel::sql_types::Bool, DB>
        for RequestExtendedAuthorizationBool
    where
        DB: diesel::backend::Backend,
        bool: diesel::deserialize::FromSql<diesel::sql_types::Bool, DB>,
    {
        fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
            bool::from_sql(value).map(Self)
        }
    }

    /// Bool that represents if Extended Authorization is always Requested or not
    #[derive(
        Clone, Copy, Debug, Eq, PartialEq, diesel::expression::AsExpression, Serialize, Deserialize,
    )]
    #[diesel(sql_type = diesel::sql_types::Bool)]
    pub struct AlwaysRequestExtendedAuthorization(bool);
    impl<DB> diesel::serialize::ToSql<diesel::sql_types::Bool, DB>
        for AlwaysRequestExtendedAuthorization
    where
        DB: diesel::backend::Backend,
        bool: diesel::serialize::ToSql<diesel::sql_types::Bool, DB>,
    {
        fn to_sql<'b>(
            &'b self,
            out: &mut diesel::serialize::Output<'b, '_, DB>,
        ) -> diesel::serialize::Result {
            self.0.to_sql(out)
        }
    }
    impl<DB> diesel::deserialize::FromSql<diesel::sql_types::Bool, DB>
        for AlwaysRequestExtendedAuthorization
    where
        DB: diesel::backend::Backend,
        bool: diesel::deserialize::FromSql<diesel::sql_types::Bool, DB>,
    {
        fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
            bool::from_sql(value).map(Self)
        }
    }
}


// File: crates/common_utils/src/types/user.rs

/// User related types
pub mod core;

/// Theme related types
pub mod theme;

pub use core::*;

pub use theme::*;


// File: crates/common_utils/src/types/keymanager.rs

#![allow(missing_docs)]

use core::fmt;

use base64::Engine;
use masking::{ExposeInterface, PeekInterface, Secret, Strategy, StrongSecret};
#[cfg(feature = "encryption_service")]
use router_env::logger;
#[cfg(feature = "km_forward_x_request_id")]
use router_env::RequestId;
use rustc_hash::FxHashMap;
use serde::{
    de::{self, Unexpected, Visitor},
    ser, Deserialize, Deserializer, Serialize,
};

use crate::{
    consts::BASE64_ENGINE,
    crypto::Encryptable,
    encryption::Encryption,
    errors::{self, CustomResult},
    id_type,
    transformers::{ForeignFrom, ForeignTryFrom},
};

macro_rules! impl_get_tenant_for_request {
    ($ty:ident) => {
        impl GetKeymanagerTenant for $ty {
            fn get_tenant_id(&self, state: &KeyManagerState) -> id_type::TenantId {
                match self.identifier {
                    Identifier::User(_) | Identifier::UserAuth(_) => state.global_tenant_id.clone(),
                    Identifier::Merchant(_) => state.tenant_id.clone(),
                }
            }
        }
    };
}

#[derive(Debug, Clone)]
pub struct KeyManagerState {
    pub tenant_id: id_type::TenantId,
    pub global_tenant_id: id_type::TenantId,
    pub enabled: bool,
    pub url: String,
    pub client_idle_timeout: Option<u64>,
    #[cfg(feature = "km_forward_x_request_id")]
    pub request_id: Option<RequestId>,
    #[cfg(feature = "keymanager_mtls")]
    pub ca: Secret<String>,
    #[cfg(feature = "keymanager_mtls")]
    pub cert: Secret<String>,
    pub infra_values: Option<serde_json::Value>,
}

impl Default for KeyManagerState {
    fn default() -> Self {
        Self::new()
    }
}

impl KeyManagerState {
    pub fn new() -> Self {
        Self {
            tenant_id: id_type::TenantId::get_default_tenant_id(),
            global_tenant_id: id_type::TenantId::get_default_global_tenant_id(),
            enabled: Default::default(),
            url: String::default(),
            client_idle_timeout: Default::default(),
            #[cfg(feature = "km_forward_x_request_id")]
            request_id: Default::default(),
            #[cfg(feature = "keymanager_mtls")]
            ca: Default::default(),
            #[cfg(feature = "keymanager_mtls")]
            cert: Default::default(),
            infra_values: Default::default(),
        }
    }
    pub fn add_confirm_value_in_infra_values(
        &self,
        is_confirm_operation: bool,
    ) -> Option<serde_json::Value> {
        self.infra_values.clone().map(|mut infra_values| {
            if is_confirm_operation {
                infra_values.as_object_mut().map(|obj| {
                    obj.insert(
                        "is_confirm_operation".to_string(),
                        serde_json::Value::Bool(true),
                    )
                });
            }
            infra_values
        })
    }
}

pub trait GetKeymanagerTenant {
    fn get_tenant_id(&self, state: &KeyManagerState) -> id_type::TenantId;
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
#[serde(tag = "data_identifier", content = "key_identifier")]
pub enum Identifier {
    User(String),
    Merchant(id_type::MerchantId),
    UserAuth(String),
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct EncryptionCreateRequest {
    #[serde(flatten)]
    pub identifier: Identifier,
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct EncryptionTransferRequest {
    #[serde(flatten)]
    pub identifier: Identifier,
    pub key: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct DataKeyCreateResponse {
    #[serde(flatten)]
    pub identifier: Identifier,
    pub key_version: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct BatchEncryptDataRequest {
    #[serde(flatten)]
    pub identifier: Identifier,
    pub data: DecryptedDataGroup,
}

impl_get_tenant_for_request!(EncryptionCreateRequest);
impl_get_tenant_for_request!(EncryptionTransferRequest);
impl_get_tenant_for_request!(BatchEncryptDataRequest);

impl<S> From<(Secret<Vec<u8>, S>, Identifier)> for EncryptDataRequest
where
    S: Strategy<Vec<u8>>,
{
    fn from((secret, identifier): (Secret<Vec<u8>, S>, Identifier)) -> Self {
        Self {
            identifier,
            data: DecryptedData(StrongSecret::new(secret.expose())),
        }
    }
}

impl<S> From<(FxHashMap<String, Secret<Vec<u8>, S>>, Identifier)> for BatchEncryptDataRequest
where
    S: Strategy<Vec<u8>>,
{
    fn from((map, identifier): (FxHashMap<String, Secret<Vec<u8>, S>>, Identifier)) -> Self {
        let group = map
            .into_iter()
            .map(|(key, value)| (key, DecryptedData(StrongSecret::new(value.expose()))))
            .collect();
        Self {
            identifier,
            data: DecryptedDataGroup(group),
        }
    }
}

impl<S> From<(Secret<String, S>, Identifier)> for EncryptDataRequest
where
    S: Strategy<String>,
{
    fn from((secret, identifier): (Secret<String, S>, Identifier)) -> Self {
        Self {
            data: DecryptedData(StrongSecret::new(secret.expose().as_bytes().to_vec())),
            identifier,
        }
    }
}

impl<S> From<(Secret<serde_json::Value, S>, Identifier)> for EncryptDataRequest
where
    S: Strategy<serde_json::Value>,
{
    fn from((secret, identifier): (Secret<serde_json::Value, S>, Identifier)) -> Self {
        Self {
            data: DecryptedData(StrongSecret::new(
                secret.expose().to_string().as_bytes().to_vec(),
            )),
            identifier,
        }
    }
}

impl<S> From<(FxHashMap<String, Secret<serde_json::Value, S>>, Identifier)>
    for BatchEncryptDataRequest
where
    S: Strategy<serde_json::Value>,
{
    fn from(
        (map, identifier): (FxHashMap<String, Secret<serde_json::Value, S>>, Identifier),
    ) -> Self {
        let group = map
            .into_iter()
            .map(|(key, value)| {
                (
                    key,
                    DecryptedData(StrongSecret::new(
                        value.expose().to_string().as_bytes().to_vec(),
                    )),
                )
            })
            .collect();
        Self {
            data: DecryptedDataGroup(group),
            identifier,
        }
    }
}

impl<S> From<(FxHashMap<String, Secret<String, S>>, Identifier)> for BatchEncryptDataRequest
where
    S: Strategy<String>,
{
    fn from((map, identifier): (FxHashMap<String, Secret<String, S>>, Identifier)) -> Self {
        let group = map
            .into_iter()
            .map(|(key, value)| {
                (
                    key,
                    DecryptedData(StrongSecret::new(value.expose().as_bytes().to_vec())),
                )
            })
            .collect();
        Self {
            data: DecryptedDataGroup(group),
            identifier,
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct EncryptDataRequest {
    #[serde(flatten)]
    pub identifier: Identifier,
    pub data: DecryptedData,
}

#[derive(Debug, Serialize, serde::Deserialize)]
pub struct DecryptedDataGroup(pub FxHashMap<String, DecryptedData>);

#[derive(Debug, Serialize, Deserialize)]
pub struct BatchEncryptDataResponse {
    pub data: EncryptedDataGroup,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct EncryptDataResponse {
    pub data: EncryptedData,
}

#[derive(Debug, Serialize, serde::Deserialize)]
pub struct EncryptedDataGroup(pub FxHashMap<String, EncryptedData>);
#[derive(Debug)]
pub struct TransientBatchDecryptDataRequest {
    pub identifier: Identifier,
    pub data: FxHashMap<String, StrongSecret<Vec<u8>>>,
}

#[derive(Debug)]
pub struct TransientDecryptDataRequest {
    pub identifier: Identifier,
    pub data: StrongSecret<Vec<u8>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct BatchDecryptDataRequest {
    #[serde(flatten)]
    pub identifier: Identifier,
    pub data: FxHashMap<String, StrongSecret<String>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DecryptDataRequest {
    #[serde(flatten)]
    pub identifier: Identifier,
    pub data: StrongSecret<String>,
}

impl_get_tenant_for_request!(EncryptDataRequest);
impl_get_tenant_for_request!(TransientBatchDecryptDataRequest);
impl_get_tenant_for_request!(TransientDecryptDataRequest);
impl_get_tenant_for_request!(BatchDecryptDataRequest);
impl_get_tenant_for_request!(DecryptDataRequest);

impl<T, S> ForeignFrom<(FxHashMap<String, Secret<T, S>>, BatchEncryptDataResponse)>
    for FxHashMap<String, Encryptable<Secret<T, S>>>
where
    T: Clone,
    S: Strategy<T> + Send,
{
    fn foreign_from(
        (mut masked_data, response): (FxHashMap<String, Secret<T, S>>, BatchEncryptDataResponse),
    ) -> Self {
        response
            .data
            .0
            .into_iter()
            .flat_map(|(k, v)| {
                masked_data.remove(&k).map(|inner| {
                    (
                        k,
                        Encryptable::new(inner.clone(), v.data.peek().clone().into()),
                    )
                })
            })
            .collect()
    }
}

impl<T, S> ForeignFrom<(Secret<T, S>, EncryptDataResponse)> for Encryptable<Secret<T, S>>
where
    T: Clone,
    S: Strategy<T> + Send,
{
    fn foreign_from((masked_data, response): (Secret<T, S>, EncryptDataResponse)) -> Self {
        Self::new(masked_data, response.data.data.peek().clone().into())
    }
}

pub trait DecryptedDataConversion<T: Clone, S: Strategy<T> + Send>: Sized {
    fn convert(
        value: &DecryptedData,
        encryption: Encryption,
    ) -> CustomResult<Self, errors::CryptoError>;
}

impl<S: Strategy<String> + Send> DecryptedDataConversion<String, S>
    for Encryptable<Secret<String, S>>
{
    fn convert(
        value: &DecryptedData,
        encryption: Encryption,
    ) -> CustomResult<Self, errors::CryptoError> {
        let string = String::from_utf8(value.clone().inner().peek().clone()).map_err(|_err| {
            #[cfg(feature = "encryption_service")]
            logger::error!("Decryption error {:?}", _err);
            errors::CryptoError::DecodingFailed
        })?;
        Ok(Self::new(Secret::new(string), encryption.into_inner()))
    }
}

impl<S: Strategy<serde_json::Value> + Send> DecryptedDataConversion<serde_json::Value, S>
    for Encryptable<Secret<serde_json::Value, S>>
{
    fn convert(
        value: &DecryptedData,
        encryption: Encryption,
    ) -> CustomResult<Self, errors::CryptoError> {
        let val = serde_json::from_slice(value.clone().inner().peek()).map_err(|_err| {
            #[cfg(feature = "encryption_service")]
            logger::error!("Decryption error {:?}", _err);
            errors::CryptoError::DecodingFailed
        })?;
        Ok(Self::new(Secret::new(val), encryption.clone().into_inner()))
    }
}

impl<S: Strategy<Vec<u8>> + Send> DecryptedDataConversion<Vec<u8>, S>
    for Encryptable<Secret<Vec<u8>, S>>
{
    fn convert(
        value: &DecryptedData,
        encryption: Encryption,
    ) -> CustomResult<Self, errors::CryptoError> {
        Ok(Self::new(
            Secret::new(value.clone().inner().peek().clone()),
            encryption.clone().into_inner(),
        ))
    }
}

impl<T, S> ForeignTryFrom<(Encryption, DecryptDataResponse)> for Encryptable<Secret<T, S>>
where
    T: Clone,
    S: Strategy<T> + Send,
    Self: DecryptedDataConversion<T, S>,
{
    type Error = error_stack::Report<errors::CryptoError>;
    fn foreign_try_from(
        (encrypted_data, response): (Encryption, DecryptDataResponse),
    ) -> Result<Self, Self::Error> {
        Self::convert(&response.data, encrypted_data)
    }
}

impl<T, S> ForeignTryFrom<(FxHashMap<String, Encryption>, BatchDecryptDataResponse)>
    for FxHashMap<String, Encryptable<Secret<T, S>>>
where
    T: Clone,
    S: Strategy<T> + Send,
    Encryptable<Secret<T, S>>: DecryptedDataConversion<T, S>,
{
    type Error = error_stack::Report<errors::CryptoError>;
    fn foreign_try_from(
        (mut encrypted_data, response): (FxHashMap<String, Encryption>, BatchDecryptDataResponse),
    ) -> Result<Self, Self::Error> {
        response
            .data
            .0
            .into_iter()
            .map(|(k, v)| match encrypted_data.remove(&k) {
                Some(encrypted) => Ok((k.clone(), Encryptable::convert(&v, encrypted.clone())?)),
                None => Err(errors::CryptoError::DecodingFailed)?,
            })
            .collect()
    }
}

impl From<(Encryption, Identifier)> for TransientDecryptDataRequest {
    fn from((encryption, identifier): (Encryption, Identifier)) -> Self {
        Self {
            data: StrongSecret::new(encryption.clone().into_inner().expose()),
            identifier,
        }
    }
}

impl From<(FxHashMap<String, Encryption>, Identifier)> for TransientBatchDecryptDataRequest {
    fn from((map, identifier): (FxHashMap<String, Encryption>, Identifier)) -> Self {
        let data = map
            .into_iter()
            .map(|(k, v)| (k, StrongSecret::new(v.clone().into_inner().expose())))
            .collect();
        Self { data, identifier }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct BatchDecryptDataResponse {
    pub data: DecryptedDataGroup,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DecryptDataResponse {
    pub data: DecryptedData,
}

#[derive(Clone, Debug)]
pub struct DecryptedData(StrongSecret<Vec<u8>>);

impl Serialize for DecryptedData {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let data = BASE64_ENGINE.encode(self.0.peek());
        serializer.serialize_str(&data)
    }
}

impl<'de> Deserialize<'de> for DecryptedData {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct DecryptedDataVisitor;

        impl Visitor<'_> for DecryptedDataVisitor {
            type Value = DecryptedData;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("string of the format {version}:{base64_encoded_data}'")
            }

            fn visit_str<E>(self, value: &str) -> Result<DecryptedData, E>
            where
                E: de::Error,
            {
                let dec_data = BASE64_ENGINE.decode(value).map_err(|err| {
                    let err = err.to_string();
                    E::invalid_value(Unexpected::Str(value), &err.as_str())
                })?;

                Ok(DecryptedData(dec_data.into()))
            }
        }

        deserializer.deserialize_str(DecryptedDataVisitor)
    }
}

impl DecryptedData {
    pub fn from_data(data: StrongSecret<Vec<u8>>) -> Self {
        Self(data)
    }

    pub fn inner(self) -> StrongSecret<Vec<u8>> {
        self.0
    }
}

#[derive(Debug)]
pub struct EncryptedData {
    pub data: StrongSecret<Vec<u8>>,
}

impl Serialize for EncryptedData {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let data = String::from_utf8(self.data.peek().clone()).map_err(ser::Error::custom)?;
        serializer.serialize_str(data.as_str())
    }
}

impl<'de> Deserialize<'de> for EncryptedData {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct EncryptedDataVisitor;

        impl Visitor<'_> for EncryptedDataVisitor {
            type Value = EncryptedData;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("string of the format {version}:{base64_encoded_data}'")
            }

            fn visit_str<E>(self, value: &str) -> Result<EncryptedData, E>
            where
                E: de::Error,
            {
                Ok(EncryptedData {
                    data: StrongSecret::new(value.as_bytes().to_vec()),
                })
            }
        }

        deserializer.deserialize_str(EncryptedDataVisitor)
    }
}

/// A trait which converts the struct to Hashmap required for encryption and back to struct
pub trait ToEncryptable<T, S: Clone, E>: Sized {
    /// Serializes the type to a hashmap
    fn to_encryptable(self) -> FxHashMap<String, E>;
    /// Deserializes the hashmap back to the type
    fn from_encryptable(
        hashmap: FxHashMap<String, Encryptable<S>>,
    ) -> CustomResult<T, errors::ParsingError>;
}


// File: crates/common_utils/src/types/authentication.rs

use crate::id_type;

/// Enum for different levels of authentication
#[derive(
    Clone,
    Debug,
    Hash,
    Eq,
    PartialEq,
    serde::Deserialize,
    serde::Serialize,
    strum::Display,
    strum::EnumString,
)]
pub enum AuthInfo {
    /// OrgLevel: Authentication at the organization level
    OrgLevel {
        /// org_id: OrganizationId
        org_id: id_type::OrganizationId,
    },
    /// MerchantLevel: Authentication at the merchant level
    MerchantLevel {
        /// org_id: OrganizationId
        org_id: id_type::OrganizationId,
        /// merchant_ids: Vec<MerchantId>
        merchant_ids: Vec<id_type::MerchantId>,
    },
    /// ProfileLevel: Authentication at the profile level
    ProfileLevel {
        /// org_id: OrganizationId
        org_id: id_type::OrganizationId,
        /// merchant_id: MerchantId
        merchant_id: id_type::MerchantId,
        /// profile_ids: Vec<ProfileId>
        profile_ids: Vec<id_type::ProfileId>,
    },
}

/// Enum for different resource types supported in client secret
#[cfg(feature = "v2")]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ResourceId {
    /// Global Payment ID (Not exposed in api_models version of enum)
    Payment(id_type::GlobalPaymentId),
    /// Global Customer ID
    Customer(id_type::GlobalCustomerId),
    /// Global Payment Methods Session ID
    PaymentMethodSession(id_type::GlobalPaymentMethodSessionId),
}

#[cfg(feature = "v2")]
impl ResourceId {
    /// Get string representation of enclosed ID type
    pub fn to_str(&self) -> &str {
        match self {
            Self::Payment(id) => id.get_string_repr(),
            Self::Customer(id) => id.get_string_repr(),
            Self::PaymentMethodSession(id) => id.get_string_repr(),
        }
    }
}


// File: crates/common_utils/src/types/user/core.rs

use diesel::{deserialize::FromSqlRow, expression::AsExpression};

use crate::id_type;

/// Struct for lineageContext
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, AsExpression, FromSqlRow)]
#[diesel(sql_type = diesel::sql_types::Jsonb)]
pub struct LineageContext {
    /// user_id: String
    pub user_id: String,

    /// merchant_id: MerchantId
    pub merchant_id: id_type::MerchantId,

    /// role_id: String
    pub role_id: String,

    /// org_id: OrganizationId
    pub org_id: id_type::OrganizationId,

    /// profile_id: ProfileId
    pub profile_id: id_type::ProfileId,

    /// tenant_id: TenantId
    pub tenant_id: id_type::TenantId,
}

crate::impl_to_sql_from_sql_json!(LineageContext);


// File: crates/common_utils/src/types/user/theme.rs

use common_enums::EntityType;
use serde::{Deserialize, Serialize};

use crate::{
    events::{ApiEventMetric, ApiEventsType},
    id_type, impl_api_event_type,
};

/// Enum for having all the required lineage for every level.
/// Currently being used for theme related APIs and queries.
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(tag = "entity_type", rename_all = "snake_case")]
pub enum ThemeLineage {
    /// Tenant lineage variant
    Tenant {
        /// tenant_id: TenantId
        tenant_id: id_type::TenantId,
    },
    /// Org lineage variant
    Organization {
        /// tenant_id: TenantId
        tenant_id: id_type::TenantId,
        /// org_id: OrganizationId
        org_id: id_type::OrganizationId,
    },
    /// Merchant lineage variant
    Merchant {
        /// tenant_id: TenantId
        tenant_id: id_type::TenantId,
        /// org_id: OrganizationId
        org_id: id_type::OrganizationId,
        /// merchant_id: MerchantId
        merchant_id: id_type::MerchantId,
    },
    /// Profile lineage variant
    Profile {
        /// tenant_id: TenantId
        tenant_id: id_type::TenantId,
        /// org_id: OrganizationId
        org_id: id_type::OrganizationId,
        /// merchant_id: MerchantId
        merchant_id: id_type::MerchantId,
        /// profile_id: ProfileId
        profile_id: id_type::ProfileId,
    },
}

impl_api_event_type!(Miscellaneous, (ThemeLineage));

impl ThemeLineage {
    /// Constructor for ThemeLineage
    pub fn new(
        entity_type: EntityType,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
        merchant_id: id_type::MerchantId,
        profile_id: id_type::ProfileId,
    ) -> Self {
        match entity_type {
            EntityType::Tenant => Self::Tenant { tenant_id },
            EntityType::Organization => Self::Organization { tenant_id, org_id },
            EntityType::Merchant => Self::Merchant {
                tenant_id,
                org_id,
                merchant_id,
            },
            EntityType::Profile => Self::Profile {
                tenant_id,
                org_id,
                merchant_id,
                profile_id,
            },
        }
    }

    /// Get the entity_type from the lineage
    pub fn entity_type(&self) -> EntityType {
        match self {
            Self::Tenant { .. } => EntityType::Tenant,
            Self::Organization { .. } => EntityType::Organization,
            Self::Merchant { .. } => EntityType::Merchant,
            Self::Profile { .. } => EntityType::Profile,
        }
    }

    /// Get the tenant_id from the lineage
    pub fn tenant_id(&self) -> &id_type::TenantId {
        match self {
            Self::Tenant { tenant_id }
            | Self::Organization { tenant_id, .. }
            | Self::Merchant { tenant_id, .. }
            | Self::Profile { tenant_id, .. } => tenant_id,
        }
    }

    /// Get the org_id from the lineage
    pub fn org_id(&self) -> Option<&id_type::OrganizationId> {
        match self {
            Self::Tenant { .. } => None,
            Self::Organization { org_id, .. }
            | Self::Merchant { org_id, .. }
            | Self::Profile { org_id, .. } => Some(org_id),
        }
    }

    /// Get the merchant_id from the lineage
    pub fn merchant_id(&self) -> Option<&id_type::MerchantId> {
        match self {
            Self::Tenant { .. } | Self::Organization { .. } => None,
            Self::Merchant { merchant_id, .. } | Self::Profile { merchant_id, .. } => {
                Some(merchant_id)
            }
        }
    }

    /// Get the profile_id from the lineage
    pub fn profile_id(&self) -> Option<&id_type::ProfileId> {
        match self {
            Self::Tenant { .. } | Self::Organization { .. } | Self::Merchant { .. } => None,
            Self::Profile { profile_id, .. } => Some(profile_id),
        }
    }

    /// Get higher lineages from the current lineage
    pub fn get_same_and_higher_lineages(self) -> Vec<Self> {
        match &self {
            Self::Tenant { .. } => vec![self],
            Self::Organization { tenant_id, .. } => vec![
                Self::Tenant {
                    tenant_id: tenant_id.clone(),
                },
                self,
            ],
            Self::Merchant {
                tenant_id, org_id, ..
            } => vec![
                Self::Tenant {
                    tenant_id: tenant_id.clone(),
                },
                Self::Organization {
                    tenant_id: tenant_id.clone(),
                    org_id: org_id.clone(),
                },
                self,
            ],
            Self::Profile {
                tenant_id,
                org_id,
                merchant_id,
                ..
            } => vec![
                Self::Tenant {
                    tenant_id: tenant_id.clone(),
                },
                Self::Organization {
                    tenant_id: tenant_id.clone(),
                    org_id: org_id.clone(),
                },
                Self::Merchant {
                    tenant_id: tenant_id.clone(),
                    org_id: org_id.clone(),
                    merchant_id: merchant_id.clone(),
                },
                self,
            ],
        }
    }
}

/// Struct for holding the theme settings for email
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct EmailThemeConfig {
    /// The entity name to be used in the email
    pub entity_name: String,

    /// The URL of the entity logo to be used in the email
    pub entity_logo_url: String,

    /// The primary color to be used in the email
    pub primary_color: String,

    /// The foreground color to be used in the email
    pub foreground_color: String,

    /// The background color to be used in the email
    pub background_color: String,
}


// File: crates/common_utils/src/id_type/refunds.rs

crate::id_type!(RefundReferenceId, "A type for refund_reference_id");
crate::impl_id_type_methods!(RefundReferenceId, "refund_reference_id");

// This is to display the `RefundReferenceId` as RefundReferenceId(abcd)
crate::impl_debug_id_type!(RefundReferenceId);
crate::impl_try_from_cow_str_id_type!(RefundReferenceId, "refund_reference_id");

// Database related implementations so that this field can be used directly in the database tables
crate::impl_queryable_id_type!(RefundReferenceId);
crate::impl_to_sql_from_sql_id_type!(RefundReferenceId);


// File: crates/common_utils/src/id_type/organization.rs

use crate::errors::{CustomResult, ValidationError};

crate::id_type!(
    OrganizationId,
    "A type for organization_id that can be used for organization ids"
);
crate::impl_id_type_methods!(OrganizationId, "organization_id");

// This is to display the `OrganizationId` as OrganizationId(abcd)
crate::impl_debug_id_type!(OrganizationId);
crate::impl_default_id_type!(OrganizationId, "org");
crate::impl_try_from_cow_str_id_type!(OrganizationId, "organization_id");

crate::impl_generate_id_id_type!(OrganizationId, "org");
crate::impl_serializable_secret_id_type!(OrganizationId);
crate::impl_queryable_id_type!(OrganizationId);
crate::impl_to_sql_from_sql_id_type!(OrganizationId);

impl OrganizationId {
    /// Get an organization id from String
    pub fn try_from_string(org_id: String) -> CustomResult<Self, ValidationError> {
        Self::try_from(std::borrow::Cow::from(org_id))
    }
}


// File: crates/common_utils/src/id_type/payout.rs

crate::id_type!(
    PayoutId,
    "A domain type for payout_id that can be used for payout ids"
);
crate::impl_id_type_methods!(PayoutId, "payout_id");
crate::impl_debug_id_type!(PayoutId);
crate::impl_try_from_cow_str_id_type!(PayoutId, "payout_id");
crate::impl_generate_id_id_type!(PayoutId, "payout");
crate::impl_queryable_id_type!(PayoutId);
crate::impl_to_sql_from_sql_id_type!(PayoutId);


// File: crates/common_utils/src/id_type/profile.rs

use std::str::FromStr;

crate::id_type!(
    ProfileId,
    "A type for profile_id that can be used for business profile ids"
);
crate::impl_id_type_methods!(ProfileId, "profile_id");

// This is to display the `ProfileId` as ProfileId(abcd)
crate::impl_debug_id_type!(ProfileId);
crate::impl_try_from_cow_str_id_type!(ProfileId, "profile_id");
crate::impl_generate_id_id_type!(ProfileId, "pro");
crate::impl_serializable_secret_id_type!(ProfileId);
crate::impl_queryable_id_type!(ProfileId);
crate::impl_to_sql_from_sql_id_type!(ProfileId);

impl crate::events::ApiEventMetric for ProfileId {
    fn get_api_event_type(&self) -> Option<crate::events::ApiEventsType> {
        Some(crate::events::ApiEventsType::BusinessProfile {
            profile_id: self.clone(),
        })
    }
}

impl FromStr for ProfileId {
    type Err = error_stack::Report<crate::errors::ValidationError>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let cow_string = std::borrow::Cow::Owned(s.to_string());
        Self::try_from(cow_string)
    }
}

// This is implemented so that we can use profile id directly as attribute in metrics
#[cfg(feature = "metrics")]
impl From<ProfileId> for router_env::opentelemetry::Value {
    fn from(val: ProfileId) -> Self {
        Self::from(val.0 .0 .0)
    }
}


// File: crates/common_utils/src/id_type/tenant.rs

use crate::{
    consts::{DEFAULT_GLOBAL_TENANT_ID, DEFAULT_TENANT},
    errors::{CustomResult, ValidationError},
};

crate::id_type!(
    TenantId,
    "A type for tenant_id that can be used for unique identifier for a tenant"
);
crate::impl_id_type_methods!(TenantId, "tenant_id");

// This is to display the `TenantId` as TenantId(abcd)
crate::impl_debug_id_type!(TenantId);
crate::impl_try_from_cow_str_id_type!(TenantId, "tenant_id");

crate::impl_serializable_secret_id_type!(TenantId);
crate::impl_queryable_id_type!(TenantId);
crate::impl_to_sql_from_sql_id_type!(TenantId);

impl TenantId {
    /// Get the default global tenant ID
    pub fn get_default_global_tenant_id() -> Self {
        Self(super::LengthId::new_unchecked(
            super::AlphaNumericId::new_unchecked(DEFAULT_GLOBAL_TENANT_ID.to_string()),
        ))
    }

    /// Get the default tenant ID
    pub fn get_default_tenant_id() -> Self {
        Self(super::LengthId::new_unchecked(
            super::AlphaNumericId::new_unchecked(DEFAULT_TENANT.to_string()),
        ))
    }

    /// Get tenant id from String
    pub fn try_from_string(tenant_id: String) -> CustomResult<Self, ValidationError> {
        Self::try_from(std::borrow::Cow::from(tenant_id))
    }
}


// File: crates/common_utils/src/id_type/merchant_connector_account.rs

use std::str::FromStr;

use crate::errors::{CustomResult, ValidationError};

crate::id_type!(
    MerchantConnectorAccountId,
    "A type for merchant_connector_id that can be used for merchant_connector_account ids"
);
crate::impl_id_type_methods!(MerchantConnectorAccountId, "merchant_connector_id");

// This is to display the `MerchantConnectorAccountId` as MerchantConnectorAccountId(abcd)
crate::impl_debug_id_type!(MerchantConnectorAccountId);
crate::impl_generate_id_id_type!(MerchantConnectorAccountId, "mca");
crate::impl_try_from_cow_str_id_type!(MerchantConnectorAccountId, "merchant_connector_id");

crate::impl_serializable_secret_id_type!(MerchantConnectorAccountId);
crate::impl_queryable_id_type!(MerchantConnectorAccountId);
crate::impl_to_sql_from_sql_id_type!(MerchantConnectorAccountId);

impl MerchantConnectorAccountId {
    /// Get a merchant connector account id from String
    pub fn wrap(merchant_connector_account_id: String) -> CustomResult<Self, ValidationError> {
        Self::try_from(std::borrow::Cow::from(merchant_connector_account_id))
    }
}

impl FromStr for MerchantConnectorAccountId {
    type Err = std::fmt::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::try_from(std::borrow::Cow::Owned(s.to_string())).map_err(|_| std::fmt::Error)
    }
}


// File: crates/common_utils/src/id_type/client_secret.rs

crate::id_type!(
    ClientSecretId,
    "A type for key_id that can be used for Ephemeral key IDs"
);
crate::impl_id_type_methods!(ClientSecretId, "key_id");

// This is to display the `ClientSecretId` as ClientSecretId(abcd)
crate::impl_debug_id_type!(ClientSecretId);
crate::impl_try_from_cow_str_id_type!(ClientSecretId, "key_id");

crate::impl_generate_id_id_type!(ClientSecretId, "csi");
crate::impl_serializable_secret_id_type!(ClientSecretId);
crate::impl_queryable_id_type!(ClientSecretId);
crate::impl_to_sql_from_sql_id_type!(ClientSecretId);

#[cfg(feature = "v2")]
impl crate::events::ApiEventMetric for ClientSecretId {
    fn get_api_event_type(&self) -> Option<crate::events::ApiEventsType> {
        Some(crate::events::ApiEventsType::ClientSecret {
            key_id: self.clone(),
        })
    }
}

crate::impl_default_id_type!(ClientSecretId, "key");

impl ClientSecretId {
    /// Generate a key for redis
    pub fn generate_redis_key(&self) -> String {
        format!("cs_{}", self.get_string_repr())
    }
}