"""Agent CLI 入口

支持多种通道，通过配置启用
"""

import argparse
import logging
import os
import sys
from pathlib import Path

from rich.console import Console
from rich.panel import Panel

from .channels.cli.ui.input import EnhancedInput
from config.agent import config, get_channel_config

console = Console()

# 创建增强输入处理器
_simple_input = EnhancedInput()

# 配置日志
log_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "logs")
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, "agent.log")

# 添加文件日志处理器
file_handler = logging.FileHandler(log_file, encoding="utf-8")
file_handler.setFormatter(logging.Formatter(
    "%(asctime)s [%(levelname)s] %(name)s:%(lineno)d %(message)s",
    datefmt="%H:%M:%S"
))

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(name)s:%(lineno)d %(message)s",
    datefmt="%H:%M:%S",
    handlers=[logging.StreamHandler(), file_handler],
)


def setup_logging(verbose: bool = False):
    """设置日志级别"""
    level = logging.DEBUG if verbose else logging.INFO
    logging.getLogger("agent").setLevel(level)
    logging.getLogger("rag").setLevel(level)
    logging.getLogger("langchain").setLevel(level)
    logging.getLogger("langchain_anthropic").setLevel(level)
    logging.getLogger("langchain_core").setLevel(level)


def create_agent(enable_rag: bool = True, enable_calculator: bool = True):
    """创建 Agent 实例"""
    from core.agent import Agent
    from .agent_tools import calculator, search_documents

    tools = []
    if enable_calculator:
        tools.append(calculator)
    if enable_rag:
        tools.append(search_documents)

    return Agent(
        tools=tools,
        max_iterations=config.max_iterations,
        show_thinking=config.show_thinking,
    )


def run_server_with_channels(
    host: str = "0.0.0.0",
    port: int = None,
    enable_rag: bool = True,
    enable_calculator: bool = True,
):
    """运行 HTTP 服务 + 启用的通道"""
    from .gateway import run_server

    port = port or config.agent_server_port

    # 创建 Agent
    agent = create_agent(enable_rag, enable_calculator)

    # 启动飞书通道（后台）
    feishu_config = get_channel_config("feishu")
    feishu_thread = None
    if feishu_config["enabled"] and feishu_config["app_id"] and feishu_config["app_secret"]:
        from .channels.feishu import FeishuStreamChannel

        channel = FeishuStreamChannel(
            feishu_config["app_id"],
            feishu_config["app_secret"],
            agent,
        )
        feishu_thread = channel.start_background(agent)
        console.print("[green]✓[/green] 飞书通道已启动")

    # 打印启动信息
    console.print(Panel.fit(
        "[bold blue]Agent HTTP 服务[/bold blue]\n"
        f"监听地址: http://{host}:{port}\n"
        f"API 端点:\n"
        f"  - POST /v1/agent/chat\n"
        f"  - POST /v1/agent/reset\n"
        f"  - GET  /health",
        border_style="blue"
    ))

    # 启动 HTTP 服务（阻塞）
    run_server(host, port, enable_rag, enable_calculator)


def run_cli_channel(enable_rag: bool = True, enable_calculator: bool = True):
    """运行 CLI 通道（本地模式）"""
    import os

    from .memory import generate_session_id
    from .channels.cli import CLIChannel
    from .memory import ConversationMemory

    channel = CLIChannel()

    # 尝试加载上一次的会话
    cwd = os.getcwd()
    last_session_id = ConversationMemory.find_session_by_directory(cwd)

    if last_session_id:
        print(f"\n当前目录: {cwd}")
        print(f"上一次的会话ID: {last_session_id[:8]}...")
        try:
            choice = _simple_input.confirm("是否继续上一个会话?", default=False)
            session_id = last_session_id if choice else generate_session_id()
        except (EOFError, OSError):
            # 非交互式环境，默认新建会话
            session_id = generate_session_id()
    else:
        session_id = generate_session_id()

    # 使用选定的 session_id 创建 Agent
    agent = create_agent(enable_rag, enable_calculator)
    agent._session_id = session_id
    if agent._memory_enabled:
        # 保留原有的 db_path
        db_path = getattr(agent._memory, 'db_path', None) if agent._memory else None
        agent._memory = agent._memory.__class__(
            session_id=session_id,
            llm=agent._llm,
            db_path=db_path,
        )
        agent._memory.load(session_id)

    # 保存会话目录映射
    if agent._memory:
        agent._memory.save(source='cli', directory=cwd)

    channel.run(agent)


def run_feishu_channel(enable_rag: bool = True, enable_calculator: bool = True):
    """运行飞书通道（阻塞）"""
    from .channels.feishu import FeishuStreamChannel

    feishu_config = get_channel_config("feishu")

    if not feishu_config["enabled"]:
        console.print("[yellow]飞书通道未启用[/yellow]")
        return

    if not feishu_config["app_id"] or not feishu_config["app_secret"]:
        console.print("[bold red]错误:[/bold red] 未配置 FEISHU_APP_ID 或 FEISHU_APP_SECRET")
        return

    agent = create_agent(enable_rag, enable_calculator)

    channel = FeishuStreamChannel(
        feishu_config["app_id"],
        feishu_config["app_secret"],
        agent,
    )

    console.print(Panel.fit(
        "[bold blue]飞书通道 (Stream 模式)[/bold blue]\n"
        "通过 WebSocket 长连接接收消息",
        border_style="blue"
    ))

    console.print("[dim]服务运行中，按 Ctrl+C 退出[/dim]")

    try:
        channel.start()
    except KeyboardInterrupt:
        channel.stop()
        console.print("\n[yellow]服务已停止[/yellow]")


def main():
    """主入口"""
    import sys

    # 检查是否直接调用 Skill（以 / 开头）
    if len(sys.argv) > 1 and sys.argv[1].startswith("/"):
        import asyncio

        from .skills import get_skill_registry
        from .skills.base import SkillContext
        from .skills.parser import SkillCommandParser

        registry = get_skill_registry()

        # 解析 Skill 命令（合并所有参数）
        skill_input = " ".join(sys.argv[1:])
        parsed = SkillCommandParser.parse(skill_input)
        if parsed:
            skill_name, skill_args = parsed

            # 设置内置 Skill 的注册表引用
            for skill in registry.list_skills():
                if hasattr(skill, 'set_registry'):
                    skill.set_registry(registry)

            # 执行 Skill
            skill_context = SkillContext(source="cli")
            result = asyncio.run(registry.execute(skill_name, skill_args, skill_context))

            if result.success:
                console.print(Panel(result.message, border_style="green"))
            else:
                console.print(f"[red]错误:[/red] {result.message}")
            return

    parser = argparse.ArgumentParser(
        description="Agent - 支持多通道",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    # 服务参数
    parser.add_argument(
        "--host",
        default="0.0.0.0",
        help="服务监听地址 (default: 0.0.0.0)"
    )
    parser.add_argument(
        "--port", "-p",
        type=int,
        help="服务端口"
    )

    # Agent 参数
    parser.add_argument(
        "--no-rag",
        action="store_true",
        help="禁用 RAG 工具"
    )
    parser.add_argument(
        "--no-calculator",
        action="store_true",
        help="禁用计算器工具"
    )
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="显示详细日志"
    )

    # 子命令
    subparsers = parser.add_subparsers(dest="command", help="可用命令")

    # 添加一个可选的位置参数来捕获以 / 开头的命令（必须放在子命令解析之后）
    # 我们将在后面手动处理这个情况

    # gateway 子命令（server 为别名，保持向后兼容）
    gateway_parser = subparsers.add_parser(
        "gateway",
        help="启动 HTTP 网关服务"
    )
    subparsers.add_parser(
        "server",
        help="启动 HTTP 网关服务 (gateway 的别名)"
    )

    # cli 子命令
    cli_parser = subparsers.add_parser(
        "cli",
        help="本地 CLI 模式"
    )

    # feishu 子命令
    feishu_parser = subparsers.add_parser(
        "feishu",
        help="飞书通道模式"
    )

    # ask 子命令
    ask_parser = subparsers.add_parser(
        "ask",
        help="单次问答"
    )
    ask_parser.add_argument("question", nargs="*", help="问题内容")

    # tool 子命令
    tool_parser = subparsers.add_parser(
        "tool",
        help="工具管理"
    )
    tool_subparsers = tool_parser.add_subparsers(dest="tool_command", help="工具子命令")

    # tool list 子命令
    tool_list_parser = tool_subparsers.add_parser(
        "list",
        help="列出已加载的工具"
    )
    tool_list_parser.add_argument("--source", "-s", choices=["builtin", "local", "pip", "mcp"],
                                   help="按来源筛选")

    # tool reload 子命令
    tool_subparsers.add_parser(
        "reload",
        help="重新加载工具"
    )

    # tool discover 子命令
    tool_discover_parser = tool_subparsers.add_parser(
        "discover",
        help="发现可用的插件"
    )

    # tool create 子命令 - 创建本地插件
    tool_create_parser = tool_subparsers.add_parser(
        "create",
        help="创建本地插件模板"
    )
    tool_create_parser.add_argument("name", help="插件名称")
    tool_create_parser.add_argument("--dir", "-d", default=".", help="创建目录")

    # skill 子命令
    skill_parser = subparsers.add_parser(
        "skill",
        help="Skill 管理"
    )
    skill_subparsers = skill_parser.add_subparsers(dest="skill_command", help="Skill 子命令")

    # skill list 子命令
    skill_list_parser = skill_subparsers.add_parser(
        "list",
        help="列出已加载的 Skill"
    )
    skill_list_parser.add_argument("--category", "-c", help="按分类筛选")
    skill_list_parser.add_argument("--verbose", "-v", action="store_true", help="显示详细信息")

    # skill reload 子命令
    skill_subparsers.add_parser(
        "reload",
        help="重新加载 Skill"
    )

    # skill discover 子命令
    skill_discover_parser = skill_subparsers.add_parser(
        "discover",
        help="发现可用的 Skill"
    )

    # skill create 子命令 - 创建本地 Skill
    skill_create_parser = skill_subparsers.add_parser(
        "create",
        help="创建本地 Skill 模板"
    )
    skill_create_parser.add_argument("name", help="Skill 名称")
    skill_create_parser.add_argument("--dir", "-d", default=".", help="创建目录")

    args = parser.parse_args()

    # 设置日志
    setup_logging(args.verbose)

    # 配置选项
    enable_rag = not args.no_rag
    enable_calculator = not args.no_calculator

    # 根据命令运行
    # 检查是否是直接调用 Skill（以 / 开头）
    if args.command and args.command.startswith("/"):
        import asyncio

        from .skills import get_skill_registry
        from .skills.base import SkillContext
        from .skills.parser import SkillCommandParser

        registry = get_skill_registry()

        # 解析 Skill 命令
        parsed = SkillCommandParser.parse(args.command)
        if parsed:
            skill_name, skill_args = parsed

            # 设置内置 Skill 的注册表引用
            for skill in registry.list_skills():
                if hasattr(skill, 'set_registry'):
                    skill.set_registry(registry)

            # 执行 Skill
            skill_context = SkillContext(source="cli")
            result = asyncio.run(registry.execute(skill_name, skill_args, skill_context))

            if result.success:
                console.print(Panel(result.message, border_style="green"))
            else:
                console.print(f"[red]错误:[/red] {result.message}")
            return

    if args.command in ("gateway", "server") or args.command is None:
        run_server_with_channels(
            host=args.host,
            port=args.port,
            enable_rag=enable_rag,
            enable_calculator=enable_calculator,
        )

    elif args.command == "cli":
        run_cli_channel(enable_rag, enable_calculator)

    elif args.command == "feishu":
        run_feishu_channel(enable_rag, enable_calculator)

    elif args.command == "ask":
        # 单次问答（直接调用 Agent）
        from .client import run_single_query
        response = run_single_query(
            " ".join(args.question),
            enable_rag=enable_rag,
            enable_calculator=enable_calculator,
        )
        console.print(Panel(response, border_style="green"))

    elif args.command == "tool":
        # 工具管理命令
        from .tools import get_tool_loader
        loader = get_tool_loader()

        if args.tool_command == "list":
            # 列出工具
            from rich.table import Table
            table = Table(title="已加载的工具")
            table.add_column("名称", style="cyan")
            table.add_column("分类", style="magenta")
            table.add_column("描述", style="white")

            for name, tool in loader.tools.items():
                table.add_row(name, tool.category, tool.description[:60])

            console.print(table)
            console.print(f"\n共加载 {len(loader.tools)} 个工具")

        elif args.tool_command == "reload":
            # 重新加载工具
            console.print("[yellow]正在重新加载工具...[/yellow]")
            loader.reload()
            console.print(f"[green]✓[/green] 已重新加载 {len(loader.tools)} 个工具")

        elif args.tool_command == "discover":
            # 发现可用插件
            from rich.table import Table
            table = Table(title="可用的插件")
            table.add_column("名称", style="cyan")
            table.add_column("来源", style="magenta")
            table.add_column("描述", style="white")

            # 使用插件注册表发现
            if hasattr(loader, 'discover_plugins'):
                plugins = loader.discover_plugins()
                for name in plugins:
                    pkg = loader.plugin_registry.packages.get(name)
                    if pkg:
                        table.add_row(name, pkg.source, pkg.description[:60] if pkg.description else "")

            console.print(table)

        elif args.tool_command == "create":
            # 创建本地插件模板

            plugin_dir = Path(args.dir)
            plugin_path = plugin_dir / args.name

            if plugin_path.exists():
                console.print(f"[red]错误:[/red] 目录已存在: {plugin_path}")
            else:
                plugin_path.mkdir(parents=True)
                # 创建 __init__.py
                init_content = f'''"""jude_agent_tool_{args.name}

Jude Agent 工具插件
"""

from .tools.base import BaseTool, ToolOutput


class {args.name.replace("-", "_").title().replace("_", "")}Tool(BaseTool):
    """自定义工具"""

    name = "{args.name}"
    description = "工具描述"
    category = "general"

    input_schema = {{
        "type": "object",
        "properties": {{
            "input": {{
                "type": "string",
                "description": "输入参数"
            }}
        }},
        "required": ["input"]
    }}

    def execute(self, parameters, context=None):
        input_text = parameters.get("input", "")
        # 实现工具逻辑
        return ToolOutput(success=True, result=f"处理结果: {{input_text}}")
'''
                (plugin_path / "__init__.py").write_text(init_content)

                # 创建工具配置文件
                tools_yaml = f'''# 工具配置
name: {args.name}
version: 0.1.0
description: 工具描述
source: local
'''
                (plugin_path / "tools.yaml").write_text(tools_yaml)

                console.print(f"[green]✓[/green] 已创建插件模板: {plugin_path}")
                console.print(f"请编辑 {plugin_path}/__init__.py 实现工具逻辑")

    elif args.command == "skill":
        # Skill 管理命令
        from .skills import get_skill_registry
        registry = get_skill_registry()

        if args.skill_command == "list":
            # 列出 Skill
            from rich.table import Table

            if args.category:
                skills = registry.list_by_category(args.category)
            else:
                skills = registry.list_skills(include_disabled=True)

            if args.verbose:
                table = Table(title="已加载的 Skill（详细）")
                table.add_column("名称", style="cyan")
                table.add_column("分类", style="magenta")
                table.add_column("类型", style="yellow")
                table.add_column("描述", style="white")

                for skill in skills:
                    enabled = "✓" if registry.is_enabled(skill.name) else "✗"
                    table.add_row(
                        f"/{skill.name}",
                        skill.category,
                        skill.skill_type.value,
                        skill.description[:60]
                    )
            else:
                table = Table(title="已加载的 Skill")
                table.add_column("名称", style="cyan")
                table.add_column("描述", style="white")

                for skill in skills:
                    enabled = "✓" if registry.is_enabled(skill.name) else "✗"
                    table.add_row(f"/{skill.name} {enabled}", skill.description[:60])

            console.print(table)
            console.print(f"\n共加载 {len(registry.list_skills())} 个 Skill")

        elif args.skill_command == "reload":
            # 重新加载 Skill
            console.print("[yellow]正在重新加载 Skill...[/yellow]")
            collection = registry.reload()

            # 重新设置内置 Skill 的注册表引用
            for skill in registry.list_skills():
                if hasattr(skill, 'set_registry'):
                    skill.set_registry(registry)

            console.print(f"[green]✓[/green] 已重新加载 {len(collection)} 个 Skill")

        elif args.skill_command == "discover":
            # 发现可用 Skill
            from rich.table import Table
            table = Table(title="可用的 Skill 来源")
            table.add_column("来源", style="cyan")
            table.add_column("数量", style="magenta")

            from .skills import get_skill_loader
            loader = get_skill_loader()
            packages = loader.packages

            source_stats = {}
            for pkg in packages.values():
                source_stats[pkg.source] = source_stats.get(pkg.source, 0) + 1

            for source, count in source_stats.items():
                table.add_row(source, str(count))

            console.print(table)
            console.print(f"\n共发现 {len(packages)} 个 Skill")

        elif args.skill_command == "create":
            # 创建本地 Skill 模板

            skill_dir = Path(args.dir)
            skill_path = skill_dir / args.name

            if skill_path.exists():
                console.print(f"[red]错误:[/red] 目录已存在: {skill_path}")
            else:
                skill_path.mkdir(parents=True)
                # 创建 __init__.py
                init_content = f'''"""jude_agent_skill_{args.name}

Jude Agent Skill
"""

from .skills.base import BaseSkill, SkillContext, SkillResult


class {args.name.replace("-", "_").title().replace("_", "")}Skill(BaseSkill):
    """自定义 Skill"""

    name = "{args.name}"
    description = "Skill 描述"
    category = "general"

    async def execute(self, args, context: SkillContext) -> SkillResult:
        # 实现 Skill 逻辑
        return SkillResult(
            success=True,
            message="Skill 执行成功",
            data={{}}
        )
'''
                (skill_path / "__init__.py").write_text(init_content)

                # 创建 Skill 配置文件
                skill_yaml = f'''# Skill 配置
name: {args.name}
version: 0.1.0
description: Skill 描述
source: local
'''
                (skill_path / "skill.yaml").write_text(skill_yaml)

                console.print(f"[green]✓[/green] 已创建 Skill 模板: {skill_path}")
                console.print(f"请编辑 {skill_path}/__init__.py 实现 Skill 逻辑")


if __name__ == "__main__":
    main()
