"""
权限与澄清组件
- PermissionBar: 权限请求选项组（允许/拒绝/始终/禁止）
- ClarifyBar: 用户澄清请求（支持选项选择和自由输入）
"""

import asyncio
from typing import TYPE_CHECKING

from textual.widget import Widget
from textual.binding import Binding
from textual.message import Message
from textual import events
from rich.text import Text

if TYPE_CHECKING:
    from textual.events import Key


class PermissionBar(Widget):
    """权限请求选项组 - 左右键选择，Enter 确认"""

    can_focus = True

    DEFAULT_CSS = """
    PermissionBar {
        height: 1;
        width: 100%;
        margin-top: 1;
        margin-left: 1;
    }
    """

    CHOICES = [
        ("y", "允许"),
        ("n", "拒绝"),
        ("a", "始终"),
        ("d", "禁止"),
    ]

    class Selected(Message):
        def __init__(self, choice: str) -> None:
            super().__init__()
            self.choice = choice

    BINDINGS = [
        Binding("left", "move_left", show=False),
        Binding("right", "move_right", show=False),
        Binding("enter", "confirm", show=False),
    ]

    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)
        self._selected_index = 0

    def render(self) -> Text:
        text = Text()
        for i, (key, label) in enumerate(self.CHOICES):
            if i > 0:
                text.append("  ")
            if i == self._selected_index:
                text.append(label, style="bold underline")
            else:
                text.append(label)
        return text

    def reset(self) -> None:
        """重置选中状态"""
        self._selected_index = 0

    def action_move_left(self) -> None:
        self._selected_index = (self._selected_index - 1) % len(self.CHOICES)
        self.refresh()

    def action_move_right(self) -> None:
        self._selected_index = (self._selected_index + 1) % len(self.CHOICES)
        self.refresh()

    def action_confirm(self) -> None:
        choice = self.CHOICES[self._selected_index][0]
        self.post_message(PermissionBar.Selected(choice))


class ClarifyBar(Widget):
    """用户澄清请求 - 支持选项选择和自由输入

自由输入... 选项可直接编辑，类似普通输入框
"""

    can_focus = True

    # 纵向展示的阈值（默认启用纵向展示）
    VERTICAL_THRESHOLD = 0

    DEFAULT_CSS = """
    ClarifyBar {
        width: 100%;
        height: auto;
        min-height: 1;
        padding: 1 0 0 0;
    }
    """

    class Selected(Message):
        def __init__(self, value: str) -> None:
            super().__init__()
            self.value = value  # 可以是选项值或用户输入

    BINDINGS = [
        Binding("left", "move_prev", show=False),
        Binding("right", "move_next", show=False),
        Binding("up", "move_prev", show=False),
        Binding("down", "move_next", show=False),
        Binding("enter", "confirm", show=False),
    ]

    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)
        self._options: list = []
        self._allow_input: bool = True
        self._selected_index: int = 0
        self._user_input: str = ""
        self._cursor_pos: int = 0
        self._is_editing: bool = False
        self._is_vertical: bool = False

    def configure(self, options: list, allow_input: bool = True) -> None:
        """配置选项和输入模式"""
        self._options = options
        self._allow_input = allow_input
        self._selected_index = 0
        self._user_input = ""
        if not options and allow_input:
            self._is_editing = True
        else:
            self._is_editing = False
        self._cursor_pos = len(self._user_input)
        self._is_vertical = self._should_use_vertical()
        self.refresh()

    def _should_use_vertical(self) -> bool:
        """判断是否应该使用纵向展示模式（默认纵向，增加行间距）"""
        return True

    def _display_width(self, text: str) -> int:
        """估算显示宽度（中文等宽字符按 2 计）"""
        import unicodedata
        width = 0
        for ch in text:
            width += 2 if unicodedata.east_asian_width(ch) in ("W", "F") else 1
        return width

    def _format_input_with_cursor(self) -> str:
        """格式化自由输入（含光标）"""
        if not self._user_input:
            return "[自由输入...]▎"
        left = self._user_input[:self._cursor_pos]
        right = self._user_input[self._cursor_pos:]
        return f"{left}▎{right}"

    @property
    def _total_options(self) -> int:
        return len(self._options) + (1 if self._allow_input else 0)

    @property
    def _is_on_free_input(self) -> bool:
        return self._allow_input and self._selected_index >= len(self._options)

    def render(self) -> Text:
        text = Text()

        if self._is_vertical:
            for i, opt in enumerate(self._options):
                label = opt.get("label", opt.get("value", f"选项{i+1}"))
                index_label = f"{i + 1}. "
                if i > 0:
                    text.append("\n")
                if i == self._selected_index and not self._is_on_free_input:
                    text.append(f"▸ {index_label}{label}", style="bold underline")
                else:
                    text.append(f"  {index_label}{label}")

            if self._allow_input:
                text.append("\n")
                if self._is_on_free_input:
                    if self._is_editing:
                        text.append(f"▸ {self._format_input_with_cursor()}", style="bold underline")
                    else:
                        text.append("▸ 自由输入...", style="bold underline")
                else:
                    text.append("  自由输入...", style="dim italic")
        else:
            for i, opt in enumerate(self._options):
                label = opt.get("label", opt.get("value", f"选项{i+1}"))
                index_label = f"{i + 1}. "
                if i > 0:
                    text.append("  ")
                if i == self._selected_index and not self._is_on_free_input:
                    text.append(f"{index_label}{label}", style="bold underline")
                else:
                    text.append(f"{index_label}{label}")

            if self._allow_input:
                if len(self._options) > 0:
                    text.append("  ", style="dim")
                if self._is_on_free_input:
                    if self._is_editing:
                        text.append(self._format_input_with_cursor(), style="bold underline")
                    else:
                        text.append("自由输入...", style="bold underline")
                else:
                    text.append("自由输入...", style="dim italic")

        return text

    def reset(self) -> None:
        """重置状态"""
        self._selected_index = 0
        self._user_input = ""
        self._cursor_pos = 0
        self._is_editing = False
        self.refresh()

    def action_move_prev(self) -> None:
        if self._is_editing:
            if self._is_vertical:
                self._is_editing = False
            elif self._user_input == "":
                self._is_editing = False
            else:
                return
        total = self._total_options
        if total > 0:
            self._selected_index = (self._selected_index - 1) % total
            if self._is_on_free_input:
                self._is_editing = True
                self._user_input = ""
                self._cursor_pos = 0
            self.refresh()

    def action_move_next(self) -> None:
        if self._is_editing:
            if self._is_vertical:
                self._is_editing = False
            else:
                return
        total = self._total_options
        if total > 0:
            self._selected_index = (self._selected_index + 1) % total
            if self._is_on_free_input:
                self._is_editing = True
                self._user_input = ""
                self._cursor_pos = 0
            self.refresh()

    def action_confirm(self) -> None:
        if self._is_on_free_input and self._is_editing:
            if self._user_input.strip():
                self.post_message(ClarifyBar.Selected(self._user_input))
            return
        if self._selected_index < len(self._options):
            value = self._options[self._selected_index].get("value")
            self.post_message(ClarifyBar.Selected(value))

    def on_key(self, event: "Key") -> None:
        """处理按键输入"""
        if self._is_on_free_input and self._is_editing:
            if event.key == "escape":
                if self._options:
                    self._is_editing = False
                    self._user_input = ""
                    self._selected_index = 0
                    self.refresh()
                event.prevent_default()
                event.stop()
            elif event.key == "backspace":
                if self._cursor_pos > 0:
                    left = self._user_input[:self._cursor_pos - 1]
                    right = self._user_input[self._cursor_pos:]
                    self._user_input = left + right
                    self._cursor_pos -= 1
                self.refresh()
                event.prevent_default()
                event.stop()
            elif event.key == "left":
                if self._cursor_pos > 0:
                    self._cursor_pos -= 1
                    self.refresh()
                    event.prevent_default()
                    event.stop()
                else:
                    if not self._is_vertical:
                        self._is_editing = False
                        self.action_move_prev()
                        event.prevent_default()
                        event.stop()
            elif event.key == "right":
                if self._cursor_pos < len(self._user_input):
                    self._cursor_pos += 1
                    self.refresh()
                    event.prevent_default()
                    event.stop()
            elif event.key in ("enter", "left", "right", "up", "down", "tab"):
                pass
            elif event.character and event.is_printable:
                left = self._user_input[:self._cursor_pos]
                right = self._user_input[self._cursor_pos:]
                self._user_input = left + event.character + right
                self._cursor_pos += 1
                self.refresh()
                event.prevent_default()
                event.stop()
