"""Dashboard summary endpoint.

Returns only the aggregates the homepage actually renders — counts, top items,
totals, and a trend-chart series. Replaces a Dashboard load that previously
fetched five full collections (raw materials, mixes, all product cost
breakdowns, scenarios, data-quality) and only used summaries from each.
"""
from __future__ import annotations

from fastapi import APIRouter, Depends
from sqlalchemy import select
from sqlalchemy.orm import Session, selectinload

from app.api.deps import AuthSession, require_client_session
from app.db.session import get_db
from app.models.mix import Mix
from app.models.product import Product
from app.models.raw_material import RawMaterial
from app.services.client_access_service import has_access_level
from app.services.costing_engine import (
    calculate_mix_cost,
    calculate_product_cost,
    get_active_price,
    calculate_raw_material_cost,
)


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


def _can(session: AuthSession, module_key: str) -> bool:
    permissions = session.module_permissions or {}
    return has_access_level(permissions.get(module_key), "view")


@router.get("/summary")
def dashboard_summary(
    session: AuthSession = Depends(require_client_session),
    db: Session = Depends(get_db),
):
    raw_materials_summary: dict | None = None
    mixes_summary: dict | None = None
    products_summary: dict | None = None
    raw_series: list[float] = []
    mix_series: list[float] = []
    product_series: list[float] = []

    if _can(session, "raw_materials") or _can(session, "dashboard"):
        materials = db.scalars(
            select(RawMaterial)
            .where(RawMaterial.tenant_id == session.tenant_id)
            .options(selectinload(RawMaterial.price_versions))
        ).all()

        total_market_value = 0.0
        latest = None
        latest_date = None
        for material in materials:
            active = get_active_price(material)
            if active is None:
                continue
            comp = calculate_raw_material_cost(material, active)
            raw_series.append(comp.cost_per_kg)
            total_market_value += active.market_value
            if latest_date is None or active.effective_date > latest_date:
                latest_date = active.effective_date
                latest = {
                    "id": material.id,
                    "name": material.name,
                    "market_value": active.market_value,
                    "cost_per_kg": comp.cost_per_kg,
                    "effective_date": active.effective_date.isoformat() if active.effective_date else None,
                }

        raw_materials_summary = {
            "count": len(materials),
            "total_market_value": round(total_market_value, 4),
            "latest": latest,
        }

    if _can(session, "mix_master") or _can(session, "dashboard"):
        mix_rows = db.scalars(
            select(Mix).where(Mix.tenant_id == session.tenant_id).order_by(Mix.name)
        ).all()
        cost_sum = 0.0
        cost_count = 0
        top_mix: dict | None = None
        for mix in mix_rows:
            result = calculate_mix_cost(db, mix.id)
            cost_per_kg = result.get("mix_cost_per_kg")
            if cost_per_kg is not None:
                mix_series.append(cost_per_kg)
                cost_sum += cost_per_kg
                cost_count += 1
            if top_mix is None or (cost_per_kg or 0) > (top_mix.get("mix_cost_per_kg") or 0):
                top_mix = {
                    "id": result["id"],
                    "name": result["name"],
                    "client_name": result["client_name"],
                    "ingredients_count": len(result["ingredients"]),
                    "total_mix_kg": result["total_mix_kg"],
                    "total_mix_cost": result["total_mix_cost"],
                    "mix_cost_per_kg": cost_per_kg,
                    "warnings": result["warnings"],
                }

        mixes_summary = {
            "count": len(mix_rows),
            "average_cost_per_kg": round(cost_sum / cost_count, 4) if cost_count else 0.0,
            "top": top_mix,
        }

    if _can(session, "products") or _can(session, "dashboard"):
        products = db.scalars(
            select(Product).where(Product.tenant_id == session.tenant_id)
        ).all()
        rows: list[dict] = []
        for product in products:
            result = calculate_product_cost(db, product.id)
            finished = result.get("finished_product_delivered") or 0.0
            product_series.append(finished)
            rows.append(
                {
                    "id": product.id,
                    "product_name": result["product_name"],
                    "client_name": result["client_name"],
                    "finished_product_delivered": finished,
                    "warnings": result["warnings"],
                }
            )

        rows.sort(key=lambda row: row["finished_product_delivered"], reverse=True)
        products_summary = {
            "count": len(products),
            "top": rows[0] if rows else None,
            "top_products": rows[:4],
        }

    return {
        "raw_materials": raw_materials_summary,
        "mixes": mixes_summary,
        "products": products_summary,
        # Pre-computed numeric series for the homepage trend chart so the
        # client doesn't need full collections to draw it.
        "trend_seeds": {
            "raw_material_cost_per_kg": raw_series,
            "mix_cost_per_kg": mix_series,
            "product_finished_delivered": product_series,
        },
    }
