use crate::sim::Simulation;
use crate::stop::StopId;

use super::helpers::{all_riders_arrived, default_config, scan};

#[test]
fn metrics_track_deliveries() {
    let mut sim = Simulation::new(&default_config(), scan()).unwrap();
    sim.spawn_rider_by_stop_id(StopId(0), StopId(1), 70.0)
        .unwrap();
    sim.spawn_rider_by_stop_id(StopId(0), StopId(2), 60.0)
        .unwrap();

    for _ in 0..20_000 {
        sim.step();
        sim.drain_events();
        if all_riders_arrived(&sim) {
            break;
        }
    }

    let m = sim.metrics();
    assert_eq!(m.total_spawned, 2);
    assert_eq!(m.total_delivered, 2);
    assert!(m.avg_wait_time > 0.0, "avg_wait should be positive");
    assert!(m.avg_ride_time > 0.0, "avg_ride should be positive");
    assert!(m.total_distance > 0.0, "elevators should have traveled");
}

#[test]
fn metrics_wait_time_increases_with_distance() {
    let mut sim1 = Simulation::new(&default_config(), scan()).unwrap();
    sim1.spawn_rider_by_stop_id(StopId(0), StopId(1), 70.0)
        .unwrap();
    for _ in 0..10_000 {
        sim1.step();
        if all_riders_arrived(&sim1) {
            break;
        }
    }
    let wait1 = sim1.metrics().avg_wait_time;

    // The wait time is spawn-to-board, which should be similar regardless of destination
    // since the elevator starts at the origin. But the total ticks should differ.
    assert!(wait1 >= 0.0);
}

#[test]
fn metrics_throughput_window() {
    let mut sim = Simulation::new(&default_config(), scan()).unwrap();
    sim.spawn_rider_by_stop_id(StopId(0), StopId(1), 70.0)
        .unwrap();

    for _ in 0..10_000 {
        sim.step();
        sim.drain_events();
        if all_riders_arrived(&sim) {
            break;
        }
    }

    assert!(
        sim.metrics().throughput >= 1,
        "Should have at least 1 delivery in window"
    );
}
