"""Oracle Triple V3 hardening regressions."""

from __future__ import annotations

import hashlib
import json
import os
from pathlib import Path
import signal
import subprocess
import sys
from typing import final, override

from pydantic import JsonValue, TypeAdapter
import pytest

from scripts.execute_nutricoach_v150_sealed_live import sandbox_command
from scripts.nutricoach_v150_concrete_host import ConcreteLiveHost
from scripts.nutricoach_v150_detached_bootstrap import (
    BootstrapDenied,
    verify_closure,
    verify_network_isolation,
)
from scripts.nutricoach_v150_sealed_authority import (
    AuthorityError,
    WriteIo,
    capture,
    restore,
    write_all,
)
from scripts.nutricoach_v150_phase_journal import PhaseJournal
from scripts.nutricoach_v150_runtime_ops import weekly_config_contract
from scripts.nutricoach_v150_sealed_controller import (
    APPROVAL_PHRASE,
    DisposableService,
    execute_disposable,
)
from tests.test_nutricoach_v150_sealed_controller import target_fixture

_OBJECT = TypeAdapter(dict[str, JsonValue])


@final
class HostileWriteIo(WriteIo):
    def __init__(self, outcomes: list[int | BaseException]) -> None:
        self.outcomes = outcomes
        self.payload = bytearray()

    @override
    def write(self, descriptor: int, payload: bytes) -> int:
        del descriptor
        outcome = self.outcomes.pop(0)
        if isinstance(outcome, BaseException):
            raise outcome
        if outcome:
            self.payload.extend(payload[:outcome])
        return outcome


def test_detached_bootstrap_rejects_transitive_source_tamper(tmp_path: Path) -> None:
    root = tmp_path / "controller"
    root.mkdir()
    entry = root / "entry.py"
    transitive = root / "transitive.py"
    _ = entry.write_text("import transitive\n")
    _ = transitive.write_text("VALUE = 1\n")
    manifest = tmp_path / "closure.json"
    files = {
        path.name: hashlib.sha256(path.read_bytes()).hexdigest()
        for path in (entry, transitive)
    }
    _ = manifest.write_text(json.dumps({"files": files}))
    assert verify_closure(manifest, root).startswith("sha256:")
    _ = transitive.write_text("VALUE = 2\n")

    with pytest.raises(BootstrapDenied, match="closure"):
        _ = verify_closure(manifest, root)


@pytest.mark.parametrize(
    "outcomes",
    [
        [1, 2, 3],
        [InterruptedError(), 6],
    ],
)
def test_global_ledger_write_all_handles_short_and_eintr(
    outcomes: list[int | BaseException],
) -> None:
    io = HostileWriteIo(outcomes)

    write_all(7, b"sealed", io)

    assert io.payload == b"sealed"


def test_global_ledger_zero_write_is_denied() -> None:
    io = HostileWriteIo([0])

    with pytest.raises(RuntimeError, match="zero_write"):
        write_all(7, b"sealed", io)


def test_bwrap_is_unconditional_clearenv_readonly_and_narrow() -> None:
    command = sandbox_command("approval")

    assert command[:2] == ("/usr/bin/bwrap", "--unshare-net")
    assert "--clearenv" in command
    assert "--ro-bind" in command
    assert command[command.index("--tmpfs") + 1] == "/tmp"
    assert command[command.index("--dev") + 1] == "/dev"
    assert "--dev-bind" not in command
    assert "NUTRICOACH_V150_NETWORK_ISOLATED" not in " ".join(command)
    assert "--bind" in command
    assert command[-2:] == ("--approval", "approval")


def test_bootstrap_network_gate_uses_current_namespace_proc_view(
    tmp_path: Path,
) -> None:
    isolated = tmp_path / "isolated"
    isolated.mkdir()
    _ = (isolated / "dev").write_text(
        "Inter-| Receive | Transmit\n"
        + " face |bytes packets errs drop fifo frame compressed multicast|"
        + "bytes packets errs drop fifo colls carrier compressed\n"
        + "    lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
    )
    _ = (isolated / "route").write_text(
        "Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT\n"
    )

    verify_network_isolation(isolated)

    exposed = tmp_path / "exposed"
    exposed.mkdir()
    _ = (exposed / "dev").write_text(
        "Inter-| Receive | Transmit\n"
        + " face |bytes packets errs drop fifo frame compressed multicast|"
        + "bytes packets errs drop fifo colls carrier compressed\n"
        + "  eth0: 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0\n"
    )
    _ = (exposed / "route").write_text(
        "Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT\n"
        + "eth0 00000000 010011AC 0003 0 0 0 00000000 0 0 0\n"
    )

    with pytest.raises(BootstrapDenied, match="network_namespace"):
        verify_network_isolation(exposed)


def test_phase_journal_requires_rollback_after_kill_boundary(tmp_path: Path) -> None:
    journal = PhaseJournal(tmp_path / "phase.json")

    journal.advance("INSTALLED")

    assert journal.recovery_required()
    assert json.loads(journal.path.read_text())["phase"] == "INSTALLED"


def test_restore_continues_but_reports_mixed_bytes(tmp_path: Path) -> None:
    first = tmp_path / "first"
    second = tmp_path / "second"
    _ = first.write_text("before-first")
    _ = second.write_text("before-second")
    snapshot = capture((first, second), tmp_path / "execution")
    snapshot.entries[0].saved.unlink()
    _ = first.write_text("after-first")
    _ = second.write_text("after-second")

    with pytest.raises(AuthorityError, match="restore"):
        restore(snapshot)

    assert second.read_text() == "before-second"


def test_created_path_lstat_rejects_symlink(tmp_path: Path) -> None:
    profile = tmp_path / "profile"
    target = tmp_path / "elsewhere"
    target.mkdir()
    successor = profile / ".strict-runtime/successor"
    successor.parent.mkdir(parents=True)
    successor.symlink_to(target, target_is_directory=True)
    host = ConcreteLiveHost.disposable(tmp_path, DisposableService())

    with pytest.raises(RuntimeError, match="created_path"):
        host.verify_created_absent()


def test_post_stop_clean_boundary_is_rechecked(tmp_path: Path) -> None:
    _ = target_fixture(tmp_path)
    host = ConcreteLiveHost.disposable(tmp_path, DisposableService())

    _ = execute_disposable(APPROVAL_PHRASE, tmp_path, host)

    assert host.clean_boundary_checks == 2


def test_nested_weekly_authority_and_inbox_omission(tmp_path: Path) -> None:
    _ = target_fixture(tmp_path)
    host = ConcreteLiveHost.disposable(tmp_path, DisposableService())
    _ = host.paths.config.write_text(
        "platforms:\n"
        + "  telegram:\n"
        + "    extra:\n"
        + "      nutrition_coaching:\n"
        + "        operator_review:\n"
        + "          user_id: '100'\n"
        + "          chat_id: '200'\n"
        + "          topic_id: 59\n"
    )

    _ = execute_disposable(APPROVAL_PHRASE, tmp_path, host)
    contract = weekly_config_contract(host.paths.config.read_text())

    assert contract["enabled"] is True
    assert contract["candidate_digest"]
    assert contract["channel_inbox_present"] is False


def test_real_offline_install_exposes_records_scripts_and_imports(
    tmp_path: Path,
) -> None:
    runtime = tmp_path / "fresh/venv"

    identity = ConcreteLiveHost.install_fresh_runtime(runtime)

    assert identity["hermes_record"]
    assert identity["profile_record"]
    assert identity["hermes_script"]
    assert identity["profile_import"]


def test_exact_systemd_and_credential_postimages_use_real_observation(
    tmp_path: Path,
) -> None:
    _ = target_fixture(tmp_path)
    credentials = tmp_path / "credentials"
    credentials.mkdir()
    for name in ("candidate-digest", "authority-pin.json"):
        _ = (credentials / name).write_text("current\n")
    host = ConcreteLiveHost.disposable(tmp_path, DisposableService())
    _ = host.paths.dropin.write_text(
        f'Environment="DUALCOACH_PROFILE_PACKAGE={host.paths.current_runtime}"\n'
        + f"LoadCredential=candidate-digest:{credentials / 'candidate-digest'}\n"
        + f"LoadCredential=authority-pin.json:{credentials / 'authority-pin.json'}\n"
    )
    before = host.service_state()

    _ = execute_disposable(APPROVAL_PHRASE, tmp_path, host)
    after = host.service_state()

    assert after["ActiveState"] == "active"
    assert after["SubState"] == "running"
    assert int(after["MainPID"]) > 0
    assert str(host.paths.successor_runtime) in after["ExecStart"]
    assert int(after["ExecMainStartTimestampMonotonic"]) > int(
        before["ExecMainStartTimestampMonotonic"]
    )
    assert host.verify_exact_postimages()


@pytest.mark.parametrize("stop_signal", [signal.SIGTERM, signal.SIGKILL])
def test_subprocess_signal_recovery_reaches_rolled_back(
    tmp_path: Path,
    stop_signal: signal.Signals,
) -> None:
    script = Path(__file__).parents[1] / "scripts/nutricoach_v150_recovery_rehearsal.py"
    read_descriptor, write_descriptor = os.pipe()
    process: subprocess.Popen[bytes] = subprocess.Popen(
        (
            sys.executable,
            str(script),
            "--root",
            str(tmp_path),
            "--mode",
            "run",
        ),
        stdout=write_descriptor,
    )
    os.close(write_descriptor)
    try:
        assert os.read(read_descriptor, 6) == b"READY\n"
    finally:
        os.close(read_descriptor)
    process.send_signal(stop_signal)
    _ = process.wait(timeout=5)
    recovery = subprocess.run(
        (
            sys.executable,
            str(script),
            "--root",
            str(tmp_path),
            "--mode",
            "recover",
        ),
        check=False,
    )

    assert recovery.returncode == 0
    phase = _OBJECT.validate_json((tmp_path / "phase.json").read_bytes())
    assert phase["phase"] == "ROLLED_BACK"
