"""
Geschützter App-Bereich: Dashboard-Lab Layout (kein Produktiv-Dashboard).

/api/app/dashboard-layout — nur mit Session + aktivem Profil (X-Profile-Id).
"""
from typing import Any, Optional

from fastapi import APIRouter, Depends, Header, HTTPException
from psycopg2.extras import Json

from auth import require_auth
from dashboard_layout_schema import (
    DashboardLayoutPayload,
    coalesce_effective_layout,
    lab_default_layout_dict,
)
from dashboard_widget_entitlements import apply_entitlements_to_layout_dict, widgets_catalog_payload
from db import get_cursor, get_db
from routers.profiles import get_pid
from system_dashboard_product_default import get_product_default_base_dict

router = APIRouter(prefix="/api/app", tags=["app-dashboard-lab"])


@router.get("/widgets/catalog")
def get_widgets_catalog(
    x_profile_id: Optional[str] = Header(default=None),
    session: dict = Depends(require_auth),
) -> dict[str, Any]:
    """Katalog inkl. allowed pro Widget (Feature / Subscription, effektiver Tier)."""
    _ = session
    pid = get_pid(x_profile_id)
    with get_db() as conn:
        return widgets_catalog_payload(pid, conn)


@router.get("/dashboard-layout")
def get_dashboard_layout(
    x_profile_id: Optional[str] = Header(default=None),
    session: dict = Depends(require_auth),
) -> dict[str, Any]:
    _ = session
    pid = get_pid(x_profile_id)
    with get_db() as conn:
        cur = get_cursor(conn)
        cur.execute(
            "SELECT dashboard_layout FROM profiles WHERE id = %s",
            (pid,),
        )
        row = cur.fetchone()
    raw = row["dashboard_layout"] if row else None
    custom, effective = coalesce_effective_layout(raw)
    with get_db() as conn:
        base_product = get_product_default_base_dict(conn)
        if not custom:
            effective = base_product
        effective = apply_entitlements_to_layout_dict(effective, pid, conn)
        product_adj = apply_entitlements_to_layout_dict(base_product, pid, conn)
        lab_adj = apply_entitlements_to_layout_dict(lab_default_layout_dict(), pid, conn)
    return {
        "custom": custom,
        "layout": effective,
        "product_default_layout": product_adj,
        "lab_default_layout": lab_adj,
    }


@router.put("/dashboard-layout")
def put_dashboard_layout(
    body: dict[str, Any],
    x_profile_id: Optional[str] = Header(default=None),
    session: dict = Depends(require_auth),
) -> dict[str, Any]:
    _ = session
    pid = get_pid(x_profile_id)
    try:
        payload = DashboardLayoutPayload.model_validate(body)
    except Exception as e:
        raise HTTPException(422, str(e)) from e
    with get_db() as conn:
        adjusted = apply_entitlements_to_layout_dict(payload.to_stored_dict(), pid, conn)
        try:
            payload = DashboardLayoutPayload.model_validate(adjusted)
        except Exception as e:
            raise HTTPException(422, str(e)) from e
    stored = payload.to_stored_dict()
    with get_db() as conn:
        cur = get_cursor(conn)
        cur.execute(
            "UPDATE profiles SET dashboard_layout = %s WHERE id = %s",
            (Json(stored), pid),
        )
        if cur.rowcount == 0:
            raise HTTPException(404, "Profil nicht gefunden")
    return {"ok": True, "layout": stored}


@router.post("/dashboard-layout/reset")
def reset_dashboard_layout(
    x_profile_id: Optional[str] = Header(default=None),
    session: dict = Depends(require_auth),
) -> dict[str, Any]:
    _ = session
    pid = get_pid(x_profile_id)
    with get_db() as conn:
        cur = get_cursor(conn)
        cur.execute(
            "UPDATE profiles SET dashboard_layout = NULL WHERE id = %s",
            (pid,),
        )
        if cur.rowcount == 0:
            raise HTTPException(404, "Profil nicht gefunden")
        base = get_product_default_base_dict(conn)
        cleared = apply_entitlements_to_layout_dict(base, pid, conn)
    return {"ok": True, "layout": cleared}
