// Wildfires layer (Wave 2) — REAL data from NASA's EONET events API.
// No time dynamics: EONET events are slow-moving, so availability games would
// mislead more than inform. Refreshed every 15 min, rebuilt wholesale.
//
// PITFALL baked in: EONET mislabels its Content-Type as `application/rss+xml`,
// but the body is JSON. fetch's res.json() ignores the header, so it works —
// we simply never gate on the content type.

export default function create(ctx) {
  const { viewer, CONFIG, lib, ui, Cesium } = ctx;
  const F = CONFIG.fires;

  const ds = new Cesium.CustomDataSource('fires');
  viewer.dataSources.add(ds);

  const glyph = lib.flameGlyph(CONFIG.colors.fire); // one shared canvas
  const fireColor = lib.cz(CONFIG.colors.fire);

  let enabled = true;
  let timer = null;
  let inFlight = false;

  ui.addLayer('fires', 'Wildfires (NASA EONET)', true, (on) => {
    enabled = on;
    ds.show = on;
  });
  ui.setStatus('fires', 'loading EONET feed…', 'warn');

  // Pick the most recent dated geometry and reduce it to a {lon, lat, date}.
  function locate(event) {
    const geoms = Array.isArray(event.geometry) ? event.geometry : [];
    if (!geoms.length) return null;
    // Latest by date (EONET lists chronologically; be robust to ordering).
    let latest = geoms[0];
    for (const gm of geoms) {
      if (gm.date && latest.date && gm.date > latest.date) latest = gm;
    }
    const c = latest.coordinates;
    if (latest.type === 'Point' && Array.isArray(c) && isFinite(c[0]) && isFinite(c[1])) {
      return { lon: c[0], lat: c[1], date: latest.date };
    }
    if (latest.type === 'Polygon' && Array.isArray(c) && Array.isArray(c[0])) {
      const ring = c[0];
      let sx = 0, sy = 0, n = 0;
      for (const pt of ring) {
        if (Array.isArray(pt) && isFinite(pt[0]) && isFinite(pt[1])) { sx += pt[0]; sy += pt[1]; n++; }
      }
      if (n) return { lon: sx / n, lat: sy / n, date: latest.date };
    }
    return null;
  }

  function build(events) {
    ds.entities.removeAll();
    let count = 0;
    for (const ev of events) {
      if (count >= F.cap) break;
      const loc = locate(ev);
      if (!loc) continue;
      const title = ev.title || 'Wildfire';
      const category = (ev.categories && ev.categories[0] && ev.categories[0].title) || 'Wildfires';
      const link = lib.safeUrl(ev.link || (ev.id ? `https://eonet.gsfc.nasa.gov/api/v3/events/${encodeURIComponent(ev.id)}` : ''));
      const dateTxt = loc.date ? new Date(loc.date).toISOString().replace('T', ' ').replace('.000Z', ' UTC') : '—';

      ds.entities.add({
        name: title,
        position: Cesium.Cartesian3.fromDegrees(loc.lon, loc.lat),
        billboard: {
          image: glyph,
          width: 14,
          height: 14,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
        },
        label: {
          text: title,
          font: '11px "Segoe UI", system-ui, sans-serif',
          fillColor: fireColor,
          outlineColor: Cesium.Color.fromCssColorString('#0a0f14'),
          outlineWidth: 3,
          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          pixelOffset: new Cesium.Cartesian2(0, -12),
          // Aggressive fade: fires cluster hard (California, Australia), so labels
          // only resolve once you've zoomed well into a region.
          translucencyByDistance: new Cesium.NearFarScalar(3.0e5, 1.0, 1.5e6, 0.0),
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
        },
        description:
          `<table class="cesium-infoBox-defaultTable"><tbody>` +
          `<tr><th>Event</th><td>${lib.escapeHtml(title)}</td></tr>` +
          `<tr><th>Category</th><td>${lib.escapeHtml(category)}</td></tr>` +
          `<tr><th>Last report</th><td>${dateTxt}</td></tr>` +
          `</tbody></table>` +
          (link ? `<p><a href="${lib.escapeHtml(link)}" target="_blank" rel="noopener">Open event on EONET ↗</a></p>` : '') +
          `<p style="opacity:.7">Active wildfire event from NASA EONET (real data).</p>`,
      });
      count++;
    }
    ui.setStatus('fires', `${count} active fires`, 'ok');
  }

  async function poll() {
    let res;
    try {
      res = await fetch(F.url);
    } catch {
      ui.setStatus('fires', 'network error — retrying', 'warn');
      return;
    }
    if (!res.ok) {
      ui.setStatus('fires', `HTTP ${res.status} — retrying`, 'warn');
      return;
    }
    let data;
    try {
      // Body is JSON despite the rss+xml Content-Type — do NOT check the header.
      data = await res.json();
    } catch {
      ui.setStatus('fires', 'bad response — retrying', 'err');
      return;
    }
    const events = Array.isArray(data && data.events) ? data.events : [];
    build(events);
  }

  async function tick() {
    timer = null;
    if (inFlight) return;
    inFlight = true;
    try {
      await poll();
    } finally {
      inFlight = false;
    }
    timer = setTimeout(tick, F.refreshMs);
  }

  tick();

  return { id: 'fires' };
}
