"""Candidate-bound one-use NutriCoach v1.5 transaction behavior."""

from __future__ import annotations

from dataclasses import replace
from pathlib import Path

import pytest

from scripts.nutricoach_v150_live_transaction import (
    APPROVAL_PHRASE,
    CANDIDATE_DIGEST,
    MANIFEST_SHA256,
    PACKAGE_DIGEST,
    ApprovalAlreadyUsed,
    ExecutionBinding,
    LiveOperation,
    TransactionError,
    execute,
)
from tests.nutricoach_v150_transaction_support import FakeHost

ROOT = Path(__file__).resolve().parents[1]
CANDIDATE = (
    ROOT / ".omo/evidence/nutricoach-v150-combined/task-1-candidate/artifacts/build-1"
)


def binding(tmp_path: Path) -> ExecutionBinding:
    return ExecutionBinding(
        candidate_digest=CANDIDATE_DIGEST,
        manifest_sha256=MANIFEST_SHA256,
        package_digest=PACKAGE_DIGEST,
        current_runtime=Path(
            "/home/cube/.hermes/profiles/dualcoachtest/.strict-runtime/"
            + "6c9c4394-v132/venv"
        ),
        successor_runtime=tmp_path / "successor/venv",
        hermes_wheel=CANDIDATE / "hermes_agent-0.17.0-py3-none-any.whl",
        hermes_wheel_sha256=(
            "5829f799160a7341f5509043c17cecbe5d10cfe25c44eb3f8fde44bbf9720d91"
        ),
        profile_wheel=CANDIDATE / "physique_checkin_cli-0.1.0-py3-none-any.whl",
        profile_wheel_sha256=(
            "bdfe94b31d9c98c233301dc2cc552e5e2d672853901bac2bdf73df7e23c709b6"
        ),
        capacity=5,
        weekly_pilot_authorized=True,
        channel_inbox_authorized=False,
    )


def live_fixture(tmp_path: Path) -> tuple[tuple[Path, ...], tuple[bytes, ...]]:
    paths = (
        tmp_path / "profile/customers/registry.json",
        tmp_path / "profile/config.yaml",
        tmp_path / "gateway.service",
    )
    payloads = (
        b'{"registry_mode":"ordinary_v1"}\n',
        b"channel_inbox: false\n",
        b"current\n",
    )
    for path, payload in zip(paths, payloads, strict=True):
        path.parent.mkdir(parents=True, exist_ok=True)
        _ = path.write_bytes(payload)
    return paths, payloads


def test_success_uses_exact_v7_sequence_and_consumes_once(tmp_path: Path) -> None:
    paths, _ = live_fixture(tmp_path)
    host = FakeHost(tmp_path)

    operation = LiveOperation(
        binding(tmp_path), APPROVAL_PHRASE, tmp_path / "run", paths
    )
    receipt = execute(operation, host)

    assert receipt.startswith("sha256:")
    assert host.stages == [
        "stop",
        "stopped_probe",
        "install",
        "off_smoke",
        "migration_dry_run",
        "migration_apply",
        "switch_systemd",
        "reload",
        "start",
        "post_fence",
    ]
    assert host.active()
    assert (tmp_path / "run/authorization-consumed.json").is_file()
    with pytest.raises(ApprovalAlreadyUsed):
        _ = execute(operation, host)


@pytest.mark.parametrize(
    "fault",
    [
        "stop",
        "stopped_probe",
        "install",
        "off_smoke",
        "migration_dry_run",
        "migration_apply",
        "switch_systemd",
        "reload",
        "start",
        "post_fence",
        "base_exception",
    ],
)
def test_every_fault_restores_snapshot_and_consumes(tmp_path: Path, fault: str) -> None:
    paths, before = live_fixture(tmp_path)
    host = FakeHost(tmp_path, fault)
    operation = LiveOperation(
        binding(tmp_path), APPROVAL_PHRASE, tmp_path / "run", paths
    )

    with pytest.raises((KeyboardInterrupt, TransactionError)):
        _ = execute(operation, host)

    assert host.active()
    assert tuple(path.read_bytes() for path in paths) == before
    assert (tmp_path / "run/authorization-consumed.json").is_file()
    assert not binding(tmp_path).successor_runtime.exists()
    assert not (tmp_path / "profile/data/weekly-pilot-authority").exists()


def test_wrong_binding_and_approval_never_reserve(tmp_path: Path) -> None:
    paths, _ = live_fixture(tmp_path)
    original = binding(tmp_path)
    wrong = replace(original, channel_inbox_authorized=True)

    with pytest.raises(TransactionError):
        _ = execute(
            LiveOperation(wrong, APPROVAL_PHRASE, tmp_path / "run", paths),
            FakeHost(tmp_path),
        )
    with pytest.raises(TransactionError):
        _ = execute(
            LiveOperation(original, "WRONG", tmp_path / "run", paths),
            FakeHost(tmp_path),
        )

    assert not (tmp_path / "run/authorization-reserved.json").exists()
    assert not (tmp_path / "run/authorization-consumed.json").exists()
