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

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct DaysToExpire(u16);

const FIELD_NAME: &str = "days_to_expire";

impl DaysToExpire {
    pub fn new(value: u16) -> Result<Self, ValidationError> {
        if value == 0 {
            return Err(ValidationError::OutOfRange {
                field: FIELD_NAME.to_string(),
                min: 1.0,
                max: u16::MAX as f64,
                actual: value as f64,
            });
        }
        Ok(Self(value))
    }

    pub fn value(&self) -> u16 {
        self.0
    }
}

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

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

    #[test]
    fn test_valid_days_to_expire() {
        let days = DaysToExpire::new(30).unwrap();
        assert_eq!(days.value(), 30);
    }

    #[test]
    fn test_invalid_days_to_expire() {
        let result = DaysToExpire::new(0);
        match result {
            Err(ValidationError::OutOfRange { field, .. }) => assert_eq!(field, "days_to_expire"),
            _ => unreachable!("was expected an validation error but got success"),
        }
    }
}
