#![allow(clippy::expect_used, clippy::unwrap_used)]

use std::sync::Arc;
use std::sync::Mutex;

use async_trait::async_trait;
use capo_agent::{AppBuilder, Config, Skill, SkillSource, UserMessage};
use futures::StreamExt;
use motosan_agent_loop::{ChatOutput, LlmClient, LlmResponse, Message, Role};
use motosan_agent_tool::ToolDef;

struct CapturingClient {
    last_system: Mutex<Option<String>>,
}

impl CapturingClient {
    fn new() -> Self {
        Self {
            last_system: Mutex::new(None),
        }
    }
}

#[async_trait]
impl LlmClient for CapturingClient {
    async fn chat(
        &self,
        messages: &[Message],
        _tools: &[ToolDef],
    ) -> motosan_agent_loop::Result<ChatOutput> {
        if let Some(sys) = messages.iter().find(|m| matches!(m.role(), Role::System)) {
            *self.last_system.lock().expect("lock") = Some(sys.text());
        }

        Ok(ChatOutput::new(LlmResponse::Message("ok".into())))
    }
}

#[tokio::test]
async fn system_prompt_includes_available_skills_block() {
    let llm = Arc::new(CapturingClient::new());

    let fixture_dir =
        std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/skills");
    let skill = Skill {
        name: "quick-tip".into(),
        description: "A quick tip used by tests".into(),
        file_path: fixture_dir.join("quick-tip.md"),
        base_dir: fixture_dir,
        disable_model_invocation: false,
        source: SkillSource::Global,
    };

    let mut config = Config::default();
    config.anthropic.api_key = Some("sk-unused-in-this-test".into());

    let app = AppBuilder::new()
        .with_config(config)
        .with_llm(Arc::clone(&llm) as Arc<dyn LlmClient>)
        .with_builtin_tools()
        .disable_context_discovery()
        .with_skills(vec![skill])
        .build()
        .await
        .expect("build");

    let _events: Vec<_> = app
        .send_user_message(UserMessage::text("hello"))
        .collect()
        .await;

    let sys = llm
        .last_system
        .lock()
        .expect("lock")
        .clone()
        .expect("system prompt captured");
    assert!(sys.contains("<available_skills>"), "got:\n{sys}");
    assert!(sys.contains("<name>quick-tip</name>"), "got:\n{sys}");
}
