export const BACKEND_PATH = '/api/';

export const CONTENT_TYPE_HEADER = 'Content-Type';
export const CONTENT_TYPE_JSON = 'application/json';

export const DEFAULT_HEADERS = {
  [CONTENT_TYPE_HEADER]: CONTENT_TYPE_JSON,
};

// generic helpers with API responses that add optional errors. Extending APIResponse on any response gives access to the code/msg to check
export interface APIResponse extends APIError {}

// models Twirp error response
export interface APIError {
  code: string;
  msg: string;
}

export async function doRequest<Data>(target: string, options: RequestInit = {}): Promise<Data> {
  const requestOptions: RequestInit = {
    ...options,
    headers: DEFAULT_HEADERS,
  };
  return fetchJSON<Data>(new Request(BACKEND_PATH + target, requestOptions));
}

// this is for doing a request that will hit the go server hosting the UI, not the API backend
export async function doLocalRequest<Data>(target: string, options: RequestInit = {}): Promise<Data> {
  const requestOptions: RequestInit = {
    ...options,
    headers: DEFAULT_HEADERS,
  };
  return fetchJSON<Data>(new Request(target, requestOptions));
}

export async function doRawRequest(target: string, options: RequestInit = {}): Promise<Response> {
  const requestOptions: RequestInit = {
    ...options,
    headers: DEFAULT_HEADERS,
  };

  return fetchData(new Request(BACKEND_PATH + target, requestOptions));
}

export async function fetchJSON<Data>(request: Request, options?: RequestInit) {
  return fetchData(request, options).then<Data>((response: Response) => response.json());
}

export function fetchData(request: Request, options?: RequestInit) {
  return fetch(request, options).then<Response>((response: Response) => {
    if (response.status >= 300) {
      return Promise.reject<Response>(response);
    }

    return response;
  });
}
