"""Verifier for sys-002: Parse Process List."""

import json
from pathlib import Path

import pytest


@pytest.fixture
def workspace(request):
    """Resolve the workspace path from the --workspace CLI flag."""
    return Path(request.config.getoption("--workspace"))


@pytest.fixture
def report(workspace):
    """Load and return the top_processes.json contents."""
    path = workspace / "top_processes.json"
    assert path.exists(), "top_processes.json not found in workspace"
    return json.loads(path.read_text())


def test_output_file_exists(workspace):
    """top_processes.json must exist in the workspace."""
    assert (workspace / "top_processes.json").exists()


def test_total_processes_count(report):
    """total_processes must equal 15 (the number of process lines)."""
    assert report["total_processes"] == 15


def test_top_5_count(report):
    """top_5_cpu must have exactly 5 entries."""
    assert len(report["top_5_cpu"]) == 5


def test_top_5_sorted_descending(report):
    """top_5_cpu must be sorted by cpu_percent descending."""
    cpus = [p["cpu_percent"] for p in report["top_5_cpu"]]
    for i in range(len(cpus) - 1):
        assert cpus[i] >= cpus[i + 1], "top_5_cpu not sorted descending"


def test_top_process_is_ml_training(report):
    """The highest CPU process should be the ML training script (45.2%)."""
    top = report["top_5_cpu"][0]
    assert top["cpu_percent"] == pytest.approx(45.2, abs=0.5)
    assert "ml_training" in top["command"] or "python" in top["command"].lower()


def test_pid_present_and_integer(report):
    """Each top process entry must have a PID as an integer."""
    for proc in report["top_5_cpu"]:
        assert "pid" in proc, "Entry missing 'pid'"
        assert isinstance(proc["pid"], int), f"PID should be integer, got {type(proc['pid'])}"


def test_command_present(report):
    """Each top process entry must have a non-empty command."""
    for proc in report["top_5_cpu"]:
        assert "command" in proc, "Entry missing 'command'"
        assert len(proc["command"]) > 0, "Command should not be empty"


def test_known_top_5_pids(report):
    """Top 5 by CPU should include PIDs: 4567 (45.2%), 6789 (22.8%), 9012 (18.4%), 3456 (15.7%), 1234 (12.5%)."""
    pids = {p["pid"] for p in report["top_5_cpu"]}
    expected_pids = {4567, 6789, 9012, 3456, 1234}
    assert pids == expected_pids, f"Expected PIDs {expected_pids}, got {pids}"


def test_total_cpu_usage(report):
    """total_cpu_usage must be approximately correct."""
    # Sum: 0+0+12.5+8.3+15.7+45.2+3.1+22.8+0.5+1.2+18.4+0.1+7.6+0.3+2.4 = 138.1
    assert report["total_cpu_usage"] == pytest.approx(138.1, abs=1.0)


def test_entries_have_required_fields(report):
    """Each entry must have user, cpu_percent, and mem_percent fields."""
    for proc in report["top_5_cpu"]:
        assert "user" in proc, "Entry missing 'user'"
        assert "cpu_percent" in proc, "Entry missing 'cpu_percent'"
        assert "mem_percent" in proc, "Entry missing 'mem_percent'"
