import apiFetch from "@wordpress/api-fetch";
import { boot } from "./boot";
import type { Errors } from "./engine/validation";

export class ApiError extends Error {
  status: number;
  code: string;
  errors: Errors;

  constructor(status: number, code: string, errors: Errors, message: string) {
    super(message);
    this.status = status;
    this.code = code;
    this.errors = errors;
  }
}

// One call to our REST routes. A refusal (422, 409...) becomes an ApiError that carries the field errors; the browser
// adds the REST nonce by itself on WordPress admin pages.
export async function request<T>(method: "GET" | "POST" | "PUT" | "DELETE", path: string, body?: unknown): Promise<T> {
  try {
    return (await apiFetch({ path: `/${boot.restNamespace}${path}`, method, data: body })) as T;
  } catch (raw) {
    const e = raw as { code?: string; message?: string; errors?: Errors; data?: { status?: number } };
    const errors = e.errors && typeof e.errors === "object" ? e.errors : {};
    throw new ApiError(e.data?.status ?? 0, e.code ?? "error", errors, e.message ?? "Request failed");
  }
}

// The first thing to tell the merchant about a failed call.
export function messageOf(error: unknown): string {
  if (error instanceof ApiError) {
    const first = Object.values(error.errors)[0];
    return first ?? error.message;
  }
  return error instanceof Error ? error.message : String(error);
}
