//! 邮件滥用评分（多维加权）。高分邮件进入隔离区。

use crate::config::smtp::SmtpConfig;
use crate::infra::auth::spf::SpfResult;

pub struct ScoringInput<'a> {
    pub subject: Option<&'a str>,
    pub spf: SpfResult,
    pub ptr_present: bool,
    pub has_bad_attachment: bool,
}

const CODE_KEYWORDS: &[&str] = &[
    "verify",
    "verification",
    "验证",
    "验证码",
    "confirm your email",
    "确认你的邮箱",
    "code de vérification",
];

pub fn compute(cfg: &SmtpConfig, input: ScoringInput) -> i32 {
    let mut score = 0i32;
    if let Some(s) = input.subject {
        let lower = s.to_lowercase();
        if CODE_KEYWORDS.iter().any(|k| lower.contains(k)) {
            score += cfg.score_weight_subject_code;
        }
    }
    if matches!(input.spf, SpfResult::Fail | SpfResult::SoftFail) {
        score += cfg.score_weight_spf_fail;
    }
    if !input.ptr_present {
        score += cfg.score_weight_ptr_missing;
    }
    if input.has_bad_attachment {
        score += cfg.score_weight_bad_attachment;
    }
    score.clamp(0, 100)
}

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

    #[test]
    fn verification_subject_scores_high() {
        let cfg = SmtpConfig::default();
        let s = compute(
            &cfg,
            ScoringInput {
                subject: Some("Please verify your email"),
                spf: SpfResult::Pass,
                ptr_present: true,
                has_bad_attachment: false,
            },
        );
        assert!(s >= cfg.score_weight_subject_code);
    }

    #[test]
    fn normal_mail_low_score() {
        let cfg = SmtpConfig::default();
        let s = compute(
            &cfg,
            ScoringInput {
                subject: Some("Hello world"),
                spf: SpfResult::Pass,
                ptr_present: true,
                has_bad_attachment: false,
            },
        );
        assert_eq!(s, 0);
    }

    #[test]
    fn spf_fail_adds_weight() {
        let cfg = SmtpConfig::default();
        let s = compute(
            &cfg,
            ScoringInput {
                subject: None,
                spf: SpfResult::Fail,
                ptr_present: true,
                has_bad_attachment: false,
            },
        );
        assert_eq!(s, cfg.score_weight_spf_fail);
    }
}
