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

/// Tipo de veículo
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum VehicleType {
    /// Carro
    Car,
    /// Ônibus
    Bus,
    /// Caminhão
    Truck,
    /// Motocicleta
    Motorcycle,
    /// Aeronave
    Aircraft,
    /// Barco
    Boat,
    /// Bicicleta
    Bicycle,
    /// Outro tipo
    Other(String),
}

impl VehicleType {
    const MAX_LENGTH: usize = 15;

    /// Cria um tipo de veículo a partir de uma string
    pub fn new(value: impl Into<String>) -> Result<Self, ValidationError> {
        let input = value.into();
        let trimmed = input.trim().to_lowercase();

        if trimmed.is_empty() {
            return Err(ValidationError::EmptyField("vehicle_type".to_string()));
        }

        if trimmed.len() > Self::MAX_LENGTH {
            return Err(ValidationError::TooLong {
                field: "vehicle_type".to_string(),
                max: Self::MAX_LENGTH,
                actual: trimmed.len(),
            });
        }

        Ok(match trimmed.as_str() {
            "car" => Self::Car,
            "bus" => Self::Bus,
            "truck" => Self::Truck,
            "motorcycle" => Self::Motorcycle,
            "aircraft" => Self::Aircraft,
            "boat" => Self::Boat,
            "bicycle" => Self::Bicycle,
            other => Self::Other(other.to_string()),
        })
    }

    pub fn as_str(&self) -> &str {
        match self {
            Self::Car => "car",
            Self::Bus => "bus",
            Self::Truck => "truck",
            Self::Motorcycle => "motorcycle",
            Self::Aircraft => "aircraft",
            Self::Boat => "boat",
            Self::Bicycle => "bicycle",
            Self::Other(s) => s,
        }
    }
}

impl fmt::Display for VehicleType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl Serialize for VehicleType {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(self.as_str())
    }
}

impl<'de> Deserialize<'de> for VehicleType {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        VehicleType::new(s).map_err(serde::de::Error::custom)
    }
}

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

    #[test]
    fn test_vehicle_type_from_str() {
        assert_eq!(VehicleType::new("car").unwrap(), VehicleType::Car);
        assert_eq!(VehicleType::new("Bus").unwrap(), VehicleType::Bus);
        assert_eq!(VehicleType::new("TRUCK").unwrap(), VehicleType::Truck);
    }

    #[test]
    fn test_vehicle_type_other() {
        let custom = VehicleType::new("scooter").unwrap();
        assert_eq!(custom.as_str(), "scooter");
    }

    #[test]
    fn test_vehicle_type_serialization() {
        let car = VehicleType::Car;
        let json = serde_json::to_string(&car).unwrap();
        assert_eq!(json, r#""car""#);
    }
}

