"""
前程无忧 (51Job) 签名算法 (crawler_core)
从小程序源码 utils/cupid.js + server/request/index.js 翻译而来

签名逻辑:
    1. 构造 path = /{endpoint}?api_key=51job&timestamp={ts}
    2. GET:  message = path + &param1=val1&param2=val2
       POST: message = path + JSON.stringify(body)
    3. sign = HMAC-SHA256(message, SIGN_KEY).hex()
"""

from __future__ import annotations

import hmac
import hashlib
import time
import random
from urllib.parse import quote


# 与小程序硬编码一致（server/config/index.js）
SIGN_KEY = "abfc8f9dcf8c3f3d8aa294ac5f2cf2cc7767e5592590f39c3f503271dd68562b"


class Job51Sign:
    """
    前程无忧请求签名

    功能: 根据请求路径、方法、参数生成 sign 和带签名的 URL path
    参数说明:
        sign_key: HMAC 密钥（默认使用小程序内置 key）
    """

    def __init__(self, *, sign_key: str = SIGN_KEY):
        self.sign_key = sign_key

    @staticmethod
    def generate_uuid() -> str:
        """生成 UUID（13位时间戳 + 随机数），用作 distinct_id / uuid"""
        ts = str(int(time.time() * 1000))
        rand = str(random.randint(1000000000, 9999999999))
        return ts + rand

    def build_sign_path(
        self,
        endpoint: str,
        method: str = "GET",
        params: dict | None = None,
        body: dict | None = None,
    ) -> tuple[str, str]:
        """
        构建签名路径和 sign 值

        Args:
            endpoint: API 路径（不含域名，如 open/noauth/jobs/detail/base/170651439）
            method:   HTTP 方法（GET / POST）
            params:   GET 请求的额外 query 参数
            body:     POST 请求的 JSON body

        Returns:
            (url_path, sign_hex)
            url_path: 完整的 URL path（含 api_key 和 timestamp）
            sign_hex: HMAC-SHA256 签名
        """
        import json

        ts = int(time.time())
        path = f"/{endpoint}?api_key=51job&timestamp={ts}"

        if method.upper() == "GET" and params:
            query_parts = []
            for k, v in params.items():
                query_parts.append(f"{quote(str(k), safe='')}={quote(str(v), safe='')}")
            if query_parts:
                path += "&" + "&".join(query_parts)

        # 签名字符串
        message = path
        if method.upper() == "POST" and body is not None:
            message += json.dumps(body, ensure_ascii=False, separators=(",", ":"))

        sign_hex = hmac.new(
            self.sign_key.encode("utf-8"),
            message.encode("utf-8"),
            hashlib.sha256,
        ).hexdigest()

        return path, sign_hex
