from types import SimpleNamespace
from typing import Any, Dict, List, Tuple

from aitop.__main__ import AITop
from aitop.core.gpu.base import GPUInfo


class _GPUPanelStub:
    def get_all_gpu_processes(
        self,
        gpu_info: List[Tuple[GPUInfo, str]],
        process_filter: str = "",
    ) -> List[Dict[str, Any]]:
        del process_filter
        processes: List[Dict[str, Any]] = []
        for gpu, vendor in gpu_info:
            for process in gpu.processes:
                process_copy = process.copy()
                process_copy.setdefault("gpu_vendor", vendor)
                processes.append(process_copy)
        return processes


def _make_gpu(index: int, pid: int, name: str) -> GPUInfo:
    return GPUInfo(
        index=index,
        name=name,
        utilization=10.0,
        memory_used=100.0,
        memory_total=200.0,
        temperature=0.0,
        power_draw=0.0,
        power_limit=0.0,
        processes=[{"pid": pid, "name": f"proc-{pid}", "memory": 10.0}],
    )


def _build_app(vendors: List[str], gpu_info: List[Tuple[GPUInfo, str]]) -> AITop:
    app = object.__new__(AITop)
    app.selected_tab = 0
    app.collector = SimpleNamespace(vendors=vendors)
    app.system_data = SimpleNamespace(gpu_info=gpu_info, processes=[])
    app.gpu_panel = _GPUPanelStub()
    app.process_filter_query = ""
    app.selected_process_index = 0
    app.selected_gpu_process_index = 0
    app.scroll_position = 0
    app.process_tree_mode = False
    return app


def test_active_tabs_hide_npu_when_not_detected() -> None:
    app = _build_app(["nvidia"], [(_make_gpu(0, 100, "GPU 0"), "nvidia")])

    active_tabs = app._get_active_tabs()

    assert active_tabs == ["OVERVIEW", "AI PROCESSES", "GPU", "MEMORY", "CPU"]


def test_active_tabs_show_npu_when_detected() -> None:
    app = _build_app(
        ["nvidia", "intel_npu"],
        [
            (_make_gpu(0, 100, "GPU 0"), "nvidia"),
            (_make_gpu(0, 200, "NPU 0"), "intel_npu"),
        ],
    )

    active_tabs = app._get_active_tabs()

    assert active_tabs == ["OVERVIEW", "AI PROCESSES", "GPU", "NPU", "MEMORY", "CPU"]


def test_filter_match_counts_split_gpu_and_npu_processes() -> None:
    app = _build_app(
        ["nvidia", "intel_npu"],
        [
            (_make_gpu(0, 100, "GPU 0"), "nvidia"),
            (_make_gpu(0, 200, "NPU 0"), "intel_npu"),
        ],
    )
    tab_indices = app._get_tab_indices()

    app.selected_tab = tab_indices["GPU"]
    gpu_matches = app._get_filter_match_counts()

    app.selected_tab = tab_indices["NPU"]
    npu_matches = app._get_filter_match_counts()

    assert gpu_matches == (1, 1)
    assert npu_matches == (1, 1)


def test_npu_tab_footer_includes_kill_and_filter_controls() -> None:
    app = _build_app(
        ["intel_npu"],
        [(_make_gpu(0, 200, "NPU 0"), "intel_npu")],
    )
    app.selected_tab = app._get_tab_indices()["NPU"]

    controls = app._get_footer_controls()

    assert ("k", "kill") in controls
    assert ("o", "settings") in controls
    assert ("ctrl+f", "search") in controls
    assert ("esc/ctrl+l", "clear") in controls
