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

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

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

/// 通过 ID 查找记忆的 namespace 和 memory_key
fn find_by_id(
    store: &SessionStore,
    id: &str,
) -> Result<Option<(String, String)>, CommandError> {
    let records = store
        .list_memories_for_scope("user", GLOBAL_SCOPE_KEY)
        .map_err(|e| CommandError::new("LIST_ERROR", e.to_string()))?;
    Ok(records
        .iter()
        .find(|r| r.id == id)
        .map(|r| (r.namespace.clone(), r.memory_key.clone())))
}

#[async_trait]
impl CommandHandler for MemoryCrudCommandHandler {
    fn can_handle(&self, cmd: &Command) -> bool {
        matches!(
            cmd,
            Command::CreateMemory { .. } | Command::UpdateMemory { .. } | Command::DeleteMemory { .. }
        )
    }

    fn metadata(&self) -> Option<CommandMetadata> {
        Some(CommandMetadata {
            name: "memory_crud",
            description: "创建、更新、删除记忆",
            usage: "/memory_crud",
        })
    }

    async fn handle(
        &self,
        cmd: Command,
        ctx: CommandContext,
    ) -> Result<CommandResponse, CommandError> {
        let scope_key = GLOBAL_SCOPE_KEY.to_string();

        match cmd {
            Command::CreateMemory {
                namespace,
                key,
                content,
            } => {
                let input = MemoryUpsert {
                    scope_kind: "user".to_string(),
                    scope_key,
                    namespace,
                    memory_key: key,
                    content,
                    source_type: "manual".to_string(),
                    source_session_id: None,
                    source_message_id: None,
                    source_message_seq: None,
                    source_channel_name: None,
                    source_chat_id: None,
                };
                self.store
                    .put_memory(&input)
                    .map_err(|e| CommandError::new("CREATE_ERROR", e.to_string()))?;
            }

            Command::UpdateMemory { id, content } => {
                let Some((namespace, memory_key)) = find_by_id(&self.store, &id)? else {
                    return Err(CommandError::new("NOT_FOUND", "记忆不存在"));
                };
                let input = MemoryUpsert {
                    scope_kind: "user".to_string(),
                    scope_key,
                    namespace,
                    memory_key,
                    content,
                    source_type: "manual".to_string(),
                    source_session_id: None,
                    source_message_id: None,
                    source_message_seq: None,
                    source_channel_name: None,
                    source_chat_id: None,
                };
                self.store
                    .update_memory(&input)
                    .map_err(|e| CommandError::new("UPDATE_ERROR", e.to_string()))?;
            }

            Command::DeleteMemory { id } => {
                let Some((namespace, memory_key)) = find_by_id(&self.store, &id)? else {
                    return Err(CommandError::new("NOT_FOUND", "记忆不存在"));
                };
                self.store
                    .delete_memory("user", &scope_key, &namespace, &memory_key)
                    .map_err(|e| CommandError::new("DELETE_ERROR", e.to_string()))?;
            }

            _ => unreachable!(),
        }

        Ok(CommandResponse::success(ctx.request_id)
            .with_metadata("memory_updated", "true"))
    }
}
