"""Fail-closed postcommit rollback for the r17 live startup failure."""

from __future__ import annotations

import argparse
import hashlib
import json
import sys
from pathlib import Path

PRESEAL = Path(
    "/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/"
    "live-transaction-preseal-v14-live-representative-r17"
)
SOURCE = PRESEAL / "controller-source"
EXECUTION = Path(
    "/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/"
    "live-executions-v14/"
    "nutricoach-v150-v14-live-representative-56-ab3a61dd"
)
LEDGER = Path(
    "/home/cube/.hermes/migrations/nutricoach-v1.5.0-combined/"
    "live-authorization-v14/"
    "nutricoach-v150-v14-live-representative-56-ab3a61dd"
)
TARGET = PRESEAL / "sealed-target.json"
RECEIPT = EXECUTION / "postcommit-rollback-receipt.json"

_target_binding = json.loads(TARGET.read_text(encoding="utf-8"))
_wheel_paths = [str(item["path"]) for item in _target_binding["wheels"]]
sys.path[:0] = [*_wheel_paths, str(SOURCE)]

from scripts.nutricoach_v150_concrete_host import ConcreteLiveHost  # noqa: E402
from scripts.nutricoach_v150_phase_journal import PhaseJournal  # noqa: E402
from scripts.nutricoach_v150_sealed_authority import (  # noqa: E402
    atomic_write,
    load_snapshot,
)
from scripts.nutricoach_v150_sealed_controller import (  # noqa: E402
    RollbackGuard,
    SealedControllerError,
)


def sha256(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest()


def require_preconditions(host: ConcreteLiveHost) -> dict[str, object]:
    phase = PhaseJournal(EXECUTION / "phase.json").phase()
    consumed = json.loads(
        (LEDGER / "authorization-consumed.json").read_text(encoding="utf-8")
    )
    state = host.service_state()
    if phase != "COMMITTED":
        raise RuntimeError(f"unexpected phase: {phase}")
    if consumed != {
        "candidate_digest": host.candidate_digest,
        "outcome": "SUCCEEDED",
        "status": "CONSUMED",
    }:
        raise RuntimeError("one-use ledger is not the committed r17 success")
    if not host.service.running:
        raise RuntimeError("r17 service is not running")
    if str(host.paths.successor_runtime) not in str(state.get("ExecStart", "")):
        raise RuntimeError("running service is not the r17 successor")
    if RECEIPT.exists():
        raise RuntimeError("postcommit rollback receipt already exists")
    return {"phase": phase, "ledger": consumed, "service": state}


def rollback() -> dict[str, object]:
    host = ConcreteLiveHost.live_target(TARGET)
    before = require_preconditions(host)
    host.load_recovery_manifest()
    journal = PhaseJournal(EXECUTION / "phase.json")
    guard = RollbackGuard(host, journal)
    guard.bind(load_snapshot(EXECUTION))
    failure = SealedControllerError(
        "manual_qa_failed: weekly candidate authority mismatch and croniter absent"
    )
    guard.rollback(failure)
    if host.rollback_failures:
        raise RuntimeError("rollback failures: " + ",".join(host.rollback_failures))
    state = host.service_state()
    if (
        journal.phase() != "ROLLED_BACK"
        or not host.service.running
        or str(host.paths.current_runtime) not in str(state.get("ExecStart", ""))
        or host.successor_root.exists()
        or host.weekly_authority.exists()
    ):
        raise RuntimeError("predecessor restoration postcondition failed")
    host.verify_preflight()
    receipt: dict[str, object] = {
        "before": before,
        "candidate_digest": host.candidate_digest,
        "committed_authority_ledger_sha256": sha256(
            LEDGER / "authorization-consumed.json"
        ),
        "critical_sha256": {
            "config": sha256(host.paths.config),
            "registry": sha256(host.paths.registry),
            "unit": sha256(host.paths.unit),
            "dropin": sha256(host.paths.dropin),
        },
        "failures": [
            "weekly reminder candidate authority disagrees",
            "croniter is not installed",
        ],
        "phase": journal.phase(),
        "predecessor_service": state,
        "schema": "nutricoach-v150-r17-postcommit-rollback-v1",
        "status": "POSTCOMMIT_STARTUP_FAILED_ROLLED_BACK",
        "successor_absent": not host.successor_root.exists(),
        "weekly_authority_absent": not host.weekly_authority.exists(),
    }
    atomic_write(
        RECEIPT,
        json.dumps(receipt, sort_keys=True, separators=(",", ":")).encode() + b"\n",
        0o400,
    )
    return receipt


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--execute", action="store_true")
    args = parser.parse_args()
    host = ConcreteLiveHost.live_target(TARGET)
    if not args.execute:
        print(json.dumps(require_preconditions(host), sort_keys=True))
        return 0
    print(json.dumps(rollback(), sort_keys=True))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
