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

/// Tipo de evento
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum EventType {
    /// Show musical
    Show,
    /// Teatro
    Theater,
    /// Cinema
    Movies,
    /// Festa
    Party,
    /// Festival
    Festival,
    /// Curso
    Course,
    /// Esporte
    Sports,
    /// Corporativo
    Corporate,
}

impl EventType {
    /// Retorna o nome do tipo de evento em português
    pub fn name(&self) -> &str {
        match self {
            EventType::Show => "Show",
            EventType::Theater => "Teatro",
            EventType::Movies => "Cinema",
            EventType::Party => "Festa",
            EventType::Festival => "Festival",
            EventType::Course => "Curso",
            EventType::Sports => "Esporte",
            EventType::Corporate => "Corporativo",
        }
    }
}

impl fmt::Display for EventType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            EventType::Show => write!(f, "show"),
            EventType::Theater => write!(f, "theater"),
            EventType::Movies => write!(f, "movies"),
            EventType::Party => write!(f, "party"),
            EventType::Festival => write!(f, "festival"),
            EventType::Course => write!(f, "course"),
            EventType::Sports => write!(f, "sports"),
            EventType::Corporate => write!(f, "corporate"),
        }
    }
}

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

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.trim().to_lowercase().as_str() {
            "show" => Ok(EventType::Show),
            "theater" | "theatre" => Ok(EventType::Theater),
            "movies" | "cinema" => Ok(EventType::Movies),
            "party" => Ok(EventType::Party),
            "festival" => Ok(EventType::Festival),
            "course" => Ok(EventType::Course),
            "sports" | "sport" => Ok(EventType::Sports),
            "corporate" => Ok(EventType::Corporate),
            _ => Err(ValidationError::InvalidFormat {
                field: "event_type".to_string(),
                message: format!("invalid event type: {}", s),
            }),
        }
    }
}

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

    #[test]
    fn test_event_type_serialization() {
        let show = EventType::Show;
        let json = serde_json::to_string(&show).unwrap();
        assert_eq!(json, r#""show""#);

        let theater = EventType::Theater;
        let json = serde_json::to_string(&theater).unwrap();
        assert_eq!(json, r#""theater""#);
    }

    #[test]
    fn test_event_type_deserialization() {
        let json = r#""show""#;
        let event_type: EventType = serde_json::from_str(json).unwrap();
        assert_eq!(event_type, EventType::Show);

        let json = r#""movies""#;
        let event_type: EventType = serde_json::from_str(json).unwrap();
        assert_eq!(event_type, EventType::Movies);
    }

    #[test]
    fn test_event_type_from_str() {
        assert_eq!("show".parse::<EventType>().unwrap(), EventType::Show);
        assert_eq!("theater".parse::<EventType>().unwrap(), EventType::Theater);
        assert_eq!("theatre".parse::<EventType>().unwrap(), EventType::Theater);
        assert_eq!("sports".parse::<EventType>().unwrap(), EventType::Sports);
        assert_eq!("sport".parse::<EventType>().unwrap(), EventType::Sports);
    }

    #[test]
    fn test_event_type_display() {
        assert_eq!(EventType::Show.to_string(), "show");
        assert_eq!(EventType::Theater.to_string(), "theater");
        assert_eq!(EventType::Movies.to_string(), "movies");
    }

    #[test]
    fn test_event_type_name() {
        assert_eq!(EventType::Show.name(), "Show");
        assert_eq!(EventType::Theater.name(), "Teatro");
        assert_eq!(EventType::Movies.name(), "Cinema");
    }
}

