use super::super::{sanitize, Verdict};
use anyhow::{anyhow, Result};
const WEIGHTS: [u32; 6] = [3, 4, 6, 7, 8, 9];
fn compute_check(body: &str) -> u32 {
let sum: u32 = body.chars().enumerate()
.map(|(i, c)| WEIGHTS[i] * c.to_digit(10).unwrap())
.sum();
37 - (sum % 37)
}
pub fn verify_mt_vat(input: &str) -> Verdict {
let clean = match super::strip_vat_prefix(input, "MT") {
Ok(body) => body,
Err(v) => return v,
};
if clean.len() != 8 {
return Verdict::Invalid { reason: format!("expected 8 digits, got {}", clean.len()) };
}
if !clean.chars().all(|c| c.is_ascii_digit()) {
return Verdict::Invalid { reason: "non-digit input".into() };
}
let body = &clean[..6];
let check: u32 = clean[6..].parse().expect("validated above");
let expected = compute_check(body);
if expected == check {
Verdict::Valid {
formatted: format!("MT{}", clean),
detected: "Maltese VAT".into(),
comment: String::new(),
}
} else {
Verdict::Invalid {
reason: format!("MT VAT check mismatch: expected {:02}, got {:02}", expected, check),
}
}
}
pub fn create_mt_vat(input: &str, _raw: bool) -> Result<String> {
let clean = sanitize(input, false);
if clean.len() != 6 {
return Err(anyhow!("expected 6 digits (body without check), got {}", clean.len()));
}
if !clean.chars().all(|c| c.is_ascii_digit()) {
return Err(anyhow!("non-digit body"));
}
let check = compute_check(&clean);
Ok(format!("MT{}{:02}", clean, check))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mt_vat_valid_15121333() {
match verify_mt_vat("15121333") {
Verdict::Valid { .. } => {}
v => panic!("{:?}", v),
}
}
#[test]
fn mt_vat_round_trip() {
let body = "151213";
let full = create_mt_vat(body, false).unwrap();
let digits: String = full.chars().filter(|c| c.is_ascii_digit()).collect();
match verify_mt_vat(&digits) {
Verdict::Valid { .. } => {}
v => panic!("{:?}", v),
}
}
#[test]
fn mt_vat_rejects_bad_check() {
match verify_mt_vat("15121300") {
Verdict::Invalid { .. } => {}
v => panic!("{:?}", v),
}
}
#[test]
fn mt_vat_rejects_wrong_length() {
match verify_mt_vat("1512133") {
Verdict::Invalid { .. } => {}
v => panic!("{:?}", v),
}
}
}