export interface SignalingEndpointHealthSnapshot {
  ok: boolean;
  serverInstanceId?: string;
}

export function resolveSignalingHttpBaseUrl(signalUrl: string | null | undefined): string | null {
  if (!signalUrl) {
    return null;
  }

  try {
    const parsed = new URL(signalUrl);

    if (parsed.protocol === 'wss:') {
      parsed.protocol = 'https:';
    } else if (parsed.protocol === 'ws:') {
      parsed.protocol = 'http:';
    } else {
      return null;
    }

    parsed.pathname = '';
    parsed.search = '';
    parsed.hash = '';

    return parsed.toString().replace(/\/$/, '');
  } catch {
    return null;
  }
}

async function readHealthSnapshot(
  baseUrl: string,
  fetchFn: typeof fetch,
  timeoutMs: number
): Promise<SignalingEndpointHealthSnapshot | null> {
  try {
    const response = await fetchFn(`${baseUrl}/api/health`, {
      method: 'GET',
      signal: AbortSignal.timeout(timeoutMs)
    });

    if (!response.ok) {
      return null;
    }

    const payload = await response.json() as { serverInstanceId?: unknown };
    const serverInstanceId = typeof payload.serverInstanceId === 'string' && payload.serverInstanceId.trim().length > 0
      ? payload.serverInstanceId.trim()
      : undefined;

    return {
      ok: true,
      serverInstanceId
    };
  } catch {
    return null;
  }
}

export async function probeSignalingEndpointHealth(
  signalUrl: string | null | undefined,
  options: {
    fetchFn?: typeof fetch;
    timeoutMs?: number;
  } = {}
): Promise<SignalingEndpointHealthSnapshot> {
  const baseUrl = resolveSignalingHttpBaseUrl(signalUrl);

  if (!baseUrl) {
    return { ok: true };
  }

  const fetchFn = options.fetchFn ?? fetch;
  const timeoutMs = options.timeoutMs ?? 5_000;
  const healthSnapshot = await readHealthSnapshot(baseUrl, fetchFn, timeoutMs);

  if (healthSnapshot?.ok) {
    return healthSnapshot;
  }

  try {
    const response = await fetchFn(`${baseUrl}/api/servers`, {
      method: 'GET',
      signal: AbortSignal.timeout(timeoutMs)
    });

    return { ok: response.ok };
  } catch {
    return { ok: false };
  }
}
