from __future__ import annotations

import hashlib
import json
import math
import os
import re
import secrets
from collections.abc import Callable
from datetime import UTC, datetime
from pathlib import Path
from typing import Annotated, Any, Final

import numpy as np
from fastapi import APIRouter, Header, HTTPException, Query
from fastapi import Path as PathParameter
from pydantic import BaseModel, ConfigDict, Field

from k1link.simulation import (
    QualificationRun,
    QualificationRunIntegrityError,
    QualificationRunNotFoundError,
    QualificationRunStore,
)
from k1link.simulation.worker_gateway import (
    STATUS_SCHEMA,
    PolygonWorkerGateway,
    SimulationWorkerGatewayError,
    SimulationWorkerRejectedError,
    SimulationWorkerUnavailableError,
    UnixSocketWorkerGateway,
)

POLYGON_RUNS_ROOT_ENV: Final = "MISSIONCORE_POLYGON_RUNS_ROOT"
POLYGON_REVIEW_ROOT_ENV: Final = "MISSIONCORE_POLYGON_REVIEW_ROOT"
POLYGON_WORKER_SOCKET_ENV: Final = "MISSIONCORE_POLYGON_WORKER_SOCKET"
POLYGON_WORKER_CONTROL_ENV: Final = "MISSIONCORE_POLYGON_WORKER_CONTROL"
MISSION_CORE_COMMIT_ENV: Final = "MISSIONCORE_COMMIT"
CATALOG_SCHEMA: Final = "missioncore.polygon-run-catalog/v1"
DETAIL_SCHEMA: Final = "missioncore.polygon-run-detail/v1"
GROUND_QUALIFICATION_SCHEMA: Final = "missioncore.polygon-ground-qualification/v1"
GROUND_FAILURE_PREVIEW_SCHEMA: Final = "missioncore.polygon-ground-failure-preview/v1"
GROUND_REPORT_ARTIFACT_KIND: Final = "goose-ground-qualification-report"
GROUND_FAILURE_ARTIFACT_KIND: Final = "goose-ground-qualification-failure-preview"
GROUND_REPORT_SCHEMA: Final = "missioncore.goose-ground-qualification-report/v1"
GROUND_FAILURE_SCHEMA: Final = "missioncore.goose-ground-qualification-failure-preview/v1"
GROUND_REVIEW_SCHEMA: Final = "missioncore.polygon-ground-review/v2"
GROUND_REVIEW_FRAME_SCHEMA: Final = "missioncore.polygon-ground-review-frame/v1"
GOOSE_REVIEW_PACK_SCHEMA: Final = "missioncore.goose-ground-review-pack/v1"
GOOSE_REVIEW_FRAME_SCHEMA: Final = "missioncore.goose-ground-review-frame/v1"
MAX_QUALIFICATION_ARTIFACT_BYTES: Final = 32 * 1024**2
MAX_REVIEW_MANIFEST_BYTES: Final = 8 * 1024**2
MAX_REVIEW_FRAME_BYTES: Final = 2 * 1024**2
MAX_REVIEW_FRAMES: Final = 2_000
MAX_REVIEW_POINTS: Final = 20_000
COMMIT_PATTERN: Final = re.compile(r"^[a-f0-9]{40}$")
GOOSE_FRAME_ID_PATTERN: Final = re.compile(
    r"^(?P<dataset_sequence_id>[A-Za-z0-9][A-Za-z0-9_-]{0,95})"
    r"__(?P<dataset_frame_number>[0-9]{4})"
    r"_(?P<sensor_timestamp_ns>[0-9]{16,20})$"
)
READ_ONLY_LIMITATIONS: Final[tuple[str, ...]] = (
    "Архивный UI-0 публикует только квалификационные доказательства; "
    "содержимое команд и mutation-маршруты в архиве отсутствуют.",
    "Артефакты представлены относительными метаданными; их содержимое не публикуется этим API.",
    "Терминальное состояние прогона не означает приёмку навигации, "
    "восприятия или физической безопасности.",
)

RootProvider = Callable[[], Path | None]
WorkerProvider = Callable[[], PolygonWorkerGateway | None]
ControlProvider = Callable[[], bool]
CommitProvider = Callable[[], str | None]


class StartStockRoverRequest(BaseModel):
    model_config = ConfigDict(extra="forbid", frozen=True)

    scenario_id: str


class AckermannCommandRequest(BaseModel):
    model_config = ConfigDict(extra="forbid", frozen=True)

    speed_mps: float = Field(ge=-1.5, le=1.5, allow_inf_nan=False)
    steering_normalized: float = Field(ge=-1.0, le=1.0, allow_inf_nan=False)


def configured_polygon_runs_root() -> Path | None:
    raw = os.environ.get(POLYGON_RUNS_ROOT_ENV)
    if raw is None or not raw.strip():
        return None
    return Path(raw.strip()).expanduser()


def configured_polygon_worker() -> PolygonWorkerGateway | None:
    raw = os.environ.get(POLYGON_WORKER_SOCKET_ENV)
    if raw is None or not raw.strip():
        return None
    return UnixSocketWorkerGateway(Path(raw.strip()).expanduser())


def configured_polygon_control() -> bool:
    return os.environ.get(POLYGON_WORKER_CONTROL_ENV, "").strip() == "internal-virtual-only"


def configured_mission_core_commit() -> str | None:
    raw = os.environ.get(MISSION_CORE_COMMIT_ENV)
    if raw is None:
        return None
    normalized = raw.strip()
    return normalized if COMMIT_PATTERN.fullmatch(normalized) else None


def build_polygon_router(
    *,
    root_provider: RootProvider = configured_polygon_runs_root,
    worker_provider: WorkerProvider = configured_polygon_worker,
    control_provider: ControlProvider = configured_polygon_control,
    commit_provider: CommitProvider = configured_mission_core_commit,
) -> APIRouter:
    router = APIRouter(prefix="/api/v1/polygon", tags=["polygon"])

    @router.get("/runs")
    def list_polygon_runs(
        limit: Annotated[int, Query(ge=1, le=100)] = 20,
    ) -> dict[str, Any]:
        store = _open_read_only_store(root_provider)
        try:
            ordered = sorted(
                store.list_runs(),
                key=lambda run: (run.created_at_utc, run.run_id),
                reverse=True,
            )
        except QualificationRunIntegrityError as exc:
            raise HTTPException(
                status_code=500,
                detail="Журнал прогонов Полигона не прошёл проверку целостности.",
            ) from exc
        return {
            "schema_version": CATALOG_SCHEMA,
            "access": "read-only",
            "items": [_run_summary(run) for run in ordered[:limit]],
            "total": len(ordered),
            "limitations": list(READ_ONLY_LIMITATIONS),
        }

    @router.get("/runs/{run_id}")
    def get_polygon_run(
        run_id: Annotated[
            str,
            PathParameter(pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"),
        ],
        event_limit: Annotated[int, Query(ge=1, le=500)] = 200,
    ) -> dict[str, Any]:
        store = _open_read_only_store(root_provider)
        try:
            run = store.load(run_id)
            events = store.list_events(run_id)
            commands = store.list_commands(run_id)
        except QualificationRunNotFoundError as exc:
            raise HTTPException(status_code=404, detail="Прогон Полигона не найден.") from exc
        except QualificationRunIntegrityError as exc:
            raise HTTPException(
                status_code=500,
                detail="Доказательства прогона не прошли проверку целостности.",
            ) from exc
        visible_events = events[-event_limit:]
        return {
            "schema_version": DETAIL_SCHEMA,
            "access": "read-only",
            "run": {
                **_run_summary(run),
                "scenario_sha256": run.scenario_sha256,
                "profile_sha256": run.profile_sha256,
                "host_profile_sha256": run.host_profile_sha256,
                "seed": run.seed,
                "parent_run_id": run.parent_run_id,
                "providers": [provider.to_dict() for provider in run.providers],
                "authority": run.authority.to_dict(),
            },
            "events": [event.to_dict() for event in visible_events],
            "events_total": len(events),
            "events_truncated": len(visible_events) != len(events),
            "commands": {
                "count": len(commands),
                "content_exposed": False,
            },
            "artifacts": [artifact.to_dict() for artifact in run.artifacts],
            "limitations": list(READ_ONLY_LIMITATIONS),
        }

    @router.get("/runs/{run_id}/qualification")
    def get_polygon_ground_qualification(
        run_id: Annotated[
            str,
            PathParameter(pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"),
        ],
    ) -> dict[str, Any]:
        store, run = _load_run(root_provider, run_id)
        report = _read_registered_json(
            store,
            run,
            artifact_kind=GROUND_REPORT_ARTIFACT_KIND,
            expected_schema=GROUND_REPORT_SCHEMA,
        )
        required = (
            "identity_sha256",
            "source_id",
            "split",
            "frame_count",
            "aggregates",
            "degradations",
            "checks",
            "worst_frames",
            "decision",
            "safety",
        )
        if any(key not in report for key in required):
            raise HTTPException(
                status_code=500,
                detail="Отчёт квалификации имеет неполный контракт.",
            )
        return {
            "schema_version": GROUND_QUALIFICATION_SCHEMA,
            "access": "read-only",
            "run_id": run.run_id,
            **{key: report[key] for key in required},
        }

    @router.get("/runs/{run_id}/qualification/failures/{frame_id}")
    def get_polygon_ground_failure_preview(
        run_id: Annotated[
            str,
            PathParameter(pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"),
        ],
        frame_id: Annotated[
            str,
            PathParameter(pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"),
        ],
    ) -> dict[str, Any]:
        store, run = _load_run(root_provider, run_id)
        preview = _read_registered_json(
            store,
            run,
            artifact_kind=GROUND_FAILURE_ARTIFACT_KIND,
            expected_schema=GROUND_FAILURE_SCHEMA,
            frame_id=frame_id,
        )
        required = (
            "source_id",
            "frame_id",
            "source_point_count",
            "point_count",
            "sampling",
            "points_xyz_m",
            "ground_truth_ground",
            "evaluated",
            "current_ground",
            "patchwork_ground",
            "current_disagreement",
            "patchwork_disagreement",
            "safety",
        )
        if any(key not in preview for key in required) or preview["frame_id"] != frame_id:
            raise HTTPException(
                status_code=500,
                detail="Preview проблемного кадра имеет неполный контракт.",
            )
        return {
            "schema_version": GROUND_FAILURE_PREVIEW_SCHEMA,
            "access": "read-only",
            "run_id": run.run_id,
            **{key: preview[key] for key in required},
        }

    @router.get("/runs/{run_id}/qualification/review")
    def get_polygon_ground_review(
        run_id: Annotated[
            str,
            PathParameter(pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"),
        ],
    ) -> dict[str, Any]:
        _, run = _load_run(root_provider, run_id)
        _, manifest = _read_ground_review_manifest(root_provider, run.run_id)
        return {
            "schema_version": GROUND_REVIEW_SCHEMA,
            "access": "read-only",
            "run_id": run.run_id,
            "identity_sha256": manifest["identity_sha256"],
            "source_id": manifest["source_id"],
            "frame_count": manifest["frame_count"],
            "preview_points": manifest["preview_points"],
            "frames": [
                {
                    **{
                        key: frame[key]
                        for key in (
                            "sequence",
                            "frame_id",
                            "source_point_count",
                            "point_count",
                            "current",
                            "patchworkpp",
                            "ground_iou_delta",
                        )
                    },
                    **_goose_frame_identity(frame["frame_id"]),
                }
                for frame in manifest["frames"]
            ],
            "safety": manifest["safety"],
        }

    @router.get("/runs/{run_id}/qualification/review/frames/{frame_id}")
    def get_polygon_ground_review_frame(
        run_id: Annotated[
            str,
            PathParameter(pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"),
        ],
        frame_id: Annotated[
            str,
            PathParameter(pattern=r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"),
        ],
    ) -> dict[str, Any]:
        _, run = _load_run(root_provider, run_id)
        pack_root, manifest = _read_ground_review_manifest(root_provider, run.run_id)
        matches = [frame for frame in manifest["frames"] if frame.get("frame_id") == frame_id]
        if len(matches) != 1:
            raise HTTPException(
                status_code=404,
                detail="Кадр визуального прогона не найден.",
            )
        frame = matches[0]
        path = _verified_review_frame_path(pack_root, frame)
        try:
            with np.load(path, allow_pickle=False) as source:
                schema = str(source["schema"][0])
                stored_frame_id = str(source["frame_id"][0])
                source_point_count = int(source["source_point_count"][0])
                xyz_cm = np.asarray(source["xyz_cm"])
                remission = np.asarray(source["remission_u8"])
                flags = np.asarray(source["flags"])
        except (OSError, ValueError, KeyError, IndexError) as exc:
            raise HTTPException(
                status_code=500,
                detail="Кадр визуального прогона повреждён.",
            ) from exc
        point_count = int(frame["point_count"])
        if (
            schema != GOOSE_REVIEW_FRAME_SCHEMA
            or stored_frame_id != frame_id
            or source_point_count != frame["source_point_count"]
            or xyz_cm.dtype != np.dtype("<i2")
            or xyz_cm.shape != (point_count, 3)
            or remission.dtype != np.uint8
            or remission.shape != (point_count,)
            or flags.dtype != np.uint8
            or flags.shape != (point_count,)
            or not 1 <= point_count <= MAX_REVIEW_POINTS
            or np.any(flags > 15)
        ):
            raise HTTPException(
                status_code=500,
                detail="Кадр визуального прогона нарушает контракт.",
            )
        evaluated = (flags & 1) != 0
        ground_truth = (flags & 2) != 0
        current = (flags & 4) != 0
        patchwork = (flags & 8) != 0
        return {
            "schema_version": GROUND_REVIEW_FRAME_SCHEMA,
            "access": "read-only",
            "run_id": run.run_id,
            "source_id": manifest["source_id"],
            "frame_id": frame_id,
            "source_point_count": source_point_count,
            "point_count": point_count,
            "sampling": "deterministic-even-index",
            "points_xyz_m": (xyz_cm.astype(np.float32) / 100.0).tolist(),
            "intensity_0_255": remission.tolist(),
            "ground_truth_ground": ground_truth.astype(np.uint8).tolist(),
            "evaluated": evaluated.astype(np.uint8).tolist(),
            "current_ground": current.astype(np.uint8).tolist(),
            "patchwork_ground": patchwork.astype(np.uint8).tolist(),
            "current_disagreement": (evaluated & (current != ground_truth))
            .astype(np.uint8)
            .tolist(),
            "patchwork_disagreement": (evaluated & (patchwork != ground_truth))
            .astype(np.uint8)
            .tolist(),
            "safety": manifest["safety"],
        }

    @router.get("/worker")
    def get_polygon_worker() -> dict[str, Any]:
        gateway = worker_provider()
        if gateway is None:
            return _unavailable_worker_status()
        try:
            status = gateway.status()
        except SimulationWorkerGatewayError:
            return _unavailable_worker_status()
        return {
            **status,
            "control_available": bool(status["control_available"] and control_provider()),
        }

    @router.get("/worker/live")
    def get_polygon_worker_live() -> dict[str, Any]:
        gateway = _required_worker(worker_provider)
        try:
            return gateway.live()
        except SimulationWorkerUnavailableError as exc:
            raise HTTPException(
                status_code=503,
                detail="Simulation Worker недоступен.",
            ) from exc
        except SimulationWorkerRejectedError as exc:
            raise HTTPException(status_code=409, detail=str(exc)) from exc
        except SimulationWorkerGatewayError as exc:
            raise HTTPException(
                status_code=502,
                detail="Simulation Worker вернул некорректное состояние.",
            ) from exc

    @router.post("/worker/runs")
    def start_polygon_worker_run(
        request: StartStockRoverRequest,
        idempotency_key: Annotated[
            str,
            Header(alias="Idempotency-Key", min_length=1, max_length=160),
        ],
    ) -> dict[str, Any]:
        if request.scenario_id != "stock-rover-ackermann":
            raise HTTPException(status_code=422, detail="Сценарий Полигона не поддерживается.")
        gateway, commit = _control_context(
            worker_provider,
            control_provider,
            commit_provider,
        )
        run_id = _new_run_id(commit)
        try:
            return gateway.start(
                run_id=run_id,
                mission_core_commit=commit,
                idempotency_key=idempotency_key,
            )
        except SimulationWorkerUnavailableError as exc:
            raise HTTPException(status_code=503, detail="Simulation Worker недоступен.") from exc
        except SimulationWorkerRejectedError as exc:
            raise HTTPException(status_code=409, detail=str(exc)) from exc
        except SimulationWorkerGatewayError as exc:
            raise HTTPException(
                status_code=502,
                detail="Simulation Worker не подтвердил запуск.",
            ) from exc

    @router.post("/worker/runs/{run_id}/stop")
    def stop_polygon_worker_run(
        run_id: Annotated[
            str,
            PathParameter(pattern=r"^[a-z0-9][a-z0-9-]{0,63}$"),
        ],
        idempotency_key: Annotated[
            str,
            Header(alias="Idempotency-Key", min_length=1, max_length=160),
        ],
    ) -> dict[str, Any]:
        gateway, _ = _control_context(
            worker_provider,
            control_provider,
            commit_provider,
        )
        try:
            return gateway.stop(run_id=run_id, idempotency_key=idempotency_key)
        except SimulationWorkerUnavailableError as exc:
            raise HTTPException(status_code=503, detail="Simulation Worker недоступен.") from exc
        except SimulationWorkerRejectedError as exc:
            raise HTTPException(status_code=409, detail=str(exc)) from exc
        except SimulationWorkerGatewayError as exc:
            raise HTTPException(
                status_code=502,
                detail="Simulation Worker не подтвердил остановку.",
            ) from exc

    @router.post("/worker/runs/{run_id}/commands")
    def command_polygon_worker_run(
        run_id: Annotated[
            str,
            PathParameter(pattern=r"^[a-z0-9][a-z0-9-]{0,63}$"),
        ],
        request: AckermannCommandRequest,
        idempotency_key: Annotated[
            str,
            Header(alias="Idempotency-Key", min_length=1, max_length=160),
        ],
    ) -> dict[str, Any]:
        gateway, _ = _control_context(
            worker_provider,
            control_provider,
            commit_provider,
        )
        try:
            return gateway.command(
                run_id=run_id,
                speed_mps=request.speed_mps,
                steering_normalized=request.steering_normalized,
                idempotency_key=idempotency_key,
            )
        except SimulationWorkerUnavailableError as exc:
            raise HTTPException(status_code=503, detail="Simulation Worker недоступен.") from exc
        except SimulationWorkerRejectedError as exc:
            raise HTTPException(status_code=409, detail=str(exc)) from exc
        except SimulationWorkerGatewayError as exc:
            raise HTTPException(
                status_code=502,
                detail="Simulation Worker не подтвердил команду ровера.",
            ) from exc

    return router


def _open_read_only_store(root_provider: RootProvider) -> QualificationRunStore:
    root = root_provider()
    if root is None:
        raise HTTPException(
            status_code=503,
            detail="Источник журналов Полигона не настроен на этом экземпляре Mission Core.",
        )
    if not root.is_absolute():
        raise HTTPException(
            status_code=503,
            detail="Источник журналов Полигона настроен некорректно.",
        )
    try:
        return QualificationRunStore(root, read_only=True)
    except QualificationRunIntegrityError as exc:
        raise HTTPException(
            status_code=503,
            detail="Источник журналов Полигона недоступен или настроен некорректно.",
        ) from exc


def _load_run(
    root_provider: RootProvider,
    run_id: str,
) -> tuple[QualificationRunStore, QualificationRun]:
    store = _open_read_only_store(root_provider)
    try:
        return store, store.load(run_id)
    except QualificationRunNotFoundError as exc:
        raise HTTPException(status_code=404, detail="Прогон Полигона не найден.") from exc
    except QualificationRunIntegrityError as exc:
        raise HTTPException(
            status_code=500,
            detail="Доказательства прогона не прошли проверку целостности.",
        ) from exc


def _read_registered_json(
    store: QualificationRunStore,
    run: QualificationRun,
    *,
    artifact_kind: str,
    expected_schema: str,
    frame_id: str | None = None,
) -> dict[str, Any]:
    candidates = [artifact for artifact in run.artifacts if artifact.kind == artifact_kind]
    if frame_id is not None:
        candidates = [
            artifact for artifact in candidates if Path(artifact.relative_path).stem == frame_id
        ]
    if len(candidates) != 1:
        raise HTTPException(
            status_code=404,
            detail="Квалификационный артефакт для этого прогона не найден.",
        )
    artifact = candidates[0]
    if artifact.byte_length > MAX_QUALIFICATION_ARTIFACT_BYTES:
        raise HTTPException(status_code=500, detail="Квалификационный артефакт слишком велик.")
    run_root = (store.root / run.run_id).resolve()
    path = run_root / artifact.relative_path
    try:
        resolved = path.resolve(strict=True)
        resolved.relative_to(run_root)
    except (OSError, ValueError) as exc:
        raise HTTPException(
            status_code=500,
            detail="Путь квалификационного артефакта нарушает границу прогона.",
        ) from exc
    if (
        path.is_symlink()
        or not resolved.is_file()
        or resolved.stat().st_size != artifact.byte_length
    ):
        raise HTTPException(
            status_code=500,
            detail="Квалификационный артефакт не прошёл проверку файла.",
        )
    digest = hashlib.sha256(resolved.read_bytes()).hexdigest()
    if digest != artifact.sha256:
        raise HTTPException(
            status_code=500,
            detail="Квалификационный артефакт не прошёл проверку SHA-256.",
        )
    try:
        value = json.loads(resolved.read_text(encoding="utf-8"))
    except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
        raise HTTPException(
            status_code=500,
            detail="Квалификационный артефакт не является допустимым JSON.",
        ) from exc
    if not isinstance(value, dict) or value.get("schema_version") != expected_schema:
        raise HTTPException(
            status_code=500,
            detail="Квалификационный артефакт имеет неизвестную схему.",
        )
    return value


def _read_ground_review_manifest(
    root_provider: RootProvider,
    run_id: str,
) -> tuple[Path, dict[str, Any]]:
    runs_root = root_provider()
    if runs_root is None or not runs_root.is_absolute():
        raise HTTPException(
            status_code=503,
            detail="Источник визуальных прогонов не настроен.",
        )
    configured = os.environ.get(POLYGON_REVIEW_ROOT_ENV, "").strip()
    review_root = (
        Path(configured).expanduser() if configured else runs_root.parent / "polygon-review-packs"
    )
    if not review_root.is_absolute():
        raise HTTPException(
            status_code=503,
            detail="Источник визуальных прогонов настроен некорректно.",
        )
    run_review_root = review_root / run_id
    try:
        resolved_review_root = review_root.resolve()
        resolved_run_root = run_review_root.resolve(strict=True)
        resolved_run_root.relative_to(resolved_review_root)
    except (OSError, ValueError) as exc:
        raise HTTPException(
            status_code=404,
            detail="Покадровый просмотр для прогона ещё не опубликован.",
        ) from exc
    candidates = sorted(
        path
        for path in resolved_run_root.iterdir()
        if path.is_dir()
        and not path.is_symlink()
        and re.fullmatch(r"review-[a-f0-9]{64}", path.name)
        and (path / "manifest.json").is_file()
    )
    if not candidates:
        raise HTTPException(
            status_code=404,
            detail="Покадровый просмотр для прогона ещё не опубликован.",
        )
    pack_root = candidates[-1]
    manifest_path = pack_root / "manifest.json"
    try:
        if manifest_path.is_symlink() or manifest_path.stat().st_size > MAX_REVIEW_MANIFEST_BYTES:
            raise OSError
        manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
    except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
        raise HTTPException(
            status_code=500,
            detail="Манифест визуального прогона повреждён.",
        ) from exc
    frames = manifest.get("frames") if isinstance(manifest, dict) else None
    safety = manifest.get("safety") if isinstance(manifest, dict) else None
    if (
        not isinstance(manifest, dict)
        or manifest.get("schema_version") != GOOSE_REVIEW_PACK_SCHEMA
        or manifest.get("source_run_id") != run_id
        or not isinstance(manifest.get("identity_sha256"), str)
        or not re.fullmatch(r"[a-f0-9]{64}", manifest["identity_sha256"])
        or pack_root.name != f"review-{manifest['identity_sha256']}"
        or not isinstance(manifest.get("source_id"), str)
        or not isinstance(manifest.get("preview_points"), int)
        or not isinstance(frames, list)
        or not 1 <= len(frames) <= MAX_REVIEW_FRAMES
        or manifest.get("frame_count") != len(frames)
        or not isinstance(safety, dict)
        or safety.get("visualization_only") is not True
        or safety.get("navigation_or_safety_accepted") is not False
    ):
        raise HTTPException(
            status_code=500,
            detail="Манифест визуального прогона нарушает контракт.",
        )
    seen: set[str] = set()
    for expected_sequence, frame in enumerate(frames):
        if (
            not isinstance(frame, dict)
            or frame.get("sequence") != expected_sequence
            or not isinstance(frame.get("frame_id"), str)
            or not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._:-]{0,127}", frame["frame_id"])
            or frame["frame_id"] in seen
            or not isinstance(frame.get("source_point_count"), int)
            or not isinstance(frame.get("point_count"), int)
            or not 1 <= frame["point_count"] <= MAX_REVIEW_POINTS
            or frame["source_point_count"] < frame["point_count"]
            or not isinstance(frame.get("relative_path"), str)
            or not isinstance(frame.get("sha256"), str)
            or not re.fullmatch(r"[a-f0-9]{64}", frame["sha256"])
            or not isinstance(frame.get("byte_length"), int)
            or not 1 <= frame["byte_length"] <= MAX_REVIEW_FRAME_BYTES
            or not _valid_review_metrics(frame.get("current"))
            or not _valid_review_metrics(frame.get("patchworkpp"))
            or not isinstance(frame.get("ground_iou_delta"), (int, float))
            or not math.isfinite(frame["ground_iou_delta"])
            or not -1 <= frame["ground_iou_delta"] <= 1
        ):
            raise HTTPException(
                status_code=500,
                detail="Индекс кадров визуального прогона нарушает контракт.",
            )
        seen.add(frame["frame_id"])
    return pack_root, manifest


def _goose_frame_identity(frame_id: str) -> dict[str, str | int]:
    match = GOOSE_FRAME_ID_PATTERN.fullmatch(frame_id)
    if match is None:
        raise HTTPException(
            status_code=500,
            detail="Идентичность GOOSE-кадра нарушает контракт.",
        )
    return {
        "dataset_sequence_id": match.group("dataset_sequence_id"),
        "dataset_frame_number": int(match.group("dataset_frame_number")),
        # Nanosecond Unix time exceeds JavaScript's safe integer range.
        "sensor_timestamp_ns": match.group("sensor_timestamp_ns"),
    }


def _valid_review_metrics(value: object) -> bool:
    if not isinstance(value, dict):
        return False
    for key in (
        "ground_iou",
        "natural_ground_recall",
        "obstacle_non_ground_recall",
    ):
        metric = value.get(key)
        if (
            not isinstance(metric, (int, float))
            or not math.isfinite(metric)
            or not 0 <= metric <= 1
        ):
            return False
    latency = value.get("latency_ms")
    return isinstance(latency, (int, float)) and math.isfinite(latency) and latency >= 0


def _verified_review_frame_path(pack_root: Path, frame: dict[str, Any]) -> Path:
    relative = Path(frame["relative_path"])
    if relative.is_absolute() or relative.parts[:1] != ("frames",):
        raise HTTPException(
            status_code=500,
            detail="Кадр визуального прогона нарушает границу.",
        )
    path = pack_root / relative
    try:
        resolved = path.resolve(strict=True)
        resolved.relative_to(pack_root)
        if (
            path.is_symlink()
            or not resolved.is_file()
            or resolved.stat().st_size != frame["byte_length"]
        ):
            raise OSError
    except (OSError, ValueError) as exc:
        raise HTTPException(
            status_code=500,
            detail="Файл визуального прогона нарушает границу.",
        ) from exc
    if hashlib.sha256(resolved.read_bytes()).hexdigest() != frame["sha256"]:
        raise HTTPException(
            status_code=500,
            detail="Кадр визуального прогона не прошёл SHA-256.",
        )
    return resolved


def _run_summary(run: QualificationRun) -> dict[str, Any]:
    return {
        "run_id": run.run_id,
        "episode_id": run.episode_id,
        "kind": run.kind.value,
        "state": run.state.value,
        "created_at_utc": run.created_at_utc,
        "started_at_utc": run.started_at_utc,
        "ended_at_utc": run.ended_at_utc,
        "terminal_reason": run.terminal_reason,
        "scenario_generation": run.scenario_generation,
        "profile_generation": run.profile_generation,
        "mission_core_commit": run.mission_core_commit,
        "host_profile_id": run.host_profile_id,
        "reproducibility_tier": run.reproducibility_tier.value,
        "clock_domain": run.clock_domain,
        "revision": run.revision,
        "provider_ids": [provider.identifier for provider in run.providers],
        "artifact_count": len(run.artifacts),
    }


def _required_worker(provider: WorkerProvider) -> PolygonWorkerGateway:
    gateway = provider()
    if gateway is None:
        raise HTTPException(
            status_code=503,
            detail="Simulation Worker не зарегистрирован на этом экземпляре Mission Core.",
        )
    return gateway


def _control_context(
    worker_provider: WorkerProvider,
    control_provider: ControlProvider,
    commit_provider: CommitProvider,
) -> tuple[PolygonWorkerGateway, str]:
    if not control_provider():
        raise HTTPException(
            status_code=403,
            detail="Lifecycle Полигона отключён на этом экземпляре Mission Core.",
        )
    gateway = _required_worker(worker_provider)
    commit = commit_provider()
    if commit is None:
        raise HTTPException(
            status_code=503,
            detail="Mission Core не привязан к точной Git-ревизии.",
        )
    return gateway, commit


def _unavailable_worker_status() -> dict[str, Any]:
    return {
        "schema_version": STATUS_SCHEMA,
        "worker_id": "mission-gpu-s1",
        "transport": "unix",
        "mode": "simulation",
        "available": False,
        "control_available": False,
        "active_run_id": None,
        "run_state": None,
        "active_provider_ids": [],
        "provider_profile": None,
        "isolation": {
            "network": "unavailable",
            "process_identity": "missioncore",
            "artifact_policy": "d-only",
        },
        "authority": {
            "scope": "virtual-only",
            "actuator_authority": False,
            "direct_actuator_setpoints_allowed": False,
        },
    }


def _new_run_id(commit: str) -> str:
    stamp = datetime.now(UTC).strftime("%Y%m%dt%H%M%Sz").lower()
    return f"s1c-{commit[:7]}-{stamp}-{secrets.token_hex(3)}"
