"""
Checkout event listener.

Handles domain events:
  transaction.completed  → if PR has checkout_id, emit checkout.payment_completed + write CheckoutActivity
  checkout.*             → write CheckoutActivity record
"""
from __future__ import annotations

import logging
from typing import Any

from src.events.base import BaseEvent
from src.events.dispatcher import on_event_async

logger = logging.getLogger(__name__)

_EVENT_DESCRIPTION_MAP = {
    "checkout.created": "Checkout was created.",
    "checkout.activated": "Checkout was activated.",
    "checkout.deactivated": "Checkout was deactivated.",
    "checkout.expired": "Checkout expired automatically.",
    "checkout.shared": "Checkout was shared.",
    "checkout.viewed": "Checkout link was viewed.",
    "checkout.payment_completed": "Payment completed through this checkout.",
    "checkout.payment_authorized": "Payment authorized through this checkout.",
    "checkout.link_regenerated": "Checkout link was regenerated.",
    "checkout.duplicated": "Checkout was duplicated.",
    "checkout.payment_submitted": "Payment was submitted through this checkout.",
}


@on_event_async("transaction.completed")
async def handle_transaction_completed(event: BaseEvent) -> None:
    """
    When a transaction completes, check if its PaymentRequest has a checkout_id.
    If so, emit checkout.payment_completed and write a CheckoutActivity.
    """
    from src.core.database import SessionCelery
    from src.events.dispatcher import EventDispatcher
    from src.events.utils import is_event_processed, mark_event_processed
    from src.apps.checkouts import crud as checkout_crud

    data: Any = event.data
    payment_request_id = data.get("payment_request_id")
    if not payment_request_id:
        return

    try:
        with SessionCelery() as db:
            if await is_event_processed(db, str(event.event_id), "checkout_handle_transaction_completed"):
                return

            from sqlalchemy import select
            from src.apps.payment_requests.models.payment_request import PaymentRequest
            pr = db.execute(
                select(PaymentRequest).where(PaymentRequest.id == payment_request_id)
            ).scalar_one_or_none()

            if pr is None or pr.checkout_id is None:
                await mark_event_processed(db, str(event.event_id), event.event_type, "checkout_handle_transaction_completed")
                return

            amount_dollars = (pr.amount or 0) / 100
            checkout_crud.create_checkout_activity(
                db,
                checkout_id=pr.checkout_id,
                merchant_id=pr.merchant_id,
                event_type="checkout.payment_completed",
                description=f"Payment of ${amount_dollars:,.2f} completed.",
            )

            await mark_event_processed(db, str(event.event_id), event.event_type, "checkout_handle_transaction_completed")

        await EventDispatcher.dispatch(BaseEvent(
            event_type="checkout.payment_completed",
            data={
                "checkout_id": pr.checkout_id,
                "payment_request_id": payment_request_id,
                "merchant_id": pr.merchant_id,
                "amount": float(pr.amount or 0),
                "tip_amount": float(getattr(pr, "tip", 0) or 0),
            },
        ))
    except Exception as exc:
        logger.error("handle_transaction_completed: error processing checkout activity: %s", exc)


def _write_checkout_activity(event: BaseEvent, event_type: str) -> None:
    """Generic handler to write a CheckoutActivity for checkout.* events."""
    from src.core.database import SessionCelery
    from src.apps.checkouts import crud as checkout_crud

    data: Any = event.data
    checkout_id = data.get("checkout_id")
    merchant_id = data.get("merchant_id")
    if not checkout_id or not merchant_id:
        return

    description = _EVENT_DESCRIPTION_MAP.get(event_type, event_type)
    try:
        with SessionCelery() as db:
            checkout_crud.create_checkout_activity(
                db,
                checkout_id=checkout_id,
                merchant_id=merchant_id,
                event_type=event_type,
                description=description,
                metadata=data,
            )
    except Exception as exc:
        logger.error("_write_checkout_activity(%s): %s", event_type, exc)


@on_event_async("checkout.activated")
async def handle_checkout_activated(event: BaseEvent) -> None:
    _write_checkout_activity(event, "checkout.activated")


@on_event_async("checkout.deactivated")
async def handle_checkout_deactivated(event: BaseEvent) -> None:
    _write_checkout_activity(event, "checkout.deactivated")


@on_event_async("checkout.expired")
async def handle_checkout_expired(event: BaseEvent) -> None:
    _write_checkout_activity(event, "checkout.expired")


@on_event_async("checkout.shared")
async def handle_checkout_shared(event: BaseEvent) -> None:
    _write_checkout_activity(event, "checkout.shared")


@on_event_async("checkout.link_regenerated")
async def handle_checkout_link_regenerated(event: BaseEvent) -> None:
    _write_checkout_activity(event, "checkout.link_regenerated")
