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

/// Memory 摘要信息（发送给前端）
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemorySummary {
    pub id: String,
    pub namespace: String,
    pub memory_key: String,
    pub content: String,
    pub created_at: i64,
    pub updated_at: i64,
}

pub struct ListMemoriesCommandHandler {
    store: Arc<SessionStore>,
}

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

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

    fn metadata(&self) -> Option<CommandMetadata> {
        Some(CommandMetadata {
            name: "list_memories",
            description: "列出所有记忆",
            usage: "/list_memories",
        })
    }

    async fn handle(
        &self,
        _cmd: Command,
        ctx: CommandContext,
    ) -> Result<CommandResponse, CommandError> {
        let records = self
            .store
            .list_memories_for_scope("user", crate::storage::GLOBAL_SCOPE_KEY)
            .map_err(|e| CommandError::new("LIST_MEMORIES_ERROR", e.to_string()))?;

        let summaries: Vec<MemorySummary> = records
            .into_iter()
            .filter(|m| m.namespace != "_meta")
            .map(|m| MemorySummary {
                id: m.id,
                namespace: m.namespace,
                memory_key: m.memory_key,
                content: m.content,
                created_at: m.created_at,
                updated_at: m.updated_at,
            })
            .collect();

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

        Ok(CommandResponse::success(ctx.request_id)
            .with_metadata("memories", &memories_json))
    }
}
