"""Python 3.8+, standard library only. Same checks as verify-webhook.mjs."""
import hashlib
import hmac
import math
import re
import time

_SIGNATURE = re.compile(r"t=([0-9]{1,16})((?:,v1=[0-9a-f]{64})+)")
_MAX_T = 2**53 - 1  # Number.MAX_SAFE_INTEGER, the largest t verify-webhook.mjs accepts


def verify_webhook(secret, raw_body, signature, now_seconds=None):
    """Verify raw bytes before parsing JSON; deduplicate only after verification.

    secret: the whole whsec_ string, prefix included; its UTF-8 bytes are the key.
    raw_body: the request body exactly as received, as bytes.
    signature: the value of the Roster-Signature header.
    """
    now = int(time.time()) if now_seconds is None else now_seconds
    if (
        not isinstance(secret, str)
        or not secret
        or not isinstance(raw_body, (bytes, bytearray))
        or not isinstance(signature, str)
        or isinstance(now, bool)
        or not isinstance(now, (int, float))
        or (isinstance(now, float) and not math.isfinite(now))
    ):
        return False
    match = _SIGNATURE.fullmatch(signature)
    if not match:
        return False
    timestamp = int(match.group(1))
    if timestamp > _MAX_T or abs(now - timestamp) > 300:
        return False
    expected = hmac.new(
        secret.encode("utf-8"),
        match.group(1).encode("ascii") + b"." + bytes(raw_body),
        hashlib.sha256,
    ).digest()
    # One v1 today; accept the delivery when any v1 matches.
    return any(
        hmac.compare_digest(expected, bytes.fromhex(candidate))
        for candidate in match.group(2).split(",v1=")[1:]
    )
