"""Admin dashboard summary counts + chart aggregations."""
from datetime import date, timedelta

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

from database import get_db
from model.state import State
from model.district import District
from model.center import Center
from model.doctor import Doctor
from model.patient import Patient
from model.measurement import Measurement
from schemas import DashboardStats

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


@router.get("/stats", response_model=DashboardStats)
def dashboard_stats(db: Session = Depends(get_db)):
    return DashboardStats(
        total_states=db.query(State).count(),
        total_districts=db.query(District).count(),
        total_centers=db.query(Center).count(),
        total_doctors=db.query(Doctor).count(),
        total_patients=db.query(Patient).count(),
    )


@router.get("/charts")
def dashboard_charts(db: Session = Depends(get_db)):
    """Aggregations for the dashboard graphs (patients & readings)."""

    # 1) readings grouped by test type
    readings_by_test_type = [
        {"label": t or "Unknown", "count": c}
        for t, c in db.query(Measurement.test_type, func.count(Measurement.id))
        .group_by(Measurement.test_type)
        .order_by(func.count(Measurement.id).desc())
        .all()
    ]

    # 2) readings grouped by status (Normal / High / Low)
    readings_by_status = [
        {"label": s or "Unknown", "count": c}
        for s, c in db.query(Measurement.status, func.count(Measurement.id))
        .group_by(Measurement.status)
        .order_by(func.count(Measurement.id).desc())
        .all()
    ]

    # 3) patients per doctor (include doctors with zero)
    patients_per_doctor = [
        {"label": name, "count": c}
        for name, c in db.query(Doctor.full_name, func.count(Patient.id))
        .select_from(Doctor)
        .outerjoin(Patient, Patient.doctor_id == Doctor.id)
        .group_by(Doctor.id, Doctor.full_name)
        .order_by(func.count(Patient.id).desc())
        .all()
    ]

    # 4) readings per day for the last 7 days (zero-filled)
    today = date.today()
    start = today - timedelta(days=6)
    rows = (
        db.query(func.date(Measurement.created_at), func.count(Measurement.id))
        .filter(func.date(Measurement.created_at) >= start)
        .group_by(func.date(Measurement.created_at))
        .all()
    )
    per_day = {}
    for d, c in rows:
        key = d.isoformat() if hasattr(d, "isoformat") else str(d)
        per_day[key] = c
    readings_last_7_days = []
    for i in range(7):
        day = start + timedelta(days=i)
        readings_last_7_days.append(
            {"label": day.strftime("%d %b"), "count": per_day.get(day.isoformat(), 0)}
        )

    return {
        "readings_by_test_type": readings_by_test_type,
        "readings_by_status": readings_by_status,
        "patients_per_doctor": patients_per_doctor,
        "readings_last_7_days": readings_last_7_days,
    }
