"""Real, preserved TMB multi-day stage summaries.

This module is deliberately separate from Journey persistence: it reads
already-preserved repository facts (the route registry's real per-day
distance/elevation summary and the matching real GeoJSON geometry) so the
product can represent the whole Tour du Mont Blanc journey honestly. It
never computes, estimates, or fabricates a value; a stage with no matching
preserved data is simply absent.

Only ``tmb_day_01`` currently has an associated Mountain Twin AnalysisRun
(see ``mountain_twin.journey.repository.tmb_day_1_repository``). Every other
stage is truthfully unanalysed: real route geometry and real distance/
elevation facts, no weather/light/conditions/snow/trail/photography/history
intelligence.
"""

from __future__ import annotations

import csv
from dataclasses import dataclass
from pathlib import Path

STAGE_SUMMARY_PATH = "data/processed/tmb_routes_summary.csv"
STAGE_GEOMETRY_DIRECTORY = "data/geojson"

# The one stage with a real Mountain Twin AnalysisRun today. Keep this in
# sync with mountain_twin.journey.repository.TMB_DAY_1_JOURNEY_ID's route.
ANALYSED_STAGE_ROUTE_IDS = frozenset({"tmb_day_01"})


@dataclass(frozen=True)
class TmbStageSummary:
    route_id: str
    day_number: int
    name: str
    distance_m: float
    ascent_m: float
    descent_m: float
    min_elevation_m: float
    max_elevation_m: float
    geometry_path: str
    has_intelligence: bool

    def to_dict(self) -> dict[str, object]:
        return {
            "route_id": self.route_id,
            "day_number": self.day_number,
            "name": self.name,
            "distance_m": self.distance_m,
            "ascent_m": self.ascent_m,
            "descent_m": self.descent_m,
            "min_elevation_m": self.min_elevation_m,
            "max_elevation_m": self.max_elevation_m,
            "geometry_path": self.geometry_path,
            "has_intelligence": self.has_intelligence,
        }


def load_tmb_stage_summaries(root: Path) -> tuple[TmbStageSummary, ...]:
    """Load real per-day TMB metrics from the preserved summary CSV.

    Reads only already-preserved, previously-validated repository data
    (never re-derives or estimates a value). A row without matching
    geometry on disk is skipped rather than represented with a guessed
    path.
    """
    summary_path = root / STAGE_SUMMARY_PATH
    if not summary_path.exists():
        return ()
    with summary_path.open(encoding="utf-8", newline="") as stream:
        rows = list(csv.DictReader(stream))
    stages: list[TmbStageSummary] = []
    for row in rows:
        route_id = row["route_id"]
        geometry_path = f"{STAGE_GEOMETRY_DIRECTORY}/{route_id}.geojson"
        if not (root / geometry_path).exists():
            continue
        day_number = int(row["tmb_day"])
        stages.append(
            TmbStageSummary(
                route_id=route_id,
                day_number=day_number,
                name=f"Day {day_number}",
                distance_m=float(row["distance_km"]) * 1000.0,
                ascent_m=float(row["ascent_m_smooth5"]),
                descent_m=float(row["descent_m_smooth5"]),
                min_elevation_m=float(row["min_elev_m"]),
                max_elevation_m=float(row["max_elev_m"]),
                geometry_path=geometry_path,
                has_intelligence=route_id in ANALYSED_STAGE_ROUTE_IDS,
            )
        )
    return tuple(sorted(stages, key=lambda stage: stage.day_number))


def stage_summaries_document(root: Path, route_id: str) -> list[dict[str, object]] | None:
    """Real multi-day stage context for a bootstrap response, or ``None``.

    Returns the full real stage list only when ``route_id`` genuinely is one
    of the known TMB fixture stages; otherwise returns ``None`` so a durable
    Journey with an unrelated route never receives a fabricated multi-day
    context it does not have.
    """
    stages = load_tmb_stage_summaries(root)
    if not any(stage.route_id == route_id for stage in stages):
        return None
    return [stage.to_dict() for stage in stages]
