use std::collections::HashMap;
use std::time::Duration;

use crate::TidalDb;
use crate::schema::{AgentPolicy, DecaySpec, EntityKind, SchemaBuilder, Window};
use crate::session as session_mod;

/// Build a minimal schema with one signal type and one session policy.
fn schema_with_policy() -> crate::schema::Schema {
    let mut builder = SchemaBuilder::new();
    let _ = builder
        .signal(
            "view",
            EntityKind::Item,
            DecaySpec::Exponential {
                half_life: Duration::from_secs(3600),
            },
        )
        .windows(&[Window::OneHour])
        .velocity(false)
        .add();
    builder.session_policy(
        "default",
        AgentPolicy {
            allowed_signals: vec!["view".to_string()],
            denied_signals: vec![],
            max_session_duration: Duration::from_secs(3600),
            max_signals_per_session: 0,
        },
    );
    builder.build().expect("schema must be valid")
}

#[test]
fn closed_sessions_evicted_when_cap_exceeded() {
    let schema = schema_with_policy();
    let db = TidalDb::builder()
        .ephemeral()
        .with_schema(schema)
        .open()
        .unwrap();

    let cap = session_mod::MAX_CLOSED_SESSIONS;

    // Open and close cap + 100 sessions to trigger at least one eviction cycle.
    for i in 0..(cap + 100) {
        let handle = db
            .start_session(i as u64, "test-agent", "default", HashMap::new())
            .unwrap();
        db.close_session(handle).unwrap();
    }

    // After eviction, the closed_sessions map should be at most cap
    // (it will be at most cap because the eviction fires when len >= cap
    // and removes EVICT_BATCH_SIZE entries).
    let len = db.closed_sessions.len();
    assert!(
        len <= cap,
        "closed_sessions should be bounded: {len} > {cap}"
    );

    db.close().unwrap();
}
