from __future__ import annotations

import importlib.util
import json
import subprocess
import sys
from pathlib import Path


SCRIPT_ROOT = Path(__file__).resolve().parents[1]
EXPORTER_PATH = SCRIPT_ROOT / "host-runaway-process-exporter.py"
REMEDIATION_PATH = SCRIPT_ROOT / "host-runaway-process-remediation.py"
CONTROLLER_PATH = SCRIPT_ROOT / "host-sustained-load-controller.py"
EVIDENCE_PATH = SCRIPT_ROOT / "host-sustained-load-evidence.py"


def load_exporter():
    spec = importlib.util.spec_from_file_location("host_runaway_process_exporter", EXPORTER_PATH)
    assert spec and spec.loader
    module = importlib.util.module_from_spec(spec)
    sys.modules[spec.name] = module
    spec.loader.exec_module(module)
    return module


def test_classifies_orphan_stockplatform_headless_group() -> None:
    exporter = load_exporter()
    rows = exporter.parse_ps_rows(
        """
        100 1 100 100 7200 65.0 S chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-aa
        101 100 100 100 7190 55.0 S chromium /opt/chrome/chromium --type=renderer /tmp/stockplatform-review-bulk-ux-aa
        200 10 200 200 600 90.0 S node pnpm --filter @awoooi/web build
        """
    )

    groups = exporter.classify_groups(rows, min_age_seconds=1800, min_cpu_percent=50)

    assert len(groups) == 1
    assert groups[0].rule_id == "stockplatform_headless_smoke"
    assert groups[0].pgid == 100
    assert groups[0].orphan_reason == "ppid_1"
    assert groups[0].cpu_percent == 120.0
    assert len(groups[0].rows) == 2


def test_ignores_non_orphan_or_young_browser_processes() -> None:
    exporter = load_exporter()
    rows = exporter.parse_ps_rows(
        """
        100 99 100 100 7200 65.0 S chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-aa
        101 100 100 100 7190 55.0 S chromium /opt/chrome/chromium /tmp/stockplatform-review-bulk-ux-aa
        300 1 300 300 60 120.0 S chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-bb
        """
    )

    assert exporter.classify_groups(rows, min_age_seconds=1800, min_cpu_percent=50) == []


def test_parses_bsd_elapsed_time_for_local_smoke() -> None:
    exporter = load_exporter()
    rows = exporter.parse_ps_rows(
        """
        100 1 100 100 01:00:00 65.0 S chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-aa
        101 100 100 100 2-00:00:10 55.0 S chromium /opt/chrome/chromium /tmp/stockplatform-review-bulk-ux-aa
        """
    )

    assert rows[0].etimes == 3600
    assert rows[1].etimes == 172810


def test_renders_ci_load_and_swap_without_authorizing_repair(tmp_path: Path) -> None:
    exporter = load_exporter()
    groups = exporter.classify_groups(
        exporter.parse_ps_rows(
            "100 1 100 100 7200 65.0 S chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-aa"
        ),
        min_age_seconds=1800,
        min_cpu_percent=50,
    )
    metrics = exporter.render_metrics(
        host="110",
        groups=groups,
        active_action_containers=3,
        active_action_process_load=exporter.ActiveCiLoad(
            group_count=2,
            process_count=4,
            cpu_percent=188.5,
            oldest_age_seconds=240,
        ),
        process_family_summary=exporter.process_family_load(
            exporter.parse_ps_rows(
                "200 1 200 200 7200 55.0 S gitea /usr/local/bin/gitea web --config /home/wooo/gitea/app.ini"
            )
        ),
        min_age_seconds=1800,
        min_cpu_percent=50,
        now=123,
        load_ratio=1.25,
        swap_ratio=1.0,
    )

    assert 'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1' in metrics
    assert 'awoooi_host_gitea_actions_active_container_count{host="110"} 3' in metrics
    assert 'awoooi_host_gitea_actions_active_process_group_count{host="110"} 2' in metrics
    assert 'awoooi_host_gitea_actions_active_process_count{host="110"} 4' in metrics
    assert 'awoooi_host_gitea_actions_active_process_cpu_percent{host="110"} 188.500000' in metrics
    assert 'awoooi_host_gitea_actions_active_process_oldest_age_seconds{host="110"} 240' in metrics
    assert 'awoooi_host_swap_used_ratio{host="110"} 1.000000' in metrics
    assert 'awoooi_host_runaway_process_remediation_authorized{host="110"} 0' in metrics
    assert 'awoooi_host_process_family_cpu_percent{host="110",family="gitea_service"} 55.000000' in metrics
    assert 'awoooi_host_process_family_top_info{host="110",family="gitea_service",comm="gitea"} 1' in metrics
    assert "/home/wooo/gitea/app.ini" not in metrics
    assert 'rule="stockplatform_headless_smoke"' in metrics


def test_counts_modern_gitea_action_container_names(tmp_path: Path) -> None:
    exporter = load_exporter()
    docker_file = tmp_path / "docker.txt"
    docker_file.write_text(
        "\n".join(
            [
                "GITEA-ACTIONS-TASK-123",
                "awoooi-cd-5901-1-e2e-smoke",
                "awoooi-cd-5873-1-source-link-smoke",
                "awoooi-code-review-3323-1-ai-code-review",
                "gitea",
                "stockplatform-v2-api-1",
            ]
        ),
        encoding="utf-8",
    )

    assert exporter.active_gitea_action_containers(docker_file) == 4


def test_counts_buildkit_runner_process_load() -> None:
    exporter = load_exporter()
    rows = exporter.parse_ps_rows(
        """
        100 10 100 100 240 0.0 S bash bash --noprofile --norc -e -o pipefail /home/wooo/.cache/act/14cc/act/workflow/8.sh
        101 100 100 100 239 1.0 S docker docker build -f apps/web/Dockerfile .
        102 101 100 100 239 2.0 S docker-buildx /home/wooo/.docker/cli-plugins/docker-buildx buildx build -f apps/web/Dockerfile .
        200 150 200 200 210 12.5 S turbo turbo build --filter=@awoooi/web --concurrency=1
        201 200 200 200 200 145.0 S node node /app/apps/web/node_modules/.bin/../next/dist/bin/next build
        250 150 250 250 30 269.0 R node node /opt/hostedtoolcache/node/20.20.2/x64/bin/pnpm install --frozen-lockfile
        300 1 300 300 9999 0.1 S act_runner act_runner daemon --config /config.yaml
        400 1 400 400 120 30.0 S node node apps/web/server.js
        """
    )

    load = exporter.active_gitea_action_process_load(rows)

    assert load.group_count == 3
    assert load.process_count == 6
    assert load.cpu_percent == 429.5
    assert load.oldest_age_seconds == 240


def test_sustained_load_evidence_classifies_hostedtoolcache_pnpm_as_ci(tmp_path: Path) -> None:
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "250 150 250 30 269.0 0.7 node node /opt/hostedtoolcache/node/20.20.2/x64/bin/pnpm install --frozen-lockfile\n",
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(EVIDENCE_PATH),
            "--host",
            "110",
            "--ps-file",
            str(ps_file),
            "--json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    payload = json.loads(result.stdout)
    assert payload["top_process_families"][0]["family"] == "gitea_actions_runner"
    assert payload["top_processes_sanitized"][0]["family"] == "gitea_actions_runner"
    assert "/opt/hostedtoolcache" not in result.stdout
    assert "pnpm install" not in result.stdout


def test_ignores_the_host_pressure_gate_process_group() -> None:
    exporter = load_exporter()
    rows = exporter.parse_ps_rows(
        """
        100 10 100 100 240 0.0 S bash bash --noprofile --norc -e -o pipefail /home/wooo/.cache/act/14cc/act/workflow/2.sh
        101 100 100 100 239 0.0 S bash bash scripts/ci/wait-host-web-build-pressure.sh
        102 101 100 100 238 0.0 S sleep sleep 10
        200 150 200 200 210 12.5 S turbo turbo build --filter=@awoooi/web --concurrency=1
        """
    )

    load = exporter.active_gitea_action_process_load(rows)

    assert load.group_count == 1
    assert load.process_count == 1
    assert load.cpu_percent == 12.5
    assert load.oldest_age_seconds == 210


def test_remediation_defaults_to_dry_run(tmp_path: Path) -> None:
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "999999 1 999999 999999 7200 65.0 S chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-aa\n",
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(REMEDIATION_PATH),
            "--ps-file",
            str(ps_file),
            "--rule",
            "stockplatform_headless_smoke",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    assert '"mode": "dry_run"' in result.stdout
    assert '"runtime_gate": 0' in result.stdout
    assert '"action": "dry_run"' in result.stdout


def test_remediation_refuses_apply_without_gates(tmp_path: Path) -> None:
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "999999 1 999999 999999 7200 65.0 S chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-aa\n",
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(REMEDIATION_PATH),
            "--ps-file",
            str(ps_file),
            "--apply",
            "--rule",
            "stockplatform_headless_smoke",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode != 0
    assert "Refusing apply" in result.stderr
    assert "--controlled-apply-id" in result.stderr
    assert "--confirm-apply" in result.stderr
    assert "--post-apply-verifier" in result.stderr


def test_remediation_accepts_controlled_apply_gate_without_owner_gate(tmp_path: Path) -> None:
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "100 1 1 100 7200 65.0 S chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-aa\n",
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(REMEDIATION_PATH),
            "--ps-file",
            str(ps_file),
            "--apply",
            "--confirm-apply",
            "--rule",
            "stockplatform_headless_smoke",
            "--controlled-apply-id",
            "CAP-20260701-HOSTLOAD",
            "--evidence-ref",
            "HostLoadAverageSustainedHigh:110",
            "--post-apply-verifier",
            "scripts/ops/host-sustained-load-controller.py --host 110 --json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    assert '"mode": "apply_sigterm"' in result.stdout
    assert '"runtime_gate": 1' in result.stdout
    assert '"controlled_apply_id": "CAP-20260701-HOSTLOAD"' in result.stdout
    assert '"owner_approval_id": ""' in result.stdout
    assert '"blocked_reason": "unsafe_pgid"' in result.stdout
    assert '"missing_process_group_count": 0' in result.stdout
    assert '"signal_error_count": 0' in result.stdout
    assert '"signaled_process_group_count": 0' in result.stdout


def test_sustained_load_controller_routes_orphan_browser_to_controlled_remediation(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 2.2',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
                'awoooi_host_gitea_actions_active_container_count{host="110"} 0',
                'awoooi_host_gitea_actions_active_process_group_count{host="110"} 0',
                'awoooi_host_runaway_browser_orphan_group_count{host="110",rule="stockplatform_headless_smoke",min_age_seconds="1800",min_cpu_percent="50"} 1',
                'awoooi_host_runaway_browser_orphan_cpu_percent{host="110",rule="stockplatform_headless_smoke",min_age_seconds="1800",min_cpu_percent="50"} 155.5',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    payload = json.loads(result.stdout)
    assert payload["classification"] == "controlled_orphan_browser_remediation_ready"
    assert payload["controlled_apply_allowed"] is True
    assert (
        "/home/wooo/scripts/host-runaway-process-remediation.py "
        "--rule stockplatform_headless_smoke"
    ) in payload["commands"]["dry_run"]
    assert "--controlled-apply-id" in payload["commands"]["controlled_apply"]
    assert "scripts/ops/" not in payload["commands"]["dry_run"]
    assert "scripts/ops/" not in payload["commands"]["post_apply_verifier"]
    assert payload["operation_boundaries"]["process_signal_performed"] is False


def test_sustained_load_controller_keeps_ci_saturation_on_runner_path(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 2.0',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
                'awoooi_host_gitea_actions_active_container_count{host="110"} 2',
                'awoooi_host_gitea_actions_active_process_group_count{host="110"} 1',
                'awoooi_host_gitea_actions_active_process_cpu_percent{host="110"} 180.0',
                'awoooi_host_gitea_actions_active_process_oldest_age_seconds{host="110"} 1900',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    payload = json.loads(result.stdout)
    assert payload["classification"] == "controlled_ci_runner_saturation_guarded"
    assert payload["controlled_apply_allowed"] is True
    assert "fail_closed" in payload["commands"]["controlled_apply"]
    assert "process_kill" not in payload["commands"]["controlled_apply"]


def test_sustained_load_controller_blocks_monitor_authority_violation(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 2.0',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 1',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert payload["classification"] == "blocked_monitor_authority_violation"
    assert payload["controlled_apply_allowed"] is False


def test_sustained_load_controller_routes_gitea_backlog_from_docker_metrics(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 2.5',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
                'awoooi_host_gitea_actions_active_container_count{host="110"} 0',
                'awoooi_host_gitea_actions_active_process_group_count{host="110"} 0',
                'awoooi_host_runaway_browser_orphan_group_count{host="110",rule="stockplatform_headless_smoke",min_age_seconds="1800",min_cpu_percent="50"} 0',
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        "\n".join(
            [
                'docker_container_cpu_cores{host="110",container_name="gitea"} 3.4',
                'docker_container_cpu_cores{host="110",container_name="redis"} 0.2',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--docker-stats-file",
            str(docker_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert payload["classification"] == "blocked_gitea_queue_or_hook_backlog_requires_playbook"
    assert payload["readback"]["top_container_cpu"]["container_name"] == "gitea"
    assert payload["controlled_apply_allowed"] is False
    assert "/home/wooo/scripts/gitea-queue-hook-backlog-playbook.py" in payload["commands"]["dry_run"]
    assert "scripts/ops/" not in payload["commands"]["dry_run"]


def test_sustained_load_controller_routes_gitea_quota_pressure_even_when_load_is_moderate(
    tmp_path: Path,
) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 0.55',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
                'awoooi_host_gitea_actions_active_container_count{host="110"} 0',
                'awoooi_host_gitea_actions_active_process_group_count{host="110"} 0',
                'awoooi_host_runaway_browser_orphan_group_count{host="110",rule="stockplatform_headless_smoke",min_age_seconds="1800",min_cpu_percent="50"} 0',
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        "\n".join(
            [
                'docker_container_cpu_cores{host="110",container_name="gitea"} 2.08',
                'docker_container_cpu_cores{host="110",container_name="redis"} 0.2',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--load5-per-core-threshold",
            "0.75",
            "--metrics-file",
            str(metrics_file),
            "--docker-stats-file",
            str(docker_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert payload["classification"] == "blocked_gitea_queue_or_hook_backlog_requires_playbook"
    assert payload["severity"] == "warning"
    assert payload["readback"]["container_cpu_threshold"] == 2.0
    assert payload["readback"]["top_container_cpu"]["cpu_cores"] == 2.08
    assert "/home/wooo/scripts/gitea-queue-hook-backlog-playbook.py" in payload["commands"]["dry_run"]
    assert "scripts/ops/" not in payload["commands"]["dry_run"]


def test_sustained_load_controller_prioritizes_hot_gitea_container_over_control_plane_average(
    tmp_path: Path,
) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 0.70',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
                'awoooi_host_gitea_actions_active_container_count{host="110"} 0',
                'awoooi_host_gitea_actions_active_process_group_count{host="110"} 0',
                'awoooi_host_runaway_browser_orphan_group_count{host="110",rule="stockplatform_headless_smoke",min_age_seconds="1800",min_cpu_percent="50"} 0',
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        "\n".join(
            [
                'docker_container_cpu_cores{host="110",container_name="gitea"} 1.59',
                'docker_container_cpu_cores{host="110",container_name="redis"} 0.2',
            ]
        ),
        encoding="utf-8",
    )
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "\n".join(
            [
                "100 1 100 75507 61.8 0.0 systemd /sbin/init",
                "101 1 101 75469 6.7 0.0 dbus-daemon @dbus-daemon --system",
                "200 1 200 75348 53.1 1.3 gitea /usr/local/bin/gitea web --config /home/wooo/gitea/app.ini",
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--load5-per-core-threshold",
            "0.75",
            "--hot-container-cpu-threshold",
            "1.0",
            "--container-cpu-threshold",
            "2.0",
            "--metrics-file",
            str(metrics_file),
            "--docker-stats-file",
            str(docker_file),
            "--ps-file",
            str(ps_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert payload["classification"] == "blocked_gitea_queue_or_hook_backlog_requires_playbook"
    assert payload["next_action"] == "run_gitea_queue_or_hook_backlog_playbook_check_mode"
    assert payload["readback"]["control_plane_process_cpu_percent"] == 68.5
    assert payload["readback"]["top_container_cpu"]["container_name"] == "gitea"
    assert "/home/wooo/scripts/gitea-queue-hook-backlog-playbook.py" in payload["commands"]["dry_run"]
    assert "/home/wooo/gitea/app.ini" not in result.stdout


def test_sustained_load_controller_ignores_stale_docker_stats_attribution(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 2.5',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
                'awoooi_host_gitea_actions_active_container_count{host="110"} 0',
                'awoooi_host_gitea_actions_active_process_group_count{host="110"} 0',
                'awoooi_host_runaway_browser_orphan_group_count{host="110",rule="stockplatform_headless_smoke",min_age_seconds="1800",min_cpu_percent="50"} 0',
                'node_textfile_mtime_seconds{file="/host/home/wooo/node_exporter_textfiles/docker_stats.prom"} 1000',
                'node_time_seconds 5000',
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        "\n".join(
            [
                'docker_container_cpu_cores{host="110",container_name="gitea"} 3.4',
                'docker_container_cpu_cores{host="110",container_name="redis"} 0.2',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--docker-stats-file",
            str(docker_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert payload["classification"] == "blocked_unknown_sustained_load_requires_source_specific_playbook"
    assert payload["readback"]["docker_stats"]["fresh"] is False
    assert payload["readback"]["top_container_cpu"] is None
    assert payload["readback"]["top_container_cpu_untrusted"]["container_name"] == "gitea"
    assert payload["controlled_apply_allowed"] is False


def test_sustained_load_controller_routes_unknown_load_to_sanitized_evidence(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 2.0',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
                'awoooi_host_gitea_actions_active_container_count{host="110"} 0',
                'awoooi_host_gitea_actions_active_process_group_count{host="110"} 0',
                'awoooi_host_runaway_browser_orphan_group_count{host="110",rule="stockplatform_headless_smoke",min_age_seconds="1800",min_cpu_percent="50"} 0',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert payload["classification"] == "blocked_unknown_sustained_load_requires_source_specific_playbook"
    assert payload["controlled_apply_allowed"] is False
    assert "/home/wooo/scripts/host-sustained-load-evidence.py" in payload["commands"]["dry_run"]
    assert "scripts/ops/" not in payload["commands"]["dry_run"]
    assert payload["operation_boundaries"]["process_signal_performed"] is False


def test_sustained_load_controller_routes_moderate_stock_container_pressure(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 0.62',
                'awoooi_host_swap_used_ratio{host="110"} 0.27',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
                'awoooi_host_gitea_actions_active_container_count{host="110"} 0',
                'awoooi_host_gitea_actions_active_process_group_count{host="110"} 0',
                'awoooi_host_runaway_browser_orphan_group_count{host="110",rule="stockplatform_headless_smoke",min_age_seconds="1800",min_cpu_percent="50"} 0',
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        "\n".join(
            [
                'docker_container_cpu_cores{host="110",container_name="stockplatform-v2-postgres-1"} 1.654',
                'docker_container_cpu_cores{host="110",container_name="gitea"} 1.092',
            ]
        ),
        encoding="utf-8",
    )
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "\n".join(
            [
                "100 1 100 73767 20.0 0.0 systemd /sbin/init",
                "200 1 200 73608 30.0 1.1 gitea /usr/local/bin/gitea web --config /home/wooo/gitea/app.ini",
                "300 1 300 60 20.8 0.2 postgres postgres: stockplatform stockplatform SELECT",
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--load5-per-core-threshold",
            "0.75",
            "--container-cpu-threshold",
            "2.0",
            "--metrics-file",
            str(metrics_file),
            "--docker-stats-file",
            str(docker_file),
            "--ps-file",
            str(ps_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert (
        payload["classification"]
        == "blocked_stockplatform_hot_query_or_api_pressure_requires_playbook"
    )
    assert payload["severity"] == "warning"
    assert payload["readback"]["hot_container_cpu_threshold"] == 1.0
    assert payload["readback"]["top_container_cpu"]["container_name"] == "stockplatform-v2-postgres-1"
    assert payload["readback"]["top_process_family"]["family"] == "gitea_service"
    assert payload["controlled_apply_allowed"] is False
    assert "/home/wooo/scripts/host-sustained-load-evidence.py" in payload["commands"]["dry_run"]
    assert "scripts/ops/" not in payload["commands"]["dry_run"]
    assert "/home/wooo/gitea/app.ini" not in result.stdout


def test_sustained_load_controller_routes_gitea_process_pressure_without_hot_container(
    tmp_path: Path,
) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 0.55',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        'docker_container_cpu_cores{host="110",container_name="gitea"} 0.20\n',
        encoding="utf-8",
    )
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "200 1 200 73608 55.5 1.1 gitea /usr/local/bin/gitea web --config /home/wooo/gitea/app.ini\n",
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--docker-stats-file",
            str(docker_file),
            "--ps-file",
            str(ps_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert payload["classification"] == "blocked_gitea_queue_or_hook_backlog_requires_playbook"
    assert payload["readback"]["gitea_process_cpu_percent"] == 55.5
    assert payload["controlled_apply_allowed"] is False
    assert "/home/wooo/scripts/gitea-queue-hook-backlog-playbook.py" in payload["commands"]["dry_run"]
    assert "/home/wooo/gitea/app.ini" not in result.stdout


def test_sustained_load_controller_routes_control_plane_family_pressure(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 0.70',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
            ]
        ),
        encoding="utf-8",
    )
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "\n".join(
            [
                "100 1 100 73767 40.0 0.0 systemd /sbin/init",
                "101 1 101 73767 15.0 0.0 dbus-daemon @dbus-daemon --system",
                "200 1 200 73608 20.0 1.1 gitea /usr/local/bin/gitea web",
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--ps-file",
            str(ps_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert payload["classification"] == "blocked_control_plane_saturation_requires_playbook"
    assert payload["readback"]["control_plane_process_cpu_percent"] == 55.0
    assert payload["next_action"] == "run_control_plane_saturation_playbook_check_mode"
    assert "/home/wooo/scripts/host-sustained-load-evidence.py" in payload["commands"]["dry_run"]
    assert "/home/wooo/scripts/host-sustained-load-controller.py" in payload["commands"]["post_apply_verifier"]
    assert "scripts/ops/" not in payload["commands"]["dry_run"]
    assert "scripts/ops/" not in payload["commands"]["post_apply_verifier"]


def test_sustained_load_controller_honors_custom_readback_paths(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="188",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="188"} 0.40',
                'awoooi_host_swap_used_ratio{host="188"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="188"} 0',
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        'docker_container_cpu_cores{host="188",container_name="momo-scheduler"} 0.70\n',
        encoding="utf-8",
    )
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text("100 1 100 3600 5.0 0.0 python python worker.py\n", encoding="utf-8")
    script_dir = tmp_path / "deployed-scripts"

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "188",
            "--metrics-file",
            str(metrics_file),
            "--docker-stats-file",
            str(docker_file),
            "--script-dir",
            str(script_dir),
            "--ps-file",
            str(ps_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 0
    payload = json.loads(result.stdout)
    assert payload["classification"] == "observing_load_within_threshold"
    assert payload["readback"]["metrics_file"] == str(metrics_file)
    assert payload["readback"]["docker_stats_file"] == str(docker_file)
    assert payload["readback"]["script_dir"] == str(script_dir)
    assert str(metrics_file) in payload["commands"]["post_apply_verifier"]
    assert str(docker_file) in payload["commands"]["post_apply_verifier"]
    assert str(script_dir / "host-sustained-load-controller.py") in payload["commands"]["post_apply_verifier"]
    assert "/home/wooo/node_exporter_textfiles" not in payload["commands"]["post_apply_verifier"]


def test_sustained_load_evidence_emits_sanitized_gitea_recommendation(tmp_path: Path) -> None:
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "\n".join(
            [
                "100 1 100 7200 280.0 1.0 gitea /usr/local/bin/gitea web --config /home/wooo/gitea/app.ini",
                "200 1 200 180 15.0 0.5 systemd systemctl show gitea-act-runner-host.service",
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        'docker_container_cpu_cores{host="110",container_name="gitea"} 3.4\n',
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(EVIDENCE_PATH),
            "--host",
            "110",
            "--ps-file",
            str(ps_file),
            "--docker-stats-file",
            str(docker_file),
            "--json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    payload = json.loads(result.stdout)
    assert payload["schema_version"] == "host_sustained_load_sanitized_evidence_v1"
    assert payload["recommendation"] == "gitea_queue_or_hook_backlog_playbook"
    assert payload["redaction"]["raw_command_lines_emitted"] is False
    assert payload["operation_boundaries"]["host_write_performed"] is False
    assert "/home/wooo" not in result.stdout


def test_sustained_load_evidence_prioritizes_hot_gitea_container_over_control_plane_average(
    tmp_path: Path,
) -> None:
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "\n".join(
            [
                "100 1 100 75507 61.8 0.0 systemd /sbin/init",
                "101 1 101 75469 6.7 0.0 dbus-daemon @dbus-daemon --system",
                "200 1 200 75348 53.1 1.3 gitea /usr/local/bin/gitea web --config /home/wooo/gitea/app.ini",
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        'docker_container_cpu_cores{host="110",container_name="gitea"} 1.4591\n',
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(EVIDENCE_PATH),
            "--host",
            "110",
            "--ps-file",
            str(ps_file),
            "--docker-stats-file",
            str(docker_file),
            "--json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    payload = json.loads(result.stdout)
    assert payload["recommendation"] == "gitea_queue_or_hook_backlog_playbook"
    assert payload["top_process_families"][0]["family"] == "systemd_control_plane"
    assert payload["top_containers"][0]["container_name"] == "gitea"
    assert "/home/wooo/gitea/app.ini" not in result.stdout


def test_sustained_load_evidence_aligns_stock_postgres_priority_with_controller(
    tmp_path: Path,
) -> None:
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "\n".join(
            [
                "100 1 100 78516 79.8 0.5 postgres postgres: stockplatform SELECT",
                "200 1 200 78513 53.1 1.3 gitea /usr/local/bin/gitea web --config /home/wooo/gitea/app.ini",
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        "\n".join(
            [
                'docker_container_cpu_cores{host="110",container_name="gitea"} 1.6725',
                'docker_container_cpu_cores{host="110",container_name="stockplatform-v2-postgres-1"} 1.6317',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(EVIDENCE_PATH),
            "--host",
            "110",
            "--ps-file",
            str(ps_file),
            "--docker-stats-file",
            str(docker_file),
            "--json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    payload = json.loads(result.stdout)
    assert payload["recommendation"] == "postgres_hot_query_or_backup_export_playbook"
    assert payload["top_containers"][0]["container_name"] == "gitea"
    assert payload["top_process_families"][0]["family"] == "postgres"
    assert "/home/wooo/gitea/app.ini" not in result.stdout


def test_sustained_load_evidence_keeps_stale_container_samples_untrusted(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'node_textfile_mtime_seconds{file="/host/home/wooo/node_exporter_textfiles/docker_stats.prom"} 1000',
                'node_time_seconds 5000',
            ]
        ),
        encoding="utf-8",
    )
    docker_file = tmp_path / "docker.prom"
    docker_file.write_text(
        'docker_container_cpu_cores{host="110",container_name="gitea"} 3.4\n',
        encoding="utf-8",
    )
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "100 1 100 120 5.0 1.0 python python monitor.py\n",
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(EVIDENCE_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--ps-file",
            str(ps_file),
            "--docker-stats-file",
            str(docker_file),
            "--json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    payload = json.loads(result.stdout)
    assert payload["recommendation"] != "gitea_queue_or_hook_backlog_playbook"
    assert payload["readback"]["docker_stats"]["fresh"] is False
    assert payload["top_containers"] == []
    assert payload["top_containers_untrusted"][0]["container_name"] == "gitea"
    assert payload["operation_boundaries"]["host_write_performed"] is False


def test_sustained_load_controller_routes_unknown_load_to_sanitized_evidence(tmp_path: Path) -> None:
    metrics_file = tmp_path / "host.prom"
    metrics_file.write_text(
        "\n".join(
            [
                'awoooi_host_runaway_process_monitor_up{host="110",mode="read_only"} 1',
                'awoooi_host_load5_per_core{host="110"} 2.4',
                'awoooi_host_swap_used_ratio{host="110"} 0.1',
                'awoooi_host_runaway_process_remediation_authorized{host="110"} 0',
            ]
        ),
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(CONTROLLER_PATH),
            "--host",
            "110",
            "--metrics-file",
            str(metrics_file),
            "--json",
        ],
        capture_output=True,
        text=True,
    )

    assert result.returncode == 75
    payload = json.loads(result.stdout)
    assert (
        payload["classification"]
        == "blocked_unknown_sustained_load_requires_source_specific_playbook"
    )
    assert payload["controlled_apply_allowed"] is False
    assert "/home/wooo/scripts/host-sustained-load-evidence.py" in payload["commands"]["dry_run"]
    assert "scripts/ops/" not in payload["commands"]["dry_run"]
    assert payload["operation_boundaries"]["host_write_performed"] is False


def test_sustained_load_evidence_sanitizes_process_details(tmp_path: Path) -> None:
    ps_file = tmp_path / "ps.txt"
    ps_file.write_text(
        "\n".join(
            [
                "101 1 101 7200 65.0 2.5 chrome /opt/chrome/chrome --headless --user-data-dir=/tmp/stockplatform-review-bulk-ux-aa --url=https://example.invalid/token",
                "102 1 102 3600 20.0 1.0 node node /srv/private/app/server.js --api-key=SECRET",
            ]
        ),
        encoding="utf-8",
    )
    docker_stats_file = tmp_path / "docker.prom"
    docker_stats_file.write_text(
        'docker_container_cpu_cores{host="110",container_name="gitea"} 3.2\n',
        encoding="utf-8",
    )

    result = subprocess.run(
        [
            sys.executable,
            str(EVIDENCE_PATH),
            "--host",
            "110",
            "--ps-file",
            str(ps_file),
            "--docker-stats-file",
            str(docker_stats_file),
            "--json",
        ],
        check=True,
        capture_output=True,
        text=True,
    )

    payload = json.loads(result.stdout)
    assert payload["schema_version"] == "host_sustained_load_sanitized_evidence_v1"
    assert payload["recommendation"] == "gitea_queue_or_hook_backlog_playbook"
    assert payload["redaction"]["raw_command_lines_emitted"] is False
    assert payload["redaction"]["workspace_paths_emitted"] is False
    assert payload["redaction"]["urls_emitted"] is False
    assert payload["operation_boundaries"]["host_write_performed"] is False
    assert "https://example.invalid/token" not in result.stdout
    assert "/tmp/stockplatform-review-bulk-ux-aa" not in result.stdout
    assert "SECRET" not in result.stdout
    assert {item["family"] for item in payload["top_process_families"]} >= {
        "headless_browser",
        "node_service",
    }
