import uuid
from typing import Any

from pydantic_ai import RunContext

from app.agents.deps import AgentDeps
from app.dependencies import restate_proxy
from app.rag.embeddings import generate_embedding
from app.rag.search import hybrid_search

LANGUAGE_FTS_MAP = {"nl": "dutch", "en": "english"}


async def search_menu_impl(
    ctx: RunContext[AgentDeps],
    query: str,
) -> list[dict[str, Any]]:
    embedding = await generate_embedding(query)
    language_fts = LANGUAGE_FTS_MAP.get(ctx.deps.language, "dutch")
    results = await hybrid_search(
        session=ctx.deps.session,
        query_text=query,
        query_embedding=embedding,
        restaurant_id=ctx.deps.restaurant_id,
        limit=8,
        language=language_fts,
        source="menu",
    )
    return [
        {
            "content": r["content"],
            "metadata": r.get("metadata") or {},
            "score": r["score"],
        }
        for r in results
    ]


async def create_order_impl(
    ctx: RunContext[AgentDeps],
    customer_email: str,
    items: list[dict[str, Any]],
    delivery_type: str = "pickup",
    notes: str | None = None,
) -> dict[str, Any]:
    order_id = str(uuid.uuid4())
    total_cents = sum(item.get("unit_price_cents", 0) * item.get("quantity", 1) for item in items)
    payload = {
        "restaurant_id": ctx.deps.restaurant_id,
        "customer_email": customer_email,
        "items": items,
        "delivery_type": delivery_type,
        "notes": notes,
        "total_cents": total_cents,
    }
    # Durable write via Restate Virtual Object — exactly-once semantics.
    await restate_proxy(
        ctx.deps.http_client,
        "OrderObject",
        order_id,
        "create",
        payload,
        mode="object",
    )
    return {
        "order_id": order_id,
        "status": "pending",
        "total_amount": f"{total_cents / 100:.2f}",
    }


async def get_payment_link_impl(
    ctx: RunContext[AgentDeps],
    order_id: str,
    amount_cents: int,
) -> dict[str, Any]:
    from app.payments.mollie import PaymentNotConfiguredError, create_payment

    try:
        # Payment creation is idempotent via Mollie's order-based dedup (not Restate-wrapped).
        result = await create_payment(
            order_id=order_id,
            amount_cents=amount_cents,
            description=f"Bestelling #{order_id[:8]}",
            redirect_url="https://example.com/order/thanks",
            client=ctx.deps.http_client,
        )
        return result
    except PaymentNotConfiguredError as exc:
        return {"status": "error", **exc.to_dict()}
