"""
Webhook signature verification.
"""

from __future__ import annotations

import hashlib
import hmac
import json
from typing import Union

from .models import WebhookEvent


class WebhookVerificationError(Exception):
    pass


def verify_webhook(
    payload: Union[bytes, str],
    signature: str,
    secret: str,
) -> None:
    """
    Verify an incoming AgentPhone webhook signature.

    Args:
        payload: Raw request body (bytes or str).
        signature: Value of the X-Webhook-Signature header (e.g. "sha256=abc123").
        secret: Your webhook secret from client.webhooks.get().secret

    Raises:
        WebhookVerificationError: If the signature is invalid.

    Example::

        from agentphone import verify_webhook, WebhookVerificationError

        @app.post("/webhook")
        async def handle(request: Request):
            body = await request.body()
            sig = request.headers["X-Webhook-Signature"]
            try:
                verify_webhook(body, sig, secret="whsec_...")
            except WebhookVerificationError:
                return Response(status_code=403)
            ...
    """
    if isinstance(payload, str):
        payload = payload.encode()

    expected = "sha256=" + hmac.new(
        secret.encode(), payload, hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(expected, signature):
        raise WebhookVerificationError("Invalid webhook signature")


def construct_event(
    payload: Union[bytes, str],
    signature: str,
    secret: str,
) -> WebhookEvent:
    """
    Verify the webhook signature and parse the event payload.

    Returns a WebhookEvent on success, raises WebhookVerificationError if invalid.

    Example::

        event = construct_event(body, sig, secret="whsec_...")
        if event.event == "agent.message":
            print(event.data.message)
    """
    verify_webhook(payload, signature, secret)

    if isinstance(payload, bytes):
        payload = payload.decode()

    return WebhookEvent.from_dict(json.loads(payload))
