/**
 * The hosted ADS-B feed will not answer an anonymous caller.
 *
 * `api.adsb.lol` replies `403` with the body
 * `"User-Agent too generic; include valid contact info."` to a request that does
 * not identify who is making it. Node's `fetch` sends no useful User-Agent, so
 * every live flight fetch this service made was refused — and refused in the one
 * way nothing notices: `getJson` turns a non-2xx into `null`, `flights/index.ts`
 * reads `null` as "serve the simulated plan", `/health` still reports
 * `flights: adsb` because the source is configured and reachable, and
 * `degraded[]` stays empty because nothing degraded at boot. Every indicator
 * said the sky was live while it was fabricated.
 *
 * The header is therefore load-bearing, and a header that is load-bearing and
 * untested is a header that comes off in a refactor. These tests exist so that
 * removing it fails here rather than in production, silently, months later.
 */

import assert from "node:assert/strict";
import { after, describe, it } from "node:test";
import { fetchAdsb } from "../flights/adsb.ts";

const realFetch = globalThis.fetch;
after(() => {
  globalThis.fetch = realFetch;
});

/** Capture the request the module makes, and answer with one empty sky. */
function captureRequest(): { headers: () => Record<string, string>; url: () => string } {
  let headers: Record<string, string> = {};
  let url = "";
  globalThis.fetch = (async (input: unknown, init?: { headers?: HeadersInit }) => {
    url = String(input);
    const raw = init?.headers ?? {};
    headers = Object.fromEntries(
      Object.entries(raw as Record<string, string>).map(([k, v]) => [k.toLowerCase(), v]),
    );
    return {
      ok: true,
      status: 200,
      headers: new Headers({ "content-type": "application/json" }),
      text: async () => JSON.stringify({ ac: [], now: 1 }),
    };
  }) as unknown as typeof globalThis.fetch;
  return { headers: () => headers, url: () => url };
}

const CENTRE = { lat: 33.82, lng: -118.05 };

describe("adsb user-agent", () => {
  it("sends a User-Agent carrying the configured contact", async () => {
    const seen = captureRequest();
    await fetchAdsb("https://api.adsb.lol", CENTRE, 60, "ops@example.com");

    const ua = seen.headers()["user-agent"];
    assert.ok(ua !== undefined, "no User-Agent was sent; adsb.lol answers 403 to that request");
    assert.match(ua, /ops@example\.com/, "the contact must reach the feed, not just a product name");
    assert.ok(
      ua.length > "tera-api".length,
      "a bare product token is what the feed calls too generic",
    );
  });

  it("still asks the allowlisted host for the region it was given", async () => {
    const seen = captureRequest();
    await fetchAdsb("https://api.adsb.lol", CENTRE, 60, "ops@example.com");
    assert.equal(seen.url(), "https://api.adsb.lol/v2/point/33.8200/-118.0500/60");
  });

  it("refuses a host that is not on the allowlist before it sends anything", async () => {
    const seen = captureRequest();
    const warned: string[] = [];
    const out = await fetchAdsb("https://data-cloud.flightradar24.com", CENTRE, 60, "ops@e.com", {
      warn: (m) => warned.push(m),
    });

    assert.equal(out, null);
    assert.equal(seen.url(), "", "a refused endpoint must never reach the network");
    assert.equal(warned.length, 1);
    assert.match(warned[0]!, /not an openly-licensed feed/);
  });
});
