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

/// Topic 摘要信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TopicSummary {
    pub topic_id: String,
    pub session_id: String,
    pub title: String,
    pub description: Option<String>,
    pub message_count: i64,
    pub created_at: i64,
    pub last_active_at: i64,
}

/// 列出 Session 的 Topics 命令处理器
pub struct ListTopicsCommandHandler {
    store: Arc<SessionStore>,
}

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

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

    fn metadata(&self) -> Option<CommandMetadata> {
        Some(CommandMetadata {
            name: "topics",
            description: "列出 Session 的所有 Topics",
            usage: "/topics <session_id>",
        })
    }

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

async fn handle_list_topics(
    handler: &ListTopicsCommandHandler,
    session_id: String,
    ctx: CommandContext,
) -> Result<CommandResponse, CommandError> {
    let topics = handler
        .store
        .list_topics(&session_id)
        .map_err(|e| CommandError::new("LIST_TOPICS_ERROR", e.to_string()))?;

    let summaries: Vec<TopicSummary> = topics
        .into_iter()
        .map(|t| TopicSummary {
            topic_id: t.id,
            session_id: t.session_id,
            title: t.title,
            description: t.description.filter(|d| !d.is_empty()),
            message_count: t.message_count,
            created_at: t.created_at,
            last_active_at: t.last_active_at,
        })
        .collect();

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

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

    Ok(CommandResponse::success(ctx.request_id)
        .with_message(MessageKind::Notification, &message)
        .with_metadata("topics", &topics_json)
        .with_metadata("session_id", &session_id)
        .with_metadata("count", &summaries.len().to_string()))
}
