// Shared blob download: fetches an endpoint and saves the response as a file.
// Works whether or not the response sets Content-Disposition (some exports
// don't), falling back to the given name. Throws on a non-OK response so callers
// can surface the failure with a toast.
export async function downloadFile(endpoint: string, fallbackName: string): Promise<void> {
  const res = await fetch(endpoint, { credentials: 'include' });
  if (!res.ok) {
    let data: { message?: string; error?: string } = {};
    try { data = await res.json(); } catch { /* ignore */ }
    throw new Error(data.message || data.error || `HTTP ${res.status}`);
  }
  const disposition = res.headers.get('Content-Disposition');
  const match = disposition?.match(/filename="?([^"]+)"?/i);
  const name = match?.[1] || fallbackName;
  const blob = await res.blob();
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url; a.download = name; a.click();
  URL.revokeObjectURL(url);
}
