"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PHXAxiosInstance = void 0;
const tslib_1 = require("tslib");
const axios_1 = tslib_1.__importDefault(require("axios"));
const async_lock_1 = tslib_1.__importDefault(require("async-lock"));
const read_env_config_1 = require("./read-env-config");
const constants_1 = require("./utils/constants");
const saveCookiesClient_1 = tslib_1.__importDefault(require("./components/Func/saveCookiesClient"));
const getCookieSession_1 = tslib_1.__importDefault(require("./components/Func/getCookieSession"));
const sessionStore_1 = require("./components/Func/sessionStore");
const js_cookie_1 = tslib_1.__importDefault(require("js-cookie"));
const save_local_storage_1 = require("./components/Func/save-local-storage");
const lock = new async_lock_1.default();
const isServer = typeof window === 'undefined';
const publicUrl = (0, read_env_config_1.getEnv)('NEXT_PUBLIC_API_GATEWAY', process.env.NEXT_PUBLIC_API_GATEWAY);
const internalUrl = (0, read_env_config_1.getEnv)('NEXT_PUBLIC_API_GATEWAY_INTERNAL', process.env.NEXT_PUBLIC_API_GATEWAY_INTERNAL);
const PHXAxiosInstance = axios_1.default.create({
    baseURL: publicUrl,
});
exports.PHXAxiosInstance = PHXAxiosInstance;
// === GLOBAL CACHE ===
let accessTokenCache = null;
let refreshingPromise = null;
// Hàm refresh access token, chỉ gọi 1 lần duy nhất tại một thời điểm
const refreshAccessToken = async () => {
    if (!refreshingPromise) {
        refreshingPromise = lock.acquire(constants_1.COOKIE_REFRESH_TOKEN, async () => {
            try {
                const url = `/api/authenticate/refresh-token`;
                const response = await axios_1.default.post(url, {});
                const newToken = response.data.token;
                const currentSession = (0, getCookieSession_1.default)();
                // Lưu lại vào cookie phía client
                currentSession === null || currentSession === void 0 ? true : delete currentSession.access_token;
                // vì chuyển đổi sang lưu vào local storage nên phải xóa cookie
                js_cookie_1.default.remove(constants_1.COOKIE_SESSION_SIGN_IN);
                (0, saveCookiesClient_1.default)({ value: { ...currentSession, access_token: newToken } });
                // Cập nhật cache
                accessTokenCache = newToken;
                return newToken;
            }
            catch (err) {
                (0, sessionStore_1.clearSession)();
                js_cookie_1.default.remove(constants_1.COOKIE_SESSION_SIGN_IN);
                (0, save_local_storage_1.deleteLocalStorage)(constants_1.COOKIE_SESSION_SIGN_IN);
                if (!isServer) {
                    window.location.href = constants_1.loginPage;
                }
                throw err;
            }
            finally {
                refreshingPromise = null;
            }
        });
    }
    return refreshingPromise;
};
// Request interceptor: luôn thêm Authorization nếu có access_token
PHXAxiosInstance.interceptors.request.use(async (config) => {
    var _a;
    config.headers = config.headers || {};
    // Ưu tiên lấy token từ cache
    let token = accessTokenCache;
    if (!token) {
        const session = (0, getCookieSession_1.default)();
        token = (session === null || session === void 0 ? void 0 : session.access_token) || null;
        if (token)
            accessTokenCache = token;
    }
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
        // Nếu đang SSR, validate trước
        if (isServer) {
            try {
                await axios_1.default.post(`${internalUrl}/authen/authenticate`, {}, { headers: { Authorization: `Bearer ${token}` } });
            }
            catch (err) {
                if (((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
                    const fresh = await refreshAccessToken();
                    config.headers.Authorization = `Bearer ${fresh}`;
                }
                else {
                    throw err;
                }
            }
        }
    }
    return config;
});
// Response interceptor: bắt lỗi 401, gọi refresh và retry
PHXAxiosInstance.interceptors.response.use((res) => res, async (error) => {
    var _a;
    const originalRequest = error.config;
    if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401 && !originalRequest._retry) {
        originalRequest._retry = true;
        try {
            const newToken = await refreshAccessToken();
            originalRequest.headers = originalRequest.headers || {};
            originalRequest.headers.Authorization = `Bearer ${newToken}`;
            return PHXAxiosInstance(originalRequest);
        }
        catch (e) {
            return Promise.reject(e);
        }
    }
    return Promise.reject(error);
});
//# sourceMappingURL=axiosInstance.js.map