use asteroidsfactory::config::parameters::*;
use asteroidsfactory::engine::{collisions, evolution, orbits};
use asteroidsfactory::observables::{lightcurve, photometry};

#[test]
fn mean_motion_positive() {
    let n = orbits::mean_motion(2.5, SOLAR_MASS);
    assert!(n > 0.0);
}

#[test]
fn synodic_period_positive() {
    let s = orbits::synodic_period(YEAR, 1.88 * YEAR);
    assert!(s > 0.0);
}

#[test]
fn synodic_same_period_infinite() {
    let s = orbits::synodic_period(YEAR, YEAR);
    assert!(s.is_infinite());
}

#[test]
fn tisserand_from_elements_range() {
    let tj = orbits::tisserand_from_elements(2.5, 0.1, 0.1, 5.2);
    assert!(tj > 2.0);
    assert!(tj < 4.0);
}

#[test]
fn resonance_width_positive() {
    let w = orbits::resonance_width(2.5, 1.0e-3, 3, 1);
    assert!(w > 0.0);
}

#[test]
fn perihelion_precession_positive() {
    let rate = orbits::perihelion_precession_rate(2.5, 0.1, 0.001, 1.0e6);
    assert!(rate > 0.0);
}

#[test]
fn kozai_lidov_period_positive() {
    let kl = orbits::kozai_lidov_period(11.86 * YEAR, 0.001, AU, 5.2 * AU, 0.05);
    assert!(kl > 0.0);
}

#[test]
fn impact_velocity_greater_than_relative() {
    let v = collisions::impact_velocity(15000.0, 500.0);
    assert!(v > 15000.0);
}

#[test]
fn specific_impact_energy_positive() {
    let q = collisions::specific_impact_energy(20000.0, 1.0e15, 1.0e10);
    assert!(q > 0.0);
}

#[test]
fn catastrophic_disruption_threshold_positive() {
    let q_star = collisions::catastrophic_disruption_threshold(5000.0, 2700.0);
    assert!(q_star > 0.0);
}

#[test]
fn crater_scaling_positive() {
    let d = collisions::crater_diameter_pi_scaling(10.0, 3000.0, 2700.0, 15000.0, 0.003);
    assert!(d > 0.0);
}

#[test]
fn collision_probability_positive() {
    let p = collisions::collision_probability(1.0e-20, 1.0e6, 5000.0);
    assert!(p > 0.0);
}

#[test]
fn collisional_lifetime_positive() {
    let lt = evolution::collisional_lifetime_estimate(5000.0, 2.5);
    assert!(lt > 0.0);
}

#[test]
fn yarkovsky_drift_nonzero() {
    let d = evolution::yarkovsky_semi_major_drift(500.0, 2500.0, 2.5, 45.0);
    assert!(d.abs() > 0.0);
}

#[test]
fn spin_up_timescale_positive() {
    let t = evolution::spin_up_timescale(500.0, 2500.0, 2.5, 6.0 * 3600.0);
    assert!(t > 0.0);
}

#[test]
fn space_weathering_timescale_positive() {
    let t = evolution::space_weathering_timescale(2.5);
    assert!(t > 0.0);
}

#[test]
fn regolith_depth_positive() {
    let mass = sphere_mass(5000.0, 2700.0);
    let g = surface_gravity(mass, 5000.0);
    let d = evolution::regolith_depth_estimate(5000.0, g);
    assert!(d > 0.0);
}

#[test]
fn absolute_magnitude_vesta_like() {
    let h = photometry::absolute_magnitude(265000.0, 0.42);
    assert!(h > 2.0);
    assert!(h < 5.0);
}

#[test]
fn apparent_brighter_when_closer() {
    let h = 20.0;
    let m_close = photometry::apparent_magnitude(h, 1.0, 0.5, 0.1);
    let m_far = photometry::apparent_magnitude(h, 2.0, 1.5, 0.1);
    assert!(m_close < m_far);
}

#[test]
fn diameter_from_h_albedo() {
    let d = photometry::diameter_from_h_albedo(3.3, 0.42);
    assert!(d > 400.0);
    assert!(d < 600.0);
}

#[test]
fn geometric_albedo_from_bond() {
    let g = photometry::geometric_albedo_from_bond(0.3, 0.5);
    assert!((g - 0.6).abs() < 0.01);
}

#[test]
fn lightcurve_amplitude_elongated() {
    let amp = lightcurve::lightcurve_amplitude(2.0);
    assert!(amp > 0.0);
}

#[test]
fn spin_barrier_period() {
    let p = lightcurve::spin_barrier_period(2700.0);
    assert!(p > 7000.0);
    assert!(p < 9000.0);
}

#[test]
fn binary_eclipse_depth_range() {
    let d = lightcurve::binary_eclipse_depth(1000.0, 500.0, 0.15, 0.15);
    assert!(d > 0.0);
    assert!(d < 1.0);
}

#[test]
fn phase_angle_geometry() {
    let alpha = lightcurve::phase_angle_from_geometry(1.0, 1.0, 1.0);
    assert!((alpha - std::f64::consts::PI / 3.0).abs() < 0.01);
}
