/**
 * Translate a remote-data fetch failure (snapshot model — spec §05 → URL datasets)
 * into the message shown when adding or refreshing a URL dataset.
 *
 * Pure and framework-free so the wording is unit-tested directly — the same split
 * as `storage-errors`. Follows the recorded error-copy resolution (docs/architecture
 * /10 → error copy): plain language, name what stopped, and — because every one of
 * these is user-fixable — point at the next step. No error codes in the user-facing
 * line (GOV.UK / NN/g #9). The recovery clause adapts to where the error shows: the
 * create/edit form can fall back to pasting inline; Refresh can only retry.
 */

import { MAX_REMOTE_BYTES, RemoteFetchError } from '../infrastructure/remote-data';

/** Where the error surfaces, which decides the recovery the copy points at. */
export type FetchRecovery = 'inline' | 'retry';

function nextStep(recovery: FetchRecovery): string {
  return recovery === 'inline'
    ? 'Check the address, or paste the data inline instead.'
    : 'Check the address and try refreshing again.';
}

function httpCause(status?: number): string {
  if (status === 404) return "The server couldn't find anything at this URL.";
  if (status === 401 || status === 403) return 'The server refused access to this URL.';
  if (status && status >= 500) return 'The server hit an error serving this URL.';
  return "The server couldn't return this URL.";
}

/**
 * The user-facing message for a fetch failure. `recovery` defaults to `inline`
 * (the add/edit form); pass `retry` for the Refresh action, which has no inline
 * fallback.
 */
export function remoteFetchErrorMessage(err: unknown, recovery: FetchRecovery = 'inline'): string {
  const next = nextStep(recovery);
  if (err instanceof RemoteFetchError) {
    switch (err.reason) {
      case 'network':
        return `Couldn't fetch this URL. Your device may be offline, or the host may block cross-origin requests. ${next}`;
      case 'http':
        return `${httpCause(err.status)} ${next}`;
      case 'empty':
        return `This URL returned no data. Make sure it points directly at a data file. ${next}`;
      case 'timeout':
        return `This URL took too long to respond. ${next}`;
      case 'too-large':
        // Neither inline-paste nor a retry helps an oversized file, so this points
        // at the only real fix instead of the shared next step.
        return `This file is too large to store as a dataset (over ${Math.round(MAX_REMOTE_BYTES / (1024 * 1024))} MB). Use a smaller file, or pre-aggregate the data before loading it.`;
    }
  }
  return `Couldn't fetch this URL. ${next}`;
}
