use crate::{
    error::{ErrorCode, KErr},
    utils::KRes,
};

pub(crate) struct VisitorCodeValidator;

impl VisitorCodeValidator {
    const VISITOR_CODE_MAX_LENGTH: usize = 255;

    pub fn validate(visitor_code: &str) -> KRes<()> {
        if visitor_code.is_empty() {
            return Err(KErr::new(ErrorCode::VisitorCodeInvalid, "Visitor code is empty"));
        }
        if visitor_code.len() > Self::VISITOR_CODE_MAX_LENGTH {
            return Err(KErr::new(
                ErrorCode::VisitorCodeInvalid,
                format!("Visitor code max length is {} bytes", Self::VISITOR_CODE_MAX_LENGTH),
            ));
        }
        Ok(())
    }
}

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

    #[rstest]
    #[case("valid_code", false, "")]
    #[case(&"a".repeat(VisitorCodeValidator::VISITOR_CODE_MAX_LENGTH), false, "")]
    #[case("", true, "Visitor code is empty")]
    #[case(
        &"a".repeat(VisitorCodeValidator::VISITOR_CODE_MAX_LENGTH + 1), true, "Visitor code max length is 255 bytes"
    )]
    fn test_visitor_code_validation(#[case] input: &str, #[case] expect_error: bool, #[case] expected_message: &str) {
        let result = VisitorCodeValidator::validate(input);
        match (expect_error, result) {
            (true, Err(e)) => {
                assert_eq!(e.code(), ErrorCode::VisitorCodeInvalid);
                assert_eq!(e.message(), expected_message);
            }
            (false, Ok(())) => {} // success case
            _ => panic!("Unexpected result for input: {}", input),
        }
    }
}
