"""
EnhancedTUI - TUI 兼容层
保持与原版相同的 API，内部通过 Textual App 实现渲染
"""

import asyncio
from typing import Optional, Dict, Any

from rich.console import Console, RenderableType
from rich.text import Text
from rich.markup import escape

from textual.widgets import RichLog
from textual.css.query import NoMatches

from interface.styles import Styles, Icons
from interface.app import DundunApp


class EnhancedTUI:
    """增强版 TUI - Textual 版本"""

    VERSION = "1.1.0"

    WELCOME_TEXT = (
        "\n"
        "[bold cyan]Dundun (D.D.) Agent[/bold cyan]\n"
        "\n"
        "[italic white]Solid as a rock, sharp as a blade.[/italic white]\n"
        "\n"
        "[italic gray50]D.D. v1.1 | Dedicated to my little Dundun[/italic gray50]"
    )

    def __init__(self):
        self._app: Optional[DundunApp] = None
        self._fallback_console = Console(force_terminal=True)
        self.debug_mode = False

    @property
    def app(self) -> Optional[DundunApp]:
        return self._app

    @app.setter
    def app(self, value: DundunApp):
        self._app = value

    @property
    def console(self) -> Console:
        return self._fallback_console

    def _write_safe(self, renderable: RenderableType, expand: bool = False) -> None:
        if self._app is not None:
            try:
                self._app.write_renderable(renderable, expand=expand)
            except Exception:
                self._fallback_console.print(renderable)
        else:
            self._fallback_console.print(renderable)

    def update_status_bar(self, **kwargs) -> None:
        """更新状态栏 - 封装 DundunApp.update_status_bar"""
        if self._app is not None:
            self._app.update_status_bar(**kwargs)

    def clear_output(self) -> None:
        """清空输出区"""
        if self._app is not None:
            self._app.clear_output()

    def print_separator(self, char: str = "─", style: str = Styles.BORDER):
        if self._app is not None:
            self._app.write_separator(char, style)
        else:
            self._fallback_console.print(char * self._fallback_console.width, style=style)

    def _get_separator_line(self, prefix: str = "", char: str = "─", min_width: int = 20) -> str:
        if self._app is not None:
            available_width = max(self._app._width - len(prefix) - 2, min_width)
        else:
            available_width = max(self._fallback_console.width - len(prefix) - 2, min_width)
        return prefix + char * available_width

    # ========== 欢迎和状态 ==========

    def print_welcome(self, config_dir: str = ""):
        welcome = Text.from_markup(self.WELCOME_TEXT)
        self._write_safe(welcome)
        self.print_separator()

    def print_status_line(self, agent: str = "general", model: str = "", session_id: str = ""):
        status = Text()
        status.append("Agent: ", style=Styles.DIM)
        status.append(agent, style=Styles.TOOL_NAME)
        if model:
            status.append("  ", style=Styles.DIM)
            status.append("Model: ", style=Styles.DIM)
            status.append(model, style=Styles.SUCCESS)
        if session_id:
            status.append("  ", style=Styles.DIM)
            status.append("Session: ", style=Styles.DIM)
            status.append(session_id[:8], style=Styles.WARNING)
        self._write_safe(status)
        self.print_separator()

    # ========== 用户输入 ==========

    def get_user_input(self, prompt: str = None) -> str:
        try:
            user_input = input(f"{Icons.PROMPT} ")
            return user_input.strip() if user_input else ""
        except EOFError:
            return "/exit"
        except KeyboardInterrupt:
            return ""

    async def get_user_input_async(self, prompt: str = None) -> str:
        if self._app is not None:
            try:
                return await self._app.get_input()
            except (EOFError, asyncio.CancelledError):
                return "/exit"
            except KeyboardInterrupt:
                return ""
        else:
            try:
                loop = asyncio.get_event_loop()
                user_input = await loop.run_in_executor(None, lambda: input(f"{Icons.PROMPT} "))
                return user_input.strip() if user_input else ""
            except EOFError:
                return "/exit"
            except KeyboardInterrupt:
                return ""

    def clear_lines(self, count: int):
        pass

    BORDER_COLOR = Styles.BORDER

    def render_user_input(self, user_input: str):
        self._write_safe(Text(""))
        self.print_separator()
        lines = user_input.split('\n')
        for i, line in enumerate(lines):
            if i == 0:
                text = Text()
                text.append(Icons.PROMPT + " ", style=Styles.PROMPT)
                text.append(line, style="italic")
                self._write_safe(text)
            else:
                text = Text("  ")
                text.append(line, style="italic")
                self._write_safe(text)
        self.print_separator()

    # ========== 消息输出 ==========

    def print_error(self, message: str):
        text = Text()
        text.append(f"{Icons.FAILURE} Error: ", style=Styles.ERROR)
        text.append(message)
        self._write_safe(text)

    def print_warning(self, message: str):
        text = Text()
        text.append(f"{Icons.WARNING} Warning: ", style=Styles.WARNING)
        text.append(message)
        self._write_safe(text)

    def print_info(self, message: str):
        text = Text()
        text.append(f"{Icons.INFO} ", style=Styles.DIM)
        text.append(message, style=Styles.DIM)
        self._write_safe(text)

    def print_success(self, message: str):
        text = Text()
        text.append(f"{Icons.SUCCESS} ", style=Styles.SUCCESS)
        text.append(message)
        self._write_safe(text)

    def print_command_result(self, message: str, success: bool = True):
        if success:
            self._write_safe(Text(message))
        else:
            self.print_error(message)

    # ========== 权限询问 ==========

    def ask_permission(
        self, permission: str, target: str,
        description: str = "", args: Dict[str, Any] = None,
    ) -> str:
        self._fallback_console.print()
        safe_permission = escape(permission)
        # 将换行替换为 \\n 保持单行显示
        safe_target = target.replace('\n', '\\n') if target else ""
        self._fallback_console.print(
            f"[dim]▎[/dim] 🔐 权限请求: [bold cyan]{safe_permission}[/bold cyan] ({safe_target})"
        )
        self._fallback_console.print(f"[dim]{self._get_separator_line('▎', '─')}[/dim]")
        self._fallback_console.print("[dim]▎[/dim] (y)允许 (n)拒绝 (a)始终 (d)禁止")
        while True:
            try:
                choice = input("▎ 请输入 › ").lower().strip()
                if choice in ["y", "n", "a", "d"]:
                    self._fallback_console.print()
                    return choice
                self._fallback_console.print(f"[{Styles.WARNING}]无效选择，请重新输入[/{Styles.WARNING}]")
            except (EOFError, KeyboardInterrupt):
                self._fallback_console.print()
                return "n"

    async def ask_permission_async(
        self, permission: str, target: str,
        description: str = "", args: Dict[str, Any] = None,
    ) -> str:
        if self._app is not None:
            return await self._app.ask_permission_async(permission, target, description, args)
        else:
            loop = asyncio.get_event_loop()
            return await loop.run_in_executor(
                None, self.ask_permission, permission, target, description, args
            )

    async def ask_clarify_async(
        self, question: str, options: list, allow_input: bool = True
    ) -> str:
        """用户澄清请求 - 支持选项和自由输入"""
        if self._app is not None:
            return await self._app.ask_clarify_async(question, options, allow_input)
        else:
            # fallback 模式：使用简单输入
            self._fallback_console.print()
            self._fallback_console.print(f"[bold yellow]❓ {question}[/bold yellow]")
            if options:
                for i, opt in enumerate(options):
                    label = opt.get("label", opt.get("value", f"选项{i+1}"))
                    self._fallback_console.print(f"   [{i+1}] {label}")
            if allow_input:
                self._fallback_console.print("[dim]请输入选项编号或直接输入内容[/dim]")

            while True:
                try:
                    user_input = input("▎ 请输入 › ").strip()
                    if not user_input:
                        continue
                    # 尝试解析为选项编号
                    try:
                        idx = int(user_input) - 1
                        if 0 <= idx < len(options):
                            self._fallback_console.print()
                            return options[idx].get("value", user_input)
                    except ValueError:
                        pass
                    # 返回用户输入
                    if allow_input:
                        self._fallback_console.print()
                        return user_input
                except (EOFError, KeyboardInterrupt):
                    self._fallback_console.print()
                    return ""

    # ========== 清屏 ==========

    def clear(self):
        if self._app is not None:
            try:
                self._app.query_one("#output-log", RichLog).clear()
            except NoMatches:
                pass
        else:
            import os
            os.system('cls' if os.name == 'nt' else 'clear')
