"""Webhook verification and parsing utilities."""
from __future__ import annotations

import hashlib
import hmac
from typing import Any

from pydantic import BaseModel, Field


class WebhookEvent(BaseModel):
    """Parsed webhook payload from RunBlob.

    Works with all resource types (images, video, photo).
    Fields are optional — only present fields will be populated.
    """

    task_uuid: str | None = None
    generation_id: str | None = None
    status: str
    result_image_url: str | None = None
    video_url: str | None = None
    image_url: str | None = None
    prompt: str | None = None
    message: str | None = None

    @property
    def id(self) -> str:
        """Universal generation ID (works for any resource)."""
        return self.task_uuid or self.generation_id or ""

    @property
    def result_url(self) -> str | None:
        """Universal result URL (image or video)."""
        return self.result_image_url or self.video_url or self.image_url

    @property
    def is_completed(self) -> bool:
        return self.status == "completed"

    @property
    def is_failed(self) -> bool:
        return self.status == "failed"

    @property
    def is_terminal(self) -> bool:
        return self.status in ("completed", "failed")


def parse_webhook_payload(body: dict[str, Any] | str | bytes) -> WebhookEvent:
    """Parse a webhook payload into a WebhookEvent.

    Accepts dict, JSON string, or bytes. Works with all resource types.

    Args:
        body: The webhook request body.

    Returns:
        Parsed WebhookEvent.

    Raises:
        ValueError: If the payload is invalid.
    """
    import json

    if isinstance(body, (str, bytes)):
        try:
            data = json.loads(body)
        except json.JSONDecodeError as exc:
            raise ValueError(f"Invalid JSON in webhook body: {exc}") from exc
    elif isinstance(body, dict):
        data = body
    else:
        raise ValueError(f"Unexpected body type: {type(body)}")

    return WebhookEvent.model_validate(data)


def verify_webhook_signature(
    body: bytes,
    signature: str,
    secret: str,
    *,
    algorithm: str = "sha256",
) -> bool:
    """Verify HMAC signature of a webhook payload.

    Args:
        body: Raw request body bytes.
        signature: Signature from X-RunBlob-Signature header.
        secret: Your webhook signing secret.
        algorithm: Hash algorithm (default sha256).

    Returns:
        True if signature is valid.
    """
    mac = hmac.new(
        secret.encode("utf-8"),
        body,
        getattr(hashlib, algorithm),
    )
    expected = mac.hexdigest()
    return hmac.compare_digest(expected, signature)
