use crate::types::validation_errors::ValidationError;
use serde::{Deserialize, Serialize};

use super::{OwnerName, OwnerTaxId};

/// Dados do proprietário do veículo
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct VehicleOwner {
    /// Documento do proprietário (obrigatório)
    pub tax_id: OwnerTaxId,

    /// Nome do proprietário (recomendado)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<OwnerName>,
}

impl VehicleOwner {
    /// Cria um builder para construir o proprietário
    pub fn builder() -> VehicleOwnerBuilder {
        VehicleOwnerBuilder::default()
    }
}

/// Builder para criar proprietários
#[derive(Default)]
pub struct VehicleOwnerBuilder {
    tax_id: Option<OwnerTaxId>,
    name: Option<OwnerName>,
}

impl VehicleOwnerBuilder {
    pub fn tax_id(mut self, tax_id: OwnerTaxId) -> Self {
        self.tax_id = Some(tax_id);
        self
    }

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

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

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

    pub fn build(self) -> Result<VehicleOwner, ValidationError> {
        Ok(VehicleOwner {
            tax_id: self
                .tax_id
                .ok_or_else(|| ValidationError::EmptyField("owner_tax_id".to_string()))?,
            name: self.name,
        })
    }
}

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

    #[test]
    fn test_vehicle_owner_builder() {
        let owner = VehicleOwner::builder()
            .tax_id_str("540.830.640-21")
            .unwrap()
            .name_str("Cicero")
            .unwrap()
            .build()
            .unwrap();

        assert_eq!(owner.tax_id.as_str(), "540.830.640-21");
        assert_eq!(owner.name.as_ref().unwrap().as_str(), "Cicero");
    }

    #[test]
    fn test_vehicle_owner_minimal() {
        let owner = VehicleOwner::builder()
            .tax_id_str("123.456.789-00")
            .unwrap()
            .build()
            .unwrap();

        assert_eq!(owner.tax_id.as_str(), "123.456.789-00");
        assert!(owner.name.is_none());
    }

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

        assert!(result.is_err());
    }

    #[test]
    fn test_vehicle_owner_serialization() {
        let owner = VehicleOwner::builder()
            .tax_id_str("111.222.333-44")
            .unwrap()
            .name_str("João")
            .unwrap()
            .build()
            .unwrap();

        let json = serde_json::to_string(&owner).unwrap();
        assert!(json.contains("111.222.333-44"));
        assert!(json.contains("João"));
    }
}

