// File: crates/api_models/src/verifications.rs

use common_utils::id_type;

/// The request body for verification of merchant (everything except domain_names are prefilled)
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplepayMerchantVerificationConfigs {
    pub domain_names: Vec<String>,
    pub encrypt_to: String,
    pub partner_internal_merchant_identifier: String,
    pub partner_merchant_name: String,
}

/// The derivation point for domain names from request body
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ApplepayMerchantVerificationRequest {
    pub domain_names: Vec<String>,
    pub merchant_connector_account_id: id_type::MerchantConnectorAccountId,
}

/// Response to be sent for the verify/applepay api
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ApplepayMerchantResponse {
    pub status_message: String,
}

/// QueryParams to be send by the merchant for fetching the verified domains
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ApplepayGetVerifiedDomainsParam {
    pub merchant_id: id_type::MerchantId,
    pub merchant_connector_account_id: id_type::MerchantConnectorAccountId,
}
/// Response to be sent for derivation of the already verified domains
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ApplepayVerifiedDomainsResponse {
    pub verified_domains: Vec<String>,
}


// File: crates/api_models/src/connector_enums.rs

pub use common_enums::connector_enums::Connector;


// File: crates/api_models/src/proxy.rs

use std::collections::HashMap;

use common_utils::request::Method;
use reqwest::header::HeaderMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use utoipa::ToSchema;

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Headers(pub HashMap<String, String>);

impl Headers {
    pub fn as_map(&self) -> &HashMap<String, String> {
        &self.0
    }

    pub fn from_header_map(headers: Option<&HeaderMap>) -> Self {
        headers
            .map(|h| {
                let map = h
                    .iter()
                    .map(|(k, v)| (k.to_string(), v.to_str().unwrap_or("").to_string()))
                    .collect();
                Self(map)
            })
            .unwrap_or_else(|| Self(HashMap::new()))
    }
}

#[derive(Debug, ToSchema, Clone, Deserialize, Serialize)]
pub struct ProxyRequest {
    /// The request body that needs to be forwarded
    pub request_body: Value,
    /// The destination URL where the request needs to be forwarded
    #[schema(value_type = String, example = "https://api.example.com/endpoint")]
    pub destination_url: url::Url,
    /// The headers that need to be forwarded
    #[schema(value_type = Object, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)]
    pub headers: Headers,
    /// The method that needs to be used for the request
    #[schema(value_type = Method, example = "Post")]
    pub method: Method,
    /// The vault token that is used to fetch sensitive data from the vault
    pub token: String,
    /// The type of token that is used to fetch sensitive data from the vault
    #[schema(value_type = TokenType, example = "payment_method_id")]
    pub token_type: TokenType,
}

#[derive(Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum TokenType {
    TokenizationId,
    PaymentMethodId,
}

#[derive(Debug, ToSchema, Clone, Deserialize, Serialize)]
pub struct ProxyResponse {
    /// The response received from the destination
    pub response: Value,
    /// The status code of the response
    pub status_code: u16,
    /// The headers of the response
    #[schema(value_type = Object, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)]
    pub response_headers: Headers,
}

impl common_utils::events::ApiEventMetric for ProxyRequest {}
impl common_utils::events::ApiEventMetric for ProxyResponse {}


// File: crates/api_models/src/events.rs

pub mod apple_pay_certificates_migration;
pub mod chat;
pub mod connector_onboarding;
pub mod customer;
pub mod dispute;
pub mod external_service_auth;
pub mod gsm;
mod locker_migration;
pub mod payment;
#[cfg(feature = "payouts")]
pub mod payouts;
#[cfg(feature = "recon")]
pub mod recon;
pub mod refund;
#[cfg(feature = "v2")]
pub mod revenue_recovery;
pub mod routing;
pub mod user;
pub mod user_role;
use common_utils::{
    events::{ApiEventMetric, ApiEventsType},
    impl_api_event_type,
};

use crate::customers::CustomerListRequest;
#[cfg(feature = "tokenization_v2")]
use crate::tokenization;
#[allow(unused_imports)]
use crate::{
    admin::*,
    analytics::{
        api_event::*, auth_events::*, connector_events::ConnectorEventsRequest,
        outgoing_webhook_event::OutgoingWebhookLogsRequest, routing_events::RoutingEventsRequest,
        sdk_events::*, search::*, *,
    },
    api_keys::*,
    cards_info::*,
    disputes::*,
    files::*,
    mandates::*,
    organization::{
        OrganizationCreateRequest, OrganizationId, OrganizationResponse, OrganizationUpdateRequest,
    },
    payment_methods::*,
    payments::*,
    user::{UserKeyTransferRequest, UserTransferKeyResponse},
    verifications::*,
};

impl ApiEventMetric for GetPaymentIntentFiltersRequest {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Analytics)
    }
}

impl ApiEventMetric for GetPaymentIntentMetricRequest {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Analytics)
    }
}

impl ApiEventMetric for PaymentIntentFiltersResponse {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Analytics)
    }
}

impl_api_event_type!(
    Miscellaneous,
    (
        PaymentMethodId,
        PaymentMethodCreate,
        PaymentLinkInitiateRequest,
        RetrievePaymentLinkResponse,
        MandateListConstraints,
        CreateFileResponse,
        MerchantConnectorResponse,
        MerchantConnectorId,
        MandateResponse,
        MandateRevokedResponse,
        RetrievePaymentLinkRequest,
        PaymentLinkListConstraints,
        MandateId,
        DisputeListGetConstraints,
        RetrieveApiKeyResponse,
        ProfileResponse,
        ProfileUpdate,
        ProfileCreate,
        RevokeApiKeyResponse,
        ToggleKVResponse,
        ToggleKVRequest,
        ToggleAllKVRequest,
        ToggleAllKVResponse,
        MerchantAccountDeleteResponse,
        MerchantAccountUpdate,
        CardInfoResponse,
        CreateApiKeyResponse,
        CreateApiKeyRequest,
        ListApiKeyConstraints,
        MerchantConnectorDeleteResponse,
        MerchantConnectorUpdate,
        MerchantConnectorCreate,
        MerchantId,
        CardsInfoRequest,
        MerchantAccountResponse,
        MerchantAccountListRequest,
        MerchantAccountCreate,
        PaymentsSessionRequest,
        ApplepayMerchantVerificationRequest,
        ApplepayMerchantResponse,
        ApplepayVerifiedDomainsResponse,
        UpdateApiKeyRequest,
        GetApiEventFiltersRequest,
        ApiEventFiltersResponse,
        GetInfoResponse,
        GetPaymentMetricRequest,
        GetRefundMetricRequest,
        GetActivePaymentsMetricRequest,
        GetSdkEventMetricRequest,
        GetAuthEventMetricRequest,
        GetAuthEventFilterRequest,
        GetPaymentFiltersRequest,
        PaymentFiltersResponse,
        GetRefundFilterRequest,
        RefundFiltersResponse,
        AuthEventFiltersResponse,
        GetSdkEventFiltersRequest,
        SdkEventFiltersResponse,
        ApiLogsRequest,
        GetApiEventMetricRequest,
        SdkEventsRequest,
        ReportRequest,
        ConnectorEventsRequest,
        OutgoingWebhookLogsRequest,
        GetGlobalSearchRequest,
        GetSearchRequest,
        GetSearchResponse,
        GetSearchRequestWithIndex,
        GetDisputeFilterRequest,
        DisputeFiltersResponse,
        GetDisputeMetricRequest,
        SankeyResponse,
        OrganizationResponse,
        OrganizationCreateRequest,
        OrganizationUpdateRequest,
        OrganizationId,
        CustomerListRequest,
        RoutingEventsRequest
    )
);

impl_api_event_type!(
    Keymanager,
    (
        TransferKeyResponse,
        MerchantKeyTransferRequest,
        UserKeyTransferRequest,
        UserTransferKeyResponse
    )
);

impl<T> ApiEventMetric for MetricsResponse<T> {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Miscellaneous)
    }
}

impl<T> ApiEventMetric for PaymentsMetricsResponse<T> {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Miscellaneous)
    }
}

impl<T> ApiEventMetric for PaymentIntentsMetricsResponse<T> {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Miscellaneous)
    }
}

impl<T> ApiEventMetric for RefundsMetricsResponse<T> {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Miscellaneous)
    }
}

impl<T> ApiEventMetric for DisputesMetricsResponse<T> {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Miscellaneous)
    }
}

impl<T> ApiEventMetric for AuthEventMetricsResponse<T> {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Miscellaneous)
    }
}

#[cfg(feature = "v2")]
impl ApiEventMetric for PaymentMethodIntentConfirmInternal {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::PaymentMethod {
            payment_method_id: self.id.clone(),
            payment_method_type: Some(self.request.payment_method_type),
            payment_method_subtype: Some(self.request.payment_method_subtype),
        })
    }
}

#[cfg(feature = "v2")]
impl ApiEventMetric for PaymentMethodIntentCreate {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::PaymentMethodCreate)
    }
}

impl ApiEventMetric for DisputeListFilters {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::ResourceListAPI)
    }
}

#[cfg(feature = "v2")]
impl ApiEventMetric for PaymentMethodSessionRequest {}

#[cfg(feature = "v2")]
impl ApiEventMetric for PaymentMethodsSessionUpdateRequest {}

#[cfg(feature = "v2")]
impl ApiEventMetric for PaymentMethodSessionResponse {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::PaymentMethodSession {
            payment_method_session_id: self.id.clone(),
        })
    }
}
#[cfg(feature = "tokenization_v2")]
impl ApiEventMetric for tokenization::GenericTokenizationRequest {}

#[cfg(feature = "tokenization_v2")]
impl ApiEventMetric for tokenization::GenericTokenizationResponse {}

#[cfg(feature = "tokenization_v2")]
impl ApiEventMetric for tokenization::DeleteTokenDataResponse {}

#[cfg(feature = "tokenization_v2")]
impl ApiEventMetric for tokenization::DeleteTokenDataRequest {}


// File: crates/api_models/src/open_router.rs

use std::{collections::HashMap, fmt::Debug};

use common_utils::{errors, id_type, types::MinorUnit};
pub use euclid::{
    dssa::types::EuclidAnalysable,
    frontend::{
        ast,
        dir::{DirKeyKind, EuclidDirFilter},
    },
};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use crate::{
    enums::{Currency, PaymentMethod},
    payment_methods,
};

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct OpenRouterDecideGatewayRequest {
    pub payment_info: PaymentInfo,
    #[schema(value_type = String)]
    pub merchant_id: id_type::ProfileId,
    pub eligible_gateway_list: Option<Vec<String>>,
    pub ranking_algorithm: Option<RankingAlgorithm>,
    pub elimination_enabled: Option<bool>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DecideGatewayResponse {
    pub decided_gateway: Option<String>,
    pub gateway_priority_map: Option<serde_json::Value>,
    pub filter_wise_gateways: Option<serde_json::Value>,
    pub priority_logic_tag: Option<String>,
    pub routing_approach: Option<String>,
    pub gateway_before_evaluation: Option<String>,
    pub priority_logic_output: Option<PriorityLogicOutput>,
    pub reset_approach: Option<String>,
    pub routing_dimension: Option<String>,
    pub routing_dimension_level: Option<String>,
    pub is_scheduled_outage: Option<bool>,
    pub is_dynamic_mga_enabled: Option<bool>,
    pub gateway_mga_id_map: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct PriorityLogicOutput {
    pub is_enforcement: Option<bool>,
    pub gws: Option<Vec<String>>,
    pub priority_logic_tag: Option<String>,
    pub gateway_reference_ids: Option<HashMap<String, String>>,
    pub primary_logic: Option<PriorityLogicData>,
    pub fallback_logic: Option<PriorityLogicData>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct PriorityLogicData {
    pub name: Option<String>,
    pub status: Option<String>,
    pub failure_reason: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ToSchema)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RankingAlgorithm {
    SrBasedRouting,
    PlBasedRouting,
    NtwBasedRouting,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct PaymentInfo {
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
    pub amount: MinorUnit,
    pub currency: Currency,
    // customerId: Option<ETCu::CustomerId>,
    // preferredGateway: Option<ETG::Gateway>,
    pub payment_type: String,
    pub metadata: Option<String>,
    // internalMetadata: Option<String>,
    // isEmi: Option<bool>,
    // emiBank: Option<String>,
    // emiTenure: Option<i32>,
    pub payment_method_type: String,
    pub payment_method: PaymentMethod,
    // paymentSource: Option<String>,
    // authType: Option<ETCa::txn_card_info::AuthType>,
    // cardIssuerBankName: Option<String>,
    pub card_isin: Option<String>,
    // cardType: Option<ETCa::card_type::CardType>,
    // cardSwitchProvider: Option<Secret<String>>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct DecidedGateway {
    pub gateway_priority_map: Option<HashMap<String, f64>>,
    pub debit_routing_output: Option<DebitRoutingOutput>,
    pub routing_approach: String,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct DebitRoutingOutput {
    pub co_badged_card_networks_info: CoBadgedCardNetworks,
    pub issuer_country: common_enums::CountryAlpha2,
    pub is_regulated: bool,
    pub regulated_name: Option<common_enums::RegulatedName>,
    pub card_type: common_enums::CardType,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct CoBadgedCardNetworksInfo {
    pub network: common_enums::CardNetwork,
    pub saving_percentage: f64,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct CoBadgedCardNetworks(pub Vec<CoBadgedCardNetworksInfo>);

impl CoBadgedCardNetworks {
    pub fn get_card_networks(&self) -> Vec<common_enums::CardNetwork> {
        self.0.iter().map(|info| info.network.clone()).collect()
    }

    pub fn get_signature_network(&self) -> Option<common_enums::CardNetwork> {
        self.0
            .iter()
            .find(|info| info.network.is_signature_network())
            .map(|info| info.network.clone())
    }
}

impl From<&DebitRoutingOutput> for payment_methods::CoBadgedCardData {
    fn from(output: &DebitRoutingOutput) -> Self {
        Self {
            co_badged_card_networks_info: output.co_badged_card_networks_info.clone(),
            issuer_country_code: output.issuer_country,
            is_regulated: output.is_regulated,
            regulated_name: output.regulated_name.clone(),
        }
    }
}

impl TryFrom<(payment_methods::CoBadgedCardData, String)> for DebitRoutingRequestData {
    type Error = error_stack::Report<errors::ParsingError>;

    fn try_from(
        (output, card_type): (payment_methods::CoBadgedCardData, String),
    ) -> Result<Self, Self::Error> {
        let parsed_card_type = card_type.parse::<common_enums::CardType>().map_err(|_| {
            error_stack::Report::new(errors::ParsingError::EnumParseFailure("CardType"))
        })?;

        Ok(Self {
            co_badged_card_networks_info: output.co_badged_card_networks_info.get_card_networks(),
            issuer_country: output.issuer_country_code,
            is_regulated: output.is_regulated,
            regulated_name: output.regulated_name,
            card_type: parsed_card_type,
        })
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CoBadgedCardRequest {
    pub merchant_category_code: common_enums::DecisionEngineMerchantCategoryCode,
    pub acquirer_country: common_enums::CountryAlpha2,
    pub co_badged_card_data: Option<DebitRoutingRequestData>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct DebitRoutingRequestData {
    pub co_badged_card_networks_info: Vec<common_enums::CardNetwork>,
    pub issuer_country: common_enums::CountryAlpha2,
    pub is_regulated: bool,
    pub regulated_name: Option<common_enums::RegulatedName>,
    pub card_type: common_enums::CardType,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ErrorResponse {
    pub status: String,
    pub error_code: String,
    pub error_message: String,
    pub priority_logic_tag: Option<String>,
    pub filter_wise_gateways: Option<serde_json::Value>,
    pub error_info: UnifiedError,
    pub is_dynamic_mga_enabled: bool,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UnifiedError {
    pub code: String,
    pub user_message: String,
    pub developer_message: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateScorePayload {
    #[schema(value_type = String)]
    pub merchant_id: id_type::ProfileId,
    pub gateway: String,
    pub status: TxnStatus,
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
}

#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct UpdateScoreResponse {
    pub message: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum TxnStatus {
    Started,
    AuthenticationFailed,
    JuspayDeclined,
    PendingVbv,
    VBVSuccessful,
    Authorized,
    AuthorizationFailed,
    Charged,
    Authorizing,
    CODInitiated,
    Voided,
    VoidedPostCharge,
    VoidInitiated,
    Nop,
    CaptureInitiated,
    CaptureFailed,
    VoidFailed,
    AutoRefunded,
    PartialCharged,
    ToBeCharged,
    Pending,
    Failure,
    Declined,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DecisionEngineConfigSetupRequest {
    pub merchant_id: String,
    pub config: DecisionEngineConfigVariant,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct GetDecisionEngineConfigRequest {
    pub merchant_id: String,
    pub algorithm: DecisionEngineDynamicAlgorithmType,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub enum DecisionEngineDynamicAlgorithmType {
    SuccessRate,
    Elimination,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type", content = "data")]
#[serde(rename_all = "camelCase")]
pub enum DecisionEngineConfigVariant {
    SuccessRate(DecisionEngineSuccessRateData),
    Elimination(DecisionEngineEliminationData),
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct DecisionEngineSuccessRateData {
    pub default_latency_threshold: Option<f64>,
    pub default_bucket_size: Option<i32>,
    pub default_hedging_percent: Option<f64>,
    pub default_lower_reset_factor: Option<f64>,
    pub default_upper_reset_factor: Option<f64>,
    pub default_gateway_extra_score: Option<Vec<DecisionEngineGatewayWiseExtraScore>>,
    pub sub_level_input_config: Option<Vec<DecisionEngineSRSubLevelInputConfig>>,
}

impl DecisionEngineSuccessRateData {
    pub fn update(&mut self, new_config: Self) {
        if let Some(threshold) = new_config.default_latency_threshold {
            self.default_latency_threshold = Some(threshold);
        }
        if let Some(bucket_size) = new_config.default_bucket_size {
            self.default_bucket_size = Some(bucket_size);
        }
        if let Some(hedging_percent) = new_config.default_hedging_percent {
            self.default_hedging_percent = Some(hedging_percent);
        }
        if let Some(lower_reset_factor) = new_config.default_lower_reset_factor {
            self.default_lower_reset_factor = Some(lower_reset_factor);
        }
        if let Some(upper_reset_factor) = new_config.default_upper_reset_factor {
            self.default_upper_reset_factor = Some(upper_reset_factor);
        }
        if let Some(gateway_extra_score) = new_config.default_gateway_extra_score {
            self.default_gateway_extra_score
                .as_mut()
                .map(|score| score.extend(gateway_extra_score));
        }
        if let Some(sub_level_input_config) = new_config.sub_level_input_config {
            self.sub_level_input_config.as_mut().map(|config| {
                config.extend(sub_level_input_config);
            });
        }
    }
}
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct DecisionEngineSRSubLevelInputConfig {
    pub payment_method_type: Option<String>,
    pub payment_method: Option<String>,
    pub latency_threshold: Option<f64>,
    pub bucket_size: Option<i32>,
    pub hedging_percent: Option<f64>,
    pub lower_reset_factor: Option<f64>,
    pub upper_reset_factor: Option<f64>,
    pub gateway_extra_score: Option<Vec<DecisionEngineGatewayWiseExtraScore>>,
}

impl DecisionEngineSRSubLevelInputConfig {
    pub fn update(&mut self, new_config: Self) {
        if let Some(payment_method_type) = new_config.payment_method_type {
            self.payment_method_type = Some(payment_method_type);
        }
        if let Some(payment_method) = new_config.payment_method {
            self.payment_method = Some(payment_method);
        }
        if let Some(latency_threshold) = new_config.latency_threshold {
            self.latency_threshold = Some(latency_threshold);
        }
        if let Some(bucket_size) = new_config.bucket_size {
            self.bucket_size = Some(bucket_size);
        }
        if let Some(hedging_percent) = new_config.hedging_percent {
            self.hedging_percent = Some(hedging_percent);
        }
        if let Some(lower_reset_factor) = new_config.lower_reset_factor {
            self.lower_reset_factor = Some(lower_reset_factor);
        }
        if let Some(upper_reset_factor) = new_config.upper_reset_factor {
            self.upper_reset_factor = Some(upper_reset_factor);
        }
        if let Some(gateway_extra_score) = new_config.gateway_extra_score {
            self.gateway_extra_score
                .as_mut()
                .map(|score| score.extend(gateway_extra_score));
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct DecisionEngineGatewayWiseExtraScore {
    pub gateway_name: String,
    pub gateway_sigma_factor: f64,
}

impl DecisionEngineGatewayWiseExtraScore {
    pub fn update(&mut self, new_config: Self) {
        self.gateway_name = new_config.gateway_name;
        self.gateway_sigma_factor = new_config.gateway_sigma_factor;
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct DecisionEngineEliminationData {
    pub threshold: f64,
}

impl DecisionEngineEliminationData {
    pub fn update(&mut self, new_config: Self) {
        self.threshold = new_config.threshold;
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MerchantAccount {
    pub merchant_id: String,
    pub gateway_success_rate_based_decider_input: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FetchRoutingConfig {
    pub merchant_id: String,
    pub algorithm: AlgorithmType,
}

#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
#[serde(rename_all = "camelCase")]
pub enum AlgorithmType {
    SuccessRate,
    Elimination,
    DebitRouting,
}


// File: crates/api_models/src/refunds.rs

use std::collections::HashMap;

pub use common_utils::types::MinorUnit;
use common_utils::{pii, types::TimeRange};
use serde::{Deserialize, Serialize};
use smithy::SmithyModel;
use time::PrimitiveDateTime;
use utoipa::ToSchema;

use super::payments::AmountFilter;
#[cfg(feature = "v1")]
use crate::admin;
use crate::{admin::MerchantConnectorInfo, enums};

#[cfg(feature = "v1")]
#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize, SmithyModel)]
#[serde(deny_unknown_fields)]
#[smithy(namespace = "com.hyperswitch.smithy.types")]
pub struct RefundRequest {
    /// The payment id against which refund is to be initiated
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "pay_mbabizu24mvu3mela5njyhpit4",
        value_type = String,
    )]
    #[smithy(value_type = "String")]
    pub payment_id: common_utils::id_type::PaymentId,

    /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment. If this is not passed by the merchant, this field shall be auto generated and provided in the API response. It is recommended to generate uuid(v4) as the refund_id.
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "ref_mbabizu24mvu3mela5njyhpit4"
    )]
    #[smithy(value_type = "Option<String>")]
    pub refund_id: Option<String>,

    /// The identifier for the Merchant Account
    #[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = Option<String>)]
    #[smithy(value_type = "Option<String>")]
    pub merchant_id: Option<common_utils::id_type::MerchantId>,

    /// Total amount for which the refund is to be initiated. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, this will default to the full payment amount
    #[schema(value_type = Option<i64> , minimum = 100, example = 6540)]
    #[smithy(value_type = "Option<i64>")]
    pub amount: Option<MinorUnit>,

    /// Reason for the refund. Often useful for displaying to users and your customer support executive. In case the payment went through Stripe, this field needs to be passed with one of these enums: `duplicate`, `fraudulent`, or `requested_by_customer`
    #[schema(max_length = 255, example = "Customer returned the product")]
    #[smithy(value_type = "Option<String>")]
    pub reason: Option<String>,

    /// To indicate whether to refund needs to be instant or scheduled. Default value is instant
    #[schema(default = "Instant", example = "Instant")]
    #[smithy(value_type = "Option<RefundType>")]
    pub refund_type: Option<RefundType>,

    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
    #[schema(value_type  = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    #[smithy(value_type = "Option<Object>")]
    pub metadata: Option<pii::SecretSerdeValue>,

    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorDetailsWrap>)]
    #[smithy(value_type = "Option<MerchantConnectorDetailsWrap>")]
    pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,

    /// Charge specific fields for controlling the revert of funds from either platform or connected account
    #[schema(value_type = Option<SplitRefund>)]
    #[smithy(value_type = "Option<SplitRefund>")]
    pub split_refunds: Option<common_types::refunds::SplitRefund>,

    /// If true, returns stringified connector raw response body
    pub all_keys_required: Option<bool>,
}

#[cfg(feature = "v2")]
#[derive(Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RefundsCreateRequest {
    /// The payment id against which refund is initiated
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "pay_mbabizu24mvu3mela5njyhpit4",
        value_type = String,
    )]
    pub payment_id: common_utils::id_type::GlobalPaymentId,

    /// Unique Identifier for the Refund given by the Merchant.
    #[schema(
        max_length = 64,
        min_length = 1,
        example = "ref_mbabizu24mvu3mela5njyhpit4",
        value_type = String,
    )]
    pub merchant_reference_id: common_utils::id_type::RefundReferenceId,

    /// The identifier for the Merchant Account
    #[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = Option<String>)]
    pub merchant_id: Option<common_utils::id_type::MerchantId>,

    /// Total amount for which the refund is to be initiated. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, this will default to the amount_captured of the payment
    #[schema(value_type = Option<i64> , minimum = 100, example = 6540)]
    pub amount: Option<MinorUnit>,

    /// Reason for the refund. Often useful for displaying to users and your customer support executive.
    #[schema(max_length = 255, example = "Customer returned the product")]
    pub reason: Option<String>,

    /// To indicate whether to refund needs to be instant or scheduled. Default value is instant
    #[schema(default = "Instant", example = "Instant")]
    pub refund_type: Option<RefundType>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type  = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    pub metadata: Option<pii::SecretSerdeValue>,

    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorAuthDetails>)]
    pub merchant_connector_details: Option<common_types::domain::MerchantConnectorAuthDetails>,

    /// If true, returns stringified connector raw response body
    pub return_raw_connector_response: Option<bool>,
}

#[cfg(feature = "v1")]
#[derive(Default, Debug, Clone, Deserialize)]
pub struct RefundsRetrieveBody {
    pub force_sync: Option<bool>,
    pub all_keys_required: Option<bool>,
}

#[cfg(feature = "v2")]
#[derive(Default, Debug, Clone, Deserialize)]
pub struct RefundsRetrieveBody {
    pub force_sync: Option<bool>,
    pub return_raw_connector_response: Option<bool>,
}

#[cfg(feature = "v2")]
#[derive(Default, Debug, Clone, Deserialize)]
pub struct RefundsRetrievePayload {
    /// `force_sync` with the connector to get refund details
    pub force_sync: Option<bool>,

    /// Merchant connector details used to make payments.
    pub merchant_connector_details: Option<common_types::domain::MerchantConnectorAuthDetails>,

    /// If true, returns stringified connector raw response body
    pub return_raw_connector_response: Option<bool>,
}

#[cfg(feature = "v1")]
#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
pub struct RefundsRetrieveRequest {
    /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refund initiated against the same payment. If the identifiers is not defined by the merchant, this filed shall be auto generated and provide in the API response. It is recommended to generate uuid(v4) as the refund_id.
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "ref_mbabizu24mvu3mela5njyhpit4"
    )]
    pub refund_id: String,

    /// `force_sync` with the connector to get refund details
    /// (defaults to false)
    pub force_sync: Option<bool>,

    /// Merchant connector details used to make payments.
    pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,

    /// If true, returns stringified connector raw response body
    pub all_keys_required: Option<bool>,
}

#[cfg(feature = "v2")]
#[derive(Debug, ToSchema, Clone, Deserialize, Serialize)]
pub struct RefundsRetrieveRequest {
    /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refund initiated against the same payment. If the identifiers is not defined by the merchant, this filed shall be auto generated and provide in the API response. It is recommended to generate uuid(v4) as the refund_id.
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "ref_mbabizu24mvu3mela5njyhpit4"
    )]
    pub refund_id: common_utils::id_type::GlobalRefundId,

    /// `force_sync` with the connector to get refund details
    /// (defaults to false)
    pub force_sync: Option<bool>,

    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorAuthDetails>)]
    pub merchant_connector_details: Option<common_types::domain::MerchantConnectorAuthDetails>,

    /// If true, returns stringified connector raw response body
    pub return_raw_connector_response: Option<bool>,
}

#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize, SmithyModel)]
#[serde(deny_unknown_fields)]
#[smithy(namespace = "com.hyperswitch.smithy.types")]
pub struct RefundUpdateRequest {
    #[serde(skip)]
    pub refund_id: String,
    /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive
    #[schema(max_length = 255, example = "Customer returned the product")]
    #[smithy(value_type = "Option<String>")]
    pub reason: Option<String>,

    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
    #[schema(value_type  = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    #[smithy(value_type = "Option<Object>")]
    pub metadata: Option<pii::SecretSerdeValue>,
}

#[cfg(feature = "v2")]
#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RefundMetadataUpdateRequest {
    /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive
    #[schema(max_length = 255, example = "Customer returned the product")]
    pub reason: Option<String>,

    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
    #[schema(value_type  = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    pub metadata: Option<pii::SecretSerdeValue>,
}

#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RefundManualUpdateRequest {
    #[serde(skip)]
    pub refund_id: String,
    /// Merchant ID
    #[schema(value_type = String)]
    pub merchant_id: common_utils::id_type::MerchantId,
    /// The status for refund
    pub status: Option<RefundStatus>,
    /// The code for the error
    pub error_code: Option<String>,
    /// The error message
    pub error_message: Option<String>,
}

#[cfg(feature = "v1")]
/// To indicate whether to refund needs to be instant or scheduled
#[derive(
    Default,
    Debug,
    Clone,
    Copy,
    ToSchema,
    Deserialize,
    Serialize,
    Eq,
    PartialEq,
    strum::Display,
    SmithyModel,
)]
#[serde(rename_all = "snake_case")]
#[smithy(namespace = "com.hyperswitch.smithy.types")]
pub enum RefundType {
    Scheduled,
    #[default]
    Instant,
}

#[cfg(feature = "v2")]
/// To indicate whether the refund needs to be instant or scheduled
#[derive(
    Default, Debug, Clone, Copy, ToSchema, Deserialize, Serialize, Eq, PartialEq, strum::Display,
)]
#[serde(rename_all = "snake_case")]
pub enum RefundType {
    Scheduled,
    #[default]
    Instant,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema, SmithyModel)]
#[smithy(namespace = "com.hyperswitch.smithy.types")]
pub struct RefundResponse {
    /// Unique Identifier for the refund
    #[smithy(value_type = "String")]
    pub refund_id: String,
    /// The payment id against which refund is initiated
    #[schema(value_type = String)]
    #[smithy(value_type = "String")]
    pub payment_id: common_utils::id_type::PaymentId,
    /// The refund amount, which should be less than or equal to the total payment amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc
    #[schema(value_type = i64 , minimum = 100, example = 6540)]
    #[smithy(value_type = "i64")]
    pub amount: MinorUnit,
    /// The three-letter ISO currency code
    #[smithy(value_type = "String")]
    pub currency: String,
    /// The status for refund
    #[smithy(value_type = "RefundStatus")]
    pub status: RefundStatus,
    /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive
    #[smithy(value_type = "Option<String>")]
    pub reason: Option<String>,
    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object
    #[schema(value_type = Option<Object>)]
    #[smithy(value_type = "Option<Object>")]
    pub metadata: Option<pii::SecretSerdeValue>,
    /// The error message
    #[smithy(value_type = "Option<String>")]
    pub error_message: Option<String>,
    /// The code for the error
    #[smithy(value_type = "Option<String>")]
    pub error_code: Option<String>,
    /// Error code unified across the connectors is received here if there was an error while calling connector
    #[smithy(value_type = "Option<String>")]
    pub unified_code: Option<String>,
    /// Error message unified across the connectors is received here if there was an error while calling connector
    #[smithy(value_type = "Option<String>")]
    pub unified_message: Option<String>,
    /// The timestamp at which refund is created
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    #[smithy(value_type = "Option<String>")]
    pub created_at: Option<PrimitiveDateTime>,
    /// The timestamp at which refund is updated
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    #[smithy(value_type = "Option<String>")]
    pub updated_at: Option<PrimitiveDateTime>,
    /// The connector used for the refund and the corresponding payment
    #[schema(example = "stripe")]
    #[smithy(value_type = "String")]
    pub connector: String,
    /// The id of business profile for this refund
    #[schema(value_type = Option<String>)]
    #[smithy(value_type = "Option<String>")]
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    /// The merchant_connector_id of the processor through which this payment went through
    #[schema(value_type = Option<String>)]
    #[smithy(value_type = "Option<String>")]
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    /// Charge specific fields for controlling the revert of funds from either platform or connected account
    #[schema(value_type = Option<SplitRefund>,)]
    #[smithy(value_type = "Option<SplitRefund>")]
    pub split_refunds: Option<common_types::refunds::SplitRefund>,
    /// Error code received from the issuer in case of failed refunds
    #[smithy(value_type = "Option<String>")]
    pub issuer_error_code: Option<String>,
    /// Error message received from the issuer in case of failed refunds
    #[smithy(value_type = "Option<String>")]
    pub issuer_error_message: Option<String>,
    /// Contains whole connector response
    #[schema(value_type = Option<String>)]
    pub raw_connector_response: Option<masking::Secret<String>>,
}

#[cfg(feature = "v1")]
impl RefundResponse {
    pub fn get_refund_id_as_string(&self) -> String {
        self.refund_id.clone()
    }
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundResponse {
    /// Global Refund Id for the refund
    #[schema(value_type = String)]
    pub id: common_utils::id_type::GlobalRefundId,
    /// The payment id against which refund is initiated
    #[schema(value_type = String)]
    pub payment_id: common_utils::id_type::GlobalPaymentId,
    /// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment.
    #[schema(
        max_length = 30,
        min_length = 30,
        example = "ref_mbabizu24mvu3mela5njyhpit4",
        value_type = Option<String>,
    )]
    pub merchant_reference_id: Option<common_utils::id_type::RefundReferenceId>,
    /// The refund amount
    #[schema(value_type = i64 , minimum = 100, example = 6540)]
    pub amount: MinorUnit,
    /// The three-letter ISO currency code
    #[schema(value_type = Currency)]
    pub currency: common_enums::Currency,
    /// The status for refund
    pub status: RefundStatus,
    /// An arbitrary string attached to the object
    pub reason: Option<String>,
    /// Metadata is useful for storing additional, unstructured information on an object
    #[schema(value_type = Option<Object>)]
    pub metadata: Option<pii::SecretSerdeValue>,
    /// The error details for the refund
    pub error_details: Option<RefundErrorDetails>,
    /// The timestamp at which refund is created
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    /// The timestamp at which refund is updated
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub updated_at: PrimitiveDateTime,
    /// The connector used for the refund and the corresponding payment
    #[schema(example = "stripe", value_type = Connector)]
    pub connector: enums::Connector,
    /// The id of business profile for this refund
    #[schema(value_type = String)]
    pub profile_id: common_utils::id_type::ProfileId,
    /// The merchant_connector_id of the processor through which this payment went through
    #[schema(value_type = String)]
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    /// The reference id of the connector for the refund
    pub connector_refund_reference_id: Option<String>,
    /// Contains raw connector response
    #[schema(value_type = Option<String>)]
    pub raw_connector_response: Option<masking::Secret<String>>,
}

#[cfg(feature = "v2")]
impl RefundResponse {
    pub fn get_refund_id_as_string(&self) -> String {
        self.id.get_string_repr().to_owned()
    }
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundErrorDetails {
    pub code: String,
    pub message: String,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundListRequest {
    /// The identifier for the payment
    #[schema(value_type = Option<String>)]
    pub payment_id: Option<common_utils::id_type::PaymentId>,
    /// The identifier for the refund
    pub refund_id: Option<String>,
    /// The identifier for business profile
    #[schema(value_type = Option<String>)]
    pub profile_id: Option<common_utils::id_type::ProfileId>,
    /// Limit on the number of objects to return
    pub limit: Option<i64>,
    /// The starting point within a list of objects
    pub offset: Option<i64>,
    /// The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc)
    #[serde(flatten)]
    pub time_range: Option<TimeRange>,
    /// The amount to filter reufnds list. Amount takes two option fields start_amount and end_amount from which objects can be filtered as per required scenarios (less_than, greater_than, equal_to and range)
    pub amount_filter: Option<AmountFilter>,
    /// The list of connectors to filter refunds list
    pub connector: Option<Vec<String>>,
    /// The list of merchant connector ids to filter the refunds list for selected label
    #[schema(value_type = Option<Vec<String>>)]
    pub merchant_connector_id: Option<Vec<common_utils::id_type::MerchantConnectorAccountId>>,
    /// The list of currencies to filter refunds list
    #[schema(value_type = Option<Vec<Currency>>)]
    pub currency: Option<Vec<enums::Currency>>,
    /// The list of refund statuses to filter refunds list
    #[schema(value_type = Option<Vec<RefundStatus>>)]
    pub refund_status: Option<Vec<enums::RefundStatus>>,
}
#[cfg(feature = "v2")]
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundListRequest {
    /// The identifier for the payment
    #[schema(value_type = Option<String>)]
    pub payment_id: Option<common_utils::id_type::GlobalPaymentId>,
    /// The identifier for the refund
    #[schema(value_type = String)]
    pub refund_id: Option<common_utils::id_type::GlobalRefundId>,
    /// Limit on the number of objects to return
    pub limit: Option<i64>,
    /// The starting point within a list of objects
    pub offset: Option<i64>,
    /// The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc)
    #[serde(flatten)]
    pub time_range: Option<TimeRange>,
    /// The amount to filter reufnds list. Amount takes two option fields start_amount and end_amount from which objects can be filtered as per required scenarios (less_than, greater_than, equal_to and range)
    pub amount_filter: Option<AmountFilter>,
    /// The list of connectors to filter refunds list
    pub connector: Option<Vec<String>>,
    /// The list of merchant connector ids to filter the refunds list for selected label
    #[schema(value_type = Option<Vec<String>>)]
    pub connector_id_list: Option<Vec<common_utils::id_type::MerchantConnectorAccountId>>,
    /// The list of currencies to filter refunds list
    #[schema(value_type = Option<Vec<Currency>>)]
    pub currency: Option<Vec<enums::Currency>>,
    /// The list of refund statuses to filter refunds list
    #[schema(value_type = Option<Vec<RefundStatus>>)]
    pub refund_status: Option<Vec<enums::RefundStatus>>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, ToSchema)]
pub struct RefundListResponse {
    /// The number of refunds included in the list
    pub count: usize,
    /// The total number of refunds in the list
    pub total_count: i64,
    /// The List of refund response object
    pub data: Vec<RefundResponse>,
}

#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, ToSchema)]
pub struct RefundListMetaData {
    /// The list of available connector filters
    pub connector: Vec<String>,
    /// The list of available currency filters
    #[schema(value_type = Vec<Currency>)]
    pub currency: Vec<enums::Currency>,
    /// The list of available refund status filters
    #[schema(value_type = Vec<RefundStatus>)]
    pub refund_status: Vec<enums::RefundStatus>,
}

#[derive(Clone, Debug, serde::Serialize, ToSchema)]
pub struct RefundListFilters {
    /// The map of available connector filters, where the key is the connector name and the value is a list of MerchantConnectorInfo instances
    pub connector: HashMap<String, Vec<MerchantConnectorInfo>>,
    /// The list of available currency filters
    #[schema(value_type = Vec<Currency>)]
    pub currency: Vec<enums::Currency>,
    /// The list of available refund status filters
    #[schema(value_type = Vec<RefundStatus>)]
    pub refund_status: Vec<enums::RefundStatus>,
}

#[derive(Clone, Debug, serde::Serialize)]
pub struct RefundAggregateResponse {
    /// The list of refund status with their count
    pub status_with_count: HashMap<enums::RefundStatus, i64>,
}

/// The status for refunds
#[derive(
    Debug,
    Eq,
    Clone,
    Copy,
    PartialEq,
    Default,
    Deserialize,
    Serialize,
    ToSchema,
    strum::Display,
    strum::EnumIter,
    SmithyModel,
)]
#[serde(rename_all = "snake_case")]
#[smithy(namespace = "com.hyperswitch.smithy.types")]
pub enum RefundStatus {
    Succeeded,
    Failed,
    #[default]
    Pending,
    Review,
}

impl From<enums::RefundStatus> for RefundStatus {
    fn from(status: enums::RefundStatus) -> Self {
        match status {
            enums::RefundStatus::Failure | enums::RefundStatus::TransactionFailure => Self::Failed,
            enums::RefundStatus::ManualReview => Self::Review,
            enums::RefundStatus::Pending => Self::Pending,
            enums::RefundStatus::Success => Self::Succeeded,
        }
    }
}

impl From<RefundStatus> for enums::RefundStatus {
    fn from(status: RefundStatus) -> Self {
        match status {
            RefundStatus::Failed => Self::Failure,
            RefundStatus::Review => Self::ManualReview,
            RefundStatus::Pending => Self::Pending,
            RefundStatus::Succeeded => Self::Success,
        }
    }
}


// File: crates/api_models/src/organization.rs

use common_enums::OrganizationType;
use common_utils::{id_type, pii};
use utoipa::ToSchema;
pub struct OrganizationNew {
    pub org_id: id_type::OrganizationId,
    pub org_type: OrganizationType,
    pub org_name: Option<String>,
}

impl OrganizationNew {
    pub fn new(org_type: OrganizationType, org_name: Option<String>) -> Self {
        Self {
            org_id: id_type::OrganizationId::default(),
            org_type,
            org_name,
        }
    }
}

#[derive(Clone, Debug, serde::Serialize)]
pub struct OrganizationId {
    pub organization_id: id_type::OrganizationId,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct OrganizationCreateRequest {
    /// Name of the organization
    pub organization_name: String,

    /// Details about the organization
    #[schema(value_type = Option<Object>)]
    pub organization_details: Option<pii::SecretSerdeValue>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Option<Object>)]
    pub metadata: Option<pii::SecretSerdeValue>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct OrganizationUpdateRequest {
    /// Name of the organization
    pub organization_name: Option<String>,

    /// Details about the organization
    #[schema(value_type = Option<Object>)]
    pub organization_details: Option<pii::SecretSerdeValue>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Option<Object>)]
    pub metadata: Option<pii::SecretSerdeValue>,

    /// Platform merchant id is unique distiguisher for special merchant in the platform org
    #[schema(value_type = String)]
    pub platform_merchant_id: Option<id_type::MerchantId>,
}
#[cfg(feature = "v1")]
#[derive(Debug, serde::Serialize, Clone, ToSchema)]
pub struct OrganizationResponse {
    /// The unique identifier for the Organization
    #[schema(value_type = String, max_length = 64, min_length = 1, example = "org_q98uSGAYbjEwqs0mJwnz")]
    pub organization_id: id_type::OrganizationId,

    /// Name of the Organization
    pub organization_name: Option<String>,

    /// Details about the organization
    #[schema(value_type = Option<Object>)]
    pub organization_details: Option<pii::SecretSerdeValue>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Option<Object>)]
    pub metadata: Option<pii::SecretSerdeValue>,
    pub modified_at: time::PrimitiveDateTime,
    pub created_at: time::PrimitiveDateTime,

    /// Organization Type of the organization
    #[schema(value_type = Option<OrganizationType>, example = "standard")]
    pub organization_type: Option<OrganizationType>,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Serialize, Clone, ToSchema)]
pub struct OrganizationResponse {
    /// The unique identifier for the Organization
    #[schema(value_type = String, max_length = 64, min_length = 1, example = "org_q98uSGAYbjEwqs0mJwnz")]
    pub id: id_type::OrganizationId,

    /// Name of the Organization
    pub organization_name: Option<String>,

    /// Details about the organization
    #[schema(value_type = Option<Object>)]
    pub organization_details: Option<pii::SecretSerdeValue>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Option<Object>)]
    pub metadata: Option<pii::SecretSerdeValue>,
    pub modified_at: time::PrimitiveDateTime,
    pub created_at: time::PrimitiveDateTime,

    /// Organization Type of the organization
    #[schema(value_type = Option<OrganizationType>, example = "standard")]
    pub organization_type: Option<OrganizationType>,
}