"""Textual Screen subclasses for porTUI."""

from __future__ import annotations

import psutil
from textual.app import ComposeResult
from textual.containers import Horizontal, Vertical
from textual.events import Key
from textual.screen import Screen
from textual.widgets import Button, Checkbox, Label, MarkdownViewer

from portui.models import PortInfo


class EscapeDismissScreen(Screen):
    """Base screen that dismisses on Escape (and optionally q/?)."""

    #: Keys that trigger dismiss.  Override in subclasses if needed.
    _DISMISS_KEYS: tuple[str, ...] = ("escape",)

    def on_key(self, event: Key) -> None:
        """Dismiss the screen when a dismiss key is pressed."""
        if event.key in self._DISMISS_KEYS:
            self.dismiss(None)


class ColumnConfigScreen(EscapeDismissScreen):
    """Screen for configuring visible columns."""

    def __init__(
        self, col_visible: tuple[bool, ...] | list[bool], names: list[str]
    ) -> None:
        super().__init__()
        self.col_visible = list(col_visible)
        self.names = names

    def compose(self) -> ComposeResult:
        """Compose the screen."""
        with Vertical(id="dialog"):
            yield Label("Toggle Columns (space to toggle, enter to apply):")
            for name, vis in zip(self.names, self.col_visible):
                checkbox = Checkbox(name, value=vis)
                checkbox.id = f"col-{name}"
                yield checkbox
            with Horizontal():
                yield Button("Apply", id="apply", variant="primary")
                yield Button("Cancel", id="cancel")

    def on_button_pressed(self, event: Button.Pressed) -> None:
        """Handle button presses."""
        if event.button.id == "apply":
            for i, name in enumerate(self.names):
                checkbox = self.query_one(f"#col-{name}", Checkbox)
                self.col_visible[i] = checkbox.value
            self.dismiss(self.col_visible)
        else:
            self.dismiss(None)


class IntervalScreen(EscapeDismissScreen):
    """Screen for selecting refresh interval."""

    INTERVALS = [1, 2, 3, 5, 10, 30, 60]

    def __init__(self, current: int) -> None:
        super().__init__()
        self.current = current

    def compose(self) -> ComposeResult:
        """Compose the screen."""
        with Vertical(id="dialog"):
            yield Label("Select refresh interval (seconds):")
            for interval in self.INTERVALS:
                variant = "primary" if interval == self.current else "default"
                label = (
                    f"{interval}s (current)"
                    if interval == self.current
                    else f"{interval}s"
                )
                yield Button(label, id=f"int-{interval}", variant=variant)
            yield Button("Cancel", id="cancel")

    def on_button_pressed(self, event: Button.Pressed) -> None:
        """Handle button presses."""
        if event.button.id and event.button.id.startswith("int-"):
            interval = int(event.button.id.split("-")[1])
            self.dismiss(interval)
        else:
            self.dismiss(None)


class PortDetailScreen(EscapeDismissScreen):
    """Overlay screen showing full details of a port/process."""

    BINDINGS = [("escape", "dismiss", "Close")]

    def __init__(self, port: PortInfo) -> None:
        super().__init__()
        self.port = port

    def compose(self) -> ComposeResult:
        """Compose the screen."""
        full_cmdline = self.port.cmdline
        try:
            proc = psutil.Process(self.port.pid)
            parts = proc.cmdline()
            if parts:
                full_cmdline = " ".join(parts)
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            pass

        with Vertical(id="detail-container"):
            yield Label(f"Process Details: {self.port.process_name}", id="title")
            yield Label(f"PID:       {self.port.pid}")
            yield Label(f"PPID:      {self.port.ppid}")
            yield Label(f"Port:      {self.port.port}/{self.port.protocol}")
            yield Label(f"IP:        {self.port.ip}")
            yield Label(f"User:      {self.port.username}")
            yield Label(f"State:     {self.port.state}")
            yield Label(f"Command:   {full_cmdline}", id="detail-command")
            yield Label("")
            yield Label("Press Escape to close", id="detail-hint")


class KillDialogScreen(EscapeDismissScreen):
    """Screen for confirming process kill."""

    def __init__(self, port: PortInfo) -> None:
        super().__init__()
        self.port = port

    def compose(self) -> ComposeResult:
        """Compose the screen."""
        with Vertical(id="dialog"):
            yield Label(f"Kill Process: {self.port.process_name}", id="title")
            yield Label(f"PID: {self.port.pid}")
            yield Label(f"Port: {self.port.port}/{self.port.protocol}")
            yield Label(f"Command: {self.port.cmdline}")
            yield Label("")
            yield Label("Choose kill method:")
            with Horizontal():
                yield Button("Graceful (SIGTERM)", id="graceful", variant="primary")
                yield Button("Force (SIGKILL)", id="force", variant="error")
                yield Button("Cancel", id="cancel")

    def on_button_pressed(self, event: Button.Pressed) -> None:
        """Handle button presses."""
        if event.button.id == "graceful":
            self.dismiss((self.port, False))
        elif event.button.id == "force":
            self.dismiss((self.port, True))
        else:
            self.dismiss(None)


class HelpScreen(EscapeDismissScreen):
    """Help screen with keyboard shortcuts."""

    BINDINGS = [
        ("escape,q", "dismiss", "Close"),
        ("?", "dismiss", "Close"),
    ]

    _DISMISS_KEYS = ("escape", "q", "?")

    HELP_TEXT = """
# Keyboard Shortcuts

## Navigation
- ↑/↓ or j/k - Navigate table rows
- Enter - Select row

## Actions
- / - Focus filter input (Escape to clear and exit)
- c - Toggle column configuration
- i - Set refresh interval
- x - Kill selected process
- r - Manual refresh
- p - Pause/resume auto-refresh
- s - Cycle sort column
- t - Toggle tree view (group by process hierarchy)
- ? - Show this help
- q - Quit

## Kill Dialog
- Select a process with ↑/↓ or j/k, then press x
- Choose "Graceful" for SIGTERM (clean shutdown)
- Choose "Force" for SIGKILL (immediate termination)
- Press Escape or "Cancel" to abort

## Tree View
- Press 't' to toggle tree view in the main table
- Child processes are indented under their parents (htop-style)
- Works with filtering and sorting

## Tips
- Auto-refresh pauses while you're typing in the filter
- The status bar shows current refresh state and port count
- Use column config to hide/show columns you don't need
- Click column headers to sort
"""

    def compose(self) -> ComposeResult:
        """Compose the screen."""
        with Vertical(id="help-container"):
            yield MarkdownViewer(self.HELP_TEXT, show_table_of_contents=False)
            yield Button("Close (Esc)", id="close", variant="primary")

    def on_button_pressed(self, event: Button.Pressed) -> None:
        """Handle button press."""
        if event.button.id == "close":
            self.dismiss()
