"""
Pytest Configuration Generator.

Generates pytest.ini configuration files for Python projects with marker
definitions based on the universal test taxonomy defined in config/test_taxonomy.py.

This solves **missing pytest marker definitions** which causes:
- pytest warnings about unknown markers
- No IDE autocomplete for test markers
- Unclear marker semantics (what does @pytest.mark.unit mean?)
- Inconsistent marker usage across tests

The generator creates pytest.ini with:
1. Standard test discovery settings (testpaths, python_files, etc.)
2. Marker definitions for all test levels (unit, integration, system, etc.)
3. Marker definitions for all test types (functional, security, performance, etc.)
4. Marker definitions for all modifiers (slow, requires-db, etc.)
5. Helpful descriptions for each marker (from taxonomy)

Usage:
    from cli.config_generators.pytest_generator import PytestConfigGenerator

    generator = PytestConfigGenerator()
    pytest_ini_content = generator.generate_pytest_ini(Path("/path/to/project"))

    # Write to file
    with open("pytest.ini", "w", encoding="utf-8") as f:
        f.write(pytest_ini_content)
"""

from pathlib import Path
from typing import Optional

from config.test_taxonomy import (
    TEST_TAXONOMY,
    get_test_levels,
    get_test_types,
    get_modifiers,
    get_test_level_description,
    get_test_type_description,
    get_modifier_description,
)


class PytestConfigGenerator:
    """
    Generate pytest.ini configuration files with test taxonomy markers.

    Responsibilities:
    - Generate pytest.ini with marker definitions from test taxonomy
    - Include standard pytest configuration (testpaths, python_files, etc.)
    - Provide helpful marker descriptions for IDE support
    - Support customization via project configuration (future)

    Example:
        >>> generator = PytestConfigGenerator()
        >>> content = generator.generate_pytest_ini(Path("/my/project"))
        >>> print(content)
        [pytest]
        testpaths = tests
        python_files = test_*.py
        ...
    """

    def __init__(self) -> None:
        """Initialize pytest configuration generator."""
        pass

    def generate_pytest_ini(
        self,
        project_path: Path,
        testpaths: Optional[str] = None,
        addopts: Optional[str] = None,
    ) -> str:
        """
        Generate pytest.ini configuration file content.

        Args:
            project_path: Path to the project directory (used for path resolution)
            testpaths: Custom test directory (default: "tests")
            addopts: Additional pytest options (default: "-v --strict-markers")

        Returns:
            String content of pytest.ini file ready to write

        Example:
            >>> generator = PytestConfigGenerator()
            >>> content = generator.generate_pytest_ini(Path("/my/project"))
            >>> assert "[pytest]" in content
            >>> assert "unit:" in content
        """
        # Use defaults if not provided
        testpaths = testpaths or "tests"
        addopts = addopts or "-v --strict-markers"

        # Build pytest.ini sections
        sections = []

        # Header comment
        sections.append(
            "# pytest.ini - Pytest configuration with test taxonomy markers"
        )
        sections.append(
            "# Generated by Trustable AI framework (trustable-ai init)"
        )
        sections.append(
            "# See: docs/architecture/decisions/ADR-004-test-marker-taxonomy.md"
        )
        sections.append("")

        # [pytest] section
        sections.append("[pytest]")
        sections.append("")

        # Test discovery settings
        sections.append("# Test Discovery")
        sections.append(f"testpaths = {testpaths}")
        sections.append("python_files = test_*.py")
        sections.append("python_classes = Test*")
        sections.append("python_functions = test_*")
        sections.append("")

        # Markers section
        sections.append("# Test Classification Markers")
        sections.append(
            "# Based on universal test taxonomy (config/test_taxonomy.py)"
        )
        sections.append("markers =")

        # Add test level markers
        sections.append("    # Test Levels (exactly one required)")
        for level in get_test_levels():
            description = get_test_level_description(level)
            sections.append(f"    {level}: {description}")

        sections.append("")

        # Add test type markers
        sections.append("    # Test Types (at least one required)")
        for test_type in get_test_types():
            description = get_test_type_description(test_type)
            sections.append(f"    {test_type}: {description}")

        sections.append("")

        # Add modifier markers
        sections.append("    # Modifiers (optional)")
        for modifier in get_modifiers():
            description = get_modifier_description(modifier)
            sections.append(f"    {modifier}: {description}")

        sections.append("")

        # Output settings
        sections.append("# Output Settings")
        sections.append("console_output_style = progress")
        sections.append(f"addopts = {addopts}")

        sections.append("")

        return "\n".join(sections)

    def write_to_file(self, content: str, output_path: Path) -> None:
        """
        Write pytest.ini content to file.

        Args:
            content: pytest.ini file content from generate_pytest_ini()
            output_path: Path to write pytest.ini file

        Raises:
            OSError: If file cannot be written
            ValueError: If content is empty

        Example:
            >>> generator = PytestConfigGenerator()
            >>> content = generator.generate_pytest_ini(Path("/my/project"))
            >>> generator.write_to_file(content, Path("/my/project/pytest.ini"))
        """
        if not content or not content.strip():
            raise ValueError("Cannot write empty pytest.ini content")

        # Create parent directory if needed
        output_path.parent.mkdir(parents=True, exist_ok=True)

        # Write file
        output_path.write_text(content, encoding="utf-8")

    def validate_pytest_ini(self, content: str) -> bool:
        """
        Validate pytest.ini content structure.

        Checks that generated content has:
        1. [pytest] section header
        2. At least one marker definition
        3. Test discovery settings (testpaths, python_files)

        Args:
            content: pytest.ini file content to validate

        Returns:
            True if valid, False otherwise

        Example:
            >>> generator = PytestConfigGenerator()
            >>> content = generator.generate_pytest_ini(Path("/my/project"))
            >>> assert generator.validate_pytest_ini(content)
        """
        if not content or not content.strip():
            return False

        # Check for [pytest] section
        if "[pytest]" not in content:
            return False

        # Check for markers section
        if "markers =" not in content:
            return False

        # Check for test discovery settings
        required_settings = ["testpaths =", "python_files =", "python_functions ="]
        for setting in required_settings:
            if setting not in content:
                return False

        return True
