"""认证：密码哈希、令牌签发/校验、短信验证码（兼容原 mock 方案）"""
import base64
import hashlib
import json
import time
import random
import re

SECRET = "pine-mock-secret-2026"
TOKEN_TTL_MS = 1000 * 60 * 60 * 12  # 12h
PHONE_RE = re.compile(r"^1\d{10}$")
CODE_TTL = 5 * 60  # 5 min

# 演示环境：内存验证码 map（phone -> {code, exp}），响应返回 debugCode
sms_codes: dict[str, dict] = {}


def hash_password(s: str) -> str:
    return hashlib.sha256(str(s).encode()).hexdigest()


def b64url(data: bytes) -> str:
    return base64.urlsafe_b64encode(data).rstrip(b"=").decode()


def make_token(username: str) -> str:
    payload = b64url(json.dumps({"username": username, "exp": int(time.time() * 1000) + TOKEN_TTL_MS}).encode())
    sig = b64url((SECRET + "." + payload).encode())
    return f"{payload}.{sig}"


def verify_token(token: str):
    if not token or not isinstance(token, str):
        return None
    parts = token.split(".")
    if len(parts) != 2:
        return None
    payload_part, sig_part = parts
    if b64url((SECRET + "." + payload_part).encode()) != sig_part:
        return None
    try:
        payload = json.loads(base64.urlsafe_b64decode(payload_part + "=" * (-len(payload_part) % 4)).decode())
        if not payload.get("exp") or payload["exp"] < time.time() * 1000:
            return None
        return {"username": payload["username"]}
    except Exception:
        return None


def send_sms_code(phone: str) -> str:
    code = str(random.randint(100000, 999999))
    sms_codes[phone] = {"code": code, "exp": time.time() + CODE_TTL}
    return code


def check_sms_code(phone: str, code: str) -> bool:
    rec = sms_codes.get(phone)
    if not rec or rec["code"] != str(code) or time.time() > rec["exp"]:
        return False
    sms_codes.pop(phone, None)
    return True
