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

/// Tipo de documento do participante
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AttendeeDocumentType {
    /// CPF
    Cpf,
    /// CNPJ
    Cnpj,
    /// RG
    Rg,
    /// Passaporte
    Passport,
    /// Outro
    Other,
}

impl fmt::Display for AttendeeDocumentType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            AttendeeDocumentType::Cpf => write!(f, "cpf"),
            AttendeeDocumentType::Cnpj => write!(f, "cnpj"),
            AttendeeDocumentType::Rg => write!(f, "rg"),
            AttendeeDocumentType::Passport => write!(f, "passport"),
            AttendeeDocumentType::Other => write!(f, "other"),
        }
    }
}

impl std::str::FromStr for AttendeeDocumentType {
    type Err = ValidationError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.trim().to_lowercase().as_str() {
            "cpf" => Ok(AttendeeDocumentType::Cpf),
            "cnpj" => Ok(AttendeeDocumentType::Cnpj),
            "rg" => Ok(AttendeeDocumentType::Rg),
            "passport" | "passaporte" => Ok(AttendeeDocumentType::Passport),
            "other" | "outro" => Ok(AttendeeDocumentType::Other),
            _ => Err(ValidationError::InvalidFormat {
                field: "attendee_document_type".to_string(),
                message: format!("invalid document type: {}", s),
            }),
        }
    }
}

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

    #[test]
    fn test_attendee_document_type_serialization() {
        let cpf = AttendeeDocumentType::Cpf;
        let json = serde_json::to_string(&cpf).unwrap();
        assert_eq!(json, r#""cpf""#);

        let passport = AttendeeDocumentType::Passport;
        let json = serde_json::to_string(&passport).unwrap();
        assert_eq!(json, r#""passport""#);
    }

    #[test]
    fn test_attendee_document_type_deserialization() {
        let json = r#""cpf""#;
        let doc_type: AttendeeDocumentType = serde_json::from_str(json).unwrap();
        assert_eq!(doc_type, AttendeeDocumentType::Cpf);

        let json = r#""passport""#;
        let doc_type: AttendeeDocumentType = serde_json::from_str(json).unwrap();
        assert_eq!(doc_type, AttendeeDocumentType::Passport);
    }

    #[test]
    fn test_attendee_document_type_from_str() {
        assert_eq!(
            "cpf".parse::<AttendeeDocumentType>().unwrap(),
            AttendeeDocumentType::Cpf
        );
        assert_eq!(
            "cnpj".parse::<AttendeeDocumentType>().unwrap(),
            AttendeeDocumentType::Cnpj
        );
        assert_eq!(
            "passport".parse::<AttendeeDocumentType>().unwrap(),
            AttendeeDocumentType::Passport
        );
    }

    #[test]
    fn test_attendee_document_type_display() {
        assert_eq!(AttendeeDocumentType::Cpf.to_string(), "cpf");
        assert_eq!(AttendeeDocumentType::Passport.to_string(), "passport");
        assert_eq!(AttendeeDocumentType::Other.to_string(), "other");
    }
}

