"""Resend webhook handler — delivery event tracking.

Receives webhook events from Resend (delivered, bounced, opened, clicked,
complained, deferred) and updates campaign recipient statuses accordingly.

Webhook signature is verified via Resend's HMAC-SHA256 header.
"""

import hashlib
import hmac
import json
import logging
import os
from datetime import datetime, timezone

from flask import Blueprint, jsonify, request

logger = logging.getLogger("agentforms.webhooks.resend")
logger.setLevel(logging.INFO)
if not logger.handlers:
    _h = logging.StreamHandler(__import__("sys").stderr)
    _h.setFormatter(logging.Formatter("[resend-webhook] %(message)s"))
    logger.addHandler(_h)

resend_bp = Blueprint("resend_webhook", __name__)

# Map Resend event types to our delivery_status values
_EVENT_MAP = {
    "delivered": "delivered",
    "bounced": "bounced",
    "opened": "opened",
    "clicked": "clicked",
    "complained": "complained",
    "deferred": "deferred",
    "sent": "sent",  # Already tracked at send time, but good to confirm
    "processing": "pending",
}

# Events that count as "delivered" for analytics
_DELIVERY_EVENTS = {"delivered", "opened", "clicked"}
# Events that count as "failed" for analytics
_FAILURE_EVENTS = {"bounced", "complained"}


def _verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    """Verify Resend webhook HMAC-SHA256 signature."""
    if not secret:
        logger.warning("RESEND_WEBHOOK_SECRET not set — skipping signature verification")
        return True

    expected = hmac.new(
        secret.encode("utf-8"),
        payload,
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(expected, signature)


def _handle_event(event_data: dict):
    """Process a single Resend webhook event and update recipient status."""
    from app.models import get_recipient_by_message_id, update_recipient_status

    message_id = event_data.get("message_id") or event_data.get("id")
    if not message_id:
        logger.warning("Webhook event missing message_id: %s", event_data.get("type"))
        return

    event_type = event_data.get("type", "")
    delivery_status = _EVENT_MAP.get(event_type)
    if not delivery_status:
        logger.warning("Unknown Resend event type: %s", event_type)
        return

    # Find the recipient by message_id
    recipient = get_recipient_by_message_id(message_id)
    if not recipient:
        logger.warning("No recipient found for message_id %s", message_id)
        return

    # Update recipient status
    update_recipient_status(
        recipient["campaign_id"],
        recipient["id"],
        delivery_status,
        error=event_data.get("error", {}).get("message") if event_type == "bounced" else None,
    )

    logger.info(
        "Updated recipient %s for campaign %s: %s (event: %s)",
        recipient["id"],
        recipient["campaign_id"],
        delivery_status,
        event_type,
    )


@resend_bp.route("/resend/webhook", methods=["POST"])
def resend_webhook():
    """Handle incoming Resend webhooks.

    Resend sends POST requests with JSON body containing event data.
    Signature is verified via X-Resend-Signature header.
    """
    # Get signature
    signature = request.headers.get("X-Resend-Signature", "")
    payload = request.get_data()

    # Verify signature
    webhook_secret = os.environ.get("RESEND_WEBHOOK_SECRET", "")
    if not _verify_signature(payload, signature, webhook_secret):
        logger.warning("Invalid webhook signature from Resend")
        return jsonify({"error": "invalid signature"}), 401

    try:
        data = request.get_json(force=True)
    except Exception as e:
        logger.warning("Failed to parse webhook payload: %s", e)
        return jsonify({"error": "invalid payload"}), 400

    # Handle single event or batch
    events = data if isinstance(data, list) else [data]

    results = {"processed": 0, "errors": []}
    for event in events:
        try:
            _handle_event(event)
            results["processed"] += 1
        except Exception as e:
            logger.error("Error processing Resend event: %s", e)
            results["errors"].append(str(e))

    return jsonify(
        {
            "status": "ok",
            "processed": results["processed"],
            "errors": results["errors"],
        }
    ), 200