-- planet_observe regression tests
--
-- Tests VSOP87 planetary positions, Sun and Moon observation,
-- and the planet_heliocentric function.
-- Reference values cross-checked against JPL Horizons.

\set boulder '''40.015N 105.270W 1655m'''::observer

-- ============================================================
-- Test 1: Sun at heliocentric origin
-- planet_heliocentric(0, t) should always return (0, 0, 0)
-- because the Sun IS the origin of heliocentric coordinates.
-- ============================================================
SELECT 'sun_origin' AS test,
       round(helio_x(planet_heliocentric(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS x,
       round(helio_y(planet_heliocentric(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS y,
       round(helio_z(planet_heliocentric(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS z;

-- ============================================================
-- Test 2: Earth heliocentric distance ~ 1 AU
-- Earth (body_id=3) should be ~0.983-1.017 AU from the Sun
-- throughout the year (eccentricity ~0.017).
-- ============================================================
SELECT 'earth_distance' AS test,
       round(helio_distance(planet_heliocentric(3, '2024-01-03 12:00:00+00'))::numeric, 3) AS perihelion,
       round(helio_distance(planet_heliocentric(3, '2024-07-05 12:00:00+00'))::numeric, 3) AS aphelion;

-- ============================================================
-- Test 3: Mars heliocentric distance ~ 1.38-1.67 AU
-- Mars (body_id=4) average distance is ~1.524 AU.
-- ============================================================
SELECT 'mars_distance' AS test,
       round(helio_distance(planet_heliocentric(4, '2024-06-21 12:00:00+00'))::numeric, 2) AS dist_au;

-- ============================================================
-- Test 4: Jupiter heliocentric distance ~ 4.95-5.46 AU
-- Jupiter (body_id=5) average distance is ~5.203 AU.
-- ============================================================
SELECT 'jupiter_distance' AS test,
       round(helio_distance(planet_heliocentric(5, '2024-06-21 12:00:00+00'))::numeric, 1) AS dist_au;

-- ============================================================
-- Test 5: planet_observe for Jupiter from Boulder
-- Jupiter should be observable (check we get a valid result,
-- not an error). Elevation will vary by time.
-- ============================================================
SELECT 'jupiter_observe' AS test,
       round(topo_azimuth(planet_observe(5, :boulder,
             '2024-03-15 03:00:00+00'))::numeric, 0) AS az_deg,
       round(topo_elevation(planet_observe(5, :boulder,
             '2024-03-15 03:00:00+00'))::numeric, 0) AS el_deg;

-- ============================================================
-- Test 6: planet_observe for Venus from Boulder
-- Venus (body_id=2) should return valid az/el.
-- ============================================================
SELECT 'venus_observe' AS test,
       round(topo_azimuth(planet_observe(2, :boulder,
             '2024-06-15 02:00:00+00'))::numeric, 0) AS az_deg,
       round(topo_elevation(planet_observe(2, :boulder,
             '2024-06-15 02:00:00+00'))::numeric, 0) AS el_deg;

-- ============================================================
-- Test 7: sun_observe from Boulder at local noon (~18:00 UTC)
-- At summer solstice noon in Boulder (MDT = UTC-6),
-- Sun should be high in the south (az ~180, el ~73 deg).
-- ============================================================
SELECT 'sun_noon' AS test,
       round(topo_azimuth(sun_observe(:boulder,
             '2024-06-21 18:00:00+00'))::numeric, 0) AS az_deg,
       round(topo_elevation(sun_observe(:boulder,
             '2024-06-21 18:00:00+00'))::numeric, 0) AS el_deg;

-- ============================================================
-- Test 8: sun_observe range should be ~1 AU = 149,597,871 km
-- ============================================================
SELECT 'sun_range' AS test,
       round(topo_range(sun_observe(:boulder,
             '2024-06-21 18:00:00+00'))::numeric, -4) AS range_km;

-- ============================================================
-- Test 9: moon_observe from Boulder
-- Should return valid az/el with range ~ 356,000-407,000 km.
-- ============================================================
SELECT 'moon_observe' AS test,
       round(topo_azimuth(moon_observe(:boulder,
             '2024-06-21 18:00:00+00'))::numeric, 0) AS az_deg,
       round(topo_elevation(moon_observe(:boulder,
             '2024-06-21 18:00:00+00'))::numeric, 0) AS el_deg,
       round(topo_range(moon_observe(:boulder,
             '2024-06-21 18:00:00+00'))::numeric, -3) AS range_km;

-- ============================================================
-- Test 10: Moon range sanity (should be 356k-407k km)
-- ============================================================
SELECT 'moon_range_check' AS test,
       topo_range(moon_observe(:boulder, '2024-06-21 18:00:00+00')) BETWEEN 350000 AND 410000 AS in_range;

-- ============================================================
-- Test 11: Error handling - cannot observe Earth from Earth
-- ============================================================
SELECT 'earth_error' AS test, planet_observe(3, :boulder, now());

-- ============================================================
-- Test 12: Error handling - invalid body_id
-- ============================================================
SELECT 'invalid_body' AS test, planet_heliocentric(9, now());

-- ============================================================
-- Test 13: All planets return valid heliocentric positions
-- Mercury through Neptune, none should error.
-- ============================================================
SELECT 'all_planets' AS test,
       body_id,
       round(helio_distance(planet_heliocentric(body_id, '2024-06-21 12:00:00+00'))::numeric, 2) AS dist_au
FROM generate_series(1, 8) AS body_id;
