//
// Typescript API generated from gofiber backend
// Copyright (C) 2022 - 2025 Fabio Prada
//
// This file was generated by github.com/millevolte/ts-rpc
//
// Apr 14, 2026 21:39:07 UTC
//

export interface ApiRestResponse {
  data?: unknown;
  error: string | null;
}

function isApiRestResponse(data: unknown): data is ApiRestResponse {
  return (
    typeof data === "object" &&
    data !== null &&
    Object.prototype.hasOwnProperty.call(data, "data") &&
    Object.prototype.hasOwnProperty.call(data, "error")
  );
}

function normalizeError(error: unknown): Error {
  if (error instanceof DOMException && error.name === "AbortError") {
    return new Error("api.error.timeouterror");
  }

  if (error instanceof TypeError && error.message === "Failed to fetch") {
    return new Error("api.error.connectionerror");
  }

  if (error instanceof Error) {
    return error;
  }

  return new Error(String(error));
}

export default class Api {
  apiUrl: string;
  localStorage: Storage | null;

  constructor(apiurl: string) {
    this.apiUrl = apiurl;
    this.localStorage = window.localStorage;
  }

  async request(
    method: string,
    url: string,
    data: unknown,
    timeout = 7000,
    upload = false,
  ): Promise<ApiRestResponse> {
    const headers: { [key: string]: string } = {
      "Cache-Control": "no-cache",
    };

    if (!upload) {
      headers["Content-Type"] = "application/json";
    }

    if (this.localStorage) {
      const auth = this.localStorage.getItem("Auth-Token");
      if (auth) {
        headers["Auth-Token"] = auth;
      }
    }

    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);
    const requestOptions: RequestInit = {
      method,
      cache: "no-store",
      mode: "cors",
      credentials: "include",
      headers,
      signal: controller.signal,
    };

    if (upload) {
      requestOptions.body = data as FormData;
    } else if (data !== null && data !== undefined) {
      requestOptions.body = JSON.stringify(data);
    }

    try {
      const response = await fetch(url, requestOptions);

      if (!response.ok) {
        throw new Error("api.error." + response.statusText);
      }

      if (this.localStorage) {
        const jwt = response.headers.get("Auth-Token");
        if (jwt) {
          this.localStorage.setItem("Auth-Token", jwt);
        }
      }

      const responseData = (await response.json()) as unknown;
      if (!isApiRestResponse(responseData)) {
        throw new Error("api.error.wrongdatatype");
      }

      if (responseData.error) {
        throw new Error(responseData.error);
      }

      return responseData;
    } catch (error: unknown) {
      throw normalizeError(error);
    } finally {
      clearTimeout(timeoutId);
    }
  }

  processResult(result: ApiRestResponse): {
    data: unknown;
    error: string | null;
  } {
    if (typeof result.data !== "object") {
      return { data: result.data, error: null };
    }

    if (!result.data) {
      result.data = {};
    }

    return { data: result.data, error: null };
  }

  processError(error: unknown): {
    data: unknown;
    error: string | null;
  } {
    const normalizedError = normalizeError(error);

    if (normalizedError.message === "api.error.timeouterror") {
      Object.defineProperty(normalizedError, "__api_error__", {
        value: normalizedError.message,
        writable: false,
      });

      return { data: null, error: normalizedError.message };
    }

    if (normalizedError.message === "api.error.connectionerror") {
      Object.defineProperty(normalizedError, "__api_error__", {
        value: normalizedError.message,
        writable: false,
      });

      return { data: null, error: normalizedError.message };
    }

    return {
      data: null,
      error: normalizedError.message,
    };
  }

  async POST(
    url: string,
    data: unknown,
    timeout?: number,
  ): Promise<{
    data: unknown;
    error: string | null;
  }> {
    try {
      const upload = url.includes("/upload/");
      const result = await this.request(
        "POST",
        this.apiUrl + url,
        data,
        timeout,
        upload,
      );

      return this.processResult(result);
    } catch (error: unknown) {
      return this.processError(error);
    }
  }

  async PUT(
    url: string,
    data: unknown,
    timeout?: number,
  ): Promise<{
    data: unknown;
    error: string | null;
  }> {
    try {
      const upload = url.includes("/upload/");
      const result = await this.request(
        "PUT",
        this.apiUrl + url,
        data,
        timeout,
        upload,
      );

      return this.processResult(result);
    } catch (error: unknown) {
      return this.processError(error);
    }
  }

  async GET(
    url: string,
    timeout?: number,
  ): Promise<{
    data: unknown;
    error: string | null;
  }> {
    try {
      const result = await this.request(
        "GET",
        this.apiUrl + url,
        null,
        timeout,
      );
      return this.processResult(result);
    } catch (error: unknown) {
      return this.processError(error);
    }
  }

  async DELETE(
    url: string,
    timeout?: number,
  ): Promise<{
    data: unknown;
    error: string | null;
  }> {
    try {
      const result = await this.request(
        "DELETE",
        this.apiUrl + url,
        null,
        timeout,
      );
      return this.processResult(result);
    } catch (error: unknown) {
      return this.processError(error);
    }
  }

  async UPLOAD(
    url: string,
    data: unknown,
    timeout?: number,
  ): Promise<{
    data: unknown;
    error: string | null;
  }> {
    try {
      const result = await this.request(
        "POST",
        this.apiUrl + url,
        data,
        timeout,
        true,
      );

      return this.processResult(result);
    } catch (error: unknown) {
      return this.processError(error);
    }
  }
}

export const api = new Api("http://localhost:3000");
