"""
KDS — Kitchen Display System router.

GET  /api/kds/items
    Returns all active (status='active') order items for open orders,
    enriched with zone name and table name. Used by the KDS frontend.

PUT  /api/orders/{order_id}/items/{item_id}/status
    Mark an item ready (active → ready). Only that transition is allowed here.
    Broadcasts item_status_changed SSE event.
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from pydantic import BaseModel
from datetime import datetime, timezone

from database import get_db
from models.order import Order, OrderItem
from models.product import Product
from models.printer import Printer
from models.table import Table
from models.user import User
from routers.deps import get_current_user
from services.sse_bus import broadcast_sync

router = APIRouter()


class ItemStatusUpdate(BaseModel):
    status: str  # only "ready" is accepted


@router.get("/items")
def kds_items(
    db: Session = Depends(get_db),
    user: User = Depends(get_current_user),
):
    """Return all active order items grouped by zone for the KDS display."""
    # Only look at open / partially_paid orders
    open_orders = db.query(Order).filter(Order.status.in_(["open", "partially_paid"])).all()
    order_ids = [o.id for o in open_orders]
    if not order_ids:
        return {"zones": []}

    order_map = {o.id: o for o in open_orders}

    items = db.query(OrderItem).filter(
        OrderItem.order_id.in_(order_ids),
        OrderItem.status == "active",
    ).order_by(OrderItem.added_at.asc()).all()

    tables_map = {t.id: (t.label or f"T{t.number}") for t in db.query(Table).all()}
    printers_map = {p.id: p.name for p in db.query(Printer).all()}

    # Zone = printer_zone_id (None = no zone)
    zones: dict = {}

    def _zone_key(zone_id):
        if zone_id is None:
            return 0
        return zone_id

    def _zone_name(zone_id):
        if zone_id is None:
            return "Χωρίς Ζώνη"
        return printers_map.get(zone_id, f"Ζώνη #{zone_id}")

    for item in items:
        product = item.product
        zone_id = product.printer_zone_id if product else None
        zkey = _zone_key(zone_id)

        if zkey not in zones:
            zones[zkey] = {
                "zone_id": zone_id,
                "zone_name": _zone_name(zone_id),
                "items": [],
            }

        order = order_map.get(item.order_id)
        table_name = tables_map.get(order.table_id) if order and order.table_id else None

        zones[zkey]["items"].append({
            "id": item.id,
            "order_id": item.order_id,
            "table_name": table_name,
            "product_name": product.name if product else f"#{item.product_id}",
            "quantity": item.quantity,
            "notes": item.notes,
            "added_at": item.added_at,
            "status": item.status,
        })

    # Sort zones: named zones first (by zone_id), then no-zone last
    zone_list = sorted(zones.values(), key=lambda z: (z["zone_id"] is None, z["zone_id"] or 0))
    return {"zones": zone_list}


@router.put("/orders/{order_id}/items/{item_id}/status")
def update_item_status(
    order_id: int,
    item_id: int,
    body: ItemStatusUpdate,
    db: Session = Depends(get_db),
    user: User = Depends(get_current_user),
):
    if body.status != "ready":
        raise HTTPException(status_code=400, detail="Only 'ready' is a valid status transition via this endpoint")

    item = db.query(OrderItem).filter(
        OrderItem.id == item_id,
        OrderItem.order_id == order_id,
    ).first()
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    if item.status != "active":
        raise HTTPException(status_code=400, detail=f"Item is '{item.status}' — only active items can be marked ready")

    item.status = "ready"
    db.commit()

    broadcast_sync("item_status_changed", {
        "order_id": order_id,
        "item_id": item_id,
        "status": "ready",
    })

    return {"status": "ready", "item_id": item_id}
