"""Orders router.

GETs read directly from Neon. POST/PATCH/DELETE proxy to Restate OrderObject.
"""

import uuid
from typing import Any

import httpx
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlmodel import select

from app.auth.tenant import get_current_restaurant, get_tenant_session
from app.cache import invalidate_restaurant_stats_cache
from app.dependencies import get_restate_client, restate_proxy
from app.models.order import Order, OrderCreate, OrderRead, OrderStatusResponse, OrderStatusUpdate
from app.models.restaurant import Restaurant

router = APIRouter(prefix="/orders", tags=["orders"])


@router.get("/", response_model=list[OrderRead])
async def list_orders(
    session: AsyncSession = Depends(get_tenant_session),
    restaurant: Restaurant = Depends(get_current_restaurant),
) -> list[Any]:
    result = await session.execute(
        select(Order).where(Order.restaurant_id == restaurant.id).limit(100)
    )
    return list(result.scalars().all())


@router.post("/", response_model=OrderRead, status_code=status.HTTP_202_ACCEPTED)
async def create_order(
    data: OrderCreate,
    restaurant: Restaurant = Depends(get_current_restaurant),
    client: httpx.AsyncClient = Depends(get_restate_client),
) -> Any:
    order_id = str(uuid.uuid4())
    payload = {**data.model_dump(mode="json"), "restaurant_id": restaurant.id}
    await restate_proxy(client, "OrderObject", order_id, "create", payload, mode="object")
    invalidate_restaurant_stats_cache(restaurant.id)
    return OrderRead(id=order_id, restaurant_id=restaurant.id, **data.model_dump(exclude={"items"}))


@router.patch(
    "/{order_id}/status",
    response_model=OrderStatusResponse,
    status_code=status.HTTP_202_ACCEPTED,
)
async def update_order_status(
    order_id: str,
    data: OrderStatusUpdate,
    session: AsyncSession = Depends(get_tenant_session),
    restaurant: Restaurant = Depends(get_current_restaurant),
    client: httpx.AsyncClient = Depends(get_restate_client),
) -> Any:
    # Verify the order exists and belongs to this restaurant
    result = await session.execute(
        select(Order).where(Order.id == order_id, Order.restaurant_id == restaurant.id)
    )
    order = result.scalar_one_or_none()
    if order is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Order {order_id} not found.",
        )

    payload = {"status": data.new_status, "restaurant_id": restaurant.id}
    await restate_proxy(client, "OrderObject", order_id, "update_status", payload, mode="object")
    invalidate_restaurant_stats_cache(restaurant.id)
    return OrderStatusResponse(id=order_id, status=data.new_status, restaurant_id=restaurant.id)


@router.delete("/{order_id}", status_code=status.HTTP_202_ACCEPTED)
async def cancel_order(
    order_id: str,
    restaurant: Restaurant = Depends(get_current_restaurant),
    client: httpx.AsyncClient = Depends(get_restate_client),
) -> dict[str, str]:
    await restate_proxy(
        client,
        "OrderObject",
        order_id,
        "cancel",
        {"restaurant_id": restaurant.id},
        mode="object",
    )
    invalidate_restaurant_stats_cache(restaurant.id)
    return {"status": "cancellation accepted"}
