"""Tools mode — enhanced capability tables with filtering and search.

Provides a focused view of tools, resources, and prompts from all
connected backend servers.  Includes a search bar for live filtering
and a detail panel for inspecting individual tool schemas.
"""

from __future__ import annotations

import logging
from typing import Any, Dict, List, Optional

from textual.app import ComposeResult
from textual.containers import Horizontal, Vertical
from textual.widgets import Input, Static

from argus_mcp.tui.screens.base import ArgusScreen
from argus_mcp.tui.widgets.capability_tables import CapabilitySection

logger = logging.getLogger(__name__)


class ToolsScreen(ArgusScreen):
    """Tools mode — capability tables with search, filtering, and detail view."""

    BINDINGS = [
        ("slash", "focus_search", "Search"),
        ("escape", "clear_search", "Clear"),
        ("c", "toggle_conflicts", "Conflicts Only"),
        ("f", "toggle_filtered", "Show Filtered"),
    ]

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self._cached_tools: List[Dict[str, Any]] = []
        self._cached_resources: List[Dict[str, Any]] = []
        self._cached_prompts: List[Dict[str, Any]] = []
        self._cached_route_map: Optional[Dict] = None
        self._conflicts_only: bool = False
        self._show_filtered: bool = False

    def compose_content(self) -> ComposeResult:
        with Vertical(id="tools-layout"):
            with Horizontal(id="tools-header-bar"):
                yield Static(
                    "[b]Tools Explorer[/b]  •  Browse, search, and inspect capabilities",
                    id="tools-header",
                )
                yield Input(
                    placeholder="Search tools, resources, prompts… (press /)",
                    id="tools-search",
                )
            yield Static("", id="tools-status-bar")
            yield CapabilitySection(id="tools-cap-section")
            yield Static("", id="tools-detail-panel")

    def on_show(self) -> None:
        """Re-populate capability tables from app-level cached data."""
        app = self.app
        caps = getattr(app, "_last_caps", None)
        if caps is not None:
            tools = [t.model_dump() for t in caps.tools]
            resources = [r.model_dump() for r in caps.resources]
            prompts = [p.model_dump() for p in caps.prompts]
            route_map = caps.route_map
            self._cached_tools = tools
            self._cached_resources = resources
            self._cached_prompts = prompts
            self._cached_route_map = route_map
            self._populate_tables()

    def _populate_tables(self, filtered_tools: Optional[List[Dict[str, Any]]] = None) -> None:
        """Populate capability tables and update conflict status bar."""
        tools = filtered_tools if filtered_tools is not None else self._cached_tools
        try:
            cap = self.query_one("#tools-cap-section", CapabilitySection)
            cap.populate(
                tools,
                self._cached_resources,
                self._cached_prompts,
                self._cached_route_map,
            )
        except Exception:
            logger.debug("Cannot populate tools cap section", exc_info=True)
        self._update_status_bar(tools)

    def _update_status_bar(self, tools: Optional[List[Dict[str, Any]]] = None) -> None:
        """Update the conflict/filter status bar."""
        all_tools = self._cached_tools
        displayed = tools or all_tools
        total = len(displayed)
        total_all = len(all_tools)
        conflicts = sum(1 for t in all_tools if t.get("renamed"))
        filtered_count = sum(1 for t in all_tools if t.get("filtered"))
        parts = [f"{total} tools"]
        if total != total_all:
            parts[0] += f" (of {total_all})"
        if conflicts:
            parts.append(f"[yellow]⚡ {conflicts} renamed[/yellow]")
        if filtered_count:
            if self._show_filtered:
                parts.append(f"[dim]{filtered_count} hidden shown[/dim]  [F] Hide")
            else:
                parts.append(f"[dim]{filtered_count} hidden[/dim]  [F] Show")
        if self._conflicts_only:
            parts.append("[bold yellow]conflicts only[/bold yellow]  [C] All")
        else:
            parts.append("[C] Conflicts only")
        try:
            self.query_one("#tools-status-bar", Static).update("  │  ".join(parts))
        except Exception:
            pass

    def on_input_changed(self, event: Input.Changed) -> None:
        """Live-filter capability tables based on search text."""
        if event.input.id != "tools-search":
            return
        query = event.value.strip().lower()
        if not query:
            # Reset to full data (respecting conflicts-only toggle)
            base = self._get_base_tools()
            self._populate_tables(base)
            return

        # Filter each category
        base_tools = self._get_base_tools()
        filtered_tools = [
            t
            for t in base_tools
            if query in (t.get("name", "") or "").lower()
            or query in (t.get("description", "") or "").lower()
            or query in (t.get("original_name", "") or "").lower()
        ]
        filtered_resources = [
            r
            for r in self._cached_resources
            if query in (r.get("name", "") or "").lower()
            or query in (r.get("uri", "") or "").lower()
            or query in (r.get("description", "") or "").lower()
        ]
        filtered_prompts = [
            p
            for p in self._cached_prompts
            if query in (p.get("name", "") or "").lower()
            or query in (p.get("description", "") or "").lower()
        ]
        try:
            cap = self.query_one("#tools-cap-section", CapabilitySection)
            cap.populate(
                filtered_tools, filtered_resources, filtered_prompts, self._cached_route_map
            )
        except Exception:
            pass
        self._update_status_bar(filtered_tools)

    def _get_base_tools(self) -> List[Dict[str, Any]]:
        """Return cached tools respecting conflict/filter toggles."""
        tools = self._cached_tools
        if not self._show_filtered:
            tools = [t for t in tools if not t.get("filtered")]
        if self._conflicts_only:
            tools = [t for t in tools if t.get("renamed")]
        return tools

    def action_focus_search(self) -> None:
        """Focus the search input."""
        try:
            self.query_one("#tools-search", Input).focus()
        except Exception:
            pass

    def action_clear_search(self) -> None:
        """Clear the search and reset filter."""
        try:
            search = self.query_one("#tools-search", Input)
            if search.value:
                search.value = ""
            else:
                # If already empty, let escape propagate
                pass
        except Exception:
            pass

    def action_toggle_conflicts(self) -> None:
        """Toggle showing only renamed/conflicting tools."""
        self._conflicts_only = not self._conflicts_only
        base = self._get_base_tools()
        self._populate_tables(base)

    def action_toggle_filtered(self) -> None:
        """Toggle visibility of filtered/hidden tools."""
        self._show_filtered = not self._show_filtered
        base = self._get_base_tools()
        self._populate_tables(base)
