
"""
PKTron Space Module.
Orbital mechanics, mission planning, satellite tools.
Delegates to cosmology for universe-scale physics.
"""
import numpy as np
_R = np.float32

G_SI = _R(6.674e-11)   # m^3 kg^-1 s^-2

# ── Orbital mechanics ─────────────────────────────────────────────────────

def circular_orbit_velocity(M_kg, r_m):
    """v_circ = sqrt(G*M/r)  in m/s"""
    return float(np.sqrt(G_SI*_R(M_kg)/_R(r_m)))

def orbital_period(M_kg, r_m):
    """T = 2*pi*sqrt(r^3/(G*M))  in seconds"""
    return float(2*_R(np.pi)*np.sqrt(_R(r_m)**3/(G_SI*_R(M_kg))))

def escape_velocity(M_kg, r_m):
    return float(np.sqrt(2*G_SI*_R(M_kg)/_R(r_m)))

def vis_viva(M_kg, r_m, a_m):
    """Vis-viva equation: v = sqrt(G*M*(2/r - 1/a))"""
    return float(np.sqrt(G_SI*_R(M_kg)*(2/_R(r_m)-1/_R(a_m))))

def hohmann_transfer(M_kg, r1_m, r2_m):
    """
    Hohmann transfer orbit between circular orbits r1 and r2.
    Returns (delta_v1, delta_v2, transfer_time) in SI.
    """
    a_t   = _R(r1_m+r2_m)/_R(2)
    v1    = _R(circular_orbit_velocity(M_kg, r1_m))
    v2    = _R(circular_orbit_velocity(M_kg, r2_m))
    v_t1  = _R(vis_viva(M_kg, r1_m, float(a_t)))
    v_t2  = _R(vis_viva(M_kg, r2_m, float(a_t)))
    dv1   = float(abs(v_t1-v1))
    dv2   = float(abs(v2-v_t2))
    t_tr  = float(_R(np.pi)*np.sqrt(a_t**3/(G_SI*_R(M_kg))))
    return {"delta_v1_m_s":dv1,"delta_v2_m_s":dv2,
            "transfer_time_s":t_tr,"total_dv_m_s":dv1+dv2}

def rocket_equation(ve, m0, mf):
    """Tsiolkovsky: delta_v = ve*ln(m0/mf)"""
    return float(_R(ve)*np.log(_R(m0)/_R(mf)))

def gravitational_slingshot(v_inf, v_planet, turning_angle_deg):
    """Approximate delta_v from gravity assist."""
    theta = np.radians(_R(turning_angle_deg))
    dv    = float(2*_R(v_planet)*np.sin(theta/2))
    return {"delta_v_m_s":dv,"v_exit":float(_R(v_inf)+dv)}

# ── Satellite tools ───────────────────────────────────────────────────────

def ground_track_period(r_m, M_earth=5.972e24):
    """Repeat ground track period for LEO satellite."""
    T     = orbital_period(M_earth, r_m)
    T_day = 86164.1   # sidereal day in seconds
    return {"orbital_period_s":T,"sidereal_day_s":T_day,
            "orbits_per_day":T_day/T}

def satellite_altitude(r_m, R_earth=6.371e6):
    return float(_R(r_m)-_R(R_earth))

def link_budget_free_space_loss(distance_m, frequency_Hz):
    """Free-space path loss in dB."""
    import numpy as np
    c   = 3e8
    lam = c/frequency_Hz
    return float(20*np.log10(4*np.pi*distance_m/lam))

# ── Planet data ───────────────────────────────────────────────────────────

SOLAR_SYSTEM = {
    "Mercury":{"mass_kg":3.301e23,"radius_m":2.440e6,"orbit_m":5.791e10},
    "Venus"  :{"mass_kg":4.867e24,"radius_m":6.052e6,"orbit_m":1.082e11},
    "Earth"  :{"mass_kg":5.972e24,"radius_m":6.371e6,"orbit_m":1.496e11},
    "Mars"   :{"mass_kg":6.417e23,"radius_m":3.390e6,"orbit_m":2.279e11},
    "Jupiter":{"mass_kg":1.898e27,"radius_m":6.991e7,"orbit_m":7.785e11},
    "Saturn" :{"mass_kg":5.683e26,"radius_m":5.823e7,"orbit_m":1.433e12},
    "Uranus" :{"mass_kg":8.681e25,"radius_m":2.536e7,"orbit_m":2.877e12},
    "Neptune":{"mass_kg":1.024e26,"radius_m":2.462e7,"orbit_m":4.495e12},
}

def planet_info(name):
    data = SOLAR_SYSTEM.get(name.capitalize())
    if data is None:
        raise KeyError(f"Unknown planet: {name}")
    M, R, a = data["mass_kg"], data["radius_m"], data["orbit_m"]
    M_sun = 1.989e30
    return {**data,
            "escape_velocity_m_s" : escape_velocity(M,R),
            "surface_gravity_m_s2": float(G_SI*_R(M)/_R(R)**2),
            "orbital_velocity_m_s": circular_orbit_velocity(M_sun,a),
            "orbital_period_days" : orbital_period(M_sun,a)/86400}
