"""
Tenant dashboard summary — aggregates KPIs for the portal dashboard.
"""
from datetime import date
from typing import Optional

from fastapi import APIRouter, Depends, Request
from sqlalchemy import and_, func, select
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.billing.models.invoice import Invoice
from src.apps.memorials.models.tribute import Tribute
from src.apps.plots.models.plot import Plot
from src.apps.records.models.record import Record
from src.apps.scheduling.models.service_event import ServiceEvent
from src.apps.sections.models.section import Section
from src.core.constants import UserRole
from src.core.dependencies import require_min_role, require_tenant
from src.core.schemas.response import success
from src.database.session import get_db

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


@router.get("/summary", response_model=dict)
async def get_dashboard_summary(
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    tenant=Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    """Aggregated KPIs for the portal dashboard."""
    tid = tenant.tenant_id
    today = date.today()

    # Plots by status
    plot_counts = await db.execute(
        select(Plot.status, func.count(Plot.id))
        .where(Plot.tenant_id == tid)
        .group_by(Plot.status)
    )
    status_map: dict[str, int] = {row[0]: row[1] for row in plot_counts}
    vacant = status_map.get("vacant", 0)
    occupied = status_map.get("occupied", 0)
    reserved = status_map.get("reserved", 0)
    total_plots = sum(status_map.values())

    # Monthly revenue (current month paid invoices)
    from sqlalchemy import extract
    rev_result = await db.execute(
        select(func.coalesce(func.sum(Invoice.paid_amount), 0))
        .where(
            Invoice.tenant_id == tid,
            Invoice.status.in_(["paid", "partial"]),
            extract("year", Invoice.updated_at) == today.year,
            extract("month", Invoice.updated_at) == today.month,
        )
    )
    monthly_revenue = float(rev_result.scalar_one() or 0)

    # Upcoming services in next 7 days
    from datetime import timedelta
    week_end = today + timedelta(days=7)
    svc_result = await db.execute(
        select(func.count(ServiceEvent.id))
        .where(
            ServiceEvent.tenant_id == tid,
            ServiceEvent.deleted_at.is_(None),
            ServiceEvent.scheduled_date >= today,
            ServiceEvent.scheduled_date <= week_end,
        )
    )
    upcoming_services = svc_result.scalar_one()

    # Pending tribute approvals
    tribute_result = await db.execute(
        select(func.count(Tribute.id))
        .where(Tribute.tenant_id == tid, Tribute.status == "pending")
    )
    pending_tributes = tribute_result.scalar_one()

    # Occupancy by section (top 6)
    sections_result = await db.execute(
        select(Section.id, Section.name)
        .where(Section.tenant_id == tid)
        .order_by(Section.name.asc())
        .limit(6)
    )
    sections = sections_result.all()

    occupancy_by_section = []
    for sec_id, sec_name in sections:
        sec_total = await db.execute(
            select(func.count(Plot.id)).where(Plot.tenant_id == tid, Plot.section_id == sec_id)
        )
        sec_occupied = await db.execute(
            select(func.count(Plot.id)).where(
                Plot.tenant_id == tid, Plot.section_id == sec_id, Plot.status == "occupied"
            )
        )
        t = sec_total.scalar_one()
        o = sec_occupied.scalar_one()
        pct = round((o / t) * 100) if t > 0 else 0
        occupancy_by_section.append({
            "section_name": sec_name,
            "occupancy_pct": pct,
            "occupied": o,
            "total": t,
        })

    return success(data={
        "vacant_plots": vacant,
        "occupied_plots": occupied,
        "reserved_plots": reserved,
        "total_plots": total_plots,
        "monthly_revenue": monthly_revenue,
        "upcoming_services_count": upcoming_services,
        "pending_tributes_count": pending_tributes,
        "occupancy_by_section": occupancy_by_section,
    })
