// @ts-nocheck
import React from 'react';
import axios from 'axios';
import {
  useAuthActions,
  useAuthOrganizationId,
  useSetGlobalErrors,
  useAuthToken,
} from './state';
import { getCookie, normalizeApiPath } from '../utils';

export default function useApiRequest() {
  const setGlobalErrors = useSetGlobalErrors();
  const { setLogout } = useAuthActions();
  const currentLocale = getCookie('locale');

  // Authentication token.
  const token = useAuthToken();

  // Authentication organization id.
  const organizationId = useAuthOrganizationId();

  const http = React.useMemo(() => {
    // Axios instance.
    const instance = axios.create();

    // Request interceptors.
    instance.interceptors.request.use(
      (request) => {
        const locale = currentLocale;

        if (token) {
          request.headers['Authorization'] = `Bearer ${token}`;
        }
        if (organizationId) {
          request.headers['organization-id'] = organizationId;
        }
        if (locale) {
          request.headers['Accept-Language'] = locale;
        }
        return request;
      },
      (error) => {
        return Promise.reject(error);
      },
    );
    // Response interceptors.
    instance.interceptors.response.use(
      (response) => response,
      (error) => {
        const { status, data } = error.response;

        if (status >= 500) {
          setGlobalErrors({ something_wrong: true });
        }
        if (status === 401) {
          setGlobalErrors({ session_expired: true });
          setLogout();
        }
        if (status === 403) {
          setGlobalErrors({ access_denied: { message: data.message } });
        }
        if (status === 429) {
          setGlobalErrors({ too_many_requests: true });
        }
        if (status === 400) {
          const lockedError = data.errors.find(
            (error) => error.type === 'TRANSACTIONS_DATE_LOCKED',
          );
          if (lockedError) {
            setGlobalErrors({ transactionsLocked: { ...lockedError.payload } });
          }
          if (
            data.errors.find(
              (e) => e.type === 'ORGANIZATION.SUBSCRIPTION.INACTIVE',
            )
          ) {
            setGlobalErrors({ subscriptionInactive: true });
          }
          if (data.errors.find((e) => e.type === 'USER_INACTIVE')) {
            setGlobalErrors({ userInactive: true });
            setLogout();
          }
        }
        return Promise.reject(error);
      },
    );
    return instance;
  }, [token, organizationId, setGlobalErrors, setLogout]);

  return React.useMemo(
    () => ({
      http,

      get(resource, params) {
        return http.get(`/api/${normalizeApiPath(resource)}`, params);
      },

      post(resource, params, config) {
        return http.post(`/api/${normalizeApiPath(resource)}`, params, config);
      },

      update(resource, slug, params) {
        return http.put(`/api/${normalizeApiPath(resource)}/${slug}`, params);
      },

      put(resource, params) {
        return http.put(`/api/${normalizeApiPath(resource)}`, params);
      },

      patch(resource, params, config) {
        return http.patch(`/api/${normalizeApiPath(resource)}`, params, config);
      },

      delete(resource, params) {
        return http.delete(`/api/${normalizeApiPath(resource)}`, params);
      },
    }),
    [http],
  );
}

export function useAuthApiRequest() {
  const http = React.useMemo(() => {
    // Axios instance.
    return axios.create();
  }, []);

  return React.useMemo(
    () => ({
      http,
      get(resource, params) {
        return http.get(`/api/${normalizeApiPath(resource)}`, params);
      },
      post(resource, params, config) {
        return http.post(`/api/${normalizeApiPath(resource)}`, params, config);
      },
      update(resource, slug, params) {
        return http.put(`/api/${normalizeApiPath(resource)}/${slug}`, params);
      },
      put(resource, params) {
        return http.put(`/api/${normalizeApiPath(resource)}`, params);
      },
      patch(resource, params, config) {
        return http.patch(`/api/${normalizeApiPath(resource)}`, params, config);
      },
      delete(resource, params) {
        return http.delete(`/api/${normalizeApiPath(resource)}`, params);
      },
    }),
    [http],
  );
}