use mercurys::physics::collisions::caloris_impactor;
use mercurys::physics::orbit::MercuryOrbit;
use mercurys::physics::rotation::MercuryRotation;
use mercurys::physics::tides::{SolarTide, bulge_variation, perihelion_aphelion_tide_ratio};
use mercurys::satellites::artificial::all_missions;
use mercurys::satellites::none::hill_sphere_radius_m;

fn main() {
    println!("=== Orbital Mechanics ===");
    let orbit = MercuryOrbit::new();
    println!("  Period: {:.2} Earth days", orbit.orbital_period_days());
    println!("  Perihelion: {:.3e} m", orbit.perihelion_m());
    println!("  Aphelion: {:.3e} m", orbit.aphelion_m());
    println!(
        "  Escape velocity: {:.0} m/s",
        MercuryOrbit::escape_velocity_at_surface()
    );
    println!(
        "  GR precession: {:.2e} rad/orbit",
        orbit.gr_perihelion_precession_rad_per_orbit()
    );

    println!("\n=== Orbit Trace (every 30°) ===");
    for deg in (0..360).step_by(30) {
        let o = MercuryOrbit::at_mean_anomaly((deg as f64).to_radians());
        let (x, y, z) = o.position();
        let r_au = (x * x + y * y + z * z).sqrt() / 1.496e11;
        println!(
            "  M={:>3}°  r={:.4} AU  irradiance={:.0} W/m²",
            deg,
            r_au,
            o.solar_irradiance()
        );
    }

    println!("\n=== Solar Tides ===");
    for (label, tide) in [
        ("Perihelion", SolarTide::at_perihelion()),
        ("Mean", SolarTide::at_mean_distance()),
        ("Aphelion", SolarTide::at_aphelion()),
    ] {
        println!(
            "  {}: tidal_accel={:.2e} m/s²  bulge={:.2e} m",
            label,
            tide.tidal_acceleration(),
            tide.tidal_bulge_height()
        );
    }
    let (bulge_peri, bulge_aph) = bulge_variation();
    println!(
        "  Bulge variation: {:.2e} — {:.2e} m",
        bulge_peri, bulge_aph
    );
    println!(
        "  Tide ratio peri/aph: {:.1}",
        perihelion_aphelion_tide_ratio()
    );

    println!("\n=== Rotation ===");
    let rot = MercuryRotation::new();
    let v_eq = rot.surface_velocity_at_latitude(0.0);
    let v_45 = rot.surface_velocity_at_latitude(45.0);
    println!("  Equatorial velocity: {:.2} m/s", v_eq);
    println!("  Velocity at 45°: {:.2} m/s", v_45);
    let (num, den) = MercuryRotation::spin_orbit_ratio();
    println!("  Spin-orbit ratio: {}:{}", num, den);
    println!(
        "  Libration amplitude: {:.4} rad",
        MercuryRotation::libration_amplitude_rad()
    );

    println!("\n=== Caloris Impact Recreation ===");
    let impactor = caloris_impactor();
    let crater = impactor.crater_diameter_m(3100.0);
    println!(
        "  Kinetic energy: {:.2e} J  ({:.0} MT)",
        impactor.kinetic_energy_j(),
        impactor.kinetic_energy_mt()
    );
    println!("  Predicted crater: {:.0} km", crater / 1000.0);
    println!(
        "  Fireball radius: {:.0} km",
        impactor.fireball_radius_m() / 1000.0
    );

    println!("\n=== Satellite Environment ===");
    println!("  Hill sphere: {:.0} km", hill_sphere_radius_m() / 1000.0);
    println!("  Known orbiters:");
    for sat in &all_missions() {
        println!(
            "    {} — periapsis={:.0}km  period={:.1}h",
            sat.name,
            sat.periapsis_km,
            sat.orbital_period_s() / 3600.0
        );
    }

    println!("\n=== Time Simulation (10 Mercury years) ===");
    let total_s = 10.0 * 7_600_521.6;
    let steps = 20;
    let dt = total_s / steps as f64;
    for i in 0..=steps {
        let t = i as f64 * dt;
        let years = t / 7_600_521.6;
        let days = t / 15_201_340.8;
        println!("  t={:.1} yr  ({:.1} solar days)", years, days);
    }
}
