import subprocess
from pathlib import Path
from typing import Any, Dict, List, Optional

from aitop.core.gpu.base import BaseGPUMonitor, GPUInfo


class _DummyMonitor(BaseGPUMonitor):
    def __init__(self, preset_path: Optional[Path]) -> None:
        self._preset_path = preset_path
        super().__init__()

    def _find_smi(self) -> Optional[Path]:
        return self._preset_path

    def get_gpu_info(self) -> List[GPUInfo]:
        return []

    def get_quick_metrics(self) -> Dict[int, Dict[str, float]]:
        return {}


def test_run_smi_command_returns_none_when_smi_path_is_missing() -> None:
    monitor = _DummyMonitor(None)

    output = monitor._run_smi_command(["missing-smi", "--query"])

    assert output is None


def test_run_smi_command_returns_none_when_smi_binary_does_not_exist(
    tmp_path: Path,
) -> None:
    missing_path = tmp_path / "fake-smi"
    monitor = _DummyMonitor(missing_path)

    output = monitor._run_smi_command([str(missing_path), "--query"])

    assert output is None


def test_run_smi_command_returns_none_when_smi_binary_not_executable(
    tmp_path: Path,
) -> None:
    smi_path = tmp_path / "fake-smi"
    smi_path.write_text("#!/bin/sh\necho ok\n", encoding="utf-8")
    smi_path.chmod(0o644)
    monitor = _DummyMonitor(smi_path)

    output = monitor._run_smi_command([str(smi_path), "--query"])

    assert output is None


def test_run_smi_command_returns_none_on_timeout(
    monkeypatch: object,
    tmp_path: Path,
) -> None:
    smi_path = tmp_path / "fake-smi"
    smi_path.write_text("#!/bin/sh\necho ok\n", encoding="utf-8")
    smi_path.chmod(0o755)
    monitor = _DummyMonitor(smi_path)

    def _timeout(*args: Any, **kwargs: Any) -> Any:
        del kwargs
        raise subprocess.TimeoutExpired(cmd=args[0], timeout=5)

    monkeypatch.setattr(subprocess, "run", _timeout)

    output = monitor._run_smi_command([str(smi_path), "--query"])

    assert output is None


def test_run_smi_command_returns_stdout_on_success(
    monkeypatch: object,
    tmp_path: Path,
) -> None:
    smi_path = tmp_path / "fake-smi"
    smi_path.write_text("#!/bin/sh\necho ok\n", encoding="utf-8")
    smi_path.chmod(0o755)
    monitor = _DummyMonitor(smi_path)

    monkeypatch.setattr(
        subprocess,
        "run",
        lambda *args, **kwargs: subprocess.CompletedProcess(
            args=args[0], returncode=0, stdout="gpu-ok", stderr=""
        ),
    )

    output = monitor._run_smi_command([str(smi_path), "--query"])

    assert output == "gpu-ok"
