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

/// Categoria do ingresso
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum TicketCategory {
    /// Estudante
    Student,
    /// Idoso
    Senior,
    /// Funcionário público
    Government,
    /// Social
    Social,
    /// Regular
    Regular,
}

impl TicketCategory {
    /// Retorna o nome da categoria em português
    pub fn name(&self) -> &str {
        match self {
            TicketCategory::Student => "Estudante",
            TicketCategory::Senior => "Idoso",
            TicketCategory::Government => "Funcionário Público",
            TicketCategory::Social => "Social",
            TicketCategory::Regular => "Regular",
        }
    }
}

impl fmt::Display for TicketCategory {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            TicketCategory::Student => write!(f, "student"),
            TicketCategory::Senior => write!(f, "senior"),
            TicketCategory::Government => write!(f, "government"),
            TicketCategory::Social => write!(f, "social"),
            TicketCategory::Regular => write!(f, "regular"),
        }
    }
}

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

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.trim().to_lowercase().as_str() {
            "student" | "estudante" => Ok(TicketCategory::Student),
            "senior" | "idoso" => Ok(TicketCategory::Senior),
            "government" | "funcionario" | "funcionário" => Ok(TicketCategory::Government),
            "social" => Ok(TicketCategory::Social),
            "regular" | "normal" => Ok(TicketCategory::Regular),
            _ => Err(ValidationError::InvalidFormat {
                field: "ticket_category".to_string(),
                message: format!("invalid ticket category: {}", s),
            }),
        }
    }
}

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

    #[test]
    fn test_ticket_category_serialization() {
        let student = TicketCategory::Student;
        let json = serde_json::to_string(&student).unwrap();
        assert_eq!(json, r#""student""#);

        let regular = TicketCategory::Regular;
        let json = serde_json::to_string(&regular).unwrap();
        assert_eq!(json, r#""regular""#);
    }

    #[test]
    fn test_ticket_category_deserialization() {
        let json = r#""student""#;
        let category: TicketCategory = serde_json::from_str(json).unwrap();
        assert_eq!(category, TicketCategory::Student);

        let json = r#""senior""#;
        let category: TicketCategory = serde_json::from_str(json).unwrap();
        assert_eq!(category, TicketCategory::Senior);
    }

    #[test]
    fn test_ticket_category_from_str() {
        assert_eq!(
            "student".parse::<TicketCategory>().unwrap(),
            TicketCategory::Student
        );
        assert_eq!(
            "estudante".parse::<TicketCategory>().unwrap(),
            TicketCategory::Student
        );
        assert_eq!(
            "senior".parse::<TicketCategory>().unwrap(),
            TicketCategory::Senior
        );
        assert_eq!(
            "regular".parse::<TicketCategory>().unwrap(),
            TicketCategory::Regular
        );
    }

    #[test]
    fn test_ticket_category_display() {
        assert_eq!(TicketCategory::Student.to_string(), "student");
        assert_eq!(TicketCategory::Senior.to_string(), "senior");
        assert_eq!(TicketCategory::Regular.to_string(), "regular");
    }

    #[test]
    fn test_ticket_category_name() {
        assert_eq!(TicketCategory::Student.name(), "Estudante");
        assert_eq!(TicketCategory::Senior.name(), "Idoso");
        assert_eq!(TicketCategory::Regular.name(), "Regular");
    }
}

