from __future__ import annotations

from pathlib import Path
from typing import Any, ClassVar

from textual import events
from textual.app import App, ComposeResult
from textual.binding import Binding, BindingType
from textual.containers import CenterMiddle, Horizontal
from textual.message import Message
from textual.widgets import Static

from vibe.cli.textual_ui.widgets.no_markup_static import NoMarkupStatic
from vibe.core.paths import TRUSTED_FOLDERS_FILE


class TrustDialogQuitException(Exception):
    pass


class TrustFolderDialog(CenterMiddle):
    can_focus = True
    can_focus_children = True

    BINDINGS: ClassVar[list[BindingType]] = [
        Binding("left", "move_left", "Left", show=False),
        Binding("right", "move_right", "Right", show=False),
        Binding("enter", "select", "Select", show=False),
        Binding("1", "select_1", "Yes", show=False),
        Binding("y", "select_1", "Yes", show=False),
        Binding("2", "select_2", "No", show=False),
        Binding("n", "select_2", "No", show=False),
    ]

    class Trusted(Message):
        pass

    class Untrusted(Message):
        pass

    def __init__(self, folder_path: Path, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.folder_path = folder_path
        self.selected_option = 0
        self.option_widgets: list[Static] = []

    def compose(self) -> ComposeResult:
        with CenterMiddle(id="trust-dialog"):
            yield NoMarkupStatic(
                "⚠ Trust this folder and all its subfolders?", id="trust-dialog-title"
            )
            yield NoMarkupStatic(
                str(self.folder_path),
                id="trust-dialog-path",
                classes="trust-dialog-path",
            )
            yield NoMarkupStatic(
                "Files that can modify your Mistral Vibe setup were found here. Do you trust this folder and all its subfolders?",
                id="trust-dialog-message",
                classes="trust-dialog-message",
            )

            with Horizontal(id="trust-options-container"):
                options = ["Yes", "No"]
                for idx, text in enumerate(options):
                    widget = NoMarkupStatic(
                        f"  {idx + 1}. {text}", classes="trust-option"
                    )
                    self.option_widgets.append(widget)
                    yield widget

            yield NoMarkupStatic(
                "← → navigate  Enter select", classes="trust-dialog-help"
            )

            yield NoMarkupStatic(
                f"Setting will be saved in: {TRUSTED_FOLDERS_FILE.path}",
                id="trust-dialog-save-info",
                classes="trust-dialog-save-info",
            )

    async def on_mount(self) -> None:
        self.selected_option = 1  # Default to "No"
        self._update_options()
        self.focus()

    def _update_options(self) -> None:
        options = ["Yes", "No"]

        if len(self.option_widgets) != len(options):
            return

        for idx, (text, widget) in enumerate(
            zip(options, self.option_widgets, strict=True)
        ):
            is_selected = idx == self.selected_option

            cursor = "› " if is_selected else "  "
            option_text = f"{cursor}{text}"

            widget.update(option_text)

            widget.remove_class("trust-cursor-selected")
            widget.remove_class("trust-option-selected")

            if is_selected:
                widget.add_class("trust-cursor-selected")
            else:
                widget.add_class("trust-option-selected")

    def action_move_left(self) -> None:
        self.selected_option = (self.selected_option - 1) % 2
        self._update_options()

    def action_move_right(self) -> None:
        self.selected_option = (self.selected_option + 1) % 2
        self._update_options()

    def action_select(self) -> None:
        self._handle_selection(self.selected_option)

    def action_select_1(self) -> None:
        self.selected_option = 0
        self._handle_selection(0)

    def action_select_2(self) -> None:
        self.selected_option = 1
        self._handle_selection(1)

    def _handle_selection(self, option: int) -> None:
        match option:
            case 0:
                self.post_message(self.Trusted())
            case 1:
                self.post_message(self.Untrusted())

    def on_blur(self, event: events.Blur) -> None:
        self.call_after_refresh(self.focus)


class TrustFolderApp(App):
    CSS_PATH = "trust_folder_dialog.tcss"

    BINDINGS: ClassVar[list[BindingType]] = [
        Binding("ctrl+q", "quit_without_saving", "Quit", show=False, priority=True),
        Binding("ctrl+c", "quit_without_saving", "Quit", show=False, priority=True),
    ]

    def __init__(self, folder_path: Path, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.folder_path = folder_path
        self._result: bool | None = None
        self._quit_without_saving = False

    def on_mount(self) -> None:
        self.theme = "textual-ansi"

    def compose(self) -> ComposeResult:
        yield TrustFolderDialog(self.folder_path)

    def action_quit_without_saving(self) -> None:
        self._quit_without_saving = True
        self.exit()

    def on_trust_folder_dialog_trusted(self, _: TrustFolderDialog.Trusted) -> None:
        self._result = True
        self.exit()

    def on_trust_folder_dialog_untrusted(self, _: TrustFolderDialog.Untrusted) -> None:
        self._result = False
        self.exit()

    def run_trust_dialog(self) -> bool | None:
        self.run()
        if self._quit_without_saving:
            raise TrustDialogQuitException()
        return self._result


def ask_trust_folder(folder_path: Path) -> bool | None:
    app = TrustFolderApp(folder_path)
    return app.run_trust_dialog()
