/**
 * RFC 9457 Problem Details Parser
 *
 * This utility parses RFC 9457 "Problem Details for HTTP APIs" responses
 * from the backend and converts them into a format suitable for display
 * in React components.
 *
 * RFC 9457 Specification: https://www.rfc-editor.org/rfc/rfc9457.html
 */

/**
 * Parse RFC 9457 Problem Detail from API response or pre-parsed JSON data
 *
 * @param {Response|Object} responseOrData - Fetch API response object or pre-parsed JSON data
 * @returns {ParsedError|null} Parsed error object, or null if not RFC 9457 format
 *
 * @typedef {Object} ParsedError
 * @property {Object<string, string>} fieldErrors - Field-specific error messages (key = field name, value = error message)
 * @property {string} generalError - General error message to display
 * @property {Object} problem - Full RFC 9457 problem detail for debugging
 * @property {string} type - Problem type URI
 * @property {number} status - HTTP status code
 * @property {string} instance - Request path that caused the error
 * @property {string} timestamp - ISO 8601 timestamp
 * @property {string} traceId - Request trace ID for debugging
 */
export function parseRFC9457Error(responseOrData) {
  try {
    let problem;

    // Check if this is already parsed JSON data (object) or a Response object
    if (responseOrData && typeof responseOrData === 'object' && !responseOrData.json) {
      // Already parsed JSON data
      problem = responseOrData;
    } else {
      // This shouldn't happen in normal usage anymore, but handle it for safety
      console.warn("[RFC9457Parser] Received Response object instead of parsed data");
      return null;
    }

    // Check if this looks like an RFC 9457 problem detail
    // RFC 9457 requires at least 'type' and 'status' fields
    if (!problem.type && !problem.status && !problem.title && !problem.detail && !problem.errors) {
      // Not an RFC 9457 format, return null to let caller handle legacy format
      return null;
    }

    // All errors from our API are RFC 9457 format
    return {
      fieldErrors: problem.errors || {},
      generalError: problem.detail || problem.title || "An error occurred",
      problem: problem, // Full problem detail for debugging/logging
      type: problem.type,
      status: problem.status,
      instance: problem.instance,
      timestamp: problem.timestamp,
      traceId: problem.trace_id,
    };
  } catch (err) {
    // If parsing fails, return null to let caller handle it
    console.error("[RFC9457Parser] Failed to parse error response:", err);
    return null;
  }
}

/**
 * Check if HTTP response is an error
 *
 * @param {Response} response - Fetch API response object
 * @returns {boolean} True if response indicates an error (status >= 400)
 */
export function isErrorResponse(response) {
  return !response.ok && response.status >= 400;
}

/**
 * Format field errors for display in forms
 *
 * Converts the fieldErrors object into an array suitable for mapping
 * in React components.
 *
 * @param {Object<string, string>} fieldErrors - Field errors from parsed error
 * @returns {Array<{field: string, message: string}>} Array of field error objects
 *
 * @example
 * const fieldErrorArray = formatFieldErrors({
 *   email: "Email is required",
 *   password: "Password must be at least 8 characters"
 * });
 * // Returns: [
 * //   { field: "email", message: "Email is required" },
 * //   { field: "password", message: "Password must be at least 8 characters" }
 * // ]
 */
export function formatFieldErrors(fieldErrors) {
  return Object.entries(fieldErrors || {}).map(([field, message]) => ({
    field,
    message,
  }));
}

/**
 * Get user-friendly error title based on problem type
 *
 * @param {string} type - Problem type URI
 * @returns {string} User-friendly title
 */
export function getProblemTypeTitle(type) {
  if (!type) return "Error";

  // Extract the last part of the URI
  const parts = type.split("/");
  const lastPart = parts[parts.length - 1];

  // Convert kebab-case to Title Case
  return lastPart
    .split("-")
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
    .join(" ");
}

/**
 * Log error details for debugging
 *
 * Logs the full RFC 9457 problem detail to console for debugging purposes.
 * Should only be called in development mode.
 *
 * @param {ParsedError} parsedError - Parsed error from parseRFC9457Error
 */
export function logErrorDetails(parsedError) {
  if (import.meta.env.DEV && parsedError.problem) {
    console.group(
      `[RFC9457] ${parsedError.problem.title} (${parsedError.status})`,
    );
    console.log("Type:", parsedError.type);
    console.log("Detail:", parsedError.generalError);
    console.log("Instance:", parsedError.instance);
    console.log("Trace ID:", parsedError.traceId);
    console.log("Timestamp:", parsedError.timestamp);

    if (parsedError.fieldErrors && Object.keys(parsedError.fieldErrors).length > 0) {
      console.log("Field Errors:", parsedError.fieldErrors);
    }

    console.log("Full Problem Detail:", parsedError.problem);
    console.groupEnd();
  }
}

/**
 * Create a structured Error object from parsed RFC 9457 response
 *
 * This is useful for throwing errors that can be caught and displayed
 * in error boundaries or catch blocks.
 *
 * @param {ParsedError} parsedError - Parsed error from parseRFC9457Error
 * @returns {Error} Error object with additional properties
 */
export function createErrorFromProblem(parsedError) {
  const error = new Error(parsedError.generalError);
  error.fieldErrors = parsedError.fieldErrors;
  error.problem = parsedError.problem;
  error.status = parsedError.status;
  error.type = parsedError.type;
  error.instance = parsedError.instance;
  error.traceId = parsedError.traceId;
  return error;
}
