//! Reset command: clear the current Claude Code session for a room.
//!
//! `{bot_name} reset` drops the stored session ID and conversation history for
//! the current room so the next message starts a brand-new Claude Code session
//! with clean context.  File-system memories (auto-memory directory) are not
//! affected — only the in-memory/persisted conversation state is cleared.

use crate::chat::transport::matrix::bot::{ConversationHistory, RoomConversation};
use crate::chat::util::strip_bot_mention;
use matrix_sdk::ruma::OwnedRoomId;
use std::path::Path;

/// A parsed reset command.
#[derive(Debug, PartialEq)]
pub struct ResetCommand;

/// Parse a reset command from a raw message body.
///
/// Strips the bot mention prefix and checks whether the command word is
/// `reset`.  Returns `None` when the message is not a reset command at all.
pub fn extract_reset_command(
    message: &str,
    bot_name: &str,
    bot_user_id: &str,
) -> Option<ResetCommand> {
    let stripped = strip_bot_mention(message, bot_name, bot_user_id);
    let trimmed = stripped
        .trim()
        .trim_start_matches(|c: char| !c.is_alphanumeric());

    let cmd = match trimmed.split_once(char::is_whitespace) {
        Some((c, _)) => c,
        None => trimmed,
    };

    if cmd.eq_ignore_ascii_case("reset") {
        Some(ResetCommand)
    } else {
        None
    }
}

/// Handle a reset command: clear the session ID and conversation entries for
/// the given room, persist the updated history, and return a confirmation.
pub async fn handle_reset(
    bot_name: &str,
    room_id: &OwnedRoomId,
    history: &ConversationHistory,
    project_root: &Path,
) -> String {
    {
        let mut guard = history.lock().await;
        let conv = guard
            .entry(room_id.clone())
            .or_insert_with(RoomConversation::default);
        conv.session_id = None;
        conv.entries.clear();
        crate::chat::transport::matrix::bot::save_history(project_root, &guard);
    }
    crate::slog!("[matrix-bot] reset command: cleared session for room {room_id} (bot={bot_name})");
    "Session reset. Starting fresh — previous context has been cleared.".to_string()
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn extract_with_display_name() {
        let cmd = extract_reset_command("Timmy reset", "Timmy", "@timmy:home.local");
        assert_eq!(cmd, Some(ResetCommand));
    }

    #[test]
    fn extract_with_full_user_id() {
        let cmd = extract_reset_command("@timmy:home.local reset", "Timmy", "@timmy:home.local");
        assert_eq!(cmd, Some(ResetCommand));
    }

    #[test]
    fn extract_with_localpart() {
        let cmd = extract_reset_command("@timmy reset", "Timmy", "@timmy:home.local");
        assert_eq!(cmd, Some(ResetCommand));
    }

    #[test]
    fn extract_case_insensitive() {
        let cmd = extract_reset_command("Timmy RESET", "Timmy", "@timmy:home.local");
        assert_eq!(cmd, Some(ResetCommand));
    }

    #[test]
    fn extract_non_reset_returns_none() {
        let cmd = extract_reset_command("Timmy help", "Timmy", "@timmy:home.local");
        assert_eq!(cmd, None);
    }

    #[test]
    fn extract_ignores_extra_args() {
        // "reset" with trailing text is still a reset command
        let cmd = extract_reset_command("Timmy reset everything", "Timmy", "@timmy:home.local");
        assert_eq!(cmd, Some(ResetCommand));
    }

    #[tokio::test]
    async fn handle_reset_clears_session_and_entries() {
        use crate::chat::transport::matrix::bot::{ConversationEntry, ConversationRole};
        use std::collections::HashMap;
        use std::sync::Arc;
        use tokio::sync::Mutex as TokioMutex;

        let room_id: OwnedRoomId = "!test:example.com".parse().unwrap();
        let history: ConversationHistory = Arc::new(TokioMutex::new({
            let mut m = HashMap::new();
            m.insert(
                room_id.clone(),
                RoomConversation {
                    session_id: Some("old-session-id".to_string()),
                    entries: vec![ConversationEntry {
                        role: ConversationRole::User,
                        sender: "@alice:example.com".to_string(),
                        content: "previous message".to_string(),
                    }],
                    ..Default::default()
                },
            );
            m
        }));

        let tmp = tempfile::tempdir().unwrap();
        let response = handle_reset("Timmy", &room_id, &history, tmp.path()).await;

        assert!(
            response.contains("reset"),
            "response should mention reset: {response}"
        );

        let guard = history.lock().await;
        let conv = guard.get(&room_id).unwrap();
        assert!(conv.session_id.is_none(), "session_id should be cleared");
        assert!(conv.entries.is_empty(), "entries should be cleared");
    }
}
