# bp/cart/global_routes.py — Global cart routes (add, quantity, delete, checkout)

from __future__ import annotations

from quart import Blueprint, g, request, redirect, url_for, make_response
from sqlalchemy import select

from shared.models.market import CartItem
from shared.infrastructure.actions import call_action
from .services import (
    current_cart_identity,
    get_cart,
    total,
    get_calendar_cart_entries,
    calendar_total,
    get_ticket_cart_entries,
    ticket_total,
)
from .services.checkout import (
    find_or_create_cart_item,
    resolve_page_config,
)


def register(url_prefix: str) -> Blueprint:
    bp = Blueprint("cart_global", __name__, url_prefix=url_prefix)

    @bp.post("/add/<int:product_id>/")
    async def add_to_cart(product_id: int):
        from shared.infrastructure.data_client import fetch_data

        ident = current_cart_identity()

        # Fetch product data from market service (cart DB doesn't have products)
        products_raw = await fetch_data(
            "market", "products-by-ids",
            params={"ids": str(product_id)},
            required=False,
        ) or []
        product_data = products_raw[0] if products_raw else None

        cart_item = await find_or_create_cart_item(
            g.s,
            product_id,
            ident["user_id"],
            ident["session_id"],
            product_title=product_data["title"] if product_data else None,
            product_slug=product_data["slug"] if product_data else None,
            product_image=product_data["image"] if product_data else None,
            product_regular_price=product_data["regular_price"] if product_data else None,
            product_special_price=product_data["special_price"] if product_data else None,
        )

        if not cart_item:
            return await make_response("Product not found", 404)

        if request.headers.get("SX-Request") == "true" or request.headers.get("HX-Request") == "true":
            # Redirect to overview for HTMX
            return redirect(url_for("defpage_cart_overview"))

        return redirect(url_for("defpage_cart_overview"))

    @bp.post("/quantity/<int:product_id>/")
    async def update_quantity(product_id: int):
        ident = current_cart_identity()
        form = await request.form
        count = int(form.get("count", 0))

        filters = [
            CartItem.deleted_at.is_(None),
            CartItem.product_id == product_id,
        ]
        if ident["user_id"] is not None:
            filters.append(CartItem.user_id == ident["user_id"])
        else:
            filters.append(CartItem.session_id == ident["session_id"])

        existing = await g.s.scalar(select(CartItem).where(*filters))

        if existing:
            existing.quantity = max(count, 0)
            await g.s.flush()

        resp = await make_response("", 200)
        resp.headers["HX-Refresh"] = "true"
        return resp

    @bp.post("/ticket-quantity/")
    async def update_ticket_quantity():
        """Adjust reserved ticket count (+/- pattern, like products)."""
        ident = current_cart_identity()
        form = await request.form
        entry_id = int(form.get("entry_id", 0))
        count = max(int(form.get("count", 0)), 0)
        tt_raw = (form.get("ticket_type_id") or "").strip()
        ticket_type_id = int(tt_raw) if tt_raw else None

        await call_action("events", "adjust-ticket-quantity", payload={
            "entry_id": entry_id, "count": count,
            "user_id": ident["user_id"],
            "session_id": ident["session_id"],
            "ticket_type_id": ticket_type_id,
        })

        resp = await make_response("", 200)
        resp.headers["HX-Refresh"] = "true"
        return resp

    @bp.post("/delete/<int:product_id>/")
    async def delete_item(product_id: int):
        ident = current_cart_identity()

        filters = [
            CartItem.deleted_at.is_(None),
            CartItem.product_id == product_id,
        ]
        if ident["user_id"] is not None:
            filters.append(CartItem.user_id == ident["user_id"])
        else:
            filters.append(CartItem.session_id == ident["session_id"])

        existing = await g.s.scalar(select(CartItem).where(*filters))

        if existing:
            await g.s.delete(existing)
            await g.s.flush()

        resp = await make_response("", 200)
        resp.headers["HX-Refresh"] = "true"
        return resp

    @bp.post("/checkout/")
    async def checkout():
        """Global checkout — delegates order creation to orders service."""
        cart = await get_cart(g.s)
        calendar_entries = await get_calendar_cart_entries(g.s)
        tickets = await get_ticket_cart_entries(g.s)

        if not cart and not calendar_entries and not tickets:
            return redirect(url_for("defpage_cart_overview"))

        product_total = total(cart) or 0
        calendar_amount = calendar_total(calendar_entries) or 0
        ticket_amount = ticket_total(tickets) or 0
        cart_total = product_total + calendar_amount + ticket_amount

        if cart_total <= 0:
            return redirect(url_for("defpage_cart_overview"))

        try:
            page_config = await resolve_page_config(g.s, cart, calendar_entries, tickets)
        except ValueError as e:
            from shared.sx.page import get_template_context
            from sxc.pages.renders import render_checkout_error_page
            tctx = await get_template_context()
            html = await render_checkout_error_page(tctx, error=str(e))
            return await make_response(html, 400)

        ident = current_cart_identity()

        # Serialize cart items for the orders service
        cart_items_data = []
        for ci in cart:
            cart_items_data.append({
                "product_id": ci.product_id,
                "product_title": ci.product_title,
                "product_slug": ci.product_slug,
                "product_image": ci.product_image,
                "product_regular_price": float(ci.product_regular_price) if ci.product_regular_price else None,
                "product_special_price": float(ci.product_special_price) if ci.product_special_price else None,
                "product_price_currency": ci.product_price_currency,
                "quantity": ci.quantity,
            })

        # Serialize calendar entries and tickets
        cal_data = []
        for e in calendar_entries:
            cal_data.append({
                "id": e.id,
                "calendar_container_id": getattr(e, "calendar_container_id", None),
            })
        ticket_data = []
        for t in tickets:
            ticket_data.append({
                "id": t.id,
                "calendar_container_id": getattr(t, "calendar_container_id", None),
            })

        page_post_id = None
        if page_config:
            page_post_id = getattr(page_config, "container_id", None)

        result = await call_action("orders", "create-order", payload={
            "cart_items": cart_items_data,
            "calendar_entries": cal_data,
            "tickets": ticket_data,
            "user_id": ident.get("user_id"),
            "session_id": ident.get("session_id"),
            "product_total": float(product_total),
            "calendar_total": float(calendar_amount),
            "ticket_total": float(ticket_amount),
            "page_post_id": page_post_id,
        })

        # Update redirect/webhook URLs with real order_id
        order_id = result["order_id"]
        hosted_url = result.get("sumup_hosted_url")

        if not hosted_url:
            from shared.sx.page import get_template_context
            from sxc.pages.renders import render_checkout_error_page
            tctx = await get_template_context()
            html = await render_checkout_error_page(tctx, error="No hosted checkout URL returned from SumUp.")
            return await make_response(html, 500)

        return redirect(hosted_url)

    return bp
