from pathlib import Path

from aitop.core.gpu.amd_npu import AMDNPUMonitor
from aitop.core.gpu.intel_npu import IntelNPUMonitor


def test_amd_npu_parses_xrt_device_names() -> None:
    output = """
    | [0000:c5:00.1] | NPU Strix |
    | [0000:c6:00.1] | NPU Hawk  |
    """

    devices = AMDNPUMonitor._parse_xrt_device_names(output)

    assert devices["0000:c5:00.1"] == "NPU Strix"
    assert devices["0000:c6:00.1"] == "NPU Hawk"


def test_amd_npu_parses_xrt_platform_power() -> None:
    output = """
    [0000:c5:00.1] : NPU Strix
      Estimated Power       : 1.277 Watts
    [0000:c6:00.1] : NPU Hawk
      Estimated Power       : 2.500 Watts
    """

    power = AMDNPUMonitor._parse_xrt_platform_power(output)

    assert power["0000:c5:00.1"] == 1.277
    assert power["0000:c6:00.1"] == 2.5


def test_amd_npu_parses_xrt_aie_processes() -> None:
    output = """
    [0000:c5:00.1] : NPU Strix
    |PID    |Ctx ID  |Status  |Instr BO   |
    |20696  |0       |Active  |64 KB      |
    |20696  |1       |Running |128 KB     |
    |20000  |2       |Idle    |0 KB       |
    """

    processes, active = AMDNPUMonitor._parse_xrt_aie_processes(output)

    assert active["0000:c5:00.1"] == 1
    assert len(processes["0000:c5:00.1"]) == 2
    assert processes["0000:c5:00.1"][0]["pid"] == 20000
    assert processes["0000:c5:00.1"][1]["pid"] == 20696
    assert processes["0000:c5:00.1"][1]["memory"] == 0.125


def test_intel_npu_compute_utilization_uses_busy_time_delta(
    monkeypatch: object,
) -> None:
    monitor = IntelNPUMonitor()
    monotonic_values = iter([10.0, 11.0])
    monkeypatch.setattr("time.monotonic", lambda: next(monotonic_values))

    first = monitor._compute_utilization(index=0, busy_time_us=1_000_000)
    second = monitor._compute_utilization(index=0, busy_time_us=1_500_000)

    assert first == 0.0
    assert second == 50.0


def test_intel_npu_builds_name_from_device_id(monkeypatch: object) -> None:
    monitor = IntelNPUMonitor()
    fake_device_path = Path("/tmp/fake")
    monkeypatch.setattr(
        monitor,
        "_read_text",
        lambda path: "0x7d1d" if str(path).endswith("/device") else "",
    )

    name = monitor._build_device_name(fake_device_path, index=2)

    assert name == "Intel AI Boost (0x7d1d)"
