"""complyform-postmark-webhook — Postmark bounce/spam complaint handler.

HTTP endpoint (Cloud Run Function gen2) triggered by Postmark webhooks.

Records bounce and spam complaint events to Firestore, calculates rolling
24hr rates, and alerts when thresholds are breached (bounce >2%,
spam >0.1%).

Contract: Firestore ``postmark_events`` TTL is 30 days (infra-configured).
"""

from __future__ import annotations

import json
import logging
from datetime import UTC, datetime, timedelta
from typing import Any

import httpx

from backend.ops._shared import log_action, send_alert_email
from backend.shared.firestore import get_db

_log = logging.getLogger(__name__)

_BOUNCE_RATE_THRESHOLD = 0.02  # 2%
_SPAM_RATE_THRESHOLD = 0.001  # 0.1%
_TTL_DAYS = 30

_POSTMARK_STATS_URL = "https://api.postmarkapp.com/stats/outbound"
_PAGERDUTY_EVENTS_URL = "https://events.pagerduty.com/v2/enqueue"


async def _get_postmark_token() -> str:
    """Retrieve Postmark server token from Secret Manager."""
    from google.cloud import secretmanager

    client = secretmanager.SecretManagerServiceClient()
    name = "projects/complyform-prod/secrets/postmark-server-token/versions/latest"
    response = client.access_secret_version(request={"name": name})
    return response.payload.data.decode("utf-8")


async def _get_pagerduty_key() -> str:
    """Retrieve PagerDuty integration key from Secret Manager."""
    from google.cloud import secretmanager

    client = secretmanager.SecretManagerServiceClient()
    name = "projects/complyform-prod/secrets/pagerduty-integration-key/versions/latest"
    response = client.access_secret_version(request={"name": name})
    return response.payload.data.decode("utf-8")


async def _get_sent_count_24hr(token: str) -> int:
    """Get total emails sent in last 24hr from Postmark stats API."""
    headers = {
        "Accept": "application/json",
        "X-Postmark-Server-Token": token,
    }
    now = datetime.now(UTC)
    from_date = (now - timedelta(hours=24)).strftime("%Y-%m-%d")
    to_date = now.strftime("%Y-%m-%d")

    async with httpx.AsyncClient(timeout=15.0) as client:
        resp = await client.get(
            _POSTMARK_STATS_URL,
            headers=headers,
            params={"fromdate": from_date, "todate": to_date},
        )
    if resp.status_code != 200:
        _log.warning("Postmark stats API returned %s", resp.status_code)
        return 0

    data = resp.json()
    return int(data.get("Sent", 0))


async def _count_events_24hr(db: Any, record_type: str) -> int:
    """Count postmark_events of given type in last 24hr."""
    cutoff = datetime.now(UTC) - timedelta(hours=24)
    query = (
        db.collection("postmark_events")
        .where("record_type", "==", record_type)
        .where("timestamp", ">=", cutoff.isoformat())
    )
    count = 0
    async for _ in query.stream():
        count += 1
    return count


async def _send_pagerduty_alert(summary: str) -> None:
    """Send PagerDuty event for critical spam complaint rate."""
    try:
        key = await _get_pagerduty_key()
        payload = {
            "routing_key": key,
            "event_action": "trigger",
            "payload": {
                "summary": summary,
                "severity": "critical",
                "source": "complyform-postmark-webhook",
            },
        }
        async with httpx.AsyncClient(timeout=15.0) as client:
            await client.post(_PAGERDUTY_EVENTS_URL, json=payload)
    except Exception:
        _log.exception("Failed to send PagerDuty alert")


async def postmark_webhook(request: Any) -> dict[str, Any]:
    """Handle Postmark bounce and spam complaint webhooks.

    Parses event type, records to Firestore, checks rolling 24hr rates,
    and alerts on threshold breaches.
    """
    try:
        if hasattr(request, "get_json"):
            body: dict[str, Any] = request.get_json(silent=True) or {}
        elif hasattr(request, "json"):
            body_data = request.json
            if callable(body_data):
                body = await body_data()
            else:
                body = body_data
        else:
            raw = await request.body() if hasattr(request, "body") else b"{}"
            body = json.loads(raw)
    except Exception:
        _log.exception("Failed to parse request body")
        return {"status": "error", "message": "invalid request body"}

    record_type: str = body.get("RecordType", body.get("Type", ""))
    if record_type not in ("Bounce", "SpamComplaint"):
        return {"status": "ignored", "record_type": record_type}

    email = body.get("Email", "")
    event_id = body.get("ID", body.get("MessageID", ""))
    fallback_ts = datetime.now(UTC).isoformat()
    timestamp = body.get(
        "BouncedAt",
        body.get("InactiveSince", fallback_ts),
    )

    now = datetime.now(UTC)
    expires_at = now + timedelta(days=_TTL_DAYS)

    db = get_db()

    # Write event to Firestore
    doc_id = str(event_id) if event_id else now.isoformat()
    await (
        db.collection("postmark_events")
        .document(doc_id)
        .set(
            {
                "type": record_type.lower(),
                "email": email,
                "record_type": record_type,
                "timestamp": timestamp,
                "expires_at": expires_at.isoformat(),
                "raw": body,
            }
        )
    )

    # Calculate rolling 24hr rates
    try:
        postmark_token = await _get_postmark_token()
        total_sent = await _get_sent_count_24hr(postmark_token)
    except Exception:
        _log.exception("Failed to get Postmark stats")
        total_sent = 0

    if total_sent > 0:
        bounces_24hr = await _count_events_24hr(db, "Bounce")
        complaints_24hr = await _count_events_24hr(db, "SpamComplaint")

        bounce_rate = bounces_24hr / total_sent
        spam_rate = complaints_24hr / total_sent

        if bounce_rate > _BOUNCE_RATE_THRESHOLD:
            await send_alert_email(
                subject="[ComplyForm] Bounce rate alert",
                body=(
                    f"Bounce rate is {bounce_rate:.2%} "
                    f"({bounces_24hr}/{total_sent} in 24hr).\n"
                    f"Threshold: {_BOUNCE_RATE_THRESHOLD:.0%}.\n\n"
                    f"Check Postmark dashboard for details."
                ),
            )

        if spam_rate > _SPAM_RATE_THRESHOLD:
            summary = (
                f"Spam complaint rate {spam_rate:.3%} "
                f"({complaints_24hr}/{total_sent}) exceeds threshold"
            )
            await _send_pagerduty_alert(summary)
            await send_alert_email(
                subject="[ComplyForm] Spam complaint rate CRITICAL",
                body=f"{summary}.\nThreshold: {_SPAM_RATE_THRESHOLD:.1%}.",
            )

    log_action(
        customer_id=None,
        action="postmark_webhook_processed",
        record_type=record_type,
        email=email,
    )

    return {"status": "ok", "record_type": record_type}
