//! Python bindings for ConversationMemory

use pyo3::prelude::*;

use flowgentra_ai::core::memory::{ConversationMemory, InMemoryConversationMemory};

use crate::error::to_py_err;
use crate::llm::PyMessage;

// ─── PyConversationMemory ──────────────────────────────────────────────────

/// In-memory conversation memory with optional sliding window.
///
/// Stores message history per thread ID.
///
/// Example:
///     mem = ConversationMemory()
///     mem.add_message("thread-1", Message.user("Hello"))
///     mem.add_message("thread-1", Message.assistant("Hi!"))
///     messages = mem.messages("thread-1")
///     print(len(messages))  # 2
#[pyclass(name = "ConversationMemory")]
pub struct PyConversationMemory {
    inner: InMemoryConversationMemory,
}

#[pymethods]
impl PyConversationMemory {
    /// Create a new conversation memory.
    ///
    /// Args:
    ///     max_messages: Optional sliding window size (keep last N messages per thread)
    #[new]
    #[pyo3(signature = (max_messages=None))]
    fn new(max_messages: Option<usize>) -> Self {
        let mut mem = InMemoryConversationMemory::new();
        if let Some(max) = max_messages {
            mem = mem.with_max_messages(max);
        }
        PyConversationMemory { inner: mem }
    }

    /// Add a message for a thread.
    fn add_message(&self, thread_id: &str, message: &PyMessage) -> PyResult<()> {
        self.inner
            .add_message(thread_id, message.inner.clone())
            .map_err(to_py_err)
    }

    /// Get messages for a thread (oldest first).
    ///
    /// Args:
    ///     thread_id: The thread identifier
    ///     limit: Optional max number of recent messages to return
    #[pyo3(signature = (thread_id, limit=None))]
    fn messages(&self, thread_id: &str, limit: Option<usize>) -> PyResult<Vec<PyMessage>> {
        let msgs = self.inner.messages(thread_id, limit).map_err(to_py_err)?;
        Ok(msgs.into_iter().map(|m| PyMessage { inner: m }).collect())
    }

    /// Clear all messages for a thread.
    fn clear(&self, thread_id: &str) -> PyResult<()> {
        self.inner.clear(thread_id).map_err(to_py_err)
    }

    fn __repr__(&self) -> String {
        "ConversationMemory(...)".to_string()
    }
}
