//! 临时邮箱 access_token 工具：构建 / 解析 / 哈希。
//!
//! token 格式：`mb.{mailbox_id}.{secret}`
//! - 明文返回给前端（仅创建/轮换时一次）
//! - 数据库只存 `hash(secret)`（SHA-256）

use sha2::{Digest, Sha256};

/// 对 secret 求 SHA-256（十六进制）。
pub fn hash_token(secret: &str) -> String {
    let mut h = Sha256::new();
    h.update(secret.as_bytes());
    format!("{:x}", h.finalize())
}

/// 生成高熵 secret（UUID×2 拼接）。
pub fn generate_secret() -> String {
    let a = uuid::Uuid::new_v4().simple().to_string();
    let b = uuid::Uuid::new_v4().simple().to_string();
    format!("{a}{b}")
}

/// 构造 token：`mb.{mailbox_id}.{secret}`
pub fn build_token(mailbox_id: i64, secret: &str) -> String {
    format!("mb.{mailbox_id}.{secret}")
}

/// 解析 token，返回 (mailbox_id, secret)。非法返回 None。
pub fn parse_token(token: &str) -> Option<(i64, String)> {
    let rest = token.strip_prefix("mb.")?;
    let (id_str, secret) = rest.split_once('.')?;
    let id: i64 = id_str.parse().ok()?;
    if secret.is_empty() {
        return None;
    }
    Some((id, secret.to_string()))
}

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

    #[test]
    fn token_roundtrip() {
        let secret = generate_secret();
        let token = build_token(42, &secret);
        let (id, s) = parse_token(&token).unwrap();
        assert_eq!(id, 42);
        assert_eq!(s, secret);
    }

    #[test]
    fn parse_rejects_malformed() {
        assert!(parse_token("xx.1.s").is_none());
        assert!(parse_token("mb.nope.s").is_none());
        assert!(parse_token("mb.1.").is_none());
    }

    #[test]
    fn hash_is_deterministic() {
        assert_eq!(hash_token("abc"), hash_token("abc"));
        assert_ne!(hash_token("abc"), hash_token("abd"));
    }
}
