"""消息渲染器 - 渲染各类消息内容"""

import logging
import re
from typing import Optional

from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from rich.syntax import Syntax
from rich.table import Table

logger = logging.getLogger("agent")


class MessageRenderer:
    """消息渲染器

    支持：
    - Markdown 渲染
    - 代码块语法高亮
    - 表格渲染
    - 面板包装
    """

    def __init__(self, console: Optional[Console] = None):
        self.console = console or Console(emoji=False)

    def render(self, message: str) -> None:
        """渲染消息

        智能判断内容类型并渲染：
        - Markdown 格式: 使用 Markdown 渲染
        - 代码块: 使用语法高亮
        - 普通文本: 直接输出
        """
        try:
            # 检测是否是 Markdown 格式
            if self._is_markdown(message):
                self._render_markdown(message)
            # 检测是否主要是代码
            elif self._is_code_block(message):
                self._render_code_block(message)
            else:
                self._render_plain(message)
        except UnicodeEncodeError as e:
            # 回退到安全打印
            logger.warning(f"Unicode 编码错误，回退到安全打印: {e}")
            safe_message = message.encode('utf-8', errors='replace').decode('utf-8')
            print(safe_message)

    def _is_markdown(self, text: str) -> bool:
        """检测是否是 Markdown 格式"""
        md_indicators = [
            r"^#{1,6}\s",  # 标题
            r"^\s*[-*+]\s",  # 列表
            r"^\s*\d+\.\s",  # 有序列表
            r"\*\*[^*]+\*\*",  # 粗体
            r"\*[^*]+\*",  # 斜体
            r"\[.+?\]\(.+?\)",  # 链接
            r"^```",  # 代码块开始
            r"^\s*\|",  # 表格
        ]
        return any(re.search(pattern, text, re.MULTILINE) for pattern in md_indicators)

    def _is_code_block(self, text: str) -> bool:
        """检测是否主要是代码"""
        lines = text.split("\n")
        if len(lines) < 2:
            return False
        # 统计看起来像代码的行
        code_like = sum(1 for line in lines if self._is_code_line(line))
        return code_like / len(lines) > 0.5

    def _is_code_line(self, line: str) -> bool:
        """判断单行是否像代码"""
        code_indicators = [
            "def ",
            "class ",
            "import ",
            "from ",
            "if ",
            "for ",
            "while ",
            "return ",
            "=> ",
            "-> ",
            "function ",
            "const ",
            "let ",
            "var ",
            "async ",
        ]
        return any(indicator in line for indicator in code_indicators)

    def _render_markdown(self, message: str) -> None:
        """渲染 Markdown"""
        md = Markdown(message)
        self.console.print(md)

    def _render_code_block(self, message: str) -> None:
        """渲染代码块"""
        # 尝试检测语言
        language = self._detect_language(message)
        syntax = Syntax(
            message,
            language,
            theme="monokai",
            line_numbers=True,
            word_wrap=False,
        )
        self.console.print(syntax)

    def _render_plain(self, message: str) -> None:
        """渲染普通文本"""
        # 处理换行
        for line in message.split("\n"):
            self.console.print(line)

    def _detect_language(self, code: str) -> str:
        """检测代码语言"""
        if "def " in code or "import " in code or "from " in code:
            return "python"
        if "function " in code or "const " in code or "let " in code:
            return "javascript"
        if "fn " in code or "let mut " in code:
            return "rust"
        if "func " in code and "package " in code:
            return "go"
        if "public " in code or "private " in code:
            return "java"
        return "text"

    def render_thinking(self, thinking: list[str]) -> None:
        """渲染思考过程"""
        if not thinking:
            return

        steps = []
        for i, step in enumerate(thinking, 1):
            steps.append(f"{i}. {step}")

        content = "\n".join(steps)
        panel = Panel(
            content,
            title="💭 思考过程",
            border_style="cyan",
            style="dim",
        )
        self.console.print(panel)

    def render_skills(self, skills_data: dict) -> None:
        """渲染技能列表"""
        table = Table(title="可用技能", show_lines=True)

        table.add_column("命令", style="cyan", no_wrap=True)
        table.add_column("描述", style="white")
        table.add_column("分类", style="magenta")

        for skill_name, skill_info in skills_data.items():
            command = f"/{skill_name}"
            description = skill_info.get("description", "")
            category = skill_info.get("category", "other")
            table.add_row(command, description, category)

        self.console.print(table)

    def render_welcome(self, version: str = "0.3.0") -> None:
        """渲染欢迎面板"""
        content = f"""
[bold cyan]Jude Agent[/bold cyan] v{version}

[bold]命令说明:[/bold]
• [cyan]/quit[/cyan] 或 [cyan]/exit[/cyan] - 退出对话
• [cyan]/reset[/cyan] - 清空对话历史
• [cyan]/think[/cyan] - 切换思考过程显示
• [cyan]/new[/cyan] - 创建新会话
• [cyan]/help[/cyan] - 查看可用 Skill

[dim]输入你的问题开始对话...[/dim]
"""
        panel = Panel(
            content.strip(),
            title="欢迎使用",
            border_style="green",
            padding=(1, 2),
        )
        self.console.print(panel)

    def render_skill_help(self, skills: list[dict]) -> None:
        """渲染技能帮助信息"""
        # 按分类组织
        categories: dict[str, list[dict]] = {}
        for skill in skills:
            cat = skill.get("category", "other")
            if cat not in categories:
                categories[cat] = []
            categories[cat].append(skill)

        for category, category_skills in categories.items():
            table = Table(title=f"{category.capitalize()} 技能", show_lines=False)
            table.add_column("命令", style="cyan", no_wrap=True, width=20)
            table.add_column("描述", style="white")

            for skill in category_skills:
                command = f"/{skill['name']}"
                description = skill.get("description", "")
                table.add_row(command, description)

            self.console.print(table)
            self.console.print()  # 空行
