use neptunes::geology::earthquakes::*;
use neptunes::geology::erosion::*;
use neptunes::geology::mountains::*;
use neptunes::geology::plate_tectonics::*;
use neptunes::geology::volcanism::*;

// ── Earthquakes (Icequakes) ──────────────────────────────────────────────

#[test]
fn icequake_from_moment_magnitude() {
    let q = Icequake::frommoment(20.0, 30.0, 50.0, 1e18);
    let mw = q.momentmagnitude();
    assert!(mw.is_finite());
    assert!(mw > 0.0);
}

#[test]
fn icequake_from_magnitude() {
    let q = Icequake::frommagnitude(10.0, 20.0, 30.0, 5.0);
    assert!(q.seismicmomentnm.is_finite());
    assert!(q.seismicmomentnm > 0.0);
}

#[test]
fn icequake_energy_positive() {
    let q = Icequake::frommoment(0.0, 0.0, 10.0, 1e16);
    let e = q.energyjoules();
    assert!(e.is_finite());
    assert!(e > 0.0);
}

#[test]
fn icequake_pwave_arrival() {
    let q = Icequake::frommoment(0.0, 0.0, 10.0, 1e16);
    let t = q.pwavearrivaltime(100.0, 4.0);
    assert!(t.is_finite());
    assert!(t > 0.0);
}

#[test]
fn icequake_swave_arrival() {
    let q = Icequake::frommoment(0.0, 0.0, 10.0, 1e16);
    let t = q.swavearrivaltime(100.0, 2.3);
    assert!(t.is_finite());
    assert!(t > 0.0);
}

#[test]
fn swave_slower_than_pwave() {
    let q = Icequake::frommoment(0.0, 0.0, 10.0, 1e16);
    let tp = q.pwavearrivaltime(100.0, 4.0);
    let ts = q.swavearrivaltime(100.0, 2.3);
    assert!(ts > tp);
}

#[test]
fn icequake_pga_at_distance() {
    let q = Icequake::frommoment(0.0, 0.0, 10.0, 1e18);
    let pga = q.pgaatdistance(50.0);
    assert!(pga.is_finite());
    assert!(pga >= 0.0);
}

#[test]
fn aftershock_rate_positive() {
    let r = aftershockrate(6.0, 1.0);
    assert!(r.is_finite());
    assert!(r >= 0.0);
}

#[test]
fn annual_frequency_positive() {
    let f = annualfrequency(4.0);
    assert!(f.is_finite());
    assert!(f >= 0.0);
}

#[test]
fn ice_pwave_velocity_positive() {
    let vp = icepwavevelocity(920.0, 8.9e9, 3.5e9);
    assert!(vp.is_finite());
    assert!(vp > 0.0);
}

#[test]
fn ice_swave_velocity_positive() {
    let vs = iceswavevelocity(920.0, 3.5e9);
    assert!(vs.is_finite());
    assert!(vs > 0.0);
}

#[test]
fn pwave_faster_than_swave() {
    let vp = icepwavevelocity(920.0, 8.9e9, 3.5e9);
    let vs = iceswavevelocity(920.0, 3.5e9);
    assert!(vp > vs);
}

#[test]
fn distance_from_sp_time() {
    let d = distancefromsptime(10.0, 18.0, 4.0, 2.3);
    assert!(d.is_finite());
    assert!(d > 0.0);
}

#[test]
fn refraction_angle_finite() {
    let a = refractionangle(4.0, 3.0, 0.3);
    assert!(a.is_finite());
}

// ── Erosion ──────────────────────────────────────────────────────────────

#[test]
fn erosion_params_wind_rate() {
    let ep = ErosionParams {
        windspeedms: 100.0,
        atmosphericdensity: 0.45,
        particlediameterm: 0.0005,
        particledensity: 1600.0,
    };
    let rate = ep.winderosionratemmyr();
    assert!(rate.is_finite());
    assert!(rate >= 0.0);
}

#[test]
fn erosion_params_sediment_yield() {
    let ep = ErosionParams {
        windspeedms: 100.0,
        atmosphericdensity: 0.45,
        particlediameterm: 0.0005,
        particledensity: 1600.0,
    };
    let sy = ep.sedimentyieldtkm2yr();
    assert!(sy.is_finite());
    assert!(sy >= 0.0);
}

#[test]
fn chemical_weathering_rate_finite() {
    let r = chemicalweatheringrate(72.0, 0.45);
    assert!(r.is_finite());
}

#[test]
fn thermal_stress_erosion_finite() {
    let r = thermalstresserosion(20.0, 1e-5);
    assert!(r.is_finite());
    assert!(r >= 0.0);
}

#[test]
fn wind_erosion_threshold_velocity() {
    let v = winderosionthresholdvelocity(0.001, 1600.0);
    assert!(v.is_finite());
    assert!(v > 0.0);
}

#[test]
fn sublimation_erosion_rate_finite() {
    let r = sublimationerosionrate(72.0, 100.0);
    assert!(r.is_finite());
}

// ── Mountains ────────────────────────────────────────────────────────────

#[test]
fn interior_ice_peak_height() {
    let m = interioricepeak();
    let h = m.height();
    assert!(h.is_finite());
    assert!(h >= 0.0);
}

#[test]
fn rocky_core_peak_height() {
    let m = rockycorepeak();
    let h = m.height();
    assert!(h.is_finite());
    assert!(h >= 0.0);
}

#[test]
fn ice_mountain_root_depth() {
    let m = interioricepeak();
    let rd = m.rootdepthm();
    assert!(rd.is_finite());
}

#[test]
fn ice_mountain_total_thickness() {
    let m = interioricepeak();
    let t = m.totalthicknessm();
    assert!(t.is_finite());
    assert!(t > 0.0);
}

#[test]
fn ice_mountain_isostatic_elevation() {
    let m = interioricepeak();
    let ie = m.isostaticelevation();
    assert!(ie.is_finite());
}

// ── Plate Tectonics ─────────────────────────────────────────────────────

#[test]
fn equatorial_cell_velocity_at_equator() {
    let cell = equatorialcell();
    let v = cell.velocityatpoint(0.0, 0.0);
    assert!(v.is_finite());
    assert!(v >= 0.0);
}

#[test]
fn equatorial_cell_velocity_cm_yr() {
    let cell = equatorialcell();
    let vcm = cell.velocitycmperyear(10.0, 20.0);
    assert!(vcm.is_finite());
}

#[test]
fn polar_cell_valid() {
    let cell = polarcell();
    assert!(cell.areakm2 > 0.0);
    assert!(cell.angularvelocitydegmyr.is_finite());
}

#[test]
fn ice_shell_root_depth() {
    let rd = iceshellrootdepth(1000.0);
    assert!(rd.is_finite());
}

#[test]
fn ice_shell_flexural_rigidity() {
    let d = iceshellflexuralrigidity(10000.0, 9e9, 0.3);
    assert!(d.is_finite());
    assert!(d > 0.0);
}

#[test]
fn surface_heat_flow_finite() {
    let q = surfaceheatflow(2.0, 0.02);
    assert!(q.is_finite());
}

#[test]
fn temperature_at_depth() {
    let t = temperatureatdepth(72.0, 1000.0, 0.02);
    assert!(t.is_finite());
    assert!(t > 72.0);
}

#[test]
fn isostatic_balance_finite() {
    let b = isostaticbalance(5000.0);
    assert!(b.is_finite());
}

// ── Volcanism ────────────────────────────────────────────────────────────

#[test]
fn water_ammonia_magma() {
    let m = CryoMagma::waterammonia();
    assert!(m.h2owtpercent > 0.0);
    assert!(m.nh3wtpercent > 0.0);
    assert!(m.temperaturek > 0.0);
}

#[test]
fn methane_rich_magma() {
    let m = CryoMagma::methanerich();
    assert!(m.ch4wtpercent > 0.0);
    assert!(m.temperaturek > 0.0);
}

#[test]
fn silicate_core_magma() {
    let m = CryoMagma::silicatecore();
    assert!(m.sio2wtpercent > 0.0);
    assert!(m.temperaturek > 0.0);
}

#[test]
fn magma_mg_number() {
    let m = CryoMagma::silicatecore();
    let mg = m.mgnumber();
    assert!(mg.is_finite());
    assert!(mg >= 0.0);
}

#[test]
fn magma_total_alkali() {
    let m = CryoMagma::waterammonia();
    let ta = m.totalalkali();
    assert!(ta.is_finite());
    assert!(ta >= 0.0);
}

#[test]
fn magma_liquidus_temp() {
    let m = CryoMagma::waterammonia();
    let lt = m.liquidustempc();
    assert!(lt.is_finite());
}

#[test]
fn magma_viscosity() {
    let m = CryoMagma::waterammonia();
    let v = m.viscositypas();
    assert!(v.is_finite());
    assert!(v > 0.0);
}

#[test]
fn magma_solidus_depression() {
    let m = CryoMagma::waterammonia();
    let sd = m.solidusdepressionc();
    assert!(sd.is_finite());
}

#[test]
fn magma_differentiation_idx() {
    let m = CryoMagma::silicatecore();
    let di = m.differentiationidx();
    assert!(di.is_finite());
}

#[test]
fn cryovolcanic_explosivity_index() {
    assert_eq!(cryovolcanicexplosivityindex(1e-7), 0);
    let vei = cryovolcanicexplosivityindex(100.0);
    assert_eq!(vei, 8);
}
