"""
Webhook sender – POST HTTP con firma HMAC-SHA256.

Config non sensibile (config):
  { "url": "https://...", "content_type": "application/json" }

Config sensibile (config_enc → config_secret):
  { "webhook_secret": "..." }   # opzionale – usato per firma HMAC

Header inviati:
  Content-Type: application/json
  X-PEChub-Event: {event_type}
  X-Hub-Signature-256: sha256={hex}   (solo se webhook_secret configurato)
  X-Delivery: {uuid}
  User-Agent: PEChub-Webhook/1.0
"""

import hashlib
import hmac
import json
import uuid as uuid_mod
from datetime import datetime

import httpx

DEFAULT_TIMEOUT = 10.0


class WebhookError(Exception):
    """Errore durante l'invio di una notifica webhook."""

    def __init__(self, message: str, http_status: int | None = None):
        super().__init__(message)
        self.http_status = http_status


async def send_webhook(
    url: str,
    payload: dict,
    event_type: str = "new_message",
    webhook_secret: str | None = None,
    timeout: float = DEFAULT_TIMEOUT,
) -> dict:
    """
    Invia un payload JSON a un webhook URL.

    Args:
        url:            URL destinatario del webhook
        payload:        dict serializzato come JSON nel body
        event_type:     valore dell'header X-PEChub-Event
        webhook_secret: segreto per firma HMAC-SHA256 (opzionale)
        timeout:        timeout HTTP in secondi

    Returns:
        dict con http_status, response_text, delivery_id

    Raises:
        WebhookError: in caso di timeout, errore di rete o HTTP >= 400
    """
    body = json.dumps(payload, ensure_ascii=False, default=str).encode("utf-8")
    delivery_id = str(uuid_mod.uuid4())

    headers = {
        "Content-Type": "application/json",
        "X-PEChub-Event": event_type,
        "X-Delivery": delivery_id,
        "User-Agent": "PEChub-Webhook/1.0",
    }

    if webhook_secret:
        sig = hmac.new(
            webhook_secret.encode("utf-8"),
            body,
            hashlib.sha256,
        ).hexdigest()
        headers["X-Hub-Signature-256"] = f"sha256={sig}"

    async with httpx.AsyncClient(timeout=timeout) as client:
        try:
            response = await client.post(url, content=body, headers=headers)
        except httpx.TimeoutException as exc:
            raise WebhookError(
                f"Timeout webhook dopo {timeout}s"
            ) from exc
        except httpx.RequestError as exc:
            raise WebhookError(f"Errore di rete webhook: {exc}") from exc

    if response.status_code >= 400:
        raise WebhookError(
            f"Webhook ha risposto con HTTP {response.status_code}: "
            f"{response.text[:200]}",
            http_status=response.status_code,
        )

    return {
        "http_status": response.status_code,
        "response_text": response.text[:500],
        "delivery_id": delivery_id,
    }


async def send_test_webhook(
    url: str,
    webhook_secret: str | None = None,
    channel_name: str = "PEChub",
) -> dict:
    """Invia un payload di test al webhook per verificare la configurazione."""
    payload = {
        "event": "test",
        "channel": channel_name,
        "timestamp": datetime.now().isoformat(),
        "message": "Notifica di test da PEChub",
        "data": {
            "subject": "[TEST] PEC di prova",
            "from_address": "test@pec.example.it",
            "pec_type": "posta_certificata",
            "direction": "inbound",
        },
    }
    return await send_webhook(
        url=url,
        payload=payload,
        event_type="test",
        webhook_secret=webhook_secret,
    )
