"""Tableau de bord."""
from __future__ import annotations

from datetime import date
from typing import Any, Literal

from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session

from ..core import isoweek
from ..core.db import get_db
from ..services import settings as settings_service
from ..services import stats as svc
from ..services.auth import Principal
from .deps import ApiError, require

router = APIRouter(prefix="/api/stats", tags=["tableau de bord"])


@router.get("")
def stats(
    period: Literal["week", "month", "year", "all", "custom"] = "week",
    year: int | None = Query(default=None, ge=2000, le=2100),
    week: int | None = Query(default=None, ge=1, le=53),
    month: int | None = Query(default=None, ge=1, le=12),
    date_from: date | None = Query(default=None, alias="from"),
    date_to: date | None = Query(default=None, alias="to"),
    compare: Literal["previous", "previous_year", "none"] = "previous",
    rule: Literal["jeudi", "prorata"] | None = None,
    drafts: bool = False,
    db: Session = Depends(get_db),
    p: Principal = Depends(require("stats.read")),
) -> dict[str, Any]:
    cy, cw = isoweek.current_week()
    ly, lw = isoweek.shift_week(cy, cw, -1)
    today = isoweek.now_paris().date()
    if period == "week":
        year, week = (year, week) if year and week else (ly, lw)
        try:
            isoweek.validate_week(year, week)
        except ValueError as e:
            raise ApiError(422, str(e), "bad_week") from None
    elif period == "month":
        year, month = (year, month) if year and month else (today.year, today.month)
    elif period == "year":
        year = year or today.year
    try:
        return svc.compute(db, period, year=year, week=week, month=month, date_from=date_from, date_to=date_to,
                           compare=compare, rule=rule or settings_service.get(db, "month_rule"),
                           include_drafts=drafts)
    except svc.StatsError as e:
        raise ApiError(422, str(e), "bad_period") from None
