// Holt Referenzwerte vom U.S. Naval Observatory und schreibt sie als Fixture
// fuer astro.test.js. Muss nur laufen, wenn man das Referenzjahr wechselt —
// der Test selbst geht nie ins Netz.
//
//   node scripts/fetch-usno-reference.mjs [Jahr]
//
// Quelle: Astronomical Applications API v4 des USNO, https://aa.usno.navy.mil/data/api
// Die API rechnet mit denselben JPL-Ephemeriden wie der Astronomical Almanac
// und ist damit eine von unserer Implementierung unabhaengige Instanz.

import { writeFile } from 'node:fs/promises'
import { setTimeout as sleep } from 'node:timers/promises'

const YEAR = Number(process.argv[2] ?? 2026)

// Station Wetterstation — dieselben Werte wie STATION in App.jsx
const LAT = 48 + 52 / 60 + 27 / 3600
const LON = 9 + 35 / 60 + 46 / 3600

const API = 'https://aa.usno.navy.mil/api'
const COORDS = `${LAT.toFixed(4)},${LON.toFixed(4)}`

// Pause zwischen den Requests. Es sind 365 Stueck an einen fremden Server —
// nicht draengeln.
const THROTTLE_MS = 200

const iso = d => d.toISOString().slice(0, 10)

async function getJson(url) {
  for (let versuch = 1; versuch <= 3; versuch++) {
    try {
      const res = await fetch(url, { signal: AbortSignal.timeout(30000) })
      if (!res.ok) throw new Error(`HTTP ${res.status}`)
      return await res.json()
    } catch (err) {
      if (versuch === 3) throw new Error(`${url}: ${err.message}`)
      await sleep(1000 * versuch)
    }
  }
}

// Sonnenauf-/untergang fuer jeden Tag des Jahres, in UTC.
//
// tz=0&dst=false laesst die API in Weltzeit antworten. Das haelt das Fixture
// frei von jeder Sommerzeit-Annahme: der Test vergleicht absolute Zeitpunkte,
// die Zeitzone ist allein Sache der Anzeige.
async function fetchSonne() {
  const sonne = {}
  const tag = new Date(Date.UTC(YEAR, 0, 1))

  while (tag.getUTCFullYear() === YEAR) {
    const datum = iso(tag)
    const json = await getJson(
      `${API}/rstt/oneday?date=${datum}&coords=${COORDS}&tz=0&dst=false`
    )
    const daten = json?.properties?.data?.sundata ?? []
    const zeit = phen => daten.find(e => e.phen === phen)?.time ?? null

    sonne[datum] = [zeit('Rise'), zeit('Set')]

    if (tag.getUTCDate() === 1) console.error(`  ${datum} ...`)
    tag.setUTCDate(tag.getUTCDate() + 1)
    await sleep(THROTTLE_MS)
  }
  return sonne
}

// Alle Hauptphasen des Jahres — ein einziger Request. Die Zeiten sind UTC.
async function fetchMondphasen() {
  const json = await getJson(`${API}/moon/phases/year?year=${YEAR}`)
  return json.phasedata.map(p => ({
    phase: p.phase,
    utc: `${p.year}-${String(p.month).padStart(2, '0')}-${String(p.day).padStart(2, '0')}T${p.time}:00Z`,
  }))
}

console.error(`Hole USNO-Referenz fuer ${YEAR} (${COORDS}) ...`)

const [sonne, mondphasen] = [await fetchSonne(), await fetchMondphasen()]

const fixture = {
  quelle: 'U.S. Naval Observatory, Astronomical Applications API v4 (https://aa.usno.navy.mil/data/api)',
  abgerufen: iso(new Date()),
  hinweis:
    'Alle Zeiten UTC. Die API rundet auf ganze Minuten — der Test rechnet das ein. '
    + 'Auf-/Untergang nach Almanach-Konvention: Meereshorizont, ohne Beobachterhoehe.',
  jahr: YEAR,
  station: { lat: LAT, lon: LON },
  sonne,
  mondphasen,
}

const ziel = new URL('../src/utils/__fixtures__/usno-reference.json', import.meta.url)
await writeFile(ziel, JSON.stringify(fixture, null, 2) + '\n')

console.error(
  `Fertig: ${Object.keys(sonne).length} Tage, ${mondphasen.length} Mondphasen -> ${ziel.pathname}`
)
