"""Read-only external data API (`/api/v1`).

A deliberately simple, API-key authenticated surface for Power BI (and any other
external reporting tool). It is intentionally separate from the cookie/JWT
session model used by the operator frontend: external tools cannot hold a
browser session, so they present a single static key instead.

Authentication: send the key either as an ``X-API-Key`` request header or an
``api_key`` query-string parameter (Power BI's Web connector supports both).
The key is configured via the ``POWERBI_API_KEY`` environment variable; when it
is blank the whole API is disabled and every request returns 503.
"""

from __future__ import annotations

import secrets
from datetime import date

from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.core.config import settings
from app.core.security_logging import log_security_event
from app.db.session import get_db
from app.models.throughput import ProductionThroughput
from app.services.throughput_service import serialize_entry

router = APIRouter(prefix="/api/v1", tags=["public-v1"])

_API_KEY_HEADER = "X-API-Key"


def require_powerbi_api_key(request: Request) -> str:
    """Authorize an external request via the static Power BI API key.

    Returns the tenant the caller may read. Raises 503 when the API is not
    configured, or 401 when the key is missing/incorrect.
    """
    configured = settings.powerbi_api_key
    if not configured:
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="The data API is not configured.",
        )

    presented = request.headers.get(_API_KEY_HEADER) or request.query_params.get("api_key") or ""
    # Constant-time comparison so the endpoint does not leak key length/contents
    # through response timing.
    if not presented or not secrets.compare_digest(presented, configured):
        log_security_event("authz.denied", role="powerbi", reason="invalid_api_key")
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid or missing API key")

    return settings.powerbi_tenant_id


@router.get("/throughput")
def list_throughput(
    date_from: date | None = Query(default=None, description="Only entries on/after this production date (YYYY-MM-DD)."),
    date_to: date | None = Query(default=None, description="Only entries on/before this production date (YYYY-MM-DD)."),
    limit: int = Query(default=5000, ge=1, le=50000),
    tenant_id: str = Depends(require_powerbi_api_key),
    db: Session = Depends(get_db),
):
    """Flat list of production throughput entries for Power BI.

    One row per packing run, oldest first so incremental refreshes append
    naturally. Each row carries the same fields the operator UI shows
    (date, product, bag size, quantity, calculated kg, QA flags, staff, notes).
    """
    stmt = select(ProductionThroughput).where(ProductionThroughput.tenant_id == tenant_id)
    if date_from is not None:
        stmt = stmt.where(ProductionThroughput.production_date >= date_from)
    if date_to is not None:
        stmt = stmt.where(ProductionThroughput.production_date <= date_to)
    stmt = stmt.order_by(ProductionThroughput.production_date.asc(), ProductionThroughput.id.asc()).limit(limit)

    return [serialize_entry(entry) for entry in db.scalars(stmt).all()]
