use neptunes::hydrology::glaciers::*;
use neptunes::hydrology::lakes::*;
use neptunes::hydrology::oceans::*;
use neptunes::hydrology::rivers::*;

// ── Glaciers ─────────────────────────────────────────────────────────────

#[test]
fn ice_density_positive() {
    let d = icedensity();
    assert!(d.is_finite());
    assert!(d > 0.0);
}

#[test]
fn water_molar_mass_from_elements() {
    let mm = watermolarmassfromelements();
    assert!(mm.is_finite());
    assert!(mm > 0.0);
}

#[test]
fn water_ice_mantle_mass_balance() {
    let layer = watericemantle();
    let mb = layer.massbalancemyr();
    assert!(mb.is_finite());
}

#[test]
fn water_ice_mantle_basal_shear() {
    let layer = watericemantle();
    let bs = layer.basalshearstresspa();
    assert!(bs.is_finite());
    assert!(bs >= 0.0);
}

#[test]
fn water_ice_mantle_deformation_velocity() {
    let layer = watericemantle();
    let dv = layer.deformationvelocitymyr();
    assert!(dv.is_finite());
}

#[test]
fn water_ice_mantle_volume() {
    let layer = watericemantle();
    let v = layer.volumem3(1e6);
    assert!(v.is_finite());
    assert!(v > 0.0);
}

#[test]
fn methane_ice_cap_valid() {
    let layer = methaneicecap();
    assert!(layer.thicknessm > 0.0);
    let mb = layer.massbalancemyr();
    assert!(mb.is_finite());
}

#[test]
fn methane_ice_cap_basal_shear() {
    let layer = methaneicecap();
    let bs = layer.basalshearstresspa();
    assert!(bs.is_finite());
}

#[test]
fn ice_rheology_viscosity_positive() {
    let v = icerheologyviscosity(200.0, 1e5);
    assert!(v.is_finite());
    assert!(v > 0.0);
}

#[test]
fn glen_strain_rate_finite() {
    let sr = glenstrainrate(200.0, 1e5);
    assert!(sr.is_finite());
    assert!(sr >= 0.0);
}

#[test]
fn shallow_ice_velocity_finite() {
    let v = shallowicevelocity(1000.0, 0.05, 200.0);
    assert!(v.is_finite());
}

// ── Lakes ────────────────────────────────────────────────────────────────

#[test]
fn hypothetical_subsurface_ocean_fields() {
    let lake = hypotheticalsubsurfaceocean();
    assert!(lake.surfaceareakm2 >= 0.0);
    assert!(lake.maxdepthm >= 0.0);
    assert!(lake.volumekm3 >= 0.0);
    assert!(lake.temperaturek >= 0.0);
}

#[test]
fn hypothetical_subsurface_ocean_mean_depth() {
    let lake = hypotheticalsubsurfaceocean();
    let md = lake.meandepthm();
    assert!(md.is_finite());
    assert!(md >= 0.0);
}

#[test]
fn cryo_lake_shoreline_development() {
    let lake = CryoLake {
        name: "TestLake",
        surfaceareakm2: 100.0,
        maxdepthm: 50.0,
        volumekm3: 3.0,
        temperaturek: 200.0,
    };
    let sdr = lake.shorelinedevelopmentratio(40.0);
    assert!(sdr.is_finite());
    assert!(sdr > 0.0);
}

#[test]
fn cryo_lake_residence_time() {
    let lake = CryoLake {
        name: "TestLake",
        surfaceareakm2: 100.0,
        maxdepthm: 50.0,
        volumekm3: 3.0,
        temperaturek: 200.0,
    };
    let rt = lake.residencetimeyears(10.0);
    assert!(rt.is_finite());
    assert!(rt > 0.0);
}

#[test]
fn cryo_lake_thermal_energy() {
    let lake = CryoLake {
        name: "TestLake",
        surfaceareakm2: 100.0,
        maxdepthm: 50.0,
        volumekm3: 3.0,
        temperaturek: 250.0,
    };
    let e = lake.thermalenergyjoulesrelative(200.0);
    assert!(e.is_finite());
}

#[test]
fn cryo_lake_longwave_radiation() {
    let lake = CryoLake {
        name: "TestLake",
        surfaceareakm2: 100.0,
        maxdepthm: 50.0,
        volumekm3: 3.0,
        temperaturek: 200.0,
    };
    let lw = lake.longwaveradiationwm2(0.95);
    assert!(lw.is_finite());
    assert!(lw >= 0.0);
}

// ── Oceans ───────────────────────────────────────────────────────────────

#[test]
fn superionic_layer_density() {
    let layer = superioniclayer();
    let d = layer.densitykgm3();
    assert!(d.is_finite());
    assert!(d > 0.0);
}

#[test]
fn superionic_layer_pressure() {
    let layer = superioniclayer();
    let p = layer.pressureatdepth(1e6);
    assert!(p.is_finite());
    assert!(p > 0.0);
}

#[test]
fn superionic_layer_sound_speed() {
    let layer = superioniclayer();
    let ss = layer.soundspeedms();
    assert!(ss.is_finite());
    assert!(ss > 0.0);
}

#[test]
fn ionic_layer_valid() {
    let layer = ioniclayer();
    assert!(layer.meantemperaturek > 0.0);
    assert!(layer.compositionh2ofraction >= 0.0);
    assert!(layer.compositionh2ofraction <= 1.0);
}

#[test]
fn molecular_layer_valid() {
    let layer = molecularlayer();
    let d = layer.densitykgm3();
    assert!(d.is_finite());
    assert!(d > 0.0);
}

#[test]
fn interior_heat_content_finite() {
    let hc = interiorheatcontentj(1.0, 1000.0);
    assert!(hc.is_finite());
}

#[test]
fn surface_longwave_radiation_positive() {
    let lw = surfacelongwaveradiationwm2(200.0, 0.95);
    assert!(lw.is_finite());
    assert!(lw > 0.0);
}

#[test]
fn vapor_pressure_over_methane() {
    let vp = vaporpressureovermethane(100.0);
    assert!(vp.is_finite());
}

#[test]
fn dissolved_gas_henry() {
    let c = dissolvedgashenry(1e5, 200.0, 1e-3);
    assert!(c.is_finite());
    assert!(c >= 0.0);
}

#[test]
fn h2o_molar_mass_positive() {
    let mm = h2omolarmass();
    assert!(mm.is_finite());
    assert!(mm > 0.0);
}

#[test]
fn interior_ocean_depth_constant() {
    const { assert!(neptunes::hydrology::oceans::INTERIOROCEANDEPTHM > 0.0) };
}

#[test]
fn ionic_ocean_density_constant() {
    const { assert!(neptunes::hydrology::oceans::IONICOCEANDENSITY > 0.0) };
}

// ── Rivers (Atmospheric Flows) ──────────────────────────────────────────

#[test]
fn equatorial_jet_stream_power() {
    let flow = equatorialjet();
    let sp = flow.streampowerwperm();
    assert!(sp.is_finite());
}

#[test]
fn equatorial_jet_specific_discharge() {
    let flow = equatorialjet();
    let sd = flow.specificdischargems();
    assert!(sd.is_finite());
}

#[test]
fn polar_jet_valid() {
    let flow = polarjet();
    assert!(flow.lengthkm > 0.0);
    assert!(flow.flowratem3s.is_finite());
}

#[test]
fn atmospheric_flow_manning_velocity() {
    let flow = equatorialjet();
    let v = flow.manningvelocity(100.0, 0.03);
    assert!(v.is_finite());
}

#[test]
fn atmospheric_flow_froude_number() {
    let flow = equatorialjet();
    let fr = flow.froudenumber(50.0, 1000.0);
    assert!(fr.is_finite());
    assert!(fr >= 0.0);
}

#[test]
fn atmospheric_flow_reynolds_number() {
    let flow = equatorialjet();
    let re = flow.reynoldsnumber(50.0, 1000.0);
    assert!(re.is_finite());
}

#[test]
fn flow_network_default() {
    let net = FlowNetwork::new();
    assert!(net.segments.is_empty());
}

#[test]
fn flow_network_add_headwater() {
    let mut net = FlowNetwork::new();
    let idx = net.addheadwater(equatorialjet());
    assert_eq!(idx, 0);
}

#[test]
fn flow_network_route_discharge() {
    let mut net = FlowNetwork::new();
    let i0 = net.addheadwater(equatorialjet());
    let i1 = net.addheadwater(polarjet());
    net.connect(i1, i0);
    let discharges = net.routedischarge();
    assert_eq!(discharges.len(), 2);
    for d in &discharges {
        assert!(d.is_finite());
    }
}

#[test]
fn neptune_jet_network_valid() {
    let net = neptunejetnetwork();
    assert!(!net.segments.is_empty());
    let od = net.outletdischarge();
    assert!(od.is_finite());
}
