# ============================================================
# src/accountable_record/commands/write_lock.py
# ============================================================
"""Write Accountable Record resolution locks.

WHY:
    write-lock is a mutating write-intent command, not a verification alias. It
    establishes current state through the read-only stages that produce
    generated artifacts, then writes data/locks/elements.lock.json so that s070
    can later verify it.

OBS (skips s070 by design):
    The command runs s010..s060 and s080, and intentionally skips s070. s070
    verifies an existing lock; on a write run the lock does not yet exist, so
    requiring s070 first would be circular. Stage execution, diagnostics
    printing, halt behavior, and state threading stay in the runner via
    run_stage_sequence_state; this command does not hand-run transforms.

OBS (fails loud, never writes a false lock):
    If generated state is absent, scaffolded, or empty, the command fails with a
    clear error rather than writing a structurally valid but meaningless lock.
"""

import json
from pathlib import Path
import sys
from typing import Any

from accountable_record.pipeline.context import PipelineRunContext
from accountable_record.pipeline.runner import run_stage_sequence_state
from accountable_record.stage_080_generated.model import GeneratedArtifact
from accountable_record.transitions.s070_resolution.s080_generated_to_lock import (
    build_element_lock_payload,
)

LOCK_ROOT = Path("data") / "locks"
ELEMENT_LOCK_PATH = LOCK_ROOT / "elements.lock.json"

# Read-only stages that establish the generated state a lock is built from.
# s070 is intentionally absent: it verifies an existing lock.
WRITE_LOCK_STAGES: tuple[str, ...] = (
    "s010",
    "s020",
    "s030",
    "s040",
    "s050",
    "s060",
    "s080",
)


def write_lock_command(context: PipelineRunContext) -> int:
    """Write resolution lock artifacts for the target repository."""
    status, state = run_stage_sequence_state(WRITE_LOCK_STAGES, context)
    if status != 0:
        return status

    generated = state.generated
    if not isinstance(generated, GeneratedArtifact):
        print(
            "write-lock requires generated artifact state from s080.",
            file=sys.stderr,
        )
        return 1

    records = generated.registry.records
    if not records:
        print(
            "write-lock requires at least one generated element record.",
            file=sys.stderr,
        )
        return 1

    lock_payload = build_element_lock_payload(
        records,
        repo_root=context.target_root,
    )

    _write_json(context.target_root / ELEMENT_LOCK_PATH, lock_payload)

    print(f"wrote {ELEMENT_LOCK_PATH.as_posix()}")
    return 0


def _write_json(path: Path, payload: dict[str, Any]) -> None:
    """Write stable JSON with a trailing newline."""
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(
        json.dumps(payload, indent=2, sort_keys=True) + "\n",
        encoding="utf-8",
    )
