from __future__ import annotations

from typing import ClassVar

from textual import events
from textual.app import ComposeResult
from textual.binding import Binding, BindingType
from textual.containers import Container, Vertical
from textual.message import Message
from textual.widgets import Input, Static

from vibe.cli.textual_ui.widgets.no_markup_static import NoMarkupStatic
from vibe.cli.textual_ui.widgets.vscode_compat import VscodeCompatInput
from vibe.core.proxy_setup import (
    SUPPORTED_PROXY_VARS,
    get_current_proxy_settings,
    set_proxy_var,
    unset_proxy_var,
)


class ProxySetupApp(Container):
    can_focus = True
    can_focus_children = True

    BINDINGS: ClassVar[list[BindingType]] = [
        Binding("up", "focus_previous", "Up", show=False),
        Binding("down", "focus_next", "Down", show=False),
    ]

    class ProxySetupClosed(Message):
        def __init__(self, saved: bool, error: str | None = None) -> None:
            super().__init__()
            self.saved = saved
            self.error = error

    def __init__(self) -> None:
        super().__init__(id="proxysetup-app")
        self.inputs: dict[str, Input] = {}
        self.initial_values: dict[str, str | None] = {}

    def compose(self) -> ComposeResult:
        self.initial_values = get_current_proxy_settings()

        with Vertical(id="proxysetup-content"):
            yield NoMarkupStatic("Proxy Configuration", classes="settings-title")

            for key, description in SUPPORTED_PROXY_VARS.items():
                yield Static(f"[bold $primary]{key}[/]", classes="proxy-label-line")

                initial_value = self.initial_values.get(key) or ""
                input_widget = VscodeCompatInput(
                    value=initial_value,
                    placeholder=description,
                    id=f"proxy-input-{key}",
                    classes="proxy-input",
                )
                self.inputs[key] = input_widget
                yield input_widget

            yield NoMarkupStatic(
                "↑↓ navigate  Enter save & exit  ESC cancel", classes="settings-help"
            )

    def focus(self, scroll_visible: bool = True) -> ProxySetupApp:
        """Override focus to focus the first input widget."""
        if self.inputs:
            first_input = list(self.inputs.values())[0]
            first_input.focus(scroll_visible=scroll_visible)
        else:
            super().focus(scroll_visible=scroll_visible)
        return self

    def action_focus_next(self) -> None:
        inputs = list(self.inputs.values())
        focused = self.screen.focused
        if focused is not None and isinstance(focused, Input) and focused in inputs:
            idx = inputs.index(focused)
            next_idx = (idx + 1) % len(inputs)
            inputs[next_idx].focus()

    def action_focus_previous(self) -> None:
        inputs = list(self.inputs.values())
        focused = self.screen.focused
        if focused is not None and isinstance(focused, Input) and focused in inputs:
            idx = inputs.index(focused)
            prev_idx = (idx - 1) % len(inputs)
            inputs[prev_idx].focus()

    def on_input_submitted(self, _event: Input.Submitted) -> None:
        self._save_and_close()

    def on_blur(self, _event: events.Blur) -> None:
        self.call_after_refresh(self._refocus_if_needed)

    def on_input_blurred(self, _event: Input.Blurred) -> None:
        self.call_after_refresh(self._refocus_if_needed)

    def _refocus_if_needed(self) -> None:
        if self.has_focus or any(inp.has_focus for inp in self.inputs.values()):
            return
        self.focus()

    def _save_and_close(self) -> None:
        try:
            for key, input_widget in self.inputs.items():
                new_value = input_widget.value.strip()
                old_value = self.initial_values.get(key) or ""

                if new_value != old_value:
                    if new_value:
                        set_proxy_var(key, new_value)
                    else:
                        unset_proxy_var(key)
        except Exception as e:
            self.post_message(self.ProxySetupClosed(saved=False, error=str(e)))
            return

        self.post_message(self.ProxySetupClosed(saved=True))

    def action_close(self) -> None:
        self.post_message(self.ProxySetupClosed(saved=False))
