import axios from 'axios';
import { toast } from 'sonner';

import deepParseJson, { handleToastError } from '@/lib/utils';

const BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL;

const api = axios.create({
    baseURL: `${BASE_URL}/v1`,
    headers: {
        'Content-Type': 'application/json',
    },
});

/* -------------------- REFRESH CONTROL -------------------- */

let isRefreshing = false;
let failedQueue: any[] = [];

const processQueue = (error: any, token: string | null = null) => {
    failedQueue.forEach((p) => {
        error ? p.reject(error) : p.resolve(token);
    });
    failedQueue = [];
};

/* -------------------- REQUEST (UNCHANGED) -------------------- */

api.interceptors.request.use((config) => {
    if (typeof window !== 'undefined') {
        const rawPersistData = localStorage.getItem('admin');
        const persistData: any = deepParseJson(rawPersistData);

        const accessToken = persistData?.auth?.token;
        if (accessToken) {
            config.headers.Authorization = accessToken;
        }
    }
    return config;
});

/* -------------------- RESPONSE (SIMPLIFIED + REFRESH) -------------------- */

api.interceptors.response.use(
    (response) => response,
    async (error) => {
        const status = error?.response?.status;
        const originalRequest = error.config;

        if (status === 401 && typeof window !== 'undefined' && !originalRequest._retry) {
            originalRequest._retry = true;

            // ⏳ Queue if refresh already in progress
            if (isRefreshing) {
                return new Promise((resolve, reject) => {
                    failedQueue.push({ resolve, reject });
                }).then((token) => {
                    originalRequest.headers.Authorization = token;
                    return api(originalRequest);
                });
            }

            isRefreshing = true;

            try {
                const rawPersistData = localStorage.getItem('admin');
                const persistData: any = deepParseJson(rawPersistData);

                const refreshToken = persistData?.auth?.refresh_token;
                if (!refreshToken) throw new Error('No refresh token');

                const response = await axios.post(
                    `${BASE_URL}/auth/refresh-token`,
                    { refresh_token: refreshToken },
                    { headers: { 'Content-Type': 'application/json' } },
                );

                const refreshData = response?.data;

                // 🔐 Handle backend logical 401
                if (!refreshData?.success || refreshData?.code === 401) {
                    throw { response: { status: 401 } };
                }

                const newToken = response.data?.data?.access_token;
                const newRefreshToken = response.data?.data?.refresh_token;

                // ✅ Update persisted auth only
                persistData.auth.token = newToken;
                persistData.auth.refresh_token = newRefreshToken;
                localStorage.setItem('admin', JSON.stringify(persistData));

                processQueue(null, newToken);

                originalRequest.headers.Authorization = newToken;
                return api(originalRequest);
            } catch (err) {
                processQueue(err, null);

                if (!(window as any).__SESSION_EXPIRED__) {
                    (window as any).__SESSION_EXPIRED__ = true;
                    toast.error('Session expired. Please login again.');
                    localStorage.removeItem('admin');
                    window.location.href = '/login';
                }

                return Promise.reject(err);
            } finally {
                isRefreshing = false;
            }
        }

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

export default api;
