"""The build plan as data, for the /plan page.

Sources of truth: import/progress.json (workspace root; mounted read-only into the
container at /srv/import). Sessions edit that file on the host at hand-back; this route
reads it on every request, so status changes show without a rebuild or a deploy.

Read-only by design: the file is the record, the page is a view of it. Counts are
computed here rather than stored so the file never carries a number that can go stale.
"""

import json
from pathlib import Path

from fastapi import APIRouter, HTTPException

router = APIRouter(prefix="/api/plan", tags=["plan"])

# Container path first, then the workspace path for local runs.
_CANDIDATES = (Path("/srv/import/progress.json"), Path(__file__).resolve().parents[3] / "import" / "progress.json")

STATUSES = ("done", "doing", "todo", "blocked", "deferred")


def _load() -> dict:
    for path in _CANDIDATES:
        if path.is_file():
            with path.open() as fh:
                return json.load(fh)
    raise HTTPException(status_code=404, detail="progress.json not found")


def _tally(tasks: list[dict]) -> dict:
    counts = {s: 0 for s in STATUSES}
    for t in tasks:
        counts[t.get("status", "todo")] = counts.get(t.get("status", "todo"), 0) + 1
    active = sum(counts[s] for s in ("done", "doing", "todo", "blocked"))
    return {"counts": counts, "total": len(tasks), "active": active, "done": counts["done"]}


@router.get("")
def read_plan() -> dict:
    plan = _load()
    all_tasks = [t for s in plan.get("streams", []) for t in s.get("tasks", [])]
    for stream in plan.get("streams", []):
        stream["tally"] = _tally(stream.get("tasks", []))
    for wave in plan.get("waves", []):
        wave["tally"] = _tally([t for t in all_tasks if t.get("wave") == wave["key"]])
    plan["tally"] = _tally(all_tasks)
    # Promises: each accepted quote line's status is derived from the tasks that deliver it,
    # so the board can never disagree with the task list.
    by_id = {t["id"]: t for t in all_tasks}
    for q in plan.get("quote", []):
        ts = [by_id[i] for i in q.get("tasks", []) if i in by_id]
        st = [t.get("status", "todo") for t in ts]
        if ts and all(x == "done" for x in st): q["status"] = "delivered"
        elif any(x == "blocked" for x in st): q["status"] = "at risk"
        elif any(x in ("doing", "done") for x in st): q["status"] = "in progress"
        else: q["status"] = "not started"
        q["done"] = sum(1 for x in st if x == "done"); q["total"] = len(ts)
        q["next_due"] = min([t["due"] for t in ts if t.get("due") and t.get("status") != "done"], default=None)
    return plan
