"""Benchmark tests for pyprojectparse module.

These tests measure performance of key operations and are excluded from regular test runs.
Run with: pytest --benchmark-only or pytest -m benchmark
"""

from __future__ import annotations

import json

import pytest

from ..models.project import Project
from ..models.solution import Solution


class TestBenchmarkProjectCreation:
    """Benchmark Project instance creation and initialization."""

    @pytest.fixture(scope="module")
    def simple_project_data(self):
        """Generate simple project data for basic creation benchmarking."""
        return {
            "name": "benchmark_project",
            "version": "1.0.0",
            "description": "Benchmark test project",
            "readme": "README.md",
            "requires_python": ">=3.8",
            "dependencies": ["requests>=2.0.0", "numpy>=1.20.0"],
            "optional_dependencies": {"dev": ["pytest>=7.0.0"], "test": ["coverage"]},
            "scripts": {"main": "src.main:main"},
            "entry_points": {},
            "authors": [{"name": "Test Author", "email": "test@example.com"}],
            "license": "MIT",
            "keywords": ["benchmark", "test"],
            "classifiers": ["Programming Language :: Python :: 3"],
            "urls": {"homepage": "https://example.com"},
            "build_backend": "setuptools.build_meta",
            "requires": ["setuptools>=45", "wheel"],
        }

    @pytest.fixture(scope="module")
    def large_project_data(self):
        """Large project data with many dependencies and metadata."""
        return {
            "name": "large_benchmark_project",
            "version": "2.0.0",
            "description": "Large benchmark test project with extensive metadata",
            "readme": "README.md",
            "requires_python": ">=3.8",
            "dependencies": [f"package_{i}>=1.0.0" for i in range(1000)],
            "optional_dependencies": {
                "dev": [f"dev_pkg_{i}" for i in range(100)],
                "test": [f"test_pkg_{i}" for i in range(100)],
                "docs": [f"docs_pkg_{i}" for i in range(50)],
            },
            "scripts": {f"script_{i}": f"src.script{i}:main" for i in range(50)},
            "entry_points": {
                f"entry_{i}": {f"entry_point_{j}": f"module{i}:func{j}" for j in range(10)} for i in range(20)
            },
            "authors": [{"name": f"Author {i}", "email": f"author{i}@example.com"} for i in range(100)],
            "license": "MIT",
            "keywords": [f"keyword_{i}" for i in range(200)],
            "classifiers": [f"Classifier :: Test {i}" for i in range(500)],
            "urls": {f"url_{i}": f"https://example{i}.com" for i in range(50)},
            "build_backend": "setuptools.build_meta",
            "requires": [f"build_req_{i}" for i in range(50)],
        }

    @pytest.mark.benchmark
    def test_create_project_from_dict_simple(self, benchmark, simple_project_data):
        """Benchmark creating Project from simple dictionary."""
        project = benchmark(Project._from_dict, simple_project_data)
        assert project.name == "benchmark_project"
        assert len(project.dependencies) == 2

    @pytest.mark.benchmark
    def test_create_project_from_dict_large(self, benchmark, large_project_data):
        """Benchmark creating Project from large dictionary with extensive metadata."""
        project = benchmark(Project._from_dict, large_project_data)
        assert project.name == "large_benchmark_project"
        assert len(project.dependencies) == 1000


class TestBenchmarkProjectProperties:
    """Benchmark Project property calculations and access."""

    @pytest.fixture(scope="module")
    def project_with_complex_deps(self):
        """Project with complex dependency specifications."""
        return Project._from_dict(
            {
                "name": "complex_deps_project",
                "version": "1.0.0",
                "description": "",
                "readme": "",
                "requires_python": ">=3.8",
                "dependencies": [
                    "requests>=2.0.0",
                    "numpy>=1.20.0,<2.0.0",
                    "pandas[excel]>=1.3.0",
                    "PyQt5>=5.15.0",
                    "scipy~=1.7.0",
                    "matplotlib>=3.3.0; python_version<'3.11'",
                    "pytest>=7.0.0; python_version>='3.8' and sys_platform=='win32'",
                    "package[extra1,extra2]>=1.0.0",
                    "another_package>=1.0.0,<2.0.0,!=1.5.0",
                ]
                * 10,  # Repeat to increase size
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": ["gui", "desktop", "benchmark"],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
        )

    @pytest.fixture(scope="module")
    def project_with_qt(self):
        """Project with Qt dependencies."""
        return Project._from_dict(
            {
                "name": "qt_project",
                "version": "1.0.0",
                "description": "",
                "readme": "",
                "requires_python": ">=3.8",
                "dependencies": ["PySide2", "requests", "PyQt6", "numpy"],
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": ["gui", "desktop", "qt"],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
        )

    @pytest.mark.benchmark
    def test_normalized_name_property(self, benchmark, project_with_complex_deps):
        """Benchmark normalized_name property access."""
        result = benchmark(lambda: project_with_complex_deps.normalized_name)
        assert "complex_deps_project" in result

    @pytest.mark.benchmark
    def test_dep_names_property(self, benchmark, project_with_complex_deps):
        """Benchmark dep_names property (dependency name extraction)."""
        dep_names = benchmark(lambda: project_with_complex_deps.dep_names)
        assert len(dep_names) > 0

    @pytest.mark.benchmark
    def test_qt_deps_property(self, benchmark, project_with_qt):
        """Benchmark qt_deps property calculation."""
        qt_deps = benchmark(lambda: project_with_qt.qt_deps)
        assert len(qt_deps) > 0

    @pytest.mark.benchmark
    def test_has_qt_property(self, benchmark, project_with_qt):
        """Benchmark has_qt property."""
        has_qt = benchmark(lambda: project_with_qt.has_qt)
        assert has_qt is True

    @pytest.mark.benchmark
    def test_qt_libname_property(self, benchmark, project_with_qt):
        """Benchmark qt_libname property."""
        libname = benchmark(lambda: project_with_qt.qt_libname)
        assert libname is not None

    @pytest.mark.benchmark
    def test_is_gui_property(self, benchmark, project_with_qt):
        """Benchmark is_gui property."""
        is_gui = benchmark(lambda: project_with_qt.is_gui)
        assert is_gui is True

    @pytest.mark.benchmark
    def test_loader_type_property(self, benchmark, project_with_qt):
        """Benchmark loader_type property."""
        loader_type = benchmark(lambda: project_with_qt.loader_type)
        assert loader_type == "gui"


class TestBenchmarkProjectRawData:
    """Benchmark Project.raw_data serialization."""

    @pytest.fixture(scope="module")
    def large_project(self):
        """Large project for serialization benchmarking."""
        return Project._from_dict(
            {
                "name": "serialization_project",
                "version": "1.0.0",
                "description": "Project for serialization benchmarking",
                "readme": "README.md",
                "requires_python": ">=3.8",
                "dependencies": [f"dep_{i}" for i in range(500)],
                "optional_dependencies": {
                    "dev": [f"dev_{i}" for i in range(100)],
                },
                "scripts": {f"script_{i}": f"src.script{i}:main" for i in range(50)},
                "entry_points": {},
                "authors": [{"name": "Test"} for _ in range(50)],
                "license": "MIT",
                "keywords": [f"keyword_{i}" for i in range(100)],
                "classifiers": [f"Classifier :: {i}" for i in range(200)],
                "urls": {f"url_{i}": f"https://example{i}.com" for i in range(50)},
                "build_backend": "setuptools.build_meta",
                "requires": [f"req_{i}" for i in range(50)],
            }
        )

    @pytest.mark.benchmark
    def test_raw_data_property(self, benchmark, large_project):
        """Benchmark raw_data property serialization."""
        raw_data = benchmark(lambda: large_project.raw_data)
        assert raw_data["name"] == "serialization_project"
        assert len(raw_data["dependencies"]) == 500


class TestBenchmarkProjectFromToml:
    """Benchmark TOML file parsing."""

    @pytest.fixture(scope="module")
    def temp_toml_file(self, tmp_path_factory):
        """Create a temporary TOML file for benchmarking."""
        temp_dir = tmp_path_factory.mktemp("toml_benchmark")
        toml_file = temp_dir / "pyproject.toml"

        toml_content = """[project]
name = "benchmark_toml_project"
version = "1.0.0"
description = "Benchmark TOML parsing"
readme = "README.md"
requires-python = ">=3.8"
dependencies = [
    "requests>=2.0.0",
    "numpy>=1.20.0",
    "pandas>=1.3.0",
    "matplotlib>=3.3.0",
    "scipy>=1.7.0",
    "pytest>=7.0.0",
]
optional-dependencies.dev = ["pytest-cov>=3.0.0", "black>=22.0.0"]
scripts.main = "src.main:main"
scripts.cli = "src.cli:main"
scripts.gui = "src.gui:main"
authors = [{name = "Test Author", email = "test@example.com"}]
license = {text = "MIT"}
keywords = ["benchmark", "toml", "parsing"]
classifiers = ["Programming Language :: Python :: 3.8"]
urls.homepage = "https://example.com"

[build-system]
requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"]
build-backend = "setuptools.build_meta"
"""

        toml_file.write_text(toml_content, encoding="utf-8")
        return toml_file

    @pytest.mark.benchmark
    def test_project_from_toml_file(self, benchmark, temp_toml_file):
        """Benchmark parsing TOML file into Project."""
        project = benchmark(Project.from_toml_file, temp_toml_file)
        assert project.name == "benchmark_toml_project"
        assert len(project.dependencies) == 6


class TestBenchmarkSolutionCreation:
    """Benchmark Solution instance creation from various sources."""

    @pytest.fixture(scope="module")
    def multiple_toml_files(self, tmp_path_factory):
        """Create multiple TOML files for solution benchmarking."""
        temp_dir = tmp_path_factory.mktemp("solution_benchmark")
        toml_files = []

        for i in range(20):
            project_dir = temp_dir / f"project_{i}"
            project_dir.mkdir()
            toml_file = project_dir / "pyproject.toml"

            toml_content = f"""[project]
name = "project_{i}"
version = "{i}.0.0"
description = "Test project {i}"
readme = "README.md"
requires-python = ">=3.8"
dependencies = ["requests>=2.0.0", "numpy>=1.20.0"]
optional-dependencies.dev = ["pytest>=7.0.0"]
scripts.main = "src.main:main"
authors = [{{name = "Author {i}"}}]
license = "MIT"
keywords = ["test", "project"]
classifiers = ["Programming Language :: Python :: 3"]
urls.homepage = "https://example.com/{i}"

[build-system]
requires = ["setuptools>=45"]
build-backend = "setuptools.build_meta"
"""

            toml_file.write_text(toml_content, encoding="utf-8")
            toml_files.append(toml_file)

        return temp_dir, toml_files

    @pytest.fixture(scope="module")
    def json_data(self):
        """Create JSON data for solution benchmarking."""
        return {
            f"project_{i}": {
                "name": f"project_{i}",
                "version": f"{i}.0.0",
                "description": f"Test project {i}",
                "readme": "README.md",
                "requires_python": ">=3.8",
                "dependencies": [f"dep_{j}" for j in range(10)],
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": ["test"],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
            for i in range(50)
        }

    @pytest.mark.benchmark
    def test_solution_from_toml_files(self, benchmark, multiple_toml_files):
        """Benchmark creating Solution from multiple TOML files."""
        root_dir, toml_files = multiple_toml_files
        solution = benchmark(Solution.from_toml_files, root_dir, toml_files)
        assert len(solution.projects) == 20

    @pytest.mark.benchmark
    def test_solution_from_json_data(self, benchmark, json_data, tmp_path_factory):
        """Benchmark creating Solution from JSON data."""
        root_dir = tmp_path_factory.mktemp("json_benchmark")
        solution = benchmark(Solution.from_json_data, root_dir, json_data)
        assert len(solution.projects) == 50


class TestBenchmarkSolutionFromJsonFile:
    """Benchmark loading Solution from JSON cache file."""

    @pytest.fixture(scope="module")
    def json_file(self, tmp_path_factory):
        """Create a JSON cache file for benchmarking."""
        temp_dir = tmp_path_factory.mktemp("json_file_benchmark")
        json_file = temp_dir / "projects.json"

        json_data = {
            f"project_{i}": {
                "name": f"project_{i}",
                "version": f"{i}.0.0",
                "description": f"Cached project {i}",
                "readme": "README.md",
                "requires_python": ">=3.8",
                "dependencies": [f"cached_dep_{j}" for j in range(20)],
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": ["cached", "benchmark"],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
            for i in range(100)
        }

        with json_file.open("w", encoding="utf-8") as f:
            json.dump(json_data, f)

        return json_file

    @pytest.mark.benchmark
    def test_solution_from_json_file(self, benchmark, json_file):
        """Benchmark loading Solution from JSON cache file."""
        solution = benchmark(Solution.from_json_file, json_file)
        assert len(solution.projects) == 100


class TestBenchmarkSolutionFromDirectory:
    """Benchmark directory scanning and parsing."""

    @pytest.fixture(scope="module")
    def nested_projects_dir(self, tmp_path_factory):
        """Create nested directory structure with multiple projects."""
        temp_dir = tmp_path_factory.mktemp("directory_benchmark")

        for i in range(10):
            # Create nested structure
            project_dir = temp_dir / "workspace" / f"repo_{i}" / "project"
            project_dir.mkdir(parents=True)

            toml_content = f"""[project]
name = "nested_project_{i}"
version = "1.0.{i}"
description = "Nested project {i}"
readme = "README.md"
requires-python = ">=3.8"
dependencies = ["requests>=2.0.0", "numpy>=1.20.0", "pandas>=1.3.0", "scipy>=1.7.0", "matplotlib>=3.3.0"]
optional-dependencies.dev = ["pytest>=7.0.0"]
scripts.cli = "src.cli:main"
authors = [{{name = "Author {i}"}}]
license = "MIT"
keywords = ["nested", "benchmark"]
classifiers = ["Programming Language :: Python :: 3"]
urls.homepage = "https://example.com/{i}"

[build-system]
requires = ["setuptools>=45"]
build-backend = "setuptools.build_meta"
"""

            (project_dir / "pyproject.toml").write_text(toml_content, encoding="utf-8")

        return temp_dir

    @pytest.mark.benchmark
    def test_solution_from_directory_scan(self, benchmark, nested_projects_dir):
        """Benchmark Solution creation from directory scan."""
        solution = benchmark(Solution.from_directory, nested_projects_dir)
        assert len(solution.projects) == 10


class TestBenchmarkSolutionWriteJson:
    """Benchmark writing Solution data to JSON cache."""

    @pytest.fixture(scope="module")
    def large_solution(self, tmp_path_factory):
        """Create a large Solution for write benchmarking."""
        temp_dir = tmp_path_factory.mktemp("write_benchmark")

        projects = {
            f"project_{i}": Project._from_dict(
                {
                    "name": f"project_{i}",
                    "version": f"{i}.0.0",
                    "description": f"Large project {i}",
                    "readme": "README.md",
                    "requires_python": ">=3.8",
                    "dependencies": [f"dep_{j}" for j in range(50)],
                    "optional_dependencies": {
                        "dev": [f"dev_{j}" for j in range(20)],
                    },
                    "scripts": {f"script_{j}": f"src.script{j}:main" for j in range(10)},
                    "entry_points": {},
                    "authors": [{"name": f"Author {i}"}],
                    "license": "MIT",
                    "keywords": [f"keyword_{j}" for j in range(30)],
                    "classifiers": [f"Classifier :: {j}" for j in range(50)],
                    "urls": {f"url_{j}": f"https://example{j}.com" for j in range(10)},
                    "build_backend": "setuptools.build_meta",
                    "requires": [f"req_{j}" for j in range(10)],
                }
            )
            for i in range(100)
        }

        return temp_dir, projects

    @pytest.mark.benchmark
    def test_solution_write_project_json(self, benchmark, large_solution, tmp_path):
        """Benchmark writing Solution data to JSON cache file."""
        _temp_dir, projects = large_solution
        test_dir = tmp_path / "test_write"
        test_dir.mkdir()

        # Delete existing cache if any
        cache_file = test_dir / "projects.json"
        if cache_file.exists():
            cache_file.unlink()

        def write_and_return():
            return Solution(root_dir=test_dir, projects=projects)

        solution = benchmark(write_and_return)
        assert cache_file.exists()
        assert len(solution.projects) == 100


class TestBenchmarkDependencyNameExtraction:
    """Benchmark dependency name extraction with various formats."""

    @pytest.fixture(scope="module")
    def complex_dependencies(self):
        """Complex dependency specifications for benchmarking."""
        return Project._from_dict(
            {
                "name": "complex_deps",
                "version": "1.0.0",
                "description": "",
                "readme": "",
                "requires_python": ">=3.8",
                "dependencies": [
                    # Simple version specifiers
                    "package1>=1.0.0",
                    "package2>=2.0.0,<3.0.0",
                    "package3~=1.5.0",
                    "package4==1.2.3",
                    "package5!=1.5.0",
                    # Extras
                    "package6[extra1]>=1.0.0",
                    "package7[extra1,extra2,extra3]>=2.0.0",
                    "package8[dev,test]>=1.0.0",
                    # Environment markers
                    "package9>=1.0.0; python_version<'3.10'",
                    "package10>=1.0.0; python_version>='3.8' and sys_platform=='win32'",
                    "package11>=1.0.0; python_version>='3.8' and sys_platform!='linux'",
                    "package12>=1.0.0; python_version>='3.8' and (sys_platform=='win32' or sys_platform=='darwin')",
                    # Combined
                    "package13[extra1,extra2]>=1.0.0,<2.0.0; python_version>='3.8'",
                    "package14~=1.0.0; python_version<'3.11'",
                    "package15[dev]>=2.0.0; python_version>='3.9' and sys_platform=='linux'",
                ]
                * 50,  # Repeat to create larger list
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": [],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
        )

    @pytest.mark.benchmark
    def test_dep_names_extraction_complex(self, benchmark, complex_dependencies):
        """Benchmark dependency name extraction with complex specs."""
        dep_names = benchmark(lambda: complex_dependencies.dep_names)
        assert len(dep_names) > 0


class TestBenchmarkQtDetection:
    """Benchmark Qt dependency detection."""

    @pytest.fixture(scope="module")
    def mixed_qt_project(self):
        """Project with mixed Qt and non-Qt dependencies."""
        return Project._from_dict(
            {
                "name": "mixed_qt_project",
                "version": "1.0.0",
                "description": "",
                "readme": "",
                "requires_python": ">=3.8",
                "dependencies": [
                    "requests>=2.0.0",
                    "PySide2>=5.15.0",
                    "numpy>=1.20.0",
                    "PyQt6>=6.0.0",
                    "pandas>=1.3.0",
                    "Qt>=5.15.0",
                    "matplotlib>=3.3.0",
                    "scipy>=1.7.0",
                ]
                * 50,
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": ["gui", "desktop", "qt", "benchmark"],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
        )

    @pytest.mark.benchmark
    def test_qt_detection_mixed(self, benchmark, mixed_qt_project):
        """Benchmark Qt dependency detection in mixed project."""
        qt_deps = benchmark(lambda: mixed_qt_project.qt_deps)
        assert len(qt_deps) > 0

    @pytest.mark.benchmark
    def test_has_qt_detection(self, benchmark, mixed_qt_project):
        """Benchmark has_qt property."""
        has_qt = benchmark(lambda: mixed_qt_project.has_qt)
        assert has_qt is True


class TestBenchmarkGuIDetection:
    """Benchmark GUI keyword detection."""

    @pytest.fixture(scope="module")
    def gui_project_large_keywords(self):
        """Project with large number of keywords."""
        return Project._from_dict(
            {
                "name": "gui_keywords_project",
                "version": "1.0.0",
                "description": "",
                "readme": "",
                "requires_python": ">=3.8",
                "dependencies": ["requests>=2.0.0"],
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": ["gui", "desktop"] + [f"keyword_{i}" for i in range(500)],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
        )

    @pytest.mark.benchmark
    def test_gui_detection_large_keywords(self, benchmark, gui_project_large_keywords):
        """Benchmark GUI detection with large keyword list."""
        is_gui = benchmark(lambda: gui_project_large_keywords.is_gui)
        assert is_gui is True


class TestBenchmarkProjectRepr:
    """Benchmark Project __repr__ method."""

    @pytest.fixture(scope="module")
    def repr_project(self):
        """Project for repr benchmarking."""
        return Project._from_dict(
            {
                "name": "repr_benchmark_project",
                "version": "1.0.0",
                "description": "Project for repr benchmarking",
                "readme": "README.md",
                "requires_python": ">=3.8",
                "dependencies": [f"dep_{i}" for i in range(100)],
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": [],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
        )

    @pytest.mark.benchmark
    def test_project_repr(self, benchmark, repr_project):
        """Benchmark Project __repr__ method."""
        result = benchmark(lambda: repr(repr_project))
        assert "repr_benchmark_project" in result


class TestBenchmarkSolutionRepr:
    """Benchmark Solution __repr__ method."""

    @pytest.fixture(scope="module")
    def repr_solution(self, tmp_path_factory):
        """Solution for repr benchmarking."""
        temp_dir = tmp_path_factory.mktemp("solution_repr_benchmark")

        projects = {
            f"project_{i}": Project._from_dict(
                {
                    "name": f"project_{i}",
                    "version": f"{i}.0.0",
                    "description": "",
                    "readme": "",
                    "requires_python": ">=3.8",
                    "dependencies": [f"dep_{j}" for j in range(10)],
                    "optional_dependencies": {},
                    "scripts": {},
                    "entry_points": {},
                    "authors": [],
                    "license": "",
                    "keywords": [],
                    "classifiers": [],
                    "urls": {},
                    "build_backend": "",
                    "requires": [],
                }
            )
            for i in range(50)
        }

        return temp_dir, projects

    @pytest.mark.benchmark
    def test_solution_repr(self, benchmark, repr_solution, tmp_path):
        """Benchmark Solution __repr__ method."""
        _temp_dir, projects = repr_solution
        test_dir = tmp_path / "test_repr"
        test_dir.mkdir()

        # Create solution and get repr
        solution = Solution(root_dir=test_dir, projects=projects)
        result = benchmark(lambda: repr(solution))
        assert "projects:" in result
        assert "50" in result


class TestBenchmarkCachedProperties:
    """Benchmark cached_property behavior and performance."""

    @pytest.fixture(scope="module")
    def cached_project(self):
        """Project for testing cached properties."""
        return Project._from_dict(
            {
                "name": "cached_project",
                "version": "1.0.0",
                "description": "",
                "readme": "",
                "requires_python": ">=3.8",
                "dependencies": [f"dep_{i}" for i in range(200)],
                "optional_dependencies": {},
                "scripts": {},
                "entry_points": {},
                "authors": [],
                "license": "",
                "keywords": ["gui", "desktop"] + [f"keyword_{i}" for i in range(100)],
                "classifiers": [],
                "urls": {},
                "build_backend": "",
                "requires": [],
            }
        )

    @pytest.mark.benchmark
    def test_cached_property_first_access(self, benchmark, cached_project):
        """Benchmark first access to cached properties."""
        # First access calculates the value
        result = benchmark(lambda: cached_project.dep_names)
        assert len(result) == 200

    @pytest.mark.benchmark
    def test_cached_property_subsequent_access(self, benchmark, cached_project):
        """Benchmark subsequent access to cached properties (should be faster)."""
        # Access once to populate cache
        _ = cached_project.dep_names
        # Now benchmark the cached access
        result = benchmark(lambda: cached_project.dep_names)
        assert len(result) == 200


class TestBenchmarkLargeScaleOperations:
    """Benchmark large-scale operations simulating real-world usage."""

    @pytest.fixture(scope="module")
    def large_scale_solution(self, tmp_path_factory):
        """Create a large-scale Solution for end-to-end benchmarking."""
        temp_dir = tmp_path_factory.mktemp("large_scale_benchmark")

        # Create 200 projects
        projects = {}
        for i in range(200):
            projects[f"project_{i}"] = Project._from_dict(
                {
                    "name": f"project_{i}",
                    "version": f"{i}.0.0",
                    "description": f"Large scale project {i}",
                    "readme": "README.md",
                    "requires_python": ">=3.8",
                    "dependencies": [f"core_dep_{j}" for j in range(20)]
                    + (["PySide2"] if i % 5 == 0 else []),  # Some projects have Qt
                    "optional_dependencies": {
                        "dev": [f"dev_{j}" for j in range(10)],
                    },
                    "scripts": {f"script_{j}": f"src.script{j}:main" for j in range(5)},
                    "entry_points": {},
                    "authors": [{"name": f"Author {i}"}],
                    "license": "MIT",
                    "keywords": ["test", "project", f"keyword_{i}"],
                    "classifiers": [f"Classifier :: {j}" for j in range(30)],
                    "urls": {f"url_{j}": f"https://example{j}.com" for j in range(10)},
                    "build_backend": "setuptools.build_meta",
                    "requires": [f"req_{j}" for j in range(5)],
                }
            )

        return temp_dir, projects

    @pytest.mark.benchmark
    def test_large_scale_solution_creation(self, benchmark, large_scale_solution, tmp_path):
        """Benchmark creating a large-scale Solution."""
        _temp_dir, projects = large_scale_solution
        test_dir = tmp_path / "large_scale"
        test_dir.mkdir()

        def create_solution():
            return Solution(root_dir=test_dir, projects=projects)

        solution = benchmark(create_solution)
        assert len(solution.projects) == 200

    @pytest.mark.benchmark
    def test_large_scale_property_access(self, benchmark, large_scale_solution, tmp_path):
        """Benchmark accessing properties of all projects in large-scale Solution."""
        _temp_dir, projects = large_scale_solution
        test_dir = tmp_path / "large_scale_props"
        test_dir.mkdir()

        solution = Solution(root_dir=test_dir, projects=projects)

        def access_all_properties():
            return [(p.normalized_name, len(p.dep_names), p.loader_type) for p in solution.projects.values()]

        results = benchmark(access_all_properties)
        assert len(results) == 200
