/** Clear timeout/error messages — shared by submit workflow and downloads. */

export const FETCH_SUBMIT_DEADLINE_MS = 180_000;
export const FETCH_EVIDENCE_DEADLINE_MS = 90_000;
export const PDF_RENDER_DEADLINE_MS = 120_000;

export function isAbortError(error: unknown): boolean {
  if (error instanceof DOMException && error.name === 'AbortError') return true;
  return error instanceof Error && error.name === 'AbortError';
}

/**
 * Fetch with a deadline; clears the timer when the request settles.
 */
export async function fetchWithTimeout(
  input: RequestInfo | URL,
  init: RequestInit | undefined,
  timeoutMs: number,
): Promise<Response> {
  const controller = new AbortController();
  const id = window.setTimeout(() => controller.abort(), timeoutMs);
  try {
    const existing = init?.signal;
    if (!existing) {
      return await fetch(input, { ...(init ?? {}), signal: controller.signal });
    }
    const forward = () => controller.abort();
    if (existing.aborted) forward();
    else existing.addEventListener('abort', forward, { once: true });
    return await fetch(input, { ...(init ?? {}), signal: controller.signal });
  } finally {
    window.clearTimeout(id);
  }
}

/** Promise.race with a clear Vietnamese timeout error (e.g. PDF render / font load). */
export function withPromiseTimeout<T>(
  promise: Promise<T>,
  timeoutMs: number,
  timeoutMessage: string,
): Promise<T> {
  let timeoutId: number | undefined;
  const timed = new Promise<never>((_, reject) => {
    timeoutId = window.setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
  });
  return Promise.race([promise, timed]).finally(() => {
    if (timeoutId !== undefined) window.clearTimeout(timeoutId);
  });
}
