use crate::balance::BalancePayment;
use crate::boleto::BoletoPayment;
use crate::credit_card::CreditCardPayment;
use crate::debit_card::DebitCardPayment;
use crate::pix::PixPayment;
use crate::transfer::TransferPayment;
use crate::voucher::VoucherPayment;
use serde::{Deserialize, Serialize};

/// Representa os diferentes tipos de pagamento suportados pela API Konduto
/// Cada variante garante que os campos obrigatórios estejam presentes
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Payment {
    Credit(CreditCardPayment),
    Debit(DebitCardPayment),
    Boleto(BoletoPayment),
    Transfer(TransferPayment),
    Voucher(VoucherPayment),
    Balance(BalancePayment),
    Pix(PixPayment),
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::PaymentStatus;

    #[test]
    fn test_payment_kind_credit() {
        let credit_payment = CreditCardPayment::new(PaymentStatus::Approved).with_amount(100.0);

        let kind = Payment::Credit(credit_payment);

        match kind {
            Payment::Credit(payment) => {
                assert_eq!(payment.status, PaymentStatus::Approved);
                assert_eq!(payment.amount, Some(100.0));
            }
            _ => panic!("Expected Credit variant"),
        }
    }

    #[test]
    fn test_payment_kind_serialization() {
        let payment = CreditCardPayment::new(PaymentStatus::Approved).with_amount(100.0);

        let kind = Payment::Credit(payment);
        let json = serde_json::to_string(&kind).unwrap();

        assert!(json.contains("\"type\":\"credit\""));
        assert!(json.contains("\"status\":\"approved\""));
    }

    #[test]
    fn test_voucher_serialization() {
        let voucher = VoucherPayment::new()
            .with_amount(10.0)
            .with_description("Desconto");

        let kind = Payment::Voucher(voucher);
        let json = serde_json::to_string(&kind).unwrap();

        assert!(json.contains("\"type\":\"voucher\""));
        assert!(json.contains("\"amount\":10"));
    }
}
