"""HMAC-SHA256 signature verification for pararam.io bot webhooks."""

from __future__ import annotations

import base64
import hashlib
import hmac

__all__ = ('extract_api_key', 'extract_url_key', 'make_signature', 'verify_signature')

URL_KEY_LENGTH = 8


def extract_url_key(secret: str) -> str:
    """Extract the URL key (first 8 chars) from a bot secret.

    The URL key is embedded in the webhook URL path to identify the bot.

    Args:
        secret: Full bot secret string.

    Returns:
        The URL key portion of the secret.
    """
    return secret[:URL_KEY_LENGTH]


def extract_api_key(secret: str) -> str:
    """Extract the API key portion from a full bot secret.

    Matches the pattern used in CoreBot: secrets longer than 50 chars
    have the API key starting at position 20.

    Args:
        secret: Full bot secret string.

    Returns:
        The API key portion of the secret.
    """
    if len(secret) > 50:
        return secret[20:]
    return secret


def _secret_to_key_bytes(secret: str) -> bytes:
    """Convert a bot secret string to HMAC key bytes.

    Pararam.io interprets the secret as a base-32 integer
    and uses its big-endian byte representation as the HMAC key.

    Args:
        secret: Bot secret string (base-32 encoded number).

    Returns:
        Key bytes for HMAC computation.
    """
    n = int(secret, 32)
    byte_length = (n.bit_length() + 7) // 8
    return n.to_bytes(byte_length, byteorder='big')


def make_signature(body: bytes, secret: str) -> str:
    """Compute the HMAC-SHA256 signature for a webhook payload.

    Args:
        body: Raw request body bytes.
        secret: Full bot secret string.

    Returns:
        Base64-encoded signature string.
    """
    key_bytes = _secret_to_key_bytes(secret)
    digest = hmac.new(key_bytes, body, hashlib.sha256).digest()
    return base64.b64encode(digest).decode()


def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    """Verify the X-Signature header of a webhook request.

    Args:
        body: Raw request body bytes.
        signature: Value of the X-Signature header.
        secret: Bot secret (or API key portion).

    Returns:
        True if the signature is valid, False if invalid or secret is malformed.
    """
    try:
        expected = make_signature(body, secret)
    except ValueError:
        return False
    return hmac.compare_digest(expected, signature)
