#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = ["anyio"]
# ///

# ─── How to run ───
# 1. Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh
# 2. Use through: uv run python scripts/run_nutricoach_v140_golden_path.py --help
# ──────────────────

"""One fresh-process production action for the Todo10 orchestrator."""

from __future__ import annotations

import hashlib
import os
import time
from datetime import datetime
from pathlib import Path
from typing import Protocol
from zoneinfo import ZoneInfo

import anyio

from checkin_cli.customer_coaching import load_customer_registry
from checkin_cli.models import ContractCheckin, ContractStatus, Event, EventType, Provenance
from checkin_cli.store import CanonicalEventTransaction

from scripts.nutricoach_v140_golden_path_adapter import GoldenPathTelegramAdapter
from scripts.nutricoach_v140_golden_path_faults import BoundaryObserver
from scripts.nutricoach_v140_golden_path_models import CliError, ProcessEvidence, StepKind, StepRequest
from scripts.nutricoach_v140_golden_path_transport import DurableFakeTelegram

KST = ZoneInfo("Asia/Seoul")


class RaceBarrier(Protocol):
    def wait(self, timeout: float | None = None) -> int: ...


class RaceLock(Protocol):
    def acquire(self, block: bool = True, timeout: float | None = None) -> bool: ...
    def release(self) -> None: ...


def _append_submission(root: Path, request: StepRequest) -> None:
    now = datetime.fromisoformat(request.now)
    ordinal = request.submission_ordinal
    if ordinal is None:
        raise CliError("submission ordinal is required")
    registry = load_customer_registry(root / "registry.json", root)
    runtime = registry.customers[0]
    event_id = f"golden-{now.date().isoformat()}-{ordinal}"
    event = Event(
        event_id=event_id, event_type=EventType.NUTRITION_CHECKIN,
        occurred_at_kst=now.isoformat(), recorded_at_kst=now.isoformat(),
        schema_version="2.0", status=ContractStatus.ACCEPTED,
        provenance=Provenance(
            source_type="telegram", source_ref=f"golden:{ordinal}",
            content_sha256=hashlib.sha256(event_id.encode()).hexdigest(),
        ),
        dedupe_key=f"golden:{now.date().isoformat()}",
        check_in=ContractCheckin(calories_kcal=2200),
    )
    transaction = CanonicalEventTransaction.for_customer_runtime(runtime)
    _ = transaction.recover()
    _ = transaction.append_many((event,))


async def _run_tick(root: Path, request: StepRequest) -> None:
    now = datetime.fromisoformat(request.now)
    provider = DurableFakeTelegram(root / "provider-transcript.jsonl", now, request.provider_mode)
    adapter = GoldenPathTelegramAdapter.open(root, now, provider)
    try:
        _ = await adapter.run_authorized_tick(now)
    finally:
        adapter.close_golden_path()


def execute_race_tick(
    root: Path, request: StepRequest, evidence_path: Path, barrier: RaceBarrier,
    lock: RaceLock,
) -> int:
    """Release two processes together, then open and execute real production ticks."""
    started = time.time_ns()
    now = datetime.fromisoformat(request.now)
    _ = barrier.wait(timeout=30)
    _ = lock.acquire()
    try:
        provider = DurableFakeTelegram(root / "provider-transcript.jsonl", now, request.provider_mode)
        adapter = GoldenPathTelegramAdapter.open(root, now, provider)
        try:
            with BoundaryObserver(root, request.step_id, request.failpoint):
                _ = anyio.run(adapter.run_authorized_tick, now)
        finally:
            adapter.close_golden_path()
    finally:
        lock.release()
    _ = evidence_path.write_text(
        ProcessEvidence(
            step_id=f"{request.step_id}-race", pid=os.getpid(), start_epoch_ns=started,
            reopened_authoritative_stores=True, exit_code=0,
        ).model_dump_json() + "\n",
        encoding="utf-8",
    )
    return 0


def execute_step(root: Path, request: StepRequest, evidence_path: Path) -> int:
    """Execute one action and atomically record the observed child identity."""
    started = time.time_ns()
    reopened = (root / "platform-config.json").exists()
    exit_code = 0
    with BoundaryObserver(root, request.step_id, request.failpoint):
        if request.kind is StepKind.SUBMIT:
            _append_submission(root, request)
        else:
            anyio.run(_run_tick, root, request)
    evidence = ProcessEvidence(
        step_id=request.step_id, pid=os.getpid(), start_epoch_ns=started,
        reopened_authoritative_stores=reopened, exit_code=exit_code,
    )
    evidence_path.parent.mkdir(parents=True, exist_ok=True)
    _ = evidence_path.write_text(evidence.model_dump_json() + "\n", encoding="utf-8")
    return exit_code
