"""Hooks Manager Dialog for viewing and installing hooks."""

from __future__ import annotations

from pathlib import Path
from typing import Any, Dict, List, Optional

from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Container, Horizontal, VerticalScroll
from textual.screen import ModalScreen
from textual.widgets import Button, Label, ListItem, ListView, Static

from ...core.hooks import (
    HookDefinition,
    InstalledHook,
    HOOK_EVENTS,
    get_available_hooks,
    get_installed_hooks,
    install_hook,
    uninstall_hook,
    validate_hooks_config_file,
)


class HooksManagerDialog(ModalScreen[Optional[str]]):
    """Dialog for managing Claude Code hooks."""

    CSS = """
    HooksManagerDialog {
        align: center middle;
    }

    HooksManagerDialog #dialog {
        width: 90%;
        max-width: 100;
        height: 85%;
        background: $surface-lighten-1;
        border: thick $accent;
        padding: 1 2;
        opacity: 1;
    }

    HooksManagerDialog #dialog-title {
        text-align: center;
        color: $accent;
        text-style: bold;
        margin-bottom: 1;
    }

    HooksManagerDialog #hooks-container {
        height: 1fr;
    }

    HooksManagerDialog #available-hooks {
        width: 1fr;
        height: 1fr;
        border: solid $primary-darken-2;
        background: $surface;
        padding: 1;
    }

    HooksManagerDialog #installed-hooks {
        width: 1fr;
        height: 1fr;
        border: solid $success-darken-2;
        background: $surface;
        padding: 1;
    }

    HooksManagerDialog .section-title {
        text-style: bold;
        color: $primary;
        margin-bottom: 1;
    }

    HooksManagerDialog #available-list {
        height: 1fr;
        min-height: 10;
    }

    HooksManagerDialog #installed-list {
        height: 1fr;
        min-height: 10;
    }

    HooksManagerDialog #hook-details {
        height: auto;
        max-height: 8;
        border: solid $primary-darken-3;
        background: $surface-darken-1;
        padding: 1;
        margin-top: 1;
    }

    HooksManagerDialog #dialog-buttons {
        align: center middle;
        height: auto;
        margin-top: 1;
    }

    HooksManagerDialog #dialog-buttons Button {
        margin: 0 1;
    }

    HooksManagerDialog #dialog-hint {
        text-align: center;
        color: $text-muted;
        margin-top: 1;
    }
    """

    BINDINGS = [
        Binding("escape", "close", "Close"),
        Binding("i", "install", "Install"),
        Binding("u", "uninstall", "Uninstall"),
        Binding("r", "refresh", "Refresh"),
    ]

    def __init__(self, plugin_dir: Optional[Path] = None) -> None:
        """Initialize the hooks manager.

        Args:
            plugin_dir: Plugin directory for finding available hooks
        """
        super().__init__()
        self.plugin_dir = plugin_dir
        self.available_hooks: List[HookDefinition] = []
        self.installed_hooks: List[InstalledHook] = []
        self.selected_hook: Optional[HookDefinition] = None
        self._id_counter = 0

    def compose(self) -> ComposeResult:
        with Container(id="dialog"):
            yield Static("Hooks Manager", id="dialog-title")

            with Horizontal(id="hooks-container"):
                with Container(id="available-hooks"):
                    yield Static("[bold]Available Hooks[/bold]", classes="section-title")
                    yield ListView(id="available-list")

                with Container(id="installed-hooks"):
                    yield Static("[bold]Installed Hooks[/bold]", classes="section-title")
                    yield ListView(id="installed-list")

            yield Static("", id="hook-details")

            yield Static(
                "[dim]i Install • u Uninstall • r Refresh • Esc Close[/dim]",
                id="dialog-hint",
            )

            with Horizontal(id="dialog-buttons"):
                yield Button("Install", variant="success", id="install")
                yield Button("Uninstall", variant="warning", id="uninstall")
                yield Button("Close", variant="default", id="close")

    async def on_mount(self) -> None:
        """Load hooks when mounted."""
        await self._load_hooks()

    async def _load_hooks(self) -> None:
        """Load available and installed hooks."""
        try:
            self.available_hooks = get_available_hooks(self.plugin_dir)
        except Exception as e:
            self.available_hooks = []
            self.notify(f"Failed to load available hooks: {e}", severity="error", timeout=3)
        try:
            self.installed_hooks = get_installed_hooks()
        except Exception as e:
            self.installed_hooks = []
            self.notify(f"Failed to load installed hooks: {e}", severity="error", timeout=3)
        self._validate_plugin_hooks_config()
        await self._update_lists()

    def _validate_plugin_hooks_config(self) -> None:
        """Validate plugin hooks.json for mutual exclusivity issues."""
        if not self.plugin_dir:
            return
        config_path = self.plugin_dir / "hooks" / "hooks.json"
        if not config_path.is_file():
            return
        is_valid, errors = validate_hooks_config_file(config_path)
        if is_valid:
            return
        message = "Hooks config issues: " + "; ".join(errors)
        self.notify(message, severity="warning", timeout=4)

    async def _update_lists(self) -> None:
        """Update the hook lists."""
        # Increment counter for unique IDs
        self._id_counter += 1
        c = self._id_counter

        # Update available hooks list
        try:
            available_list = self.query_one("#available-list", ListView)
            await available_list.clear()

            if not self.available_hooks:
                available_list.append(ListItem(Static("[dim]No hooks found[/dim]")))
            else:
                for idx, hook in enumerate(self.available_hooks):
                    status = "[green]✓[/green] " if hook.is_installed else "[dim]○[/dim] "
                    label_text = f"{status}{hook.name} [dim]({hook.event})[/dim]"
                    available_list.append(ListItem(Static(label_text), id=f"avail-{c}-{idx}"))
        except Exception as e:
            self.notify(f"Failed to update available list: {e}", severity="error", timeout=3)

        # Update installed hooks list
        try:
            installed_list = self.query_one("#installed-list", ListView)
            await installed_list.clear()

            if not self.installed_hooks:
                installed_list.append(ListItem(Static("[dim]No hooks installed[/dim]")))
            else:
                for idx, inst_hook in enumerate(self.installed_hooks):
                    # Extract hook name from command
                    cmd = inst_hook.command
                    name = cmd.split("/")[-1].replace(".py", "").replace(".sh", "") if "/" in cmd else cmd
                    label_text = f"[green]●[/green] {name} [dim]({inst_hook.event})[/dim]"
                    installed_list.append(ListItem(Static(label_text), id=f"inst-{c}-{idx}"))
        except Exception as e:
            self.notify(f"Failed to update installed list: {e}", severity="error", timeout=3)

    def _sanitize_id(self, name: str) -> str:
        """Sanitize a name for use as a widget ID."""
        return name.replace(".", "-").replace("_", "-").replace(" ", "-").lower()

    def on_list_view_selected(self, event: ListView.Selected) -> None:
        """Handle list selection."""
        item_id = event.item.id or ""

        if item_id.startswith("avail-"):
            # ID format: avail-{counter}-{index}
            parts = item_id.split("-")
            if len(parts) >= 3:
                try:
                    idx = int(parts[-1])
                    if 0 <= idx < len(self.available_hooks):
                        hook = self.available_hooks[idx]
                        self.selected_hook = hook
                        self._show_hook_details(hook)
                except (ValueError, IndexError):
                    pass

    def _show_hook_details(self, hook: HookDefinition) -> None:
        """Show details for selected hook."""
        details = self.query_one("#hook-details", Static)

        status = "[green]Installed[/green]" if hook.is_installed else "[yellow]Not installed[/yellow]"
        text = f"""[bold]{hook.name}[/bold] · {status}
Event: [cyan]{hook.event}[/cyan]
{hook.description}
"""
        details.update(text)

    async def action_install(self) -> None:
        """Install the selected hook."""
        if not self.selected_hook:
            return

        if self.selected_hook.is_installed:
            self.notify("Hook already installed", severity="warning", timeout=2)
            return

        success, msg = install_hook(self.selected_hook)
        if success:
            self.notify(msg, severity="information", timeout=2)
            await self._load_hooks()
        else:
            self.notify(msg, severity="error", timeout=3)

    async def action_uninstall(self) -> None:
        """Uninstall the selected hook."""
        if not self.selected_hook:
            return

        if not self.selected_hook.is_installed:
            self.notify("Hook not installed", severity="warning", timeout=2)
            return

        success, msg = uninstall_hook(self.selected_hook)
        if success:
            self.notify(msg, severity="information", timeout=2)
            await self._load_hooks()
        else:
            self.notify(msg, severity="error", timeout=3)

    async def action_refresh(self) -> None:
        """Refresh the hooks lists."""
        await self._load_hooks()
        self.notify("Refreshed", severity="information", timeout=1)

    def action_close(self) -> None:
        """Close the dialog."""
        self.dismiss(None)

    async def on_button_pressed(self, event: Button.Pressed) -> None:
        """Handle button presses."""
        if event.button.id == "install":
            await self.action_install()
        elif event.button.id == "uninstall":
            await self.action_uninstall()
        elif event.button.id == "close":
            self.action_close()
