use crate::command::context::CommandContext;
use crate::command::handler::{CommandHandler, CommandMetadata};
use crate::command::response::{CommandError, CommandResponse, MessageKind};
use crate::command::Command;
use crate::protocol::SessionSummary;
use crate::storage::SessionStore;
use async_trait::async_trait;
use std::sync::Arc;

/// 按通道列出会话命令处理器
pub struct ListSessionsByChannelCommandHandler {
    store: Arc<SessionStore>,
}

impl ListSessionsByChannelCommandHandler {
    pub fn new(store: Arc<SessionStore>) -> Self {
        Self { store }
    }
}

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

    fn metadata(&self) -> Option<CommandMetadata> {
        Some(CommandMetadata {
            name: "list_by_channel",
            description: "列出指定通道的所有会话",
            usage: "/list_by_channel <channel_name>",
        })
    }

    async fn handle(
        &self,
        cmd: Command,
        ctx: CommandContext,
    ) -> Result<CommandResponse, CommandError> {
        match cmd {
            Command::ListSessionsByChannel {
                channel_name,
                include_archived,
            } => handle_list_sessions_by_channel(self, channel_name, include_archived, ctx).await,
            _ => unreachable!(),
        }
    }
}

async fn handle_list_sessions_by_channel(
    handler: &ListSessionsByChannelCommandHandler,
    channel_name: String,
    include_archived: bool,
    ctx: CommandContext,
) -> Result<CommandResponse, CommandError> {
    let sessions = handler
        .store
        .list_sessions(&channel_name, include_archived)
        .map_err(|e| CommandError::new("LIST_SESSIONS_ERROR", e.to_string()))?;

    let summaries: Vec<SessionSummary> = sessions
        .into_iter()
        .map(|s| SessionSummary {
            session_id: s.id,
            title: s.title,
            channel_name: s.channel_name,
            chat_id: s.chat_id,
            message_count: s.message_count,
            last_active_at: s.last_active_at,
            archived_at: s.archived_at,
        })
        .collect();

    let sessions_json = serde_json::to_string(&summaries)
        .map_err(|e| CommandError::new("SERIALIZE_ERROR", e.to_string()))?;

    let message = format!(
        "Found {} session(s) in channel '{}'",
        summaries.len(),
        channel_name
    );

    Ok(CommandResponse::success(ctx.request_id)
        .with_message(MessageKind::Notification, &message)
        .with_metadata("sessions", &sessions_json)
        .with_metadata("channel_name", &channel_name)
        .with_metadata("count", &summaries.len().to_string()))
}
