import { ApiResponse } from "apisauce"

// Base problem types without error details
type BaseProblem =
  /**
   * Times up.
   */
  | { kind: "timeout"; temporary: true }
  /**
   * Cannot connect to the server for some reason.
   */
  | { kind: "cannot-connect"; temporary: true }
  /**
   * The server experienced a problem. Any 5xx error.
   */
  | { kind: "server" }
  /**
   * We're not allowed because we haven't identified ourself. This is 401.
   */
  | { kind: "unauthorized" }
  /**
   * We don't have access to perform that request. This is 403.
   */
  | { kind: "forbidden" }
  /**
   * Unable to find that resource.  This is a 404.
   */
  | { kind: "not-found" }
  /**
   * All other 4xx series errors.
   */
  | { kind: "rejected" }
  /**
   * Something truly unexpected happened. Most likely can try again. This is a catch all.
   */
  | { kind: "unknown"; temporary: true }
  /**
   * The data we received is not in the expected format.
   */
  | { kind: "bad-data" }

// Extended problem type that includes optional error code and message from API response
export type GeneralApiProblem = BaseProblem & {
  errorCode?: string
  errorMessage?: string
}

/**
 * Extracts error code from API response data.
 * Handles both { code: "E001" } and { error: { code: "E001" } } formats.
 */
function extractErrorCode(data: any): string | undefined {
  if (!data) return undefined
  return data.code || data.error?.code
}

/**
 * Extracts error message from API response data.
 * Handles both { message: "..." } and { error: { message: "..." } } formats.
 */
function extractErrorMessage(data: any): string | undefined {
  if (!data) return undefined
  return data.message || data.error?.message
}

/**
 * Attempts to get a common cause of problems from an api response.
 *
 * @param response The api response.
 */
export function getGeneralApiProblem(response: ApiResponse<any>): GeneralApiProblem | null {
  // Extract error details from response data (if available)
  const errorCode = extractErrorCode(response.data)
  const errorMessage = extractErrorMessage(response.data)

  switch (response.problem) {
    case "CONNECTION_ERROR":
      return { kind: "cannot-connect", temporary: true, errorCode, errorMessage }
    case "NETWORK_ERROR":
      return { kind: "cannot-connect", temporary: true, errorCode, errorMessage }
    case "TIMEOUT_ERROR":
      return { kind: "timeout", temporary: true, errorCode, errorMessage }
    case "SERVER_ERROR":
      return { kind: "server", errorCode, errorMessage }
    case "UNKNOWN_ERROR":
      return { kind: "unknown", temporary: true, errorCode, errorMessage }
    case "CLIENT_ERROR":
      switch (response.status) {
        case 401:
          return { kind: "unauthorized", errorCode, errorMessage }
        case 403:
          return { kind: "forbidden", errorCode, errorMessage }
        case 404:
          return { kind: "not-found", errorCode, errorMessage }
        default:
          return { kind: "rejected", errorCode, errorMessage }
      }
    case "CANCEL_ERROR":
      return null
  }

  return null
}
