use crate::command::context::CommandContext;
use crate::command::handler::{CommandHandler, CommandMetadata};
use crate::command::handlers::list_topics::TopicSummary;
use crate::command::response::{CommandError, CommandResponse, MessageKind};
use crate::command::Command;
use crate::gateway::session::SessionManager;
use crate::storage::SessionStore;
use async_trait::async_trait;
use std::sync::Arc;

/// 删除话题命令处理器
pub struct DeleteTopicCommandHandler {
    store: Arc<SessionStore>,
    session_manager: Option<SessionManager>,
}

impl DeleteTopicCommandHandler {
    pub fn new(store: Arc<SessionStore>) -> Self {
        Self {
            store,
            session_manager: None,
        }
    }

    pub fn with_session_manager(mut self, session_manager: SessionManager) -> Self {
        self.session_manager = Some(session_manager);
        self
    }
}

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

    fn metadata(&self) -> Option<CommandMetadata> {
        Some(CommandMetadata {
            name: "delete",
            description: "删除指定话题",
            usage: "/delete <topic_id>",
        })
    }

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

async fn handle_delete_topic(
    handler: &DeleteTopicCommandHandler,
    topic_id: String,
    ctx: CommandContext,
) -> Result<CommandResponse, CommandError> {
    let session_id = ctx
        .session_id
        .as_deref()
        .ok_or_else(|| CommandError::new("NO_SESSION", "No active session"))?;

    // 验证话题存在
    let topic = handler
        .store
        .get_topic(&topic_id)
        .map_err(|e| CommandError::new("GET_TOPIC_ERROR", e.to_string()))?
        .ok_or_else(|| {
            CommandError::new("TOPIC_NOT_FOUND", format!("Topic not found: {}", topic_id))
        })?;

    let topic_title = topic.title.clone();

    // 删除话题（存储层方法已存在）
    handler
        .store
        .delete_topic(&topic_id)
        .map_err(|e| CommandError::new("DELETE_TOPIC_ERROR", e.to_string()))?;

    // 查询更新后的话题列表，返回给前端刷新侧边栏
    let topics = handler
        .store
        .list_topics(session_id)
        .map_err(|e| CommandError::new("LIST_TOPICS_ERROR", e.to_string()))?;

    let topic_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(&topic_summaries)
            .map_err(|e| CommandError::new("SERIALIZE_ERROR", e.to_string()))?;

    let message = format!("✓ 已删除话题: {}", topic_title);

    Ok(CommandResponse::success(ctx.request_id)
        .with_message(MessageKind::Notification, &message)
        .with_metadata("topics", &topics_json)
        .with_metadata("deleted_topic_id", &topic_id))
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::storage::SessionStore;
    use std::sync::Arc;

    fn create_test_handler() -> DeleteTopicCommandHandler {
        let store = Arc::new(SessionStore::in_memory().unwrap());
        DeleteTopicCommandHandler::new(store)
    }

    #[tokio::test]
    async fn test_delete_topic_success() {
        let handler = create_test_handler();
        let store = handler.store.clone();

        // 先创建 session 和 topic
        let session = store.create_session("test_channel", Some("test")).unwrap();
        let topic = store
            .create_topic(&session.id, "test topic", None)
            .unwrap();

        let ctx = CommandContext::new("test", "test_channel")
            .with_session_id(&session.id)
            .with_chat_id(&session.id);
        let cmd = Command::DeleteTopic {
            topic_id: topic.id.clone(),
        };

        let result = handler.handle(cmd, ctx).await;
        assert!(result.is_ok());

        let resp = result.unwrap();
        assert!(resp.success);
        assert!(resp.metadata.contains_key("deleted_topic_id"));

        // 验证话题已被删除
        let deleted = store.get_topic(&topic.id).unwrap();
        assert!(deleted.is_none());
    }

    #[tokio::test]
    async fn test_delete_nonexistent_topic() {
        let handler = create_test_handler();
        let store = handler.store.clone();

        let session = store.create_session("test_channel", Some("test")).unwrap();
        let ctx = CommandContext::new("test", "test_channel")
            .with_session_id(&session.id)
            .with_chat_id(&session.id);
        let cmd = Command::DeleteTopic {
            topic_id: "nonexistent".to_string(),
        };

        let result = handler.handle(cmd, ctx).await;
        assert!(result.is_err());
    }

    #[test]
    fn test_can_handle() {
        let handler = create_test_handler();
        assert!(handler.can_handle(&Command::DeleteTopic {
            topic_id: "test".to_string()
        }));
        assert!(!handler.can_handle(&Command::Help));
    }
}
