"""Order creation and SumUp checkout helpers.

Moved from cart/bp/cart/services/checkout.py.
Only the order-side logic lives here; find_or_create_cart_item stays in cart.
"""
from __future__ import annotations

from typing import Optional
from urllib.parse import urlencode
from types import SimpleNamespace

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload

from shared.models.order import Order, OrderItem
from shared.config import config
from shared.events import emit_activity
from shared.infrastructure.actions import call_action
from shared.infrastructure.data_client import fetch_data


async def resolve_page_config_from_post_id(post_id: int) -> Optional[SimpleNamespace]:
    """Fetch the PageConfig for *post_id* from the blog service."""
    raw_pc = await fetch_data(
        "blog", "page-config",
        params={"container_type": "page", "container_id": post_id},
        required=False,
    )
    return SimpleNamespace(**raw_pc) if raw_pc else None


async def create_order(
    session: AsyncSession,
    cart_items: list[dict],
    calendar_entries: list,
    user_id: Optional[int],
    session_id: Optional[str],
    product_total: float,
    calendar_total: float,
    *,
    ticket_total: float = 0,
    page_post_id: int | None = None,
) -> Order:
    """Create an Order + OrderItems from serialized cart data."""
    cart_total = product_total + calendar_total + ticket_total
    currency = (cart_items[0].get("product_price_currency") if cart_items else None) or "GBP"

    order = Order(
        user_id=user_id,
        session_id=session_id,
        status="pending",
        currency=currency,
        total_amount=cart_total,
    )
    session.add(order)
    await session.flush()

    for ci in cart_items:
        price = ci.get("product_special_price") or ci.get("product_regular_price") or 0
        oi = OrderItem(
            order=order,
            product_id=ci["product_id"],
            product_title=ci.get("product_title"),
            product_slug=ci.get("product_slug"),
            product_image=ci.get("product_image"),
            quantity=ci.get("quantity", 1),
            unit_price=price,
            currency=currency,
        )
        session.add(oi)

    await call_action("events", "claim-entries-for-order", payload={
        "order_id": order.id, "user_id": user_id,
        "session_id": session_id, "page_post_id": page_post_id,
    })
    await call_action("events", "claim-tickets-for-order", payload={
        "order_id": order.id, "user_id": user_id,
        "session_id": session_id, "page_post_id": page_post_id,
    })

    await emit_activity(
        session,
        activity_type="Create",
        actor_uri="internal:orders",
        object_type="rose:Order",
        object_data={
            "order_id": order.id,
            "user_id": user_id,
            "session_id": session_id,
        },
        source_type="order",
        source_id=order.id,
    )

    return order


def build_sumup_description(cart_items: list[dict], order_id: int, *, ticket_count: int = 0) -> str:
    titles = [ci.get("product_title") for ci in cart_items if ci.get("product_title")]
    item_count = sum(ci.get("quantity", 1) for ci in cart_items)
    parts = []
    if titles:
        if len(titles) <= 3:
            parts.append(", ".join(titles))
        else:
            parts.append(", ".join(titles[:3]) + f" + {len(titles) - 3} more")
    if ticket_count:
        parts.append(f"{ticket_count} ticket{'s' if ticket_count != 1 else ''}")
    summary = ", ".join(parts) if parts else "order items"
    total_count = item_count + ticket_count
    return f"Order {order_id} ({total_count} item{'s' if total_count != 1 else ''}): {summary}"


def build_sumup_reference(order_id: int, page_config=None) -> str:
    if page_config and page_config.sumup_checkout_prefix:
        prefix = page_config.sumup_checkout_prefix
    else:
        sumup_cfg = config().get("sumup", {}) or {}
        prefix = sumup_cfg.get("checkout_reference_prefix", "")
    return f"{prefix}{order_id}"


def build_webhook_url(base_url: str) -> str:
    sumup_cfg = config().get("sumup", {}) or {}
    webhook_secret = sumup_cfg.get("webhook_secret")
    if webhook_secret:
        sep = "&" if "?" in base_url else "?"
        return f"{base_url}{sep}{urlencode({'token': webhook_secret})}"
    return base_url


def validate_webhook_secret(token: Optional[str]) -> bool:
    sumup_cfg = config().get("sumup", {}) or {}
    webhook_secret = sumup_cfg.get("webhook_secret")
    if not webhook_secret:
        return True
    return token is not None and token == webhook_secret


async def get_order_with_details(session: AsyncSession, order_id: int) -> Optional[Order]:
    result = await session.execute(
        select(Order)
        .options(selectinload(Order.items))
        .where(Order.id == order_id)
    )
    return result.scalar_one_or_none()
