import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import Cookies from 'js-cookie';
import toast from 'react-hot-toast';
import { API_ENDPOINTS, COOKIE_KEYS, ROUTES } from '@/constants';

// ─── Axios Instance ───────────────────────────────────────────────────────────

const axiosInstance = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api',
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
    Accept: 'application/json',
    'device-id': 'web-user-panel',
    'device-type': 'web',
    'device-token': 'web-user-panel-token',
    'ram': '8GB',
    'rom': '256GB',
    'brand': 'Web',
    'model': 'Browser',
    'app-version': '1.0.0',
    'is-mobile': 'false',
  },
  timeout: 15000,
});

// ─── Token Refresh State ──────────────────────────────────────────────────────

let isRefreshing = false;
let failedQueue: Array<{
  resolve: (value: unknown) => void;
  reject: (reason: unknown) => void;
}> = [];

const processQueue = (error: AxiosError | null) => {
  failedQueue.forEach(({ resolve, reject }) => {
    if (error) {
      reject(error);
    } else {
      resolve(undefined);
    }
  });
  failedQueue = [];
};

// ─── Request Interceptor ──────────────────────────────────────────────────────

axiosInstance.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const token = Cookies.get(COOKIE_KEYS.ACCESS_TOKEN);
    if (token) {
      config.headers.Authorization = `${token}`;
    }
    return config;
  },
  (error: AxiosError) => Promise.reject(error),
);

// ─── Response Interceptor ─────────────────────────────────────────────────────

axiosInstance.interceptors.response.use(
  (response: AxiosResponse) => response,
  async (error: AxiosError) => {
    const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };

    if (!error.response) {
      toast.error('Network error. Please check your connection.');
      return Promise.reject(error);
    }

    const { status } = error.response;

    // ── 401 Unauthorized ── Try to refresh token once
    if (status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject });
        })
          .then(() => axiosInstance(originalRequest))
          .catch((err) => Promise.reject(err));
      }

      originalRequest._retry = true;
      isRefreshing = true;

      try {
        const { data } = await axiosInstance.post(API_ENDPOINTS.REFRESH_TOKEN);
        const newToken = data?.data?.access_token || data?.data?.new_token;
        if (newToken) {
          Cookies.set(COOKIE_KEYS.ACCESS_TOKEN, newToken);
        }
        processQueue(null);
        return axiosInstance(originalRequest);
      } catch (refreshError) {
        processQueue(refreshError as AxiosError);
        Cookies.remove(COOKIE_KEYS.ACCESS_TOKEN);
        if (typeof window !== 'undefined') {
          window.location.href = ROUTES.LOGIN;
        }
        return Promise.reject(refreshError);
      } finally {
        isRefreshing = false;
      }
    }

    // ── 403 Forbidden ──
    if (status === 403) {
      toast.error('Access denied. You do not have permission.');
    }

    // ── 404 Not Found ──
    if (status === 404) {
      // Silently handle or show toast based on context
    }

    // ── 422 Validation ──
    if (status === 422) {
      const responseData = error.response.data as { message?: string };
      toast.error(responseData?.message || 'Validation error.');
    }

    // ── 500 Server Error ──
    if (status >= 500) {
      toast.error('Something went wrong on our end. Please try again.');
    }

    return Promise.reject(error);
  },
);

export default axiosInstance;
