use super::{SellerId, SellerName};
use crate::types::shared::date_iso_8601::DateIso8601;
use crate::types::validation_errors::ValidationError;
use serde::{Deserialize, Serialize};

/// Dados do vendedor no marketplace
///
/// Ref: <https://docs.konduto.com/reference/seller>
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Seller {
    /// ID único do vendedor (obrigatório)
    pub id: SellerId,

    /// Nome da loja ou vendedor (recomendado)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<SellerName>,

    /// Data de criação da loja no marketplace (recomendado, formato ISO 8601: YYYY-MM-DD)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub created_at: Option<DateIso8601>,
}

impl Seller {
    /// Cria um builder para construir um vendedor
    pub fn builder() -> SellerBuilder {
        SellerBuilder::default()
    }
}

/// Builder para criar vendedores
#[derive(Default)]
pub struct SellerBuilder {
    id: Option<SellerId>,
    name: Option<SellerName>,
    created_at: Option<DateIso8601>,
}

impl SellerBuilder {
    pub fn id(mut self, id: SellerId) -> Self {
        self.id = Some(id);
        self
    }

    pub fn id_str(mut self, id: impl Into<String>) -> Result<Self, ValidationError> {
        self.id = Some(SellerId::try_new(id)?);
        Ok(self)
    }

    pub fn name(mut self, name: SellerName) -> Self {
        self.name = Some(name);
        self
    }

    pub fn name_str(mut self, name: impl Into<String>) -> Result<Self, ValidationError> {
        self.name = Some(SellerName::try_new(name)?);
        Ok(self)
    }

    pub fn created_at(mut self, date: DateIso8601) -> Self {
        self.created_at = Some(date);
        self
    }

    pub fn created_at_str(mut self, date: impl Into<String>) -> Result<Self, ValidationError> {
        self.created_at = Some(DateIso8601::new(date)?);
        Ok(self)
    }

    pub fn build(self) -> Result<Seller, ValidationError> {
        Ok(Seller {
            id: self
                .id
                .ok_or_else(|| ValidationError::EmptyField("seller_id".to_string()))?,
            name: self.name,
            created_at: self.created_at,
        })
    }
}

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

    #[test]
    fn test_seller_complete() {
        let seller = Seller::builder()
            .id_str("37")
            .unwrap()
            .name_str("Loja do João")
            .unwrap()
            .created_at_str("2009-11-25")
            .unwrap()
            .build()
            .unwrap();

        assert_eq!(seller.id.as_str(), "37");
        assert_eq!(seller.name.as_ref().unwrap().as_str(), "Loja do João");
        assert_eq!(seller.created_at.as_ref().unwrap().as_str(), "2009-11-25");
    }

    #[test]
    fn test_seller_minimal() {
        let seller = Seller::builder().id_str("123").unwrap().build().unwrap();

        assert_eq!(seller.id.as_str(), "123");
        assert!(seller.name.is_none());
        assert!(seller.created_at.is_none());
    }

    #[test]
    fn test_seller_missing_id() {
        let result = Seller::builder().name_str("Test").unwrap().build();

        assert!(result.is_err());
    }

    #[test]
    fn test_seller_with_name_only() {
        let seller = Seller::builder()
            .id_str("99")
            .unwrap()
            .name_str("Marketplace Store")
            .unwrap()
            .build()
            .unwrap();

        assert_eq!(seller.id.as_str(), "99");
        assert_eq!(seller.name.as_ref().unwrap().as_str(), "Marketplace Store");
        assert!(seller.created_at.is_none());
    }

    #[test]
    fn test_seller_serialization() {
        let seller = Seller::builder()
            .id_str("37")
            .unwrap()
            .name_str("Loja do João")
            .unwrap()
            .created_at_str("2009-11-25")
            .unwrap()
            .build()
            .unwrap();

        let json = serde_json::to_string_pretty(&seller).unwrap();
        assert!(json.contains("37"));
        assert!(json.contains("Loja do João"));
        assert!(json.contains("2009-11-25"));
    }

    #[test]
    fn test_seller_deserialization() {
        let json = r#"{
            "id": "37",
            "name": "Loja do João",
            "created_at": "2009-11-25"
        }"#;

        let seller: Seller = serde_json::from_str(json).unwrap();
        assert_eq!(seller.id.as_str(), "37");
        assert_eq!(seller.name.as_ref().unwrap().as_str(), "Loja do João");
    }

    #[test]
    fn test_seller_deserialization_minimal() {
        let json = r#"{
            "id": "123"
        }"#;

        let seller: Seller = serde_json::from_str(json).unwrap();
        assert_eq!(seller.id.as_str(), "123");
        assert!(seller.name.is_none());
        assert!(seller.created_at.is_none());
    }

    #[test]
    fn test_seller_roundtrip() {
        let original = Seller::builder()
            .id_str("42")
            .unwrap()
            .name_str("Tech Store")
            .unwrap()
            .created_at_str("2020-01-15")
            .unwrap()
            .build()
            .unwrap();

        let json = serde_json::to_string(&original).unwrap();
        let deserialized: Seller = serde_json::from_str(&json).unwrap();

        assert_eq!(original, deserialized);
    }

    #[test]
    fn test_seller_clone() {
        let seller = Seller::builder()
            .id_str("1")
            .unwrap()
            .name_str("Clone Test")
            .unwrap()
            .build()
            .unwrap();

        let cloned = seller.clone();
        assert_eq!(seller, cloned);
    }

    #[test]
    fn test_seller_debug() {
        let seller = Seller::builder().id_str("99").unwrap().build().unwrap();

        let debug_str = format!("{:?}", seller);
        assert!(debug_str.contains("Seller"));
        assert!(debug_str.contains("99"));
    }
}
