"""HubSpot webhook request verification helpers."""

from __future__ import annotations

import base64
import hashlib
import hmac
import re
import time

_HUBSPOT_V3_URI_DECODE_MAP = {
    "%3A": ":",
    "%2F": "/",
    "%3F": "?",
    "%40": "@",
    "%21": "!",
    "%24": "$",
    "%27": "'",
    "%28": "(",
    "%29": ")",
    "%2A": "*",
    "%2C": ",",
    "%3B": ";",
}
_PERCENT_ESCAPE_PATTERN = re.compile(r"%[0-9A-Fa-f]{2}")


def canonicalize_hubspot_v3_uri(request_uri: str) -> str:
    def _replace(match: re.Match[str]) -> str:
        token = match.group(0).upper()
        return _HUBSPOT_V3_URI_DECODE_MAP.get(token, match.group(0))

    return _PERCENT_ESCAPE_PATTERN.sub(_replace, str(request_uri or ""))


def verify_hubspot_signature(
    signing_secret: str,
    *,
    signature_version: str,
    signature: str,
    method: str,
    request_uri: str,
    body: bytes,
    timestamp: str | None = None,
    max_age_seconds: int = 300,
    now: float | None = None,
) -> bool:
    if not signing_secret or not signature:
        return False

    version = str(signature_version or "").strip().lower()
    if version == "v1":
        try:
            body_text = body.decode("utf-8")
        except Exception:
            body_text = body.decode("utf-8", errors="replace")
        expected = hashlib.sha256(f"{signing_secret}{body_text}".encode("utf-8")).hexdigest()
        return hmac.compare_digest(expected, signature)

    if version == "v3":
        if not timestamp:
            return False
        try:
            timestamp_ms = int(str(timestamp).strip())
        except Exception:
            return False
        now_seconds = float(now if now is not None else time.time())
        if abs(now_seconds - (timestamp_ms / 1000.0)) > max(1, int(max_age_seconds)):
            return False

        canonical_uri = canonicalize_hubspot_v3_uri(request_uri)
        source = (
            str(method or "").upper().encode("utf-8")
            + canonical_uri.encode("utf-8")
            + (body or b"")
            + str(timestamp).encode("utf-8")
        )
        digest = hmac.new(signing_secret.encode("utf-8"), source, hashlib.sha256).digest()
        expected = base64.b64encode(digest).decode("utf-8")
        return hmac.compare_digest(expected, signature)

    return False


__all__ = ["canonicalize_hubspot_v3_uri", "verify_hubspot_signature"]
