from __future__ import annotations

import json
import math
import os
import re
import shutil
import sqlite3
import stat
import threading
from collections.abc import Iterator
from contextlib import contextmanager
from pathlib import Path
from typing import Any, cast
from uuid import uuid4

from k1link.artifacts import utc_now_iso

from .models import (
    LabSessionBinding,
    LayoutConflictError,
    ObservationArtifactCandidate,
    ObservationSessionCandidate,
    RecordedMediaArtifact,
    ReplayArtifact,
    ReplayCommand,
    SessionArtifact,
    SessionDetail,
    SessionIntegrityError,
    SessionModality,
    SessionNotFoundError,
    SessionNotReplayableError,
    SessionPage,
    SessionSource,
    SessionStatus,
    SessionSummary,
    WorkspaceLayout,
)
from .plugin_contract import ObservationArchiveSource

IDENTIFIER_PATTERN = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")
MAX_LAYOUT_BYTES = 256 * 1024
DATABASE_NAME = "mission-core.sqlite3"
LAB_ARCHIVE_ID = "missioncore.lab-instances"
LAB_ORIGIN = "missioncore.lab-instance/v1"
LAB_ID_PATTERN = re.compile(r"^LAB [A-Z][A-Z0-9._-]{0,31}$")
SHA256_PATTERN = re.compile(r"^[a-f0-9]{64}$")

SCHEMA_SQL = """
CREATE TABLE IF NOT EXISTS observation_sessions (
    session_id TEXT PRIMARY KEY,
    plugin_id TEXT NOT NULL,
    archive_id TEXT NOT NULL,
    display_name TEXT NOT NULL,
    status TEXT NOT NULL CHECK (status IN ('ready', 'interrupted', 'failed')),
    started_at_utc TEXT,
    completed_at_utc TEXT,
    duration_seconds REAL,
    modalities_json TEXT NOT NULL,
    replayable INTEGER NOT NULL CHECK (replayable IN (0, 1)),
    origin TEXT NOT NULL,
    source_count INTEGER NOT NULL,
    total_bytes INTEGER NOT NULL,
    primary_replay_artifact_id TEXT,
    timeline_origin_epoch_ns INTEGER,
    timeline_origin_monotonic_ns INTEGER,
    allowed_root TEXT NOT NULL,
    session_root TEXT NOT NULL,
    created_at_utc TEXT NOT NULL,
    updated_at_utc TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS observation_sessions_recent
ON observation_sessions(started_at_utc DESC, session_id DESC);

CREATE TABLE IF NOT EXISTS observation_session_artifacts (
    session_id TEXT NOT NULL REFERENCES observation_sessions(session_id) ON DELETE CASCADE,
    artifact_id TEXT NOT NULL,
    kind TEXT NOT NULL,
    media_type TEXT NOT NULL,
    byte_length INTEGER NOT NULL,
    sha256 TEXT,
    integrity_status TEXT NOT NULL,
    locator TEXT NOT NULL,
    replay_byte_length INTEGER NOT NULL DEFAULT 0,
    PRIMARY KEY (session_id, artifact_id)
);

CREATE TABLE IF NOT EXISTS observation_session_sources (
    session_id TEXT NOT NULL REFERENCES observation_sessions(session_id) ON DELETE CASCADE,
    source_id TEXT NOT NULL,
    semantic_channel_id TEXT NOT NULL,
    modality TEXT NOT NULL,
    status TEXT NOT NULL,
    seekable INTEGER NOT NULL CHECK (seekable IN (0, 1)),
    artifact_id TEXT NOT NULL,
    PRIMARY KEY (session_id, source_id),
    FOREIGN KEY (session_id, artifact_id)
        REFERENCES observation_session_artifacts(session_id, artifact_id)
        ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS observation_lab_instances (
    session_id TEXT PRIMARY KEY
        REFERENCES observation_sessions(session_id) ON DELETE CASCADE,
    source_session_id TEXT NOT NULL
        REFERENCES observation_sessions(session_id) ON DELETE RESTRICT,
    lab_id TEXT NOT NULL,
    result_kind TEXT NOT NULL,
    result_id TEXT NOT NULL,
    source_result_id TEXT,
    config_sha256 TEXT,
    run_created_at_utc TEXT NOT NULL,
    published_at_utc TEXT NOT NULL,
    provenance_json TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS observation_lab_instances_source
ON observation_lab_instances(source_session_id, published_at_utc DESC);

CREATE TABLE IF NOT EXISTS workspace_layouts (
    workspace_id TEXT PRIMARY KEY,
    layout_schema_version INTEGER NOT NULL,
    revision INTEGER NOT NULL,
    name TEXT NOT NULL,
    layout_json TEXT NOT NULL,
    updated_at_utc TEXT NOT NULL
);
"""


def resolve_missioncore_data_dir(repository_root: Path) -> Path:
    configured = os.environ.get("MISSIONCORE_DATA_DIR", "").strip()
    if configured:
        return Path(configured).expanduser().resolve()
    return (repository_root.expanduser().resolve() / ".runtime" / "mission-core").resolve()


def resolve_missioncore_evidence_dir(repository_root: Path) -> Path:
    """Return the private source-of-record root for new observation sessions."""

    configured = os.environ.get("MISSIONCORE_EVIDENCE_DIR", "").strip()
    if configured:
        return Path(configured).expanduser().resolve()
    return (resolve_missioncore_data_dir(repository_root) / "evidence" / "sessions").resolve()


class SessionStore:
    """SQLite catalog plus confined filesystem references for host observation sessions."""

    def __init__(self, repository_root: Path, *, data_dir: Path | None = None) -> None:
        self.repository_root = repository_root.expanduser().resolve()
        self.data_dir = (
            data_dir.expanduser().resolve()
            if data_dir is not None
            else resolve_missioncore_data_dir(self.repository_root)
        )
        self.data_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
        with _ignore_os_error():
            self.data_dir.chmod(0o700)
        self.database_path = self.data_dir / DATABASE_NAME
        self._lock = threading.RLock()
        self._initialize()

    def reconcile_archive(self, source: ObservationArchiveSource) -> tuple[str, ...]:
        """Reconcile one plugin-owned evidence namespace into the host catalog."""

        allowed_root = source.root.expanduser().resolve()
        candidates = source.discover(allowed_root)
        imported: list[str] = []
        for candidate in candidates:
            try:
                self._upsert_candidate(source, candidate)
            except SessionIntegrityError:
                # One incomplete/corrupt evidence directory must not starve a
                # later valid session in the same plugin archive. Keep any
                # previously indexed row because the candidate is still
                # physically present, but never admit its current artifacts.
                continue
            imported.append(candidate.session_id)
        with self._lock, self._connect() as connection:
            connection.execute("BEGIN IMMEDIATE")
            discovered = {candidate.session_id for candidate in candidates}
            indexed = connection.execute(
                "SELECT session_id FROM observation_sessions "
                "WHERE plugin_id = ? AND archive_id = ? AND allowed_root = ?",
                (source.plugin_id, source.archive_id, str(allowed_root)),
            ).fetchall()
            referenced_sources = {
                row["source_session_id"]
                for row in connection.execute(
                    "SELECT DISTINCT source_session_id FROM observation_lab_instances"
                ).fetchall()
            }
            stale = [
                row["session_id"]
                for row in indexed
                if row["session_id"] not in discovered
                and row["session_id"] not in referenced_sources
            ]
            connection.executemany(
                "DELETE FROM observation_sessions WHERE session_id = ?",
                ((session_id,) for session_id in stale),
            )
            connection.commit()
        return tuple(imported)

    def list_recent(self, *, limit: int = 20, cursor: str | None = None) -> SessionPage:
        if not 1 <= limit <= 100:
            raise ValueError("limit must be within 1..100")
        parameters: list[object] = []
        where = ""
        with self._connect() as connection:
            if cursor is not None:
                _validate_identifier(cursor, "session cursor")
                cursor_row = connection.execute(
                    "SELECT started_at_utc, session_id FROM observation_sessions "
                    "WHERE session_id = ?",
                    (cursor,),
                ).fetchone()
                if cursor_row is None:
                    raise SessionNotFoundError("observation session cursor was not found")
                where = "WHERE (COALESCE(started_at_utc, ''), session_id) < (COALESCE(?, ''), ?)"
                parameters.extend((cursor_row["started_at_utc"], cursor_row["session_id"]))
            parameters.append(limit + 1)
            rows = connection.execute(
                f"SELECT * FROM observation_sessions {where} "  # noqa: S608 - static clause
                "ORDER BY COALESCE(started_at_utc, '') DESC, session_id DESC LIMIT ?",
                parameters,
            ).fetchall()
            lab_rows = (
                {
                    row["session_id"]: row
                    for row in connection.execute(
                        "SELECT * FROM observation_lab_instances WHERE session_id IN "
                        f"({','.join('?' for _ in rows)})",  # noqa: S608 - placeholder count only
                        tuple(row["session_id"] for row in rows),
                    ).fetchall()
                }
                if rows
                else {}
            )
        has_more = len(rows) > limit
        selected = rows[:limit]
        items = tuple(
            _summary_from_row(
                row,
                lab=(
                    _lab_binding_from_row(lab_rows[row["session_id"]])
                    if row["session_id"] in lab_rows
                    else None
                ),
            )
            for row in selected
        )
        next_cursor = items[-1].session_id if has_more and items else None
        return SessionPage(items=items, next_cursor=next_cursor)

    def get_session(self, session_id: str) -> SessionDetail:
        _validate_identifier(session_id, "session id")
        with self._connect() as connection:
            row = connection.execute(
                "SELECT * FROM observation_sessions WHERE session_id = ?",
                (session_id,),
            ).fetchone()
            if row is None:
                raise SessionNotFoundError("observation session was not found")
            source_rows = connection.execute(
                "SELECT source_id, semantic_channel_id, modality, status, seekable, artifact_id "
                "FROM observation_session_sources WHERE session_id = ? ORDER BY source_id",
                (session_id,),
            ).fetchall()
            artifact_rows = connection.execute(
                "SELECT artifact_id, kind, media_type, byte_length, sha256, integrity_status "
                "FROM observation_session_artifacts WHERE session_id = ? ORDER BY artifact_id",
                (session_id,),
            ).fetchall()
            lab_row = connection.execute(
                "SELECT * FROM observation_lab_instances WHERE session_id = ?",
                (session_id,),
            ).fetchone()
        sources = tuple(
            SessionSource(
                source_id=source["source_id"],
                semantic_channel_id=source["semantic_channel_id"],
                modality=cast(SessionModality, source["modality"]),
                status=source["status"],
                seekable=bool(source["seekable"]),
                artifact_id=source["artifact_id"],
            )
            for source in source_rows
        )
        artifacts = tuple(
            SessionArtifact(
                artifact_id=artifact["artifact_id"],
                kind=artifact["kind"],
                media_type=artifact["media_type"],
                byte_length=artifact["byte_length"],
                sha256=artifact["sha256"],
                integrity_status=artifact["integrity_status"],
            )
            for artifact in artifact_rows
        )
        return SessionDetail(
            summary=_summary_from_row(
                row,
                lab=None if lab_row is None else _lab_binding_from_row(lab_row),
            ),
            sources=sources,
            artifacts=artifacts,
        )

    def get_lab_instance(self, session_id: str) -> LabSessionBinding | None:
        """Return immutable LAB provenance without exposing filesystem locators."""

        _validate_identifier(session_id, "session id")
        with self._connect() as connection:
            row = connection.execute(
                "SELECT * FROM observation_lab_instances WHERE session_id = ?",
                (session_id,),
            ).fetchone()
        return None if row is None else _lab_binding_from_row(row)

    def publish_lab_instance(
        self,
        *,
        session_id: str,
        source_session_id: str,
        display_name: str,
        lab_id: str,
        result_kind: str,
        result_id: str,
        run_created_at_utc: str,
        source_result_id: str | None = None,
        config_sha256: str | None = None,
        provenance: dict[str, Any] | None = None,
        duration_seconds: float | None = None,
        include_recorded_media: bool = True,
    ) -> LabSessionBinding:
        """Append one immutable catalog projection over an existing source session.

        Artifact/source rows are copied as references to the sealed evidence.
        No raw payload is copied and the LAB row uses a distinct archive id so
        device-plugin reconciliation cannot replace it.
        """

        _validate_identifier(session_id, "LAB session id")
        _validate_identifier(source_session_id, "source session id")
        if session_id == source_session_id:
            raise ValueError("LAB session id must differ from its source")
        if LAB_ID_PATTERN.fullmatch(lab_id) is None:
            raise ValueError("LAB id must use the form 'LAB E21'")
        _validate_identifier(result_kind, "LAB result kind")
        _validate_identifier(result_id, "LAB result id")
        if source_result_id is not None:
            _validate_identifier(source_result_id, "LAB source result id")
        if config_sha256 is not None and SHA256_PATTERN.fullmatch(config_sha256) is None:
            raise ValueError("LAB configuration SHA-256 is invalid")
        normalized_name = display_name.strip()
        if not 1 <= len(normalized_name) <= 160:
            raise ValueError("LAB display name must contain 1..160 characters")
        _require_utc_timestamp(run_created_at_utc, "LAB run creation time")
        if duration_seconds is not None and (
            isinstance(duration_seconds, bool)
            or not math.isfinite(duration_seconds)
            or duration_seconds <= 0
        ):
            raise ValueError("LAB duration must be a positive finite value")
        serialized_provenance = _serialize_provenance(provenance or {})
        published_at = utc_now_iso()

        with self._lock, self._connect() as connection:
            connection.execute("BEGIN IMMEDIATE")
            source = connection.execute(
                "SELECT * FROM observation_sessions WHERE session_id = ?",
                (source_session_id,),
            ).fetchone()
            if source is None:
                connection.rollback()
                raise SessionNotFoundError("LAB source observation session was not found")
            if (
                connection.execute(
                    "SELECT 1 FROM observation_lab_instances WHERE session_id = ?",
                    (source_session_id,),
                ).fetchone()
                is not None
            ):
                connection.rollback()
                raise SessionIntegrityError("LAB instances cannot be chained")

            existing = connection.execute(
                "SELECT * FROM observation_lab_instances WHERE session_id = ?",
                (session_id,),
            ).fetchone()
            expected = {
                "source_session_id": source_session_id,
                "lab_id": lab_id,
                "result_kind": result_kind,
                "result_id": result_id,
                "source_result_id": source_result_id,
                "config_sha256": config_sha256,
                "run_created_at_utc": run_created_at_utc,
                "provenance_json": serialized_provenance,
            }
            if existing is not None:
                if any(existing[key] != value for key, value in expected.items()):
                    connection.rollback()
                    raise SessionIntegrityError(
                        "LAB session id is already bound to different provenance"
                    )
                connection.commit()
                return _lab_binding_from_row(existing)
            if (
                connection.execute(
                    "SELECT 1 FROM observation_sessions WHERE session_id = ?",
                    (session_id,),
                ).fetchone()
                is not None
            ):
                connection.rollback()
                raise SessionIntegrityError("LAB session id already exists in the catalog")

            connection.execute(
                "INSERT INTO observation_sessions "
                "(session_id, plugin_id, archive_id, display_name, status, "
                "started_at_utc, completed_at_utc, duration_seconds, modalities_json, "
                "replayable, origin, source_count, total_bytes, "
                "primary_replay_artifact_id, timeline_origin_epoch_ns, "
                "timeline_origin_monotonic_ns, allowed_root, session_root, "
                "created_at_utc, updated_at_utc) "
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
                (
                    session_id,
                    source["plugin_id"],
                    LAB_ARCHIVE_ID,
                    normalized_name,
                    source["status"],
                    run_created_at_utc,
                    run_created_at_utc,
                    (
                        source["duration_seconds"]
                        if duration_seconds is None
                        else duration_seconds
                    ),
                    source["modalities_json"],
                    source["replayable"],
                    LAB_ORIGIN,
                    source["source_count"],
                    source["total_bytes"],
                    source["primary_replay_artifact_id"],
                    source["timeline_origin_epoch_ns"],
                    source["timeline_origin_monotonic_ns"],
                    source["allowed_root"],
                    source["session_root"],
                    published_at,
                    published_at,
                ),
            )
            connection.execute(
                "INSERT INTO observation_session_artifacts "
                "(session_id, artifact_id, kind, media_type, byte_length, sha256, "
                "integrity_status, locator, replay_byte_length) "
                "SELECT ?, artifact_id, kind, media_type, byte_length, sha256, "
                "integrity_status, locator, replay_byte_length "
                "FROM observation_session_artifacts WHERE session_id = ? "
                "AND (? OR kind <> 'recorded-video')",
                (session_id, source_session_id, include_recorded_media),
            )
            connection.execute(
                "INSERT INTO observation_session_sources "
                "(session_id, source_id, semantic_channel_id, modality, status, "
                "seekable, artifact_id) "
                "SELECT ?, source_id, semantic_channel_id, modality, status, "
                "seekable, artifact_id FROM observation_session_sources "
                "WHERE session_id = ? AND (? OR modality <> 'video')",
                (session_id, source_session_id, include_recorded_media),
            )
            connection.execute(
                "INSERT INTO observation_lab_instances "
                "(session_id, source_session_id, lab_id, result_kind, result_id, "
                "source_result_id, config_sha256, run_created_at_utc, "
                "published_at_utc, provenance_json) "
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
                (
                    session_id,
                    source_session_id,
                    lab_id,
                    result_kind,
                    result_id,
                    source_result_id,
                    config_sha256,
                    run_created_at_utc,
                    published_at,
                    serialized_provenance,
                ),
            )
            connection.commit()
        binding = self.get_lab_instance(session_id)
        if binding is None:
            raise SessionIntegrityError("LAB session publication was not durable")
        return binding

    def delete_session(self, session_id: str) -> None:
        """Permanently delete one exact catalogued evidence directory and row."""

        _validate_identifier(session_id, "session id")
        with self._lock:
            with self._connect() as connection:
                lab = connection.execute(
                    "SELECT 1 FROM observation_lab_instances WHERE session_id = ?",
                    (session_id,),
                ).fetchone()
                if lab is not None:
                    connection.execute("BEGIN IMMEDIATE")
                    deleted = connection.execute(
                        "DELETE FROM observation_sessions WHERE session_id = ?",
                        (session_id,),
                    ).rowcount
                    connection.commit()
                    if deleted != 1:
                        raise SessionNotFoundError("observation session was not found")
                    return
                dependent = connection.execute(
                    "SELECT session_id FROM observation_lab_instances "
                    "WHERE source_session_id = ? LIMIT 1",
                    (session_id,),
                ).fetchone()
                if dependent is not None:
                    raise SessionIntegrityError(
                        "source session has LAB instances; remove those instances first"
                    )
                row = connection.execute(
                    "SELECT allowed_root, session_root FROM observation_sessions "
                    "WHERE session_id = ?",
                    (session_id,),
                ).fetchone()
            if row is None:
                raise SessionNotFoundError("observation session was not found")

            allowed_root = Path(row["allowed_root"]).expanduser().resolve()
            session_root = Path(row["session_root"]).expanduser()
            try:
                unresolved_parent = session_root.parent.resolve(strict=True)
            except OSError as exc:
                raise SessionIntegrityError("session deletion root is unavailable") from exc
            if (
                unresolved_parent != allowed_root
                or session_root.name != session_id
                or session_root == allowed_root
            ):
                raise SessionIntegrityError("session deletion target escapes its allowed root")

            if session_root.exists() or session_root.is_symlink():
                try:
                    metadata = session_root.lstat()
                except OSError as exc:
                    raise SessionIntegrityError("session deletion target is unavailable") from exc
                if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
                    raise SessionIntegrityError("session deletion target is not a real directory")
                tombstone = allowed_root / f".{session_id}.{uuid4().hex}.deleting"
                try:
                    os.replace(session_root, tombstone)
                    shutil.rmtree(tombstone)
                except OSError as exc:
                    if tombstone.exists() and not session_root.exists():
                        with _ignore_os_error():
                            os.replace(tombstone, session_root)
                    raise SessionIntegrityError("session evidence could not be deleted") from exc

            with self._connect() as connection:
                connection.execute("BEGIN IMMEDIATE")
                deleted = connection.execute(
                    "DELETE FROM observation_sessions WHERE session_id = ?",
                    (session_id,),
                ).rowcount
                connection.commit()
            if deleted != 1:
                raise SessionNotFoundError("observation session was not found")

    def prepare_replay(
        self,
        session_id: str,
        *,
        speed: float = 1.0,
        loop: bool = False,
    ) -> ReplayCommand:
        detail = self.get_session(session_id)
        if not detail.summary.replayable:
            raise SessionNotReplayableError("observation session has no replayable spatial source")
        if not 0 <= speed <= 100:
            raise ValueError("speed must be within 0..100")
        with self._connect() as connection:
            session = connection.execute(
                "SELECT plugin_id, allowed_root, session_root, "
                "primary_replay_artifact_id, timeline_origin_epoch_ns, "
                "timeline_origin_monotonic_ns FROM observation_sessions WHERE session_id = ?",
                (session_id,),
            ).fetchone()
            artifact_rows = connection.execute(
                "SELECT artifact_id, media_type, byte_length, replay_byte_length, locator, sha256 "
                "FROM observation_session_artifacts WHERE session_id = ? "
                "AND replay_byte_length > 0 ORDER BY artifact_id",
                (session_id,),
            ).fetchall()
        if session is None or not artifact_rows:
            raise SessionNotReplayableError("observation session replay artifact is unavailable")
        primary_artifact_id = session["primary_replay_artifact_id"]
        epoch_ns = session["timeline_origin_epoch_ns"]
        monotonic_ns = session["timeline_origin_monotonic_ns"]
        if (
            not isinstance(primary_artifact_id, str)
            or not isinstance(epoch_ns, int)
            or not isinstance(monotonic_ns, int)
        ):
            raise SessionNotReplayableError("observation session replay contract is incomplete")
        allowed_root = Path(session["allowed_root"])
        session_root = Path(session["session_root"])
        artifacts = tuple(
            ReplayArtifact(
                artifact_id=row["artifact_id"],
                path=_resolve_confined_artifact(
                    allowed_root,
                    session_root,
                    Path(row["locator"]),
                ),
                media_type=row["media_type"],
                file_byte_length=int(row["byte_length"]),
                replay_byte_length=int(row["replay_byte_length"]),
                expected_sha256=row["sha256"],
            )
            for row in artifact_rows
        )
        if sum(artifact.artifact_id == primary_artifact_id for artifact in artifacts) != 1:
            raise SessionNotReplayableError("observation session primary artifact is unavailable")
        return ReplayCommand(
            session_id=session_id,
            plugin_id=session["plugin_id"],
            allowed_root=allowed_root,
            session_root=session_root,
            primary_artifact_id=primary_artifact_id,
            artifacts=artifacts,
            timeline_origin_epoch_ns=epoch_ns,
            timeline_origin_monotonic_ns=monotonic_ns,
            speed=float(speed),
            loop=loop,
        )

    def list_recorded_media(self, session_id: str) -> tuple[RecordedMediaArtifact, ...]:
        """Return confined archived-video handles without exposing device ids."""

        _validate_identifier(session_id, "session id")
        with self._connect() as connection:
            session = connection.execute(
                "SELECT allowed_root, session_root FROM observation_sessions WHERE session_id = ?",
                (session_id,),
            ).fetchone()
            if session is None:
                raise SessionNotFoundError("observation session was not found")
            rows = connection.execute(
                "SELECT DISTINCT a.artifact_id, a.locator, a.byte_length "
                "FROM observation_session_artifacts AS a "
                "JOIN observation_session_sources AS source "
                "ON source.session_id = a.session_id AND source.artifact_id = a.artifact_id "
                "WHERE a.session_id = ? AND a.kind = 'recorded-video' "
                "AND source.modality = 'video' ORDER BY a.artifact_id",
                (session_id,),
            ).fetchall()
        return tuple(
            _recorded_media_from_row(
                session_id=session_id,
                allowed_root=Path(session["allowed_root"]),
                session_root=Path(session["session_root"]),
                artifact_id=row["artifact_id"],
                locator=Path(row["locator"]),
                byte_length=row["byte_length"],
            )
            for row in rows
        )

    def get_recorded_media(
        self,
        session_id: str,
        artifact_id: str,
    ) -> RecordedMediaArtifact:
        _validate_identifier(artifact_id, "recorded media artifact id")
        matches = tuple(
            artifact
            for artifact in self.list_recorded_media(session_id)
            if artifact.artifact_id == artifact_id
        )
        if len(matches) != 1:
            raise SessionNotFoundError("recorded media source was not found")
        return matches[0]

    def get_layout(self, workspace_id: str) -> WorkspaceLayout:
        _validate_identifier(workspace_id, "workspace id")
        with self._connect() as connection:
            row = connection.execute(
                "SELECT * FROM workspace_layouts WHERE workspace_id = ?",
                (workspace_id,),
            ).fetchone()
        if row is None:
            raise SessionNotFoundError("workspace layout was not found")
        return _layout_from_row(row)

    def save_layout(
        self,
        workspace_id: str,
        *,
        schema_version: int,
        expected_revision: int,
        name: str,
        layout: dict[str, Any],
    ) -> WorkspaceLayout:
        _validate_identifier(workspace_id, "workspace id")
        if schema_version not in {1, 2}:
            raise ValueError("workspace layout schema version is unsupported")
        if expected_revision < 0:
            raise ValueError("expected revision must be non-negative")
        normalized_name = name.strip()
        if not 1 <= len(normalized_name) <= 160:
            raise ValueError("layout name must contain 1..160 characters")
        serialized = _serialize_layout(layout)
        updated_at = utc_now_iso()

        with self._lock, self._connect() as connection:
            connection.execute("BEGIN IMMEDIATE")
            current = connection.execute(
                "SELECT revision FROM workspace_layouts WHERE workspace_id = ?",
                (workspace_id,),
            ).fetchone()
            current_revision = 0 if current is None else int(current["revision"])
            if current_revision != expected_revision:
                connection.rollback()
                raise LayoutConflictError("workspace layout revision changed")
            revision = current_revision + 1
            connection.execute(
                "INSERT INTO workspace_layouts "
                "(workspace_id, layout_schema_version, revision, name, layout_json, "
                "updated_at_utc) VALUES (?, ?, ?, ?, ?, ?) "
                "ON CONFLICT(workspace_id) DO UPDATE SET "
                "layout_schema_version = excluded.layout_schema_version, "
                "revision = excluded.revision, name = excluded.name, "
                "layout_json = excluded.layout_json, updated_at_utc = excluded.updated_at_utc",
                (
                    workspace_id,
                    schema_version,
                    revision,
                    normalized_name,
                    serialized,
                    updated_at,
                ),
            )
            connection.commit()
        return WorkspaceLayout(
            workspace_id=workspace_id,
            schema_version=schema_version,
            revision=revision,
            name=normalized_name,
            layout=json.loads(serialized),
            updated_at_utc=updated_at,
        )

    def _initialize(self) -> None:
        with self._connect() as connection:
            connection.executescript(SCHEMA_SQL)
            self._migrate_transient_tool_windows(connection)
            session_columns = {
                row["name"] for row in connection.execute("PRAGMA table_info(observation_sessions)")
            }
            for name, declaration in (
                ("plugin_id", "TEXT NOT NULL DEFAULT ''"),
                ("archive_id", "TEXT NOT NULL DEFAULT ''"),
                ("primary_replay_artifact_id", "TEXT"),
                ("timeline_origin_epoch_ns", "INTEGER"),
                ("timeline_origin_monotonic_ns", "INTEGER"),
            ):
                if name in session_columns:
                    continue
                connection.execute(
                    f"ALTER TABLE observation_sessions ADD COLUMN {name} {declaration}"  # noqa: S608
                )
            artifact_columns = {
                row["name"]
                for row in connection.execute("PRAGMA table_info(observation_session_artifacts)")
            }
            if "replay_byte_length" not in artifact_columns:
                connection.execute(
                    "ALTER TABLE observation_session_artifacts "
                    "ADD COLUMN replay_byte_length INTEGER NOT NULL DEFAULT 0"
                )
            connection.commit()
        with _ignore_os_error():
            self.database_path.chmod(0o600)

    def _migrate_transient_tool_windows(self, connection: sqlite3.Connection) -> None:
        """Remove v1 scene-tool visibility that never belonged in a layout."""

        rows = connection.execute(
            "SELECT workspace_id, layout_json FROM workspace_layouts "
            "WHERE workspace_id = ? AND layout_schema_version = 1",
            ("observation.spatial",),
        ).fetchall()
        for row in rows:
            try:
                layout = json.loads(row["layout_json"])
            except (TypeError, json.JSONDecodeError):
                continue
            if not isinstance(layout, dict) or "tool_windows" not in layout:
                continue
            layout.pop("tool_windows", None)
            connection.execute(
                "UPDATE workspace_layouts "
                "SET layout_schema_version = 2, layout_json = ? "
                "WHERE workspace_id = ? AND layout_schema_version = 1",
                (_serialize_layout(layout), row["workspace_id"]),
            )

    def _upsert_candidate(
        self,
        source: ObservationArchiveSource,
        candidate: ObservationSessionCandidate,
    ) -> None:
        _validate_identifier(candidate.session_id, "observation session id")
        _validate_identifier(source.plugin_id, "device plugin id")
        _validate_identifier(source.archive_id, "observation archive id")
        allowed_root = candidate.allowed_root.resolve()
        session_root = candidate.session_root.resolve()
        if not session_root.is_relative_to(allowed_root):
            raise SessionIntegrityError("observation session root escapes its allowed root")
        if allowed_root != source.root.expanduser().resolve():
            raise SessionIntegrityError("plugin candidate does not belong to its archive root")
        sources = candidate.sources
        artifacts = _validated_candidate_artifacts(candidate, session_root)
        _validate_candidate_replay(candidate, artifacts)
        now = utc_now_iso()
        modalities_json = json.dumps(list(candidate.modalities), separators=(",", ":"))

        with self._lock, self._connect() as connection:
            connection.execute("BEGIN IMMEDIATE")
            existing = connection.execute(
                "SELECT plugin_id, archive_id, allowed_root, session_root, created_at_utc "
                "FROM observation_sessions WHERE session_id = ?",
                (candidate.session_id,),
            ).fetchone()
            unclaimed_pre_plugin_row = existing is not None and (
                existing["plugin_id"] == "" and existing["archive_id"] == ""
            )
            if existing is not None and (
                Path(existing["allowed_root"]).resolve() != allowed_root
                or Path(existing["session_root"]).resolve() != session_root
                or (
                    not unclaimed_pre_plugin_row
                    and (
                        existing["plugin_id"] != source.plugin_id
                        or existing["archive_id"] != source.archive_id
                    )
                )
            ):
                connection.rollback()
                raise SessionIntegrityError("session id is already bound to another archive")
            created_at = existing["created_at_utc"] if existing is not None else now
            connection.execute(
                "INSERT INTO observation_sessions "
                "(session_id, plugin_id, archive_id, display_name, status, "
                "started_at_utc, completed_at_utc, "
                "duration_seconds, modalities_json, replayable, origin, source_count, "
                "total_bytes, primary_replay_artifact_id, timeline_origin_epoch_ns, "
                "timeline_origin_monotonic_ns, allowed_root, "
                "session_root, created_at_utc, updated_at_utc) "
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
                "ON CONFLICT(session_id) DO UPDATE SET "
                "plugin_id = excluded.plugin_id, archive_id = excluded.archive_id, "
                "display_name = excluded.display_name, status = excluded.status, "
                "started_at_utc = excluded.started_at_utc, "
                "completed_at_utc = excluded.completed_at_utc, "
                "duration_seconds = excluded.duration_seconds, "
                "modalities_json = excluded.modalities_json, "
                "replayable = excluded.replayable, source_count = excluded.source_count, "
                "total_bytes = excluded.total_bytes, "
                "primary_replay_artifact_id = excluded.primary_replay_artifact_id, "
                "timeline_origin_epoch_ns = excluded.timeline_origin_epoch_ns, "
                "timeline_origin_monotonic_ns = excluded.timeline_origin_monotonic_ns, "
                "updated_at_utc = excluded.updated_at_utc",
                (
                    candidate.session_id,
                    source.plugin_id,
                    source.archive_id,
                    candidate.display_name,
                    candidate.status,
                    candidate.started_at_utc,
                    candidate.completed_at_utc,
                    candidate.duration_seconds,
                    modalities_json,
                    int(candidate.replayable),
                    source.archive_id,
                    len(sources),
                    candidate.total_bytes,
                    candidate.primary_replay_artifact_id,
                    candidate.timeline_origin_epoch_ns,
                    candidate.timeline_origin_monotonic_ns,
                    str(allowed_root),
                    str(session_root),
                    created_at,
                    now,
                ),
            )
            connection.execute(
                "DELETE FROM observation_session_sources WHERE session_id = ?",
                (candidate.session_id,),
            )
            connection.execute(
                "DELETE FROM observation_session_artifacts WHERE session_id = ?",
                (candidate.session_id,),
            )
            connection.executemany(
                "INSERT INTO observation_session_artifacts "
                "(session_id, artifact_id, kind, media_type, byte_length, sha256, "
                "integrity_status, locator, replay_byte_length) "
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
                [
                    (
                        candidate.session_id,
                        artifact.artifact_id,
                        artifact.kind,
                        artifact.media_type,
                        artifact.byte_length,
                        artifact.sha256,
                        artifact.integrity_status,
                        str(artifact.locator),
                        artifact.replay_byte_length,
                    )
                    for artifact in artifacts
                ],
            )
            connection.executemany(
                "INSERT INTO observation_session_sources "
                "(session_id, source_id, semantic_channel_id, modality, status, seekable, "
                "artifact_id) VALUES (?, ?, ?, ?, ?, ?, ?)",
                [
                    (
                        candidate.session_id,
                        source.source_id,
                        source.semantic_channel_id,
                        source.modality,
                        source.status,
                        int(source.seekable),
                        source.artifact_id,
                    )
                    for source in sources
                ],
            )
            connection.commit()

    @contextmanager
    def _connect(self) -> Iterator[sqlite3.Connection]:
        connection = sqlite3.connect(self.database_path, timeout=5.0)
        connection.row_factory = sqlite3.Row
        try:
            connection.execute("PRAGMA foreign_keys = ON")
            connection.execute("PRAGMA synchronous = FULL")
            connection.execute("PRAGMA busy_timeout = 5000")
            connection.execute("PRAGMA journal_mode = WAL")
            yield connection
        finally:
            connection.close()


def _validated_candidate_artifacts(
    candidate: ObservationSessionCandidate,
    session_root: Path,
) -> tuple[ObservationArtifactCandidate, ...]:
    artifacts = candidate.artifacts
    artifact_ids: set[str] = set()
    for artifact in artifacts:
        _validate_identifier(artifact.artifact_id, "observation artifact id")
        if artifact.artifact_id in artifact_ids:
            raise SessionIntegrityError("observation session contains duplicate artifacts")
        artifact_ids.add(artifact.artifact_id)
        if artifact.byte_length < 0 or not 0 <= artifact.replay_byte_length <= artifact.byte_length:
            raise SessionIntegrityError("observation artifact has invalid byte boundaries")
        try:
            locator = artifact.locator.resolve(strict=True)
        except OSError as exc:
            raise SessionIntegrityError("observation artifact is missing") from exc
        if not locator.is_relative_to(session_root) or not (locator.is_file() or locator.is_dir()):
            raise SessionIntegrityError("observation artifact escapes its session root")
        if artifact.replay_byte_length > 0 and not locator.is_file():
            raise SessionIntegrityError("replay input artifact must be a regular file")
    source_ids: set[str] = set()
    for source in candidate.sources:
        _validate_identifier(source.source_id, "observation source id")
        if source.source_id in source_ids:
            raise SessionIntegrityError("observation session contains duplicate sources")
        if source.artifact_id not in artifact_ids:
            raise SessionIntegrityError("observation source references an unknown artifact")
        source_ids.add(source.source_id)
    return artifacts


def _validate_candidate_replay(
    candidate: ObservationSessionCandidate,
    artifacts: tuple[ObservationArtifactCandidate, ...],
) -> None:
    primary_id = candidate.primary_replay_artifact_id
    replay_artifacts = tuple(artifact for artifact in artifacts if artifact.replay_byte_length > 0)
    if candidate.replayable:
        if (
            primary_id is None
            or sum(artifact.artifact_id == primary_id for artifact in replay_artifacts) != 1
            or candidate.timeline_origin_epoch_ns is None
            or candidate.timeline_origin_monotonic_ns is None
        ):
            raise SessionIntegrityError("replayable observation contract is incomplete")
        if candidate.timeline_origin_epoch_ns < 0 or candidate.timeline_origin_monotonic_ns < 0:
            raise SessionIntegrityError("observation timeline origin is invalid")
    elif primary_id is not None or replay_artifacts:
        raise SessionIntegrityError("non-replayable observation declares replay artifacts")


def _summary_from_row(
    row: sqlite3.Row,
    *,
    lab: LabSessionBinding | None = None,
) -> SessionSummary:
    raw_modalities = json.loads(row["modalities_json"])
    modalities = tuple(cast(SessionModality, value) for value in raw_modalities)
    return SessionSummary(
        session_id=row["session_id"],
        display_name=row["display_name"],
        status=cast(SessionStatus, row["status"]),
        started_at_utc=row["started_at_utc"],
        completed_at_utc=row["completed_at_utc"],
        duration_seconds=row["duration_seconds"],
        modalities=modalities,
        source_count=row["source_count"],
        total_bytes=row["total_bytes"],
        replayable=bool(row["replayable"]),
        origin=row["origin"],
        lab=lab,
    )


def _lab_binding_from_row(row: sqlite3.Row) -> LabSessionBinding:
    try:
        provenance = json.loads(row["provenance_json"])
    except (TypeError, json.JSONDecodeError) as exc:
        raise SessionIntegrityError("stored LAB provenance is invalid") from exc
    if not isinstance(provenance, dict):
        raise SessionIntegrityError("stored LAB provenance is not an object")
    return LabSessionBinding(
        session_id=row["session_id"],
        source_session_id=row["source_session_id"],
        lab_id=row["lab_id"],
        result_kind=row["result_kind"],
        result_id=row["result_id"],
        source_result_id=row["source_result_id"],
        config_sha256=row["config_sha256"],
        run_created_at_utc=row["run_created_at_utc"],
        published_at_utc=row["published_at_utc"],
        provenance=provenance,
    )


def _serialize_provenance(value: dict[str, Any]) -> str:
    try:
        serialized = json.dumps(
            value,
            ensure_ascii=False,
            sort_keys=True,
            separators=(",", ":"),
            allow_nan=False,
        )
    except (TypeError, ValueError) as exc:
        raise ValueError("LAB provenance must be JSON-compatible") from exc
    if len(serialized.encode("utf-8")) > 256 * 1024:
        raise ValueError("LAB provenance exceeds 256 KiB")
    return serialized


def _require_utc_timestamp(value: str, field: str) -> None:
    from datetime import datetime

    try:
        parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
    except ValueError as exc:
        raise ValueError(f"{field} is invalid") from exc
    if parsed.tzinfo is None:
        raise ValueError(f"{field} must include a timezone")


def _layout_from_row(row: sqlite3.Row) -> WorkspaceLayout:
    payload = json.loads(row["layout_json"])
    if not isinstance(payload, dict):
        raise SessionIntegrityError("stored workspace layout is not a JSON object")
    return WorkspaceLayout(
        workspace_id=row["workspace_id"],
        schema_version=row["layout_schema_version"],
        revision=row["revision"],
        name=row["name"],
        layout=payload,
        updated_at_utc=row["updated_at_utc"],
    )


def _resolve_confined_artifact(
    allowed_root: Path,
    session_root: Path,
    locator: Path,
) -> Path:
    try:
        allowed = allowed_root.resolve(strict=True)
        session = session_root.resolve(strict=True)
        artifact = locator.resolve(strict=True)
    except OSError as exc:
        raise SessionIntegrityError("session replay artifact is missing") from exc
    if (
        not allowed.is_dir()
        or not session.is_dir()
        or not artifact.is_file()
        or not session.is_relative_to(allowed)
        or not artifact.is_relative_to(session)
    ):
        raise SessionIntegrityError("session replay artifact escapes its allowed root")
    return artifact


def _recorded_media_from_row(
    *,
    session_id: str,
    allowed_root: Path,
    session_root: Path,
    artifact_id: str,
    locator: Path,
    byte_length: int,
) -> RecordedMediaArtifact:
    _validate_identifier(artifact_id, "recorded media artifact id")
    try:
        allowed = allowed_root.resolve(strict=True)
        session = session_root.resolve(strict=True)
        media_root = (session / "media").resolve(strict=True)
        artifact = locator.resolve(strict=True)
    except OSError as exc:
        raise SessionIntegrityError("recorded media artifact is missing") from exc
    if (
        not allowed.is_dir()
        or not session.is_dir()
        or not media_root.is_dir()
        or not artifact.is_dir()
        or not session.is_relative_to(allowed)
        or not media_root.is_relative_to(session)
        or artifact.parent != media_root
    ):
        raise SessionIntegrityError("recorded media artifact escapes its session root")
    if not isinstance(byte_length, int) or isinstance(byte_length, bool) or byte_length < 1:
        raise SessionIntegrityError("recorded media artifact has an invalid byte length")
    public_suffix = artifact_id.removeprefix("recorded-video-")
    public_source_id = f"recorded.camera.{public_suffix}"
    _validate_identifier(public_source_id, "recorded media source id")
    return RecordedMediaArtifact(
        session_id=session_id,
        public_source_id=public_source_id,
        artifact_id=artifact_id,
        source_path=artifact,
        byte_length=byte_length,
    )


def _serialize_layout(layout: dict[str, Any]) -> str:
    try:
        serialized = json.dumps(layout, ensure_ascii=False, separators=(",", ":"))
    except (TypeError, ValueError) as exc:
        raise ValueError("layout must be a JSON object") from exc
    if len(serialized.encode("utf-8")) > MAX_LAYOUT_BYTES:
        raise ValueError("layout exceeds the 256 KiB storage boundary")
    return serialized


def _validate_identifier(value: str, label: str) -> None:
    if not IDENTIFIER_PATTERN.fullmatch(value):
        raise ValueError(f"{label} has an invalid shape")


@contextmanager
def _ignore_os_error() -> Iterator[None]:
    try:
        yield
    except OSError:
        return
