import { useLoadingStore } from '@/stores/loading'
import { useAuthStore } from '@/stores/auth'
import axios from 'axios'

let instance = null
let isRefreshing = false;
let failedQueue = [];

function processQueue(error, token = null) {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });
  failedQueue = [];
}

// interceptor가 없는 별도의 axios 인스턴스 생성
const refreshAxios = axios.create({
      baseURL: import.meta.env.VITE_APP_API_URL, // 최종 API URL
      withCredentials: false,
      timeout: 60 * 1000,
      responseType: 'json',
      responseEncoding: 'utf8',
      xsrfHeaderName: 'X-XSRF-TOKEN',
      progress: false,
    });

const useAxios = () => {
  /************************************************************************
  |    Axios
  ************************************************************************/
  const { $log } = useNuxtApp()
  const store = useLoadingStore()

  if (!instance) {
    // 환경 변수에서 API URL과 포트를 가져옵니다
    const apiBaseUrl = import.meta.env.VITE_APP_API_URL
    const apiPort = import.meta.env.VITE_APP_API_PORT
    const fullApiUrl = `${apiBaseUrl}:${apiPort}`

    let loadingPassUrl = [      
      '/p5g/fm/eventViewer'
    ]

    instance = axios.create({
      baseURL: apiBaseUrl, // 최종 API URL
      withCredentials: false,
      timeout: 60 * 1000,
      responseType: 'json',
      responseEncoding: 'utf8',
      xsrfHeaderName: 'X-XSRF-TOKEN',
      progress: false,
    });

    /**
     * 요청 인터셉터
     */
    instance.interceptors.request.use(function (config) {
        $log.debug("[REQ]" + config.url)
        let accessToken = useAuthStore().getAccessToken;

        // 개발 모드일 때는 env에서 VITE_APP_DEV_TOKEN 사용
        if (import.meta.env.MODE === 'development' && import.meta.env.VITE_APP_DEV_TOKEN) {
          accessToken = import.meta.env.VITE_APP_DEV_TOKEN;
        }
        config.headers = {
          ...config.headers, // 기존 헤더 유지
          'Accept': 'application/json',
          'Access-Token': accessToken ? accessToken : '', // 동적으로 토큰 세팅
        };

        // 멀티파트 요청이면 Content-Type을 자동으로 설정하지 않음
        if (config.headers['Content-Type'] !== 'multipart/form-data') {
          if (!config.headers['Content-Type']) {
            config.headers['Content-Type'] = 'application/json;charset=UTF-8';
          }
        }


        if(!loadingPassUrl.includes(config.url)) {
          store.plusCount()
        }

        return config
      },
      function (error) {
        $log.error("[REQ][ERR]" + error)
        if (!loadingPassUrl.includes(config.url)) {
          store.minusCount()
        }
          // 요청 에러에도 로딩카운트 감소
        if (error.config && !loadingPassUrl.includes(error.config.url)) {
          store.minusCount()
        }

        return Promise.reject(error)
      }
    )

    /**
     * 응답 인터셉터
     */
    instance.interceptors.response.use(
      response => {
        if(!loadingPassUrl.includes(response.config.url)) {
          store.minusCount()
        }
        return response;
      },
      async error => {
         // 응답 에러에도 로딩카운트 감소(최대한 항상 호출)
        if (error.config && !loadingPassUrl.includes(error.config.url)) {
          store.minusCount()
        }


        if (error.response && error.response.status === 401) {
          const authStore = useAuthStore();
          const originalRequest = error.config;

          // refreshToken이 있고, 재발급 시도가 아닌 경우
          if (authStore.getRefreshToken && !originalRequest._retry) {
            if (isRefreshing) {
              // 이미 재발급 중이면 큐에 쌓았다가 처리
              return new Promise(function(resolve, reject) {
                failedQueue.push({resolve, reject});
              }).then(token => {
                originalRequest.headers['Access-Token'] = `${token}`;
                return instance(originalRequest);
              }).catch(err => {
                return Promise.reject(err);
              });
            }

            originalRequest._retry = true;
            isRefreshing = true;
            store.plusCount(); // refreshToken 요청 로딩 시작


            try {
              let __REQ = {
                refreshToken: authStore.getRefreshToken
              }
              // refreshAxios로 refreshToken 요청
              const res = await refreshAxios.post('/roulette/refreshToken', __REQ);
              // 다양한 응답 구조에서 accessToken 추출
              let newAccessToken = res.data.accessToken;

              if (!newAccessToken && res.data.data && res.data.data.accessToken) {
                newAccessToken = res.data.data.accessToken;
              }
              if (!newAccessToken && res.data.token) {
                newAccessToken = res.data.token;
              }

              if (!newAccessToken) {
                if (typeof window !== 'undefined') {
                  alert('세션이 만료되었습니다. 다시 로그인 해주세요.');
                  window.location.href = '/';
                }
                authStore.setLogout();
                throw new Error('No accessToken in refreshToken response');
              }

              authStore.setAccessToken(newAccessToken);
              processQueue(null, newAccessToken);
              isRefreshing = false;
              originalRequest.headers['Access-Token'] = `${newAccessToken}`;
              store.minusCount();
              // instance로 원래 요청 재시도
              return instance(originalRequest);

            } catch (refreshError) {
              processQueue(refreshError, null);
              isRefreshing = false;
              store.minusCount(); // refreshToken 요청 로딩 끝

              // refreshToken 만료(401, 403)만 로그아웃, 그 외는 안내
              if (refreshError.response && (refreshError.response.status === 401 || refreshError.response.status === 403)) {                                
                authStore.setLogout();
                if (typeof window !== 'undefined') {
                  alert('로그인 세션이 만료되었습니다. 다시 로그인 해주세요.');
                  window.location.href = '/';
                }
              } else {
                if (typeof window !== 'undefined') {
                  alert('일시적인 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.');
                  //window.location.href = '/';
                }
              }
              return Promise.reject(refreshError);
            }


          } else {            
            if(!error.response.data.messages.errorCode){
              authStore.setLogout();            
              if (typeof window !== 'undefined') {
                window.location.href = '/';
              }
            }
          }
        }
        return Promise.reject(error);
      }
    );
  }

  return instance
}

export default useAxios