use hyperswitch_masking::Secret;
use serde::{Deserialize, Serialize};
// PaymentsResponse
#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum PayloadPaymentStatus {
    Authorized,
    Declined,
    Processed,
    #[default]
    Processing,
    Rejected,
    Voided,
    #[serde(other)]
    Unknown,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PayloadPaymentsResponse {
    PayloadCardsResponse(PayloadCardsResponseData),
}

/// Newtype wrapping `PayloadPaymentsResponse` for the PostCaptureVoid flow.
/// A distinct type is required so its `TryFrom` impl does not conflict with
/// the blanket `TryFrom<ResponseRouterData<F, PayloadPaymentsResponse, ...>>` impl.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadPostCaptureVoidResponse(pub PayloadPaymentsResponse);

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum AvsResponse {
    NoMatch,
    Zip,
    Street,
    StreetAndZip,
    #[serde(other)]
    Unknown,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PayloadCardsResponseData {
    pub amount: Option<f64>,
    pub avs: Option<AvsResponse>,
    pub customer_id: Option<Secret<String>>,
    #[serde(rename = "id")]
    pub transaction_id: String,
    #[serde(rename = "payment_method_id")]
    pub connector_payment_method_id: Option<Secret<String>>,
    pub processing_id: Option<Secret<String>>,
    pub processing_method_id: Option<String>,
    pub ref_number: Option<String>,
    pub status: PayloadPaymentStatus,
    pub status_code: Option<String>,
    pub status_message: Option<String>,
    #[serde(rename = "type")]
    pub response_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomerResponse {
    pub id: String,
}
// Type definition for Refund Response
// Added based on assumptions since this is not provided in the documentation
#[derive(Debug, Copy, Serialize, Default, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum RefundStatus {
    Declined,
    Processed,
    #[default]
    Processing,
    Rejected,
    #[serde(other)]
    Unknown,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct PayloadRefundResponse {
    pub amount: Option<f64>,
    #[serde(rename = "id")]
    pub transaction_id: String,
    pub ledger: Option<serde_json::Value>,
    #[serde(rename = "payment_method_id")]
    pub connector_payment_method_id: Option<Secret<String>>,
    pub processing_id: Option<Secret<String>>,
    pub ref_number: Option<String>,
    pub status: RefundStatus,
    pub status_code: Option<String>,
    pub status_message: Option<String>,
}

#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct PayloadErrorResponse {
    pub error_type: String,
    pub error_description: String,
    pub object: String,
    /// Payload returns arbitrary details in JSON format
    pub details: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum PayloadWebhooksTrigger {
    Payment,
    Processed,
    Authorized,
    Credit,
    Refund,
    Reversal,
    Void,
    AutomaticPayment,
    Decline,
    Deposit,
    Reject,
    #[serde(rename = "payment_activation:status")]
    PaymentActivationStatus,
    #[serde(rename = "payment_link:status")]
    PaymentLinkStatus,
    ProcessingStatus,
    BankAccountReject,
    Chargeback,
    ChargebackReversal,
    #[serde(rename = "transaction:operation")]
    TransactionOperation,
    #[serde(rename = "transaction:operation:clear")]
    TransactionOperationClear,
    #[serde(other)]
    Unknown,
}
impl PayloadWebhooksTrigger {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Payment => "payment",
            Self::Processed => "processed",
            Self::Authorized => "authorized",
            Self::Credit => "credit",
            Self::Refund => "refund",
            Self::Reversal => "reversal",
            Self::Void => "void",
            Self::AutomaticPayment => "automatic_payment",
            Self::Decline => "decline",
            Self::Deposit => "deposit",
            Self::Reject => "reject",
            Self::PaymentActivationStatus => "payment_activation:status",
            Self::PaymentLinkStatus => "payment_link:status",
            Self::ProcessingStatus => "processing_status",
            Self::BankAccountReject => "bank_account_reject",
            Self::Chargeback => "chargeback",
            Self::ChargebackReversal => "chargeback_reversal",
            Self::TransactionOperation => "transaction:operation",
            Self::TransactionOperationClear => "transaction:operation:clear",
            Self::Unknown => "unknown",
        }
    }
}

// Webhook response structures
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadWebhookEvent {
    pub object: String, // Added to match actual webhook structure
    pub trigger: PayloadWebhooksTrigger,
    pub webhook_id: String,
    pub triggered_at: String, // Added to match actual webhook structure
    // Webhooks Payload
    pub triggered_on: PayloadEventDetails,
    pub url: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadEventDetails {
    #[serde(rename = "id")]
    pub transaction_id: Option<String>,
    pub object: String,
    pub value: Option<serde_json::Value>, // Changed to handle any value type including null
}

// Response struct for ACH SetupMandate using /payment_methods API
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadPaymentMethodResponse {
    pub id: String, // Payment method ID (pm_xxx)
    pub account_holder: Option<Secret<String>>,
    pub customer_id: Option<String>, // Same as account_id sent
    pub verification_status: Option<PayloadVerificationStatus>,
    pub status: Option<String>, // "active"
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub enum PayloadVerificationStatus {
    Verified,
    OwnerVerified,
    NotVerified,
    #[serde(other)]
    Other,
}

impl PayloadVerificationStatus {
    pub fn is_verified(&self) -> bool {
        matches!(self, Self::Verified | Self::OwnerVerified)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PayloadWebhookRegisterResponse {
    pub id: String,
    pub trigger: String,
    pub url: String,
}
