import { geoConfig } from "./config";
import type { Coordinates, GeocodeResult } from "./types";

type NominatimRow = {
  lat: string;
  lon: string;
  display_name: string;
};

/**
 * Geokodiert EINE Adresszeile gegen das selbstgehostete Nominatim.
 *
 * REIN: kein DB-Zugriff. Admin/Wehr-CRUD rufen diese Funktion und schreiben
 * `lat/lng` selbst (kein zweiter `geocodeBrigade`-Pfad). `countrycodes=at`
 * begrenzt auf Österreich. Timeout/Abort über `geoConfig.httpTimeoutMs`.
 *
 * Wirft NIE — meldet `status: "ok" | "not_found" | "error"`.
 */
export async function geocodeAddress(address: string): Promise<GeocodeResult> {
  const query = address.trim();
  if (!query) return { status: "not_found" };

  const params = new URLSearchParams({
    q: query,
    format: "jsonv2",
    addressdetails: "0",
    limit: "1",
    countrycodes: "at",
  });
  const url = `${geoConfig.nominatimUrl}/search?${params.toString()}`;

  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), geoConfig.httpTimeoutMs);
  try {
    const res = await fetch(url, {
      signal: controller.signal,
      headers: { "User-Agent": "FlorianNetz/1.0 (self-hosted)" },
    });
    if (!res.ok) {
      return { status: "error", reason: `HTTP ${res.status}` };
    }
    const rows = (await res.json()) as NominatimRow[];
    const top = rows[0];
    if (!top) return { status: "not_found" };

    const coords: Coordinates = {
      lat: Number.parseFloat(top.lat),
      lng: Number.parseFloat(top.lon),
    };
    if (Number.isNaN(coords.lat) || Number.isNaN(coords.lng)) {
      return { status: "error", reason: "Ungültige Koordinaten." };
    }
    return { status: "ok", coords, displayName: top.display_name };
  } catch (e) {
    const reason = e instanceof Error ? e.message : "Unbekannter Fehler";
    return { status: "error", reason };
  } finally {
    clearTimeout(timer);
  }
}

/** Health-Probe für Nominatim. */
export async function nominatimHealthy(): Promise<boolean> {
  const r = await geocodeAddress("St. Pölten");
  return r.status === "ok" || r.status === "not_found";
}
