"""Candidate-bound NutriCoach v1.5 one-use live transaction controller."""

from __future__ import annotations

from types import TracebackType
from typing import Literal, Self, final

from scripts.nutricoach_v150_live_authority import (
    ApprovalLedger,
    SnapshotAuthority,
    capture,
    file_digest,
    restore,
)
from scripts.nutricoach_v150_live_models import (
    APPROVAL_PHRASE,
    CANDIDATE_DIGEST,
    CURRENT_RUNTIME,
    HERMES_WHEEL,
    HERMES_WHEEL_SHA256,
    MANIFEST_SHA256,
    PACKAGE_DIGEST,
    PROFILE_WHEEL,
    PROFILE_WHEEL_SHA256,
    ApprovalAlreadyUsed,
    ExecutionBinding,
    LiveHost,
    LiveOperation,
    TransactionError,
)

__all__ = [
    "APPROVAL_PHRASE",
    "CANDIDATE_DIGEST",
    "MANIFEST_SHA256",
    "PACKAGE_DIGEST",
    "ApprovalAlreadyUsed",
    "ExecutionBinding",
    "LiveOperation",
    "TransactionError",
    "execute",
]


def _verify_binding(binding: ExecutionBinding, approval: str) -> None:
    expected = (
        binding.candidate_digest == CANDIDATE_DIGEST
        and binding.manifest_sha256 == MANIFEST_SHA256
        and binding.package_digest == PACKAGE_DIGEST
        and binding.current_runtime == CURRENT_RUNTIME
        and binding.hermes_wheel == HERMES_WHEEL
        and binding.profile_wheel == PROFILE_WHEEL
        and binding.hermes_wheel_sha256 == HERMES_WHEEL_SHA256
        and binding.profile_wheel_sha256 == PROFILE_WHEEL_SHA256
        and binding.capacity == 5
        and binding.weekly_pilot_authorized
        and not binding.channel_inbox_authorized
        and approval == APPROVAL_PHRASE
    )
    if not expected:
        raise TransactionError("sealed_binding")
    if (
        file_digest(binding.hermes_wheel) != HERMES_WHEEL_SHA256
        or file_digest(binding.profile_wheel) != PROFILE_WHEEL_SHA256
    ):
        raise TransactionError("wheel_drift")


@final
class TransactionGuard:
    """Restore post-stop bytes and initial service state on every failure."""

    def __init__(self, operation: LiveOperation, host: LiveHost) -> None:
        self._operation = operation
        self._host = host
        self._authority: SnapshotAuthority | None = None
        self._committed = False

    def __enter__(self) -> Self:
        """Open the stop-through-readiness rollback boundary."""
        return self

    def bind(self, authority: SnapshotAuthority) -> None:
        """Bind durable rollback authority before installation."""
        self._authority = authority

    def commit(self) -> None:
        """Mark complete verified success."""
        self._committed = True

    def _rollback(self, original: BaseException) -> None:
        failures: list[str] = []
        try:
            if self._host.active():
                self._host.stop()
        except (KeyboardInterrupt, OSError, SystemExit, TransactionError):
            failures.append("stop")
        authority = self._authority
        if authority is not None:
            for stage, action in (
                ("snapshot_restore", lambda: restore(authority)),
                (
                    "created_remove",
                    lambda: self._host.remove_created(self._operation.binding),
                ),
                ("systemd_reload", self._host.reload),
            ):
                try:
                    action()
                except (KeyboardInterrupt, OSError, SystemExit, TransactionError):
                    failures.append(stage)
        try:
            if not self._host.active():
                self._host.start()
        except (KeyboardInterrupt, OSError, SystemExit, TransactionError):
            failures.append("service_restore")
        if not self._host.active():
            failures.append("service_postcheck")
        if failures:
            raise TransactionError(f"rollback:{','.join(failures)}") from original

    def __exit__(
        self,
        error_type: type[BaseException] | None,
        error: BaseException | None,
        traceback: TracebackType | None,
    ) -> Literal[False]:
        """Rollback every BaseException or uncommitted return."""
        del error_type, traceback
        if error is not None:
            self._rollback(error)
        elif not self._committed:
            missing = TransactionError("uncommitted")
            self._rollback(missing)
            raise missing
        return False


def execute(operation: LiveOperation, host: LiveHost) -> str:
    """Execute the sealed stop-through-readiness transaction exactly once."""
    _verify_binding(operation.binding, operation.approval)
    ledger = ApprovalLedger(operation.execution_root)
    ledger.reserve()
    try:
        with TransactionGuard(operation, host) as guard:
            host.stop()
            if host.active():
                raise TransactionError("stop_incomplete")
            authority = capture(operation.mutable_paths, operation.execution_root)
            guard.bind(authority)
            host.stopped_probe(operation.binding)
            host.install(operation.binding)
            host.off_smoke(operation.binding)
            host.migration_dry_run(operation.binding)
            host.migration_apply(operation.binding)
            host.switch_systemd(operation.binding)
            host.reload()
            host.start()
            if not host.active():
                raise TransactionError("start_incomplete")
            host.post_fence(operation.binding)
            ledger.consume("SUCCEEDED")
            guard.commit()
        return authority.manifest_digest
    except (KeyboardInterrupt, OSError, SystemExit, TransactionError) as error:
        try:
            ledger.consume("FAILED")
        except OSError:
            raise TransactionError("authorization_consumption_failed") from error
        raise
