import axios, { AxiosRequestConfig } from 'axios';
import jwt_decode from 'jwt-decode';
import {} from '../controllers';

import {
  GetAllResponse,
  GetDataResponse,
  GetOneResponse,
  GetRelationshipsDataResponse,
} from '../requests';

import { store } from '../store';

/* CONTROLLER_EXPORTS */

export const API = (
  method: string,
  url: string,
  data?: any,
  headers?: any
) => {
  const API = axios.create({
    baseURL: process.env.REACT_APP_BASE_URL
  });

  API.interceptors.request.use(
    async config => {
      const {} = store.getState();

      if (
        config.headers?.authorization &&
        config.url !== '' &&
        store.getState()
      ) {
        const { exp }: { exp: number } = jwt_decode('');

        if (exp * 1000 - 30000 < Date.now()) {
          // await store.dispatch();

          const {} = store.getState();

          config.headers.authorization = `Bearer ${store.getState()}`;
        }
      }

      return config;
    },
    error => {
      return Promise.reject(error);
    },
  );

  API.interceptors.response.use(
    response => {
      const {
        data,
        included,
      } = response.data as GetAllResponse<any, any, any> |
        GetOneResponse<any, any, any>;

      const relations = [];

      if (Array.isArray(data)) {
        data.forEach((datum) => {
          const includes: GetDataResponse<any>[] = [];

          included?.forEach((include: GetDataResponse<any>) => {
            relations.forEach((relation) => {
              if (datum.relationships) {
                datum.relationships[relation]?.data.forEach(
                  (relationshipDatum: GetRelationshipsDataResponse) => {
                    if (
                      relationshipDatum.id === include.id &&
                      relationshipDatum.type === include.type
                    ) {
                      includes.push(include);
                    }
                  }
                );
              }
            });
          });

          datum.included = includes;
        });
      } else {
        const includes: GetDataResponse<any>[] = [];

        included?.forEach((include: GetDataResponse<any>) => {
          relations.forEach((relation) => {
            if (data.relationships) {
              data.relationships[relation]?.data.forEach(
                (datum: GetRelationshipsDataResponse) => {
                  if (datum.id === include.id && datum.type === include.type) {
                    includes.push(include);
                  }
                }
              );
            }
          });
        });

        data.included = includes;
      }

      return response;
    },
    error => {
      return Promise.reject(error);
    },
  );

  return API.request({ method, url, data, headers } as AxiosRequestConfig);
};
