"""Tenant dashboard — aggregates KPIs, weekly services, and capacity for the
portal dashboard landing page (INDL-40).
"""
import logging
import time

from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.dashboard.services.dashboard_service import DashboardService
from src.core.constants import UserRole
from src.core.dependencies import require_min_role, require_tenant
from src.core.exceptions import RateLimitError
from src.core.schemas.response import success
from src.database.session import get_db

logger = logging.getLogger(__name__)

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

_RATE_LIMIT_MAX_CALLS = 30
_RATE_LIMIT_WINDOW_SECONDS = 60


async def _check_rate_limit(user_id: str) -> None:
    """Redis counter: max _RATE_LIMIT_MAX_CALLS per window per user (SEC-05).

    Fails open (no limit) if Redis is unavailable, matching the codebase-wide
    convention so the endpoint still works in environments without Redis
    (e.g. the test suite).
    """
    from src.database.session import get_redis

    client = await get_redis()
    if client is None:
        return
    try:
        key = f"dashboard_rl:{user_id}"
        count = await client.incr(key)
        if count == 1:
            await client.expire(key, _RATE_LIMIT_WINDOW_SECONDS)
        if count > _RATE_LIMIT_MAX_CALLS:
            ttl = await client.ttl(key)
            raise RateLimitError(
                "Too many dashboard requests — please wait a moment and try again.",
                retry_after=max(int(ttl), 1),
            )
    except RateLimitError:
        raise
    except Exception:
        pass
    finally:
        try:
            await client.aclose()
        except Exception:
            pass


@router.get("", response_model=dict)
async def get_dashboard(
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    """Aggregated dashboard payload: KPIs, weekly services, capacity, and
    public site URL — tenant-scoped, cached in Redis for 60 seconds."""
    await _check_rate_limit(str(current_user.id))
    started = time.monotonic()
    service = DashboardService(db)
    data = await service.get_dashboard(tenant_id)
    logger.info(
        "dashboard_access",
        extra={
            "tenant_id": str(tenant_id),
            "user_id": str(current_user.id),
            "role": current_user.role,
            "cache_hit": service.last_cache_hit,
            "response_time_ms": round((time.monotonic() - started) * 1000, 1),
        },
    )
    return success(data=data.model_dump(mode="json"), message="Dashboard data retrieved")
