/**
 * @file fetchHelper.ts - Central HTTP fetch helper utilities used by all API modules.
 * Provides URL assembly with query parameters, a custom FetchError class that handles 401 (Unauthorized) responses by triggering reauthentication, and is the foundation for all API communication in the RWP application.
 */

import { toast } from 'react-toastify';
import { showGlobalReauthModal } from '../contexts/ReauthContext.tsx';
import { clearAuthKeys } from '../services/authService.ts';
import { StatusCodes } from 'http-status-codes';
import i18next from 'i18next';

/**
 * Assembles a parameterized URL from the supplied API method URL and object with parameter values.
 *
 * @param methodUrl Full URL of API method, incl. protocol, host, and endpoint
 * @param paramsObject Object with query parameter names as keys and optional values
 * ```tsx
 * {
 *   latestVersion: latestVersion?.toString(),
 *   type: type // normal strings can be empty
 * }
 * ```
 * @returns URL object with query parameters included, ready to be used in a Fetch API call
 */
export function assembleQueryParams(methodUrl: string, paramsObject: object) {
  const queryParams = new URLSearchParams();
  Object.entries(paramsObject).forEach(([key, value]) => {
    if (value !== undefined) {
      queryParams.append(key, value);
    }
  });

  const url = new URL(methodUrl);
  url.search = queryParams.toString();
  return url;
}

/**
 * Basic error class meant for use when handling errors resulting from Fetch API calls.
 */
export class FetchError extends Error {
  response?: Response;
  status?: number;

  /**
   * Assembles a FetchError instance and shows the Reauthentication modal if the response code is 401 (Unauthorized).
   *
   * @param message Error message to be used in ErrorConstructor
   * @param response Response object to be returned with error
   */
  constructor(message: string, response?: Response) {
    super(message);
    this.response = response;
    this.status = response?.status;

    if (response?.status === StatusCodes.UNAUTHORIZED) {
      toast.error(i18next.t('utils.fetch_helper.errors.token_expired'), {
        toastId: 'api-token-expired',
      });

      // Preserve username and prompt reauthentication
      clearAuthKeys(true);
      showGlobalReauthModal();
    }
  }
}
