import axios from 'axios';
import router from './router';
import { clearStaffSession, reconcileStaffSessionFromToken, useAuthStore } from './stores/auth';
import { ensureStaffSession, resetStaffSessionHydration } from './utils/session-hydrate';

const api = axios.create({ baseURL: '/api' });

let handling401 = false;
let handling403Portal = false;

const PORTAL_MISMATCH_MESSAGES = new Set(['Admin access only', 'Agent access only']);

function requestPath(config: { url?: string; baseURL?: string } | undefined): string {
  if (!config?.url) return '';
  const base = config.baseURL ?? '';
  return `${base}${config.url}`;
}

api.interceptors.request.use((config) => {
  const t = localStorage.getItem('manage_token');
  if (t) config.headers.Authorization = `Bearer ${t}`;

  reconcileStaffSessionFromToken();
  const auth = useAuthStore();
  const path = requestPath(config);

  if (path.includes('/admin/') && auth.isAgent.value) {
    return Promise.reject(
      Object.assign(new Error('Agent portal blocked admin API'), {
        isPortalMismatch: true,
        blockedPath: path,
      }),
    );
  }
  if (path.includes('/agent/') && auth.isAdmin.value) {
    return Promise.reject(
      Object.assign(new Error('Admin portal blocked agent API'), {
        isPortalMismatch: true,
        blockedPath: path,
      }),
    );
  }

  return config;
});

api.interceptors.response.use(
  (res) => res,
  async (err) => {
    if (err.isPortalMismatch) {
      await ensureStaffSession();
      if (router.currentRoute.value.path !== '/login') {
        await router.replace('/');
      }
      return Promise.reject(err);
    }

    if (err.response?.status === 401 && !handling401) {
      handling401 = true;
      clearStaffSession();
      resetStaffSessionHydration();
      if (router.currentRoute.value.path !== '/login') {
        await router.replace('/login');
      }
      handling401 = false;
    }

    if (
      err.response?.status === 403 &&
      !handling403Portal &&
      PORTAL_MISMATCH_MESSAGES.has(err.response?.data?.message)
    ) {
      handling403Portal = true;
      await ensureStaffSession();
      handling403Portal = false;

      const auth = useAuthStore();
      const path = requestPath(err.config);
      const isAdminApi = path.includes('/admin/');
      const isAgentApi = path.includes('/agent/');

      if ((isAdminApi && auth.isAgent.value) || (isAgentApi && auth.isAdmin.value)) {
        if (router.currentRoute.value.path !== '/login') {
          await router.replace('/');
        }
        return Promise.reject(err);
      }

      if (err.config) {
        return api.request(err.config);
      }

      clearStaffSession();
      if (router.currentRoute.value.path !== '/login') {
        await router.replace('/login');
      }
    }

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

export default api;
