use crate::bus::InboundMessage;
use crate::command::context::CommandContext;
use crate::command::response::{CommandError, CommandResponse};
use crate::command::Command;
use crate::agent::AgentError;
use crate::gateway::session::SessionManager;
use async_trait::async_trait;
use std::sync::Arc;

/// 命令元数据（用于帮助系统）
#[derive(Debug, Clone)]
pub struct CommandMetadata {
    pub name: &'static str,
    pub description: &'static str,
    pub usage: &'static str,
}

/// 命令处理器 trait
///
/// 实现此 trait 来处理特定类型的命令
/// 处理器是渠道无关的，只关心 Command 本身
#[async_trait]
pub trait CommandHandler: Send + Sync {
    /// 是否可以处理此命令
    fn can_handle(&self, cmd: &Command) -> bool;

    /// 返回命令元数据（用于 /help 命令）
    fn metadata(&self) -> Option<CommandMetadata> {
        None
    }

    /// 执行命令
    ///
    /// # Arguments
    /// * `cmd` - 要执行的命令
    /// * `ctx` - 命令执行上下文
    ///
    /// # Returns
    /// * `Ok(CommandResponse)` - 命令执行成功
    /// * `Err(CommandError)` - 命令执行失败
    async fn handle(
        &self,
        cmd: Command,
        ctx: CommandContext,
    ) -> Result<CommandResponse, CommandError>;
}

/// InChat 命令处理器 trait
///
/// 用于处理在聊天中直接输入的命令（如 Feishu/WeChat 等通道）
/// 接收 InboundMessage 和 SessionManager
#[async_trait]
pub trait InChatCommandHandler: Send + Sync {
    /// 是否可以处理此命令
    fn can_handle(&self, cmd: &Command) -> bool;

    /// 执行命令
    ///
    /// # Arguments
    /// * `cmd` - 要执行的命令
    /// * `inbound` - 入站消息（包含通道信息）
    /// * `session_manager` - 会话管理器（用于获取 session）
    ///
    /// # Returns
    /// * `Ok(Some(msg))` - 命令执行成功，返回要发送给用户的消息
    /// * `Ok(None)` - 命令执行成功，无需发送消息
    /// * `Err(AgentError)` - 命令执行失败
    async fn handle(
        &self,
        cmd: Command,
        inbound: &InboundMessage,
        session_manager: &SessionManager,
    ) -> Result<Option<String>, AgentError>;
}

/// 命令路由器
///
/// 负责将命令分发到合适的处理器
pub struct CommandRouter {
    handlers: Vec<Box<dyn CommandHandler>>,
    metadata: Arc<std::sync::Mutex<Vec<CommandMetadata>>>,
}

impl CommandRouter {
    /// 创建新的命令路由器
    pub fn new() -> Self {
        Self {
            handlers: Vec::new(),
            metadata: Arc::new(std::sync::Mutex::new(Vec::new())),
        }
    }

    /// 注册命令处理器
    ///
    /// # Arguments
    /// * `handler` - 要注册的处理器
    pub fn register(&mut self, handler: Box<dyn CommandHandler>) {
        if let Some(meta) = handler.metadata() {
            self.metadata.lock().unwrap().push(meta);
        }
        self.handlers.push(handler);
    }

    /// 获取已注册命令的元数据列表（用于 Help 命令）
    pub fn metadata_arc(&self) -> Arc<std::sync::Mutex<Vec<CommandMetadata>>> {
        self.metadata.clone()
    }

    /// 分发命令到合适的处理器
    ///
    /// # Arguments
    /// * `cmd` - 要执行的命令
    /// * `ctx` - 命令执行上下文
    ///
    /// # Returns
    /// * `Ok(CommandResponse)` - 命令执行成功
    /// * `Err(CommandError)` - 没有合适的处理器或执行失败
    pub async fn dispatch(
        &self,
        cmd: Command,
        ctx: CommandContext,
    ) -> Result<CommandResponse, CommandError> {
        // 查找能处理此命令的处理器
        for handler in &self.handlers {
            if handler.can_handle(&cmd) {
                return handler.handle(cmd, ctx).await;
            }
        }

        // 没有找到合适的处理器
        Err(CommandError::new(
            "NO_HANDLER",
            format!("No handler found for command: {}", cmd.name()),
        ))
    }

    /// 分发命令，返回响应（如果失败则返回错误响应）
    ///
    /// 与 `dispatch` 不同，此方法不会返回 Err，
    /// 而是将错误包装在 CommandResponse 中
    pub async fn dispatch_with_response(
        &self,
        cmd: Command,
        ctx: CommandContext,
    ) -> CommandResponse {
        let request_id = ctx.request_id;
        match self.dispatch(cmd, ctx).await {
            Ok(response) => response,
            Err(err) => CommandResponse::error(request_id, err),
        }
    }
}

impl Default for CommandRouter {
    fn default() -> Self {
        Self::new()
    }
}

/// InChat 命令路由器
///
/// 负责将在聊天中输入的命令分发到合适的处理器
pub struct InChatCommandRouter {
    handlers: Vec<Box<dyn InChatCommandHandler>>,
}

impl InChatCommandRouter {
    /// 创建新的 InChat 命令路由器
    pub fn new() -> Self {
        Self {
            handlers: Vec::new(),
        }
    }

    /// 注册 InChat 命令处理器
    ///
    /// # Arguments
    /// * `handler` - 要注册的处理器
    pub fn register(&mut self, handler: Box<dyn InChatCommandHandler>) {
        self.handlers.push(handler);
    }

    /// 分发命令到合适的处理器
    ///
    /// # Arguments
    /// * `cmd` - 要执行的命令
    /// * `inbound` - 入站消息
    /// * `session_manager` - 会话管理器
    ///
    /// # Returns
    /// * `Ok(Some(msg))` - 命令被处理，返回成功消息
    /// * `Ok(None)` - 没有合适的处理器
    /// * `Err(AgentError)` - 执行失败
    pub async fn dispatch(
        &self,
        cmd: Command,
        inbound: &InboundMessage,
        session_manager: &SessionManager,
    ) -> Result<Option<String>, AgentError> {
        // 查找能处理此命令的处理器
        for handler in &self.handlers {
            if handler.can_handle(&cmd) {
                let result = handler.handle(cmd, inbound, session_manager).await?;
                return Ok(result);
            }
        }

        // 没有找到合适的处理器
        Ok(None)
    }
}

impl Default for InChatCommandRouter {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use uuid::Uuid;

    struct TestHandler;

    #[async_trait]
    impl CommandHandler for TestHandler {
        fn can_handle(&self, cmd: &Command) -> bool {
            matches!(cmd, Command::CreateSession { .. })
        }

        async fn handle(
            &self,
            _cmd: Command,
            ctx: CommandContext,
        ) -> Result<CommandResponse, CommandError> {
            Ok(CommandResponse::success(ctx.request_id)
                .with_message(crate::command::response::MessageKind::Notification, "ok"))
        }
    }

    struct NoOpHandler;

    #[async_trait]
    impl CommandHandler for NoOpHandler {
        fn can_handle(&self, _cmd: &Command) -> bool {
            false
        }

        async fn handle(
            &self,
            _cmd: Command,
            _ctx: CommandContext,
        ) -> Result<CommandResponse, CommandError> {
            unreachable!()
        }
    }

    #[tokio::test]
    async fn test_router_finds_handler() {
        let mut router = CommandRouter::new();
        router.register(Box::new(TestHandler));
        router.register(Box::new(NoOpHandler));

        let ctx = CommandContext::new("test", "test");
        let cmd = Command::CreateSession { title: None };

        let result = router.dispatch(cmd, ctx).await;

        assert!(result.is_ok());
        let resp = result.unwrap();
        assert!(resp.success);
    }

    #[tokio::test]
    async fn test_router_no_handler() {
        let router = CommandRouter::new();

        let ctx = CommandContext::new("test", "test");
        let cmd = Command::CreateSession { title: None };

        let result = router.dispatch(cmd, ctx).await;

        assert!(result.is_err());
    }
}
