//! Integration test: importer trait progress events fire in expected order.
//!
//! Drives a full `ChatGptImporter::import` against a fixture and asserts on
//! the `ImportProgressEvent` sequence observed on the paired receiver.

use std::sync::Arc;
use tempfile::TempDir;

use dirigent_archivist::{
    backends::JsonlBackend,
    coordinator::Archivist,
    import::{
        ImportConfig, ImportProgressEvent, ImportProgressSink, ImportTarget, ImporterRegistry,
    },
};

#[tokio::test]
async fn progress_event_sequence_is_well_formed() {
    // 1. Setup an in-memory archivist (JsonlBackend in tempdir).
    let dir = TempDir::new().unwrap();
    let backend = Arc::new(JsonlBackend::new(dir.path().to_path_buf()).await.unwrap());
    let archivist = Archivist::from_single_backend("main".into(), backend)
        .await
        .unwrap();
    let archivist = Arc::new(archivist);

    // 2. Use the chatgpt fixture — a minimal conversations.json with a
    //    user + assistant message pair.
    let fixture = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("../dirigent_chatgpt/tests/fixtures/minimal.json");
    assert!(
        fixture.exists(),
        "chatgpt fixture missing at {}",
        fixture.display()
    );

    let cfg = ImportConfig {
        source: "chatgpt".into(),
        params: {
            let mut m = std::collections::BTreeMap::new();
            m.insert("path".into(), serde_json::json!(fixture.display().to_string()));
            m
        },
    };

    // 3. Run the import with a channel sink.
    let registry = ImporterRegistry::default();
    let importer = registry.get("chatgpt").expect("chatgpt registered");
    let (sink, mut rx) = ImportProgressSink::channel();

    let archivist_for_job = archivist.clone();
    let job = tokio::spawn(async move {
        importer
            .import(&cfg, &*archivist_for_job, ImportTarget::default(), sink)
            .await
    });

    // 4. Collect all events until the sender side is dropped.
    let mut events = Vec::new();
    while let Some(evt) = rx.recv().await {
        events.push(evt);
    }
    let stats = job.await.unwrap().expect("import");

    // 5. Assertions on the event sequence.
    // Must contain at least one SessionStarted before any SessionFinished.
    let started_idx = events
        .iter()
        .position(|e| matches!(e, ImportProgressEvent::SessionStarted { .. }));
    let finished_idx = events
        .iter()
        .position(|e| matches!(e, ImportProgressEvent::SessionFinished { .. }));

    assert!(started_idx.is_some(), "expected a SessionStarted event");
    assert!(finished_idx.is_some(), "expected a SessionFinished event");
    assert!(
        started_idx.unwrap() < finished_idx.unwrap(),
        "SessionStarted must precede SessionFinished"
    );

    // Stats shows at least 2 messages written (chatgpt fixture has a user
    // + assistant pair).
    assert!(
        stats.messages_written >= 2,
        "expected messages to be written, got stats {:?}",
        stats
    );
    assert_eq!(stats.sessions_imported, 1);
}
