"""Benchmark tests for which module performance."""

import platform
from typing import List, Tuple

import pytest

from ..cli import WINDOWS_BUILTINS, WindowsBuiltinCommands, find_executable


@pytest.fixture(scope="module")
def builtin_commands() -> List[str]:
    """Provide a list of Windows built-in commands for testing."""
    if platform.system() != "Windows":
        pytest.skip("Benchmark tests only run on Windows")
    return ["dir", "echo", "cls", "cd", "md", "rd", "del", "copy", "move", "type"]


@pytest.mark.benchmark(group="builtin_detection")
def test_detect_builtins_performance(benchmark, builtin_commands: List[str]) -> None:
    """Benchmark performance of detecting built-in commands."""

    def detect_all_builtins() -> List[Tuple[str, str]]:
        return [find_executable(cmd, fuzzy=False) for cmd in builtin_commands]

    result = benchmark(detect_all_builtins)
    assert len(result) == len(builtin_commands)
    # All should be found on Windows
    assert all(path is not None for _, path in result)


@pytest.mark.benchmark(group="builtin_detection")
def test_windows_builtins_cached_property(benchmark) -> None:
    """Benchmark cached property access for Windows built-ins."""

    def access_cached_properties() -> tuple:
        commands = WINDOWS_BUILTINS.commands
        path = WINDOWS_BUILTINS.cmd_exe_path
        return commands, path

    # First access (computes and caches)
    commands1, path1 = benchmark(access_cached_properties)

    # Second access (uses cache)
    commands2, path2 = WINDOWS_BUILTINS.commands, WINDOWS_BUILTINS.cmd_exe_path

    # Verify caching works
    assert commands1 is commands2  # Same object (cached)
    assert path1 is path2  # Same object (cached)


@pytest.mark.benchmark(group="regular_executables")
def test_detect_regular_executables_performance(benchmark) -> None:
    """Benchmark performance of detecting regular executables."""

    def detect_regular() -> List[Tuple[str, str]]:
        # Common executables that should exist
        executables = ["cmd", "notepad", "ping"]
        return [find_executable(cmd, fuzzy=False) for cmd in executables]

    result = benchmark(detect_regular)
    assert len(result) == 3


@pytest.mark.parametrize("command", ["dir", "echo", "cls"])
@pytest.mark.benchmark(group="individual_builtin")
def test_individual_builtin_performance(benchmark, command: str) -> None:
    """Benchmark performance of individual built-in command detection."""

    def detect_builtin() -> Tuple[str, str]:
        return find_executable(command, fuzzy=False)

    name, path = benchmark(detect_builtin)
    assert name == command
    assert path is not None
    assert "cmd.exe (built-in)" in path


@pytest.mark.benchmark(group="is_builtin_method")
def test_is_builtin_method_performance(benchmark) -> None:
    """Benchmark performance of is_builtin method calls."""

    def check_multiple_commands() -> List[bool]:
        commands = ["dir", "echo", "cls", "nonexistent", "another_fake"]
        return [WINDOWS_BUILTINS.is_builtin(cmd) for cmd in commands]

    results = benchmark(check_multiple_commands)
    assert results == [True, True, True, False, False]


@pytest.mark.skipif(platform.system() != "Windows", reason="Windows-only benchmark")
class TestWindowsBuiltinCommandsBenchmark:
    """Benchmark tests for WindowsBuiltinCommands class."""

    @pytest.mark.benchmark(group="class_initialization")
    def test_class_initialization_performance(self, benchmark) -> None:
        """Benchmark initialization of WindowsBuiltinCommands."""

        def create_instance():
            return WindowsBuiltinCommands()

        instance = benchmark(create_instance)
        assert instance is not None
        assert hasattr(instance, "is_builtin")

    @pytest.mark.benchmark(group="property_caching")
    def test_property_caching_efficiency(self, benchmark) -> None:
        """Test that cached properties provide performance benefits."""
        instance = WindowsBuiltinCommands()

        # Benchmark first access (computation)
        def first_access():
            return instance.commands, instance.cmd_exe_path

        commands1, path1 = benchmark(first_access)

        # Benchmark second access (cache hit)
        def second_access():
            return instance.commands, instance.cmd_exe_path

        commands2, path2 = second_access()  # Direct call for cache test

        # Verify caching
        assert commands1 is commands2
        assert path1 is path2
