-- refraction regression tests
--
-- Tests atmospheric refraction (Bennett 1982), pressure/temperature
-- correction, apparent elevation, and refracted pass prediction.

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

-- ISS TLE for pass prediction tests (inline in CTEs below)

-- ============================================================
-- Test 1: Refraction at horizon (0 deg) ~ 0.57 deg
-- Bennett: R = 1/tan(0 + 7.31/4.4) arcmin ~ 34.5 arcmin ~ 0.575 deg
-- ============================================================
SELECT 'refr_horizon' AS test,
       round(atmospheric_refraction(0.0)::numeric, 2) AS refr_deg;

-- ============================================================
-- Test 2: Refraction at 30 deg ~ 0.03 deg
-- ============================================================
SELECT 'refr_30deg' AS test,
       round(atmospheric_refraction(30.0)::numeric, 3) AS refr_deg;

-- ============================================================
-- Test 3: Refraction at zenith (90 deg) ~ 0 deg
-- ============================================================
SELECT 'refr_zenith' AS test,
       round(atmospheric_refraction(90.0)::numeric, 4) AS refr_deg;

-- ============================================================
-- Test 4: Refraction at 10 deg ~ 0.09 deg
-- ============================================================
SELECT 'refr_10deg' AS test,
       round(atmospheric_refraction(10.0)::numeric, 3) AS refr_deg;

-- ============================================================
-- Test 5: Domain guard - refraction at -5 deg should return 0
-- (below -1 deg validity range)
-- ============================================================
SELECT 'refr_below_range' AS test,
       atmospheric_refraction(-5.0) AS refr_deg;

-- ============================================================
-- Test 6: Domain guard - refraction at -10 deg returns 0 (no NaN)
-- ============================================================
SELECT 'refr_deep_neg' AS test,
       atmospheric_refraction(-10.0) AS refr_deg,
       atmospheric_refraction(-10.0) = atmospheric_refraction(-10.0) AS is_finite;

-- ============================================================
-- Test 7: Refraction at exactly -1 deg (edge of domain)
-- Should return a small positive value
-- ============================================================
SELECT 'refr_minus1' AS test,
       atmospheric_refraction(-1.0) > 0 AS positive;

-- ============================================================
-- Test 8: Extended refraction with P/T correction
-- Standard: P=1010, T=10 should match basic function
-- ============================================================
SELECT 'refr_ext_standard' AS test,
       round(atmospheric_refraction_ext(0.0, 1010.0, 10.0)::numeric, 2) AS refr_deg,
       round(atmospheric_refraction(0.0)::numeric, 2) AS refr_basic,
       round(atmospheric_refraction_ext(0.0, 1010.0, 10.0)::numeric, 4) =
       round(atmospheric_refraction(0.0)::numeric, 4) AS match;

-- ============================================================
-- Test 9: Extended refraction - cold high-altitude
-- At P=700 mbar, T=-20 C, refraction should be reduced
-- ============================================================
SELECT 'refr_ext_cold' AS test,
       round(atmospheric_refraction_ext(0.0, 700.0, -20.0)::numeric, 2) AS refr_deg,
       atmospheric_refraction_ext(0.0, 700.0, -20.0) <
       atmospheric_refraction(0.0) AS less_than_standard;

-- ============================================================
-- Test 10: Extended refraction - hot sea level
-- At P=1013, T=35 C, refraction should be slightly different
-- ============================================================
SELECT 'refr_ext_hot' AS test,
       round(atmospheric_refraction_ext(0.0, 1013.0, 35.0)::numeric, 2) AS refr_deg;

-- ============================================================
-- Test 11: Apparent elevation for a topocentric observation
-- Sun near horizon: geometric el small -> apparent el higher
-- ============================================================
SELECT 'apparent_el' AS test,
       round(topo_elevation(sun_observe(:boulder, '2024-03-20 00:30:00+00'))::numeric, 1) AS geometric,
       round(topo_elevation_apparent(sun_observe(:boulder, '2024-03-20 00:30:00+00'))::numeric, 1) AS apparent,
       topo_elevation_apparent(sun_observe(:boulder, '2024-03-20 00:30:00+00')) >
       topo_elevation(sun_observe(:boulder, '2024-03-20 00:30:00+00')) AS refraction_positive;

-- ============================================================
-- Test 12: Apparent elevation for star high up (refraction small)
-- Polaris from Boulder has el ~49 deg; refraction ~0.01 deg
-- ============================================================
SELECT 'apparent_el_high' AS test,
       round(topo_elevation_apparent(
           star_observe(2.530303, 89.2641, :boulder, '2024-06-15 04:00:00+00'))::numeric, 1) AS apparent_deg;

-- ============================================================
-- Test 13: Refracted pass prediction returns results
-- Using the ISS TLE, should find passes in a week window
-- ============================================================
WITH iss AS (
    SELECT '1 25544U 98067A   24001.50000000  .00016717  00000-0  10270-3 0  9025
2 25544  51.6400 208.9163 0006703  30.1694  61.7520 15.50100486 00001'::tle AS t
)
SELECT 'refracted_passes' AS test,
       count(*) > 0 AS has_passes
FROM iss, predict_passes_refracted(
    t, :boulder,
    '2024-01-02 00:00:00+00', '2024-01-09 00:00:00+00');

-- ============================================================
-- Test 14: Refracted passes find at least as many as standard
-- Because refracted horizon is -0.569 deg, satellites visible ~35s earlier
-- ============================================================
SELECT 'refracted_more_passes' AS test,
       (SELECT count(*) FROM predict_passes_refracted(
           '1 25544U 98067A   24001.50000000  .00016717  00000-0  10270-3 0  9025
2 25544  51.6400 208.9163 0006703  30.1694  61.7520 15.50100486 00001'::tle,
           :boulder,
           '2024-01-02 00:00:00+00', '2024-01-09 00:00:00+00'))
       >=
       (SELECT count(*) FROM predict_passes(
           '1 25544U 98067A   24001.50000000  .00016717  00000-0  10270-3 0  9025
2 25544  51.6400 208.9163 0006703  30.1694  61.7520 15.50100486 00001'::tle,
           :boulder,
           '2024-01-02 00:00:00+00', '2024-01-09 00:00:00+00'))
       AS refracted_ge_standard;

-- ============================================================
-- Test 15: Monotonicity - refraction decreases with elevation
-- ============================================================
SELECT 'refr_monotonic' AS test,
       atmospheric_refraction(0.0) > atmospheric_refraction(10.0) AS r0_gt_r10,
       atmospheric_refraction(10.0) > atmospheric_refraction(30.0) AS r10_gt_r30,
       atmospheric_refraction(30.0) > atmospheric_refraction(60.0) AS r30_gt_r60,
       atmospheric_refraction(60.0) > atmospheric_refraction(90.0) AS r60_gt_r90;
