use crate::impl_nutype_error_conversion;
use nutype::nutype;

/// ID único do pedido
///
/// # Validações
/// - Não pode ser vazio (após trim)
/// - Máximo 100 caracteres
/// - Deve conter apenas caracteres alfanuméricos, hífens (-) ou underscores (_)
///
/// # Exemplos
/// ```
/// use konduto::OrderId;
///
/// // IDs válidos
/// let id1 = OrderId::try_new("10000000001").unwrap();
/// let id2 = OrderId::try_new("ORDER-123-456").unwrap();
/// let id3 = OrderId::try_new("ORDER_123_456").unwrap();
///
/// // IDs inválidos
/// assert!(OrderId::try_new("").is_err());                    // vazio
/// assert!(OrderId::try_new("order@123").is_err());           // caractere inválido (@)
/// assert!(OrderId::try_new("a".repeat(101)).is_err());       // muito longo
/// ```
#[nutype(
    sanitize(trim),
    validate(
        not_empty,
        len_char_max = 100,
        predicate = |s| s.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_')
    ),
    derive(
        Debug,
        Clone,
        PartialEq,
        Eq,
        Display,
        AsRef,
        Deref,
        Serialize,
        Deserialize,
    )
)]
pub struct OrderId(String);

impl OrderId {
    /// Retorna o ID como string slice (compatibilidade)
    pub fn as_str(&self) -> &str {
        self.as_ref()
    }
}

impl_nutype_error_conversion!(OrderIdError);

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

    #[test]
    fn test_order_id_valid() {
        let id = OrderId::try_new("10000000001").unwrap();
        assert_eq!(id.as_str(), "10000000001");
    }

    #[test]
    fn test_order_id_with_dashes() {
        let id = OrderId::try_new("ORDER-123-456").unwrap();
        assert_eq!(id.as_str(), "ORDER-123-456");
    }

    #[test]
    fn test_order_id_with_underscores() {
        let id = OrderId::try_new("ORDER_123_456").unwrap();
        assert_eq!(id.as_str(), "ORDER_123_456");
    }

    #[test]
    fn test_order_id_empty() {
        let result = OrderId::try_new("");
        assert!(result.is_err());
    }

    #[test]
    fn test_order_id_too_long() {
        let long = "a".repeat(101);
        let result = OrderId::try_new(long);
        assert!(result.is_err());
    }

    #[test]
    fn test_order_id_invalid_chars() {
        let result = OrderId::try_new("order@123");
        assert!(result.is_err());
    }
}
