// 公共类型模型。
//
// 判定不是布尔值,而是「状态 + 证据 + 原因」三件套:
// 每一层都把自己看到的证据留下来,调用方可以解释任何一个结论。

///|
/// 认证状态。对应 RFC 8601 的 result 取值。
pub enum AuthStatus {
  Pass
  Fail
  SoftFail
  None_
  Neutral
  TempError
  PermError
} derive(Eq)

///|
/// 一条判定证据。
pub struct Evidence {
  /// 证据来源:`dkim` / `spf` / `dmarc`
  kind : String
  /// 人类可读的证据标签
  label : String
  /// 具体细节,例如命中的标签、规范化后的字节数
  detail : String
}

///|
/// 单条 DKIM 签名的验签结果。
pub struct DkimResult {
  domain : String
  selector : String
  algorithm : String
  status : AuthStatus
  reason : String
  evidence : Array[Evidence]
}

///|
/// SPF 求值结果。
pub struct SpfResult {
  domain : String
  identity : String
  status : AuthStatus
  /// 命中的 qualifier:`+` `-` `~` `?`
  qualifier : String
  /// 命中的机制,例如 `include:_spf.example.com`
  mechanism : String
  reason : String
  dns_lookups : Int
  void_lookups : Int
}

///|
/// DMARC 对齐与策略结果。
pub struct DmarcResult {
  domain : String
  policy : String
  disposition : String
  dkim_aligned : Bool
  spf_aligned : Bool
  status : AuthStatus
  reason : String
}

///|
/// 一封邮件的完整认证结果。
pub struct AuthReport {
  dkim : Array[DkimResult]
  spf : SpfResult?
  dmarc : DmarcResult?
}

///|
/// 判定状态的短名称,用于渲染。
pub fn AuthStatus::label(self : AuthStatus) -> String {
  match self {
    Pass => "pass"
    Fail => "fail"
    SoftFail => "softfail"
    None_ => "none"
    Neutral => "neutral"
    TempError => "temperror"
    PermError => "permerror"
  }
}