export type HealthResult = { healthy: boolean; reason: string };
export async function probeHealth(url: string, request: typeof fetch = fetch): Promise<HealthResult> {
  try {
    const response = await request(url, { signal: AbortSignal.timeout(10000), redirect: "error", cache: "no-store" });
    if (!response.ok) return { healthy: false, reason: `HTTP ${response.status}` };
    const body = await response.json() as { status?: string };
    return body.status === "ok" ? { healthy: true, reason: "ok" } : { healthy: false, reason: "Invalid health response" };
  } catch { return { healthy: false, reason: "Health check unavailable" }; }
}
export function healthObserver(emit: (event: Record<string, unknown>) => void, threshold = 3) {
  let failures = 0;
  let incident = false;
  let initialized = false;
  return (result: HealthResult) => {
    failures = result.healthy ? 0 : failures + 1;
    const failed = failures >= threshold;
    const event = !initialized && result.healthy ? "monitor_started" : failed && !incident ? "health_failed" : incident && result.healthy ? "health_recovered" : null;
    if (event) emit({ event, timestamp: new Date().toISOString(), reason: result.reason, failures });
    if (failed) incident = true;
    if (result.healthy) incident = false;
    initialized = true;
  };
}

/** Keep secrets, SQL values, request bodies, OAuth queries and cookies out of logs. */
export function errorDetails(error: Error) {
  return {
    type: ["Error", "TypeError", "RangeError", "SyntaxError", "SQLiteError"].includes(error.name) ? error.name : "Error",
    frames: (error.stack ?? "").split("\n").slice(1).flatMap(line => {
      const location = line.match(/([A-Za-z0-9_.-]+\.(?:js|ts|tsx):\d+:\d+)/);
      return location ? [location[1]] : [];
    }).slice(0, 8),
  };
}
