"""Main application screen for Ghostty Settings TUI."""

from textual.app import ComposeResult
from textual.containers import Horizontal
from textual.screen import Screen
from textual.widgets import Footer, Header

from ..widgets.sidebar import CategorySidebar, CategorySelected
from ..widgets.option_panel import OptionPanel
from ..widgets.option_row import OptionChanged
from ..models import OptionModel
from ..categories import get_category_icon


def filter_by_category(
    category: str,
    options: dict[str, OptionModel]
) -> list[OptionModel]:
    """Filter options by category.

    Args:
        category: Category name to filter by
        options: Dictionary of option name to OptionModel

    Returns:
        List of OptionModels in the category, sorted by name
    """
    filtered = [
        model for model in options.values()
        if model.definition.category == category
    ]
    filtered.sort(key=lambda m: m.definition.name)
    return filtered


class MainScreen(Screen):
    """Primary application screen with sidebar and option panel."""

    DEFAULT_CSS = """
    MainScreen {
        layout: horizontal;
    }

    MainScreen > Horizontal {
        height: 100%;
    }
    """

    def __init__(
        self,
        options: dict[str, OptionModel],
        categories: list[str],
        **kwargs
    ) -> None:
        """Initialize main screen.

        Args:
            options: Dictionary of option name to OptionModel
            categories: List of category names in display order
        """
        super().__init__(**kwargs)
        self._options = options
        self._categories = categories
        self._current_category = categories[0] if categories else ""
        self._modified_options: set[str] = set()

    def compose(self) -> ComposeResult:
        """Compose the screen layout."""
        yield Header()

        with Horizontal():
            # Build category data
            category_data = [
                (cat, f"{get_category_icon(cat)} {cat}", self._count_category(cat))
                for cat in self._categories
            ]

            yield CategorySidebar(categories=category_data, id="sidebar")
            yield OptionPanel(id="option-panel")

        yield Footer()

    def _count_category(self, category: str) -> int:
        """Count options in a category."""
        return sum(
            1 for opt in self._options.values()
            if opt.definition.category == category
        )

    def on_mount(self) -> None:
        """Initialize display on mount."""
        if self._current_category:
            self._show_category(self._current_category)

    def _show_category(self, category: str) -> None:
        """Show options for a category."""
        self._current_category = category
        options = filter_by_category(category, self._options)
        panel = self.query_one("#option-panel", OptionPanel)
        panel.show_category(category, options)

    def on_category_selected(self, event: CategorySelected) -> None:
        """Handle category selection."""
        self._show_category(event.category)

    def on_option_changed(self, event: OptionChanged) -> None:
        """Handle option value change."""
        self._modified_options.add(event.option_name)

        # Update the option model
        if event.option_name in self._options:
            self._options[event.option_name].current.value = event.new_value
            self._options[event.option_name].current.is_modified = True

    def get_modified_options(self) -> dict[str, str | None]:
        """Get all modified option values."""
        panel = self.query_one("#option-panel", OptionPanel)
        return panel.get_modified_values()

    @property
    def has_unsaved_changes(self) -> bool:
        """Check if there are unsaved changes."""
        return len(self._modified_options) > 0
