"""Pytest fixtures for Ghostty Settings TUI tests."""

import os
import tempfile
from pathlib import Path
from typing import Generator

import pytest

from ghostty_tui.models import ConfigValue, OptionDefinition, OptionModel, OptionType
from ghostty_tui.parser import GhosttyParser


@pytest.fixture
def sample_schema_path() -> Path:
    """Path to sample schema file."""
    return Path(__file__).parent.parent / "sample_data" / "ghostty_schema_sample.txt"


@pytest.fixture
def sample_schema(sample_schema_path: Path) -> str:
    """Raw content of sample schema file."""
    return sample_schema_path.read_text()


@pytest.fixture
def parser() -> GhosttyParser:
    """Create a GhosttyParser instance."""
    return GhosttyParser()


@pytest.fixture
def parsed_options(parser: GhosttyParser, sample_schema_path: Path) -> list[OptionDefinition]:
    """Parsed option definitions from sample schema."""
    return parser.parse_from_file(sample_schema_path)


@pytest.fixture
def options_dict(parsed_options: list[OptionDefinition]) -> dict[str, OptionDefinition]:
    """Parsed options as dictionary."""
    return {opt.name: opt for opt in parsed_options}


@pytest.fixture
def tmp_config_file() -> Generator[Path, None, None]:
    """Create a temporary config file for testing."""
    with tempfile.NamedTemporaryFile(
        mode="w",
        suffix=".config",
        delete=False
    ) as f:
        f.write("# Test configuration\n")
        f.write("font-size = 14\n")
        f.write("cursor-style = bar\n")
        f.write("# Commented option\n")
        f.write("# background = #ffffff\n")
        f.write("\n")
        f.write("window-title = Test Terminal\n")
        config_path = Path(f.name)

    yield config_path

    # Cleanup
    config_path.unlink(missing_ok=True)
    backup_path = config_path.with_suffix(".config.bak")
    backup_path.unlink(missing_ok=True)


@pytest.fixture
def tmp_config_dir() -> Generator[Path, None, None]:
    """Create a temporary config directory."""
    with tempfile.TemporaryDirectory() as tmpdir:
        yield Path(tmpdir)


@pytest.fixture
def option_factory():
    """Factory for creating OptionDefinition instances."""
    def _create(
        name: str = "test-option",
        option_type: OptionType = OptionType.STRING,
        default_value: str | None = None,
        description: str = "Test description",
        category: str = "Other",
        enum_values: tuple[str, ...] = ()
    ) -> OptionDefinition:
        return OptionDefinition(
            name=name,
            option_type=option_type,
            default_value=default_value,
            description=description,
            category=category,
            enum_values=enum_values
        )
    return _create


@pytest.fixture
def config_value_factory():
    """Factory for creating ConfigValue instances."""
    def _create(
        name: str = "test-option",
        value: str | None = None,
        line_number: int | None = None,
        is_modified: bool = False
    ) -> ConfigValue:
        return ConfigValue(
            name=name,
            value=value,
            line_number=line_number,
            is_modified=is_modified
        )
    return _create


@pytest.fixture
def option_model_factory(option_factory, config_value_factory):
    """Factory for creating OptionModel instances."""
    def _create(
        name: str = "test-option",
        option_type: OptionType = OptionType.STRING,
        default_value: str | None = None,
        current_value: str | None = None,
        is_modified: bool = False
    ) -> OptionModel:
        definition = option_factory(
            name=name,
            option_type=option_type,
            default_value=default_value
        )
        current = config_value_factory(
            name=name,
            value=current_value,
            is_modified=is_modified
        )
        return OptionModel(definition=definition, current=current)
    return _create


@pytest.fixture
def mock_ghostty_output() -> str:
    """Sample Ghostty CLI output for testing."""
    return """# The font size in points.
font-size = 12

# The cursor style.
# Valid values: block, bar, underline
cursor-style = block

# Enable cursor blinking.
cursor-blink = false

# The window title.
window-title = Ghostty
"""


@pytest.fixture
def sample_options_dict(option_factory) -> dict[str, OptionModel]:
    """Sample options dictionary for testing."""
    options = {}

    # Boolean option
    opt1 = option_factory(
        name="cursor-blink",
        option_type=OptionType.BOOLEAN,
        default_value="false",
        category="Cursor"
    )
    options["cursor-blink"] = OptionModel(
        definition=opt1,
        current=ConfigValue(name="cursor-blink", value="false")
    )

    # Integer option
    opt2 = option_factory(
        name="font-size",
        option_type=OptionType.INTEGER,
        default_value="12",
        category="Font"
    )
    options["font-size"] = OptionModel(
        definition=opt2,
        current=ConfigValue(name="font-size", value="14", is_modified=True)
    )

    # Enum option
    opt3 = option_factory(
        name="cursor-style",
        option_type=OptionType.ENUM,
        default_value="block",
        category="Cursor",
        enum_values=("block", "bar", "underline")
    )
    options["cursor-style"] = OptionModel(
        definition=opt3,
        current=ConfigValue(name="cursor-style", value="bar")
    )

    # String option
    opt4 = option_factory(
        name="window-title",
        option_type=OptionType.STRING,
        default_value="Ghostty",
        category="Window"
    )
    options["window-title"] = OptionModel(
        definition=opt4,
        current=ConfigValue(name="window-title")
    )

    return options
