use async_trait::async_trait;

use crate::error::Result;

/// A provider that builds dynamic context to inject into the conversation
/// before each agent loop run.
///
/// Implementations can supply RAG-retrieved documents, user profile data,
/// tool documentation, upstream workflow outputs, or any other contextual
/// information the LLM should consider.
///
/// The returned string is injected as a `System` message at the beginning
/// of the conversation. If the returned string is empty, no message is added.
#[async_trait]
pub trait ContextProvider: Send + Sync {
    /// Build a context string from the user query.
    ///
    /// Called exactly once per [`AgentLoop::run`](crate::AgentLoop::run) invocation,
    /// before the main reasoning loop begins.
    async fn build(&self, query: &str) -> Result<String>;
}

/// A simple context provider that always returns a fixed string.
///
/// Used internally by [`AgentLoopBuilder::system_prompt`](crate::AgentLoopBuilder::system_prompt).
pub(crate) struct StringContextProvider(pub(crate) String);

#[async_trait]
impl ContextProvider for StringContextProvider {
    async fn build(&self, _query: &str) -> Result<String> {
        Ok(self.0.clone())
    }
}
