"""主消息处理工作流。"""

import uuid
from typing import Any

import inngest

from butler.config import settings
from butler.session import SessionMode
from butler.session.wrapper import TmuxWrapper
from butler.security.guardrail import is_dangerous_command, get_danger_reason
from butler.skills.base import SkillContext, SkillRegistry
from butler.skills.log_skill import LogSkill
from butler.skills.system_skill import SystemSkill
from butler.workflows import inngest_client

tmux = TmuxWrapper(session_prefix=settings.session_prefix)
log_skill = LogSkill()
system_skill = SystemSkill()

# Pre-build skill registry
_skill_registry: SkillRegistry | None = None


def _get_skill_registry() -> SkillRegistry:
    """延迟构建 skill registry 避免循环导入。"""
    global _skill_registry
    if _skill_registry is None:
        _skill_registry = SkillRegistry()
        _skill_registry.register(log_skill)
        _skill_registry.register(system_skill)
    return _skill_registry


@inngest_client.create_function(
    fn_id="handle-im-message",
    name="Handle IM Message",
    trigger=inngest.TriggerEvent(event="im/message"),
)
async def handle_im_message(ctx: inngest.Context, step: inngest.Step) -> dict[str, Any]:
    """主消息处理流程。"""
    user_id = ctx.event.data.get("user_id", "")
    content = ctx.event.data.get("content", "")
    message_id = ctx.event.data.get("message_id", str(uuid.uuid4()))

    # 类型检查
    if not isinstance(user_id, str):
        user_id = str(user_id)
    if not isinstance(content, str):
        content = str(content)

    # 检查权限
    if not settings.is_user_allowed(user_id):
        return {"status": "unauthorized", "message": f"用户 {user_id} 无权限"}

    # 获取或创建会话
    async def get_session() -> str:
        return tmux.get_or_create_session(user_id)

    session_name = await step.run("get-or-create-session", get_session)

    # 检测模式
    async def detect() -> SessionMode:
        return tmux.detect_mode(session_name)

    current_mode = await step.run("detect-mode", detect)

    # 交互模式直接透传
    if current_mode == SessionMode.INTERACTIVE:
        async def passthrough() -> None:
            tmux.send_keys(session_name, content, enter=False)

        await step.run("passthrough", passthrough)

        async def capture() -> str:
            return tmux.capture_pane(session_name)

        output = await step.run("capture-output", capture)
        return {"status": "success", "mode": "interactive", "output": output[-2000:]}

    # 检查 Skill
    registry = _get_skill_registry()
    skill = registry.find_matching(content)
    if skill:
        args = skill.parse_args(content)
        skill_ctx = SkillContext(
            session_name=session_name,
            user_id=user_id,
            session_state={},
            args=args,
        )
        result = await step.run("execute-skill", lambda: skill.execute(skill_ctx))
        return {"status": "success", "mode": "skill", "skill_name": skill.name, "output": result.output}

    # 危险命令检查
    if settings.guardrail_enabled and is_dangerous_command(content):
        reason = get_danger_reason(content) or "潜在危险命令"
        await step.send_event(
            "send-approval-request",
            inngest.Event(
                name="im/command-needs-approval",
                data={
                    "user_id": user_id,
                    "command": content,
                    "reason": reason,
                    "session_name": session_name,
                    "message_id": message_id,
                },
            ),
        )
        return {"status": "pending_approval", "mode": "nl", "reason": reason}

    # 执行命令
    async def execute() -> None:
        tmux.send_keys(session_name, content, enter=True)

    await step.run("execute-command", execute)

    async def capture_output() -> str:
        return tmux.capture_pane(session_name)

    output = await step.run("capture-output", capture_output)

    log_skill.log_command(user_id, session_name, content, output[:500])

    return {"status": "success", "mode": "nl", "output": output[-2000:]}
