"""Stripe webhook handling with signature verification."""

from __future__ import annotations

import logging

import stripe
from stripe import SignatureVerificationError

from billing.config import get_config
from billing.models import WebhookEvent

logger = logging.getLogger("billing.webhooks")

# Events this module understands and returns structured data for.
HANDLED_EVENTS = frozenset(
    {
        "checkout.session.completed",
        "customer.subscription.updated",
        "customer.subscription.deleted",
        "invoice.payment_succeeded",
        "invoice.payment_failed",
    }
)


def handle_webhook(payload: bytes, signature: str) -> WebhookEvent:
    """Verify and parse a Stripe webhook event.

    Verifies the webhook signature using the configured webhook secret,
    then extracts structured data for known event types.

    Args:
        payload: Raw request body bytes from the webhook POST.
        signature: Value of the Stripe-Signature header.

    Returns:
        WebhookEvent with the event type and extracted data.

    Raises:
        ValueError: If signature verification fails.
    """
    config = get_config()

    try:
        event = stripe.Webhook.construct_event(
            payload,
            signature,
            config.stripe_webhook_secret,
        )
    except SignatureVerificationError as e:
        logger.warning("Webhook signature verification failed: %s", e)
        raise ValueError("Invalid webhook signature") from e

    event_type = event.type
    event_data: dict = {}

    if event_type not in HANDLED_EVENTS:
        logger.debug("Unhandled webhook event type: %s", event_type)
        return WebhookEvent(type=event_type, data=event.data.object)

    obj = event.data.object

    if event_type == "checkout.session.completed":
        event_data = {
            "session_id": obj.id,
            "customer_id": obj.customer,
            "user_id": obj.client_reference_id,
            "subscription_id": obj.subscription,
            "email": obj.customer_email or obj.customer_details.get("email")
            if obj.customer_details
            else obj.customer_email,
            "metadata": dict(obj.metadata) if obj.metadata else {},
        }

    elif event_type == "customer.subscription.updated":
        event_data = {
            "subscription_id": obj.id,
            "customer_id": obj.customer,
            "status": obj.status,
            "cancel_at_period_end": obj.cancel_at_period_end,
            "current_period_end": obj.current_period_end,
            "items": [
                {"price_id": item.price.id, "quantity": item.quantity}
                for item in obj["items"]["data"]
            ],
        }

    elif event_type == "customer.subscription.deleted":
        event_data = {
            "subscription_id": obj.id,
            "customer_id": obj.customer,
            "status": obj.status,
            "ended_at": obj.ended_at,
        }

    elif event_type == "invoice.payment_succeeded":
        event_data = {
            "invoice_id": obj.id,
            "customer_id": obj.customer,
            "subscription_id": obj.subscription,
            "amount_paid": obj.amount_paid,
            "currency": obj.currency,
            "hosted_invoice_url": obj.hosted_invoice_url,
            "pdf_url": obj.invoice_pdf,
        }

    elif event_type == "invoice.payment_failed":
        event_data = {
            "invoice_id": obj.id,
            "customer_id": obj.customer,
            "subscription_id": obj.subscription,
            "amount_due": obj.amount_due,
            "currency": obj.currency,
            "attempt_count": obj.attempt_count,
            "next_payment_attempt": obj.next_payment_attempt,
        }

    logger.info("Processed webhook event: %s", event_type)
    return WebhookEvent(type=event_type, data=event_data)
