"""增强输入 - 支持命令补全和多行输入"""

import os
from typing import Optional

# 尝试导入 readline 以改进 CJK 字符处理
# macOS 使用 libedit 兼容的 readline
# readline 模块会在导入后自动替换 Python 的 input() 函数，
# 提供更好的字符处理（包括 CJK 字符的显示宽度和删除）
_READLINE_AVAILABLE = False
try:
    import readline
    _READLINE_AVAILABLE = True
except ImportError:
    pass

# 环境变量控制输入模式
# AGENT_CLI_SIMPLE_MODE=1 时使用标准 input()，避免终端兼容性问题
# AGENT_CLI_SIMPLE_MODE=0 时强制使用 prompt_toolkit
# 默认在 iTerm2 中使用简单模式（因为 CJK 兼容性问题）
_env_mode = os.environ.get("AGENT_CLI_SIMPLE_MODE")
if _env_mode is not None:
    _USE_SIMPLE_MODE = _env_mode == "1"
else:
    # 默认检测 iTerm2
    _TERM = os.environ.get("TERM_PROGRAM", "")
    _USE_SIMPLE_MODE = _TERM == "iTerm.app"

# 尝试导入 wcwidth 用于正确计算 CJK 字符宽度
try:
    import wcwidth

    def get_char_width(char: str) -> int:
        """获取字符的终端显示宽度

        CJK 字符（中、日、韩文）在终端中占 2 个字符宽度，
        wcwidth 库可以正确计算 Unicode 字符的显示宽度。
        """
        width = wcwidth.wcwidth(char)
        return width if width is not None else 1

except ImportError:
    def get_char_width(char: str) -> int:
        """回退：使用简单长度计算"""
        return len(char)


# 尝试导入 prompt_toolkit，如果失败则使用回退实现
try:
    from prompt_toolkit import PromptSession
    from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
    from prompt_toolkit.completion import Completion
    from prompt_toolkit.formatted_text import FormattedText
    from prompt_toolkit.history import InMemoryHistory
    from prompt_toolkit.input.defaults import create_input
    from prompt_toolkit.key_binding import KeyBindings
    from prompt_toolkit.key_binding.defaults import load_basic_bindings, merge_key_bindings
    PROMPT_TOOLKIT_AVAILABLE = True
except ImportError:
    PROMPT_TOOLKIT_AVAILABLE = False


class CommandCompleter:
    """命令补全器"""

    def __init__(self, commands: list[str]):
        self.commands = commands

    def get_completions(self, document, complete_event):
        """获取补全建议"""
        if not PROMPT_TOOLKIT_AVAILABLE:
            return

        text = document.text_before_cursor
        # 只在输入 / 时触发补全
        if text.startswith("/"):
            word = text[1:].lower()
            for cmd in self.commands:
                if cmd.lower().startswith(word):
                    yield Completion(f"/{cmd}", start_position=1)


class EnhancedInput:
    """增强输入处理器

    支持：
    - 命令自动补全（需要 prompt_toolkit）
    - 命令历史（需要 prompt_toolkit）
    - 快捷键支持
    - 如果依赖未安装则回退到标准 input
    - 设置 AGENT_CLI_SIMPLE_MODE=1 可强制使用标准 input，避免终端兼容性问题

    CJK 兼容性：
    - prompt_toolkit >= 3.0.43 修复了多个 CJK 相关问题
    - 使用 FormattedText 增强渲染兼容性
    - 配置 allow_cursor_in_narrow_line 处理 CJK 字符宽度
    - 简单模式使用 readline 改进 CJK 字符删除显示
    """

    def __init__(self, commands: Optional[list[str]] = None):
        self.commands = commands or []
        self._session = None
        self._simple_mode = _USE_SIMPLE_MODE or not PROMPT_TOOLKIT_AVAILABLE
        # 记录是否已经提示过简单模式
        self._simple_mode_warned = False
        # 记录是否已配置 readline
        self._readline_configured = False
        # 配置 readline 以改进 CJK 处理
        self._configure_readline()

    def _configure_readline(self) -> None:
        """配置 readline 以改进 CJK 字符处理

        readline 可以更好地处理 CJK 字符的显示宽度，
        特别是删除操作时的光标定位。
        """
        if not _READLINE_AVAILABLE or self._readline_configured:
            return

        try:
            # 设置 vi 模式（可选，也可以使用 emacs 模式）
            # readline.parse_and_bind("bind ^I vi")
            # 设置 Ctrl+D 不退出
            readline.parse_and_bind("set editing-mode vi")
            # 尝试启用 Unicode 支持（如果 readline 版本支持）
            # 这可以帮助 readline 正确处理 CJK 字符
            try:
                readline.parse_and_bind("set input-meta on")
                readline.parse_and_bind("set output-meta on")
                readline.parse_and_bind("set convert-meta off")
            except Exception:
                pass
            self._readline_configured = True
        except Exception:
            pass

    def _create_session(self):
        """创建 PromptSession

        针对 iTerm2 + CJK 字符的优化配置：
        - enable_history_search: 启用历史搜索
        - 使用 FormattedText 避免纯文本渲染问题
        """
        if not PROMPT_TOOLKIT_AVAILABLE:
            return None

        # 创建自定义绑定
        custom_bindings = KeyBindings()

        @custom_bindings.add("c-c")
        def handle_interrupt(event):
            """Ctrl+C 处理"""
            event.app.exit(exception=KeyboardInterrupt)

        # 合并默认绑定和自定义绑定
        bindings = merge_key_bindings([
            load_basic_bindings(),  # 默认的 Backspace、Delete 等绑定
            custom_bindings,
        ])

        completer = CommandCompleter(self.commands) if self.commands else None

        # 使用默认输入模式，让 prompt_toolkit 自动检测最佳输入方式
        # 不再强制使用 VT100，这样可以在 iTerm2 中更好地处理 CJK 字符
        input_obj = create_input()

        # 配置 CJK 友好的 session
        # prompt_toolkit 3.0.43+ 对 CJK 支持有改进
        session = PromptSession(
            history=InMemoryHistory(),
            completer=completer,
            auto_suggest=AutoSuggestFromHistory(),
            key_bindings=bindings,
            input=input_obj,
            # 启用历史搜索
            enable_history_search=True,
        )
        return session

    def prompt(
        self,
        message: str = "你: ",
        default: str = "",
        placeholder: str = "输入内容...",
    ) -> str:
        """显示输入提示

        Args:
            message: 输入提示符
            default: 默认值
            placeholder: 占位符

        Returns:
            用户输入的内容
        """
        # 使用简单模式（标准 input），避免终端兼容性问题
        if self._simple_mode:
            # 首次使用简单模式时给出提示
            if not self._simple_mode_warned:
                self._simple_mode_warned = True
                if _USE_SIMPLE_MODE:
                    term = os.environ.get("TERM_PROGRAM", "")
                    if term == "iTerm.app":
                        if _READLINE_AVAILABLE:
                            print("提示: iTerm2 检测到，自动使用简单模式（含 readline 改进）")
                        else:
                            print("提示: iTerm2 检测到，自动使用简单模式")
                        print("      如需使用增强模式: AGENT_CLI_SIMPLE_MODE=0 uv run agent cli")
                    else:
                        print("提示: 使用简单模式 (AGENT_CLI_SIMPLE_MODE=1)")
                elif not PROMPT_TOOLKIT_AVAILABLE:
                    print("提示: prompt_toolkit 未安装，使用标准输入")

            try:
                # 使用 readline 改进 CJK 字符处理
                # readline 可以更正确地处理 CJK 字符的显示宽度和删除
                if _READLINE_AVAILABLE:
                    # 设置当前行缓冲，以便 readline 可以正确处理
                    return input(message).strip()
                return input(message).strip()
            except (EOFError, OSError):
                # 非交互式环境
                return ""

        # 尝试使用 prompt_toolkit
        if PROMPT_TOOLKIT_AVAILABLE:
            try:
                if self._session is None:
                    self._session = self._create_session()

                if self._session:
                    # 使用 FormattedText 避免 CJK 字符渲染问题
                    # 将字符串消息转换为 FormattedText 格式
                    if isinstance(message, str):
                        formatted_message = FormattedText([("bold", message)])
                    else:
                        formatted_message = message

                    result = self._session.prompt(
                        formatted_message,
                        default=default,
                        placeholder=placeholder,
                    )
                    return result.strip()
            except Exception:
                # 回退到标准 input
                try:
                    return input(message).strip()
                except (EOFError, OSError):
                    return ""

        return input(message).strip()

    def prompt_multiline(
        self,
        message: str = "输入内容（空行结束）: ",
        end_marker: str = "",
    ) -> str:
        """多行输入

        Args:
            message: 输入提示符
            end_marker: 结束标记（空行结束则为空）

        Returns:
            用户输入的多行内容
        """
        lines = []
        print(message)

        while True:
            try:
                line = input()
                if end_marker and line.strip() == end_marker:
                    break
                if not end_marker and not line.strip():
                    break
                lines.append(line)
            except EOFError:
                break
            except KeyboardInterrupt:
                print("\n输入取消")
                break

        return "\n".join(lines)

    def confirm(self, message: str, default: bool = False) -> bool:
        """确认提示

        Args:
            message: 确认消息
            default: 默认选择

        Returns:
            用户确认返回 True，否则返回 False
        """
        choices = "[Y/n]" if default else "[y/N]"

        while True:
            response = input(f"{message} {choices}: ").strip().lower()
            if not response:
                return default
            if response in ["y", "yes"]:
                return True
            if response in ["n", "no"]:
                return False
            print("请输入 y 或 n")

    def select(
        self,
        message: str,
        options: list[str],
        default: Optional[int] = None,
    ) -> Optional[int]:
        """选择提示

        Args:
            message: 选择提示消息
            options: 选项列表
            default: 默认选项索引

        Returns:
            选择的索引，未选择返回 None
        """
        print(f"\n{message}")

        for i, option in enumerate(options, 1):
            marker = ">" if default == i - 1 else " "
            print(f"  {marker} {i}. {option}")

        while True:
            try:
                response = input("\n选择: ").strip()
                if not response and default is not None:
                    return default
                idx = int(response) - 1
                if 0 <= idx < len(options):
                    return idx
                print(f"请输入 1-{len(options)} 之间的数字")
            except ValueError:
                print("请输入有效的数字")
            except EOFError:
                return None

    def update_commands(self, commands: list[str]) -> None:
        """更新命令列表"""
        self.commands = commands
        # 重新创建 session 以应用新命令
        if PROMPT_TOOLKIT_AVAILABLE:
            self._session = None


def create_enhanced_input(commands: Optional[list[str]] = None) -> EnhancedInput:
    """创建增强输入处理器"""
    return EnhancedInput(commands)
