import * as Sentry from '@sentry/react';
import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import { WHITE_LIST_URLS } from '@/shared/api/urls';
import { StorageKeys } from '@/shared/constants/local-storage';
import { checkIsAxiosError, getLocalStorage } from '@/shared/lib';
import { finalizeConfig, extractAccessToken, extractRequestId } from './utils';
import { HEADER_USER_AGENT } from '@/shared/constants/url';

const onRequestFulfilled = (config: InternalAxiosRequestConfig) => {
  config.headers['Content-Type'] = 'application/json;charset=UTF-8';
  config.headers['X-User-Agent'] = HEADER_USER_AGENT;
  
  if(WHITE_LIST_URLS.includes(config?.url ?? '')){
    if(config.headers.hasOwnProperty('Authorization')){
      delete config.headers.Authorization;
    }
  }
  else{
    const accessToken = getLocalStorage(StorageKeys.AccessToken);
    const tokenType = getLocalStorage(StorageKeys.TokenType);
    config.headers.Authorization = `${tokenType} ${accessToken}`;
    // config.headers['X-Request-id'] = getLocalStorage(StorageKeys.requestId) ?? '';
  }
  return finalizeConfig(config);
};

const onRequestRejected = (error: any) => {
  const { method, url, params, data, headers } = error.config;
  Sentry.setContext('API Request Detail', {
    method,
    url,
    params,
    data,
    headers,
  });

  return Promise.reject(error);
};

const onResponseFulfilled = (response: AxiosResponse) => {
  extractAccessToken(response);
  extractRequestId(response);
  return {
    ...response,
    data: response.data.data,
  };
};

const onResponseRejected = (error: AxiosError) => {
  if (error?.response) {
    const { data, status } = error.response;
    extractRequestId(error?.response);
    Sentry.setContext('API Response Detail', {
      status,
      data,
    });
  }
  return new Promise((_resolve, reject) => {
    if (checkIsAxiosError(error)) {
      // iOS의 경우 window에서 unload event가 일어날때 네트워크 에러가 발생하곤 해서 이런 케이스를 방지하기 위해 지연시킴
      // location.href, location.reload 등으로 unload event가 일어나면 자바스크립트 런타임이 초기화되므로 settimeout으로 인한 네트워크 에러가 트리거 x
      setTimeout(() => reject(error), 300);
    } else {
      reject(error);
    }
  });
};

export const initAxios = () => {
  axios.defaults.withCredentials = true;
  axios.defaults.timeout = 15000;
  axios.defaults.transitional = {
    clarifyTimeoutError: true,
    forcedJSONParsing: true,
    silentJSONParsing: true,
  };
  axios.interceptors.request.use(onRequestFulfilled, onRequestRejected);
  axios.interceptors.response.use(onResponseFulfilled, onResponseRejected);
};
