#!/usr/bin/env python3
"""Checks https://lunonis.com/accuracy yourself.

pip install pyswisseph
curl -O https://lunonis.com/accuracy/lunonis-vs-swiss-ephemeris.json
python verify.py lunonis-vs-swiss-ephemeris.json
"""
import json
import sys
from datetime import datetime, timezone
from zoneinfo import ZoneInfo

import swisseph as swe

BODIES = {'sun': swe.SUN, 'moon': swe.MOON, 'mercury': swe.MERCURY, 'venus': swe.VENUS, 'mars': swe.MARS,
          'jupiter': swe.JUPITER, 'saturn': swe.SATURN, 'uranus': swe.URANUS, 'neptune': swe.NEPTUNE, 'pluto': swe.PLUTO}


def sep(a, b):
    d = abs(a - b) % 360
    return min(d, 360 - d) * 3600


worst = {}
zones_checked = zones_matching = 0
for c in json.load(open(sys.argv[1]))['cases']:
    if c['tz'] != 'UTC':
        utc = datetime.fromisoformat(f"{c['date']}T{c['time']}").replace(tzinfo=ZoneInfo(c['tz'])).astimezone(timezone.utc)
        zones_checked += 1
        zones_matching += utc.strftime('%Y-%m-%dT%H:%M:%SZ') == c['utc']
    date, time = c['utc'].split('T')
    y, m, d = map(int, date.split('-'))
    jd = swe.julday(y, m, d, int(time[:2]) + int(time[3:5]) / 60)
    ours = c['lunonis']
    for name, body in BODIES.items():
        worst[name] = max(worst.get(name, 0), sep(swe.calc_ut(jd, body, swe.FLG_MOSEPH)[0][0], ours['bodies'][name]))
    cusps, angles = swe.houses(jd, c['lat'], c['lon'], b'P')
    worst['asc'] = max(worst.get('asc', 0), sep(angles[0], ours['asc']))
    worst['mc'] = max(worst.get('mc', 0), sep(angles[1], ours['mc']))
    worst['cusps'] = max([worst.get('cusps', 0)] + [sep(x, y) for x, y in zip(cusps, ours['cusps'])])

print('Swiss Ephemeris', swe.version)
print(f'Local times converted to the same UTC: {zones_matching} of {zones_checked}')
for name, seconds in worst.items():
    print(f'{name:8} largest difference {seconds:5.1f} arcseconds')
