import axios from 'axios';

const api = axios.create({
  baseURL: '',
  withCredentials: true,
  timeout: 120_000,
  headers: {
    'Content-Type': 'application/json',
  },
});

// ─── CSRF token handling ────────────────────────────────────────────────────
// The backend enforces X-CSRF-Token on all authenticated state-changing
// requests (POST/PUT/DELETE/PATCH). Fetch the token lazily from
// /api/csrf-token, cache it, and attach it via the request interceptor.
let csrfToken: string | null = null;
let csrfFetch: Promise<string | null> | null = null;

async function fetchCsrfToken(): Promise<string | null> {
  if (!csrfFetch) {
    csrfFetch = axios
      .get<{ token: string }>('/api/csrf-token', { withCredentials: true })
      .then((res) => {
        csrfToken = res.data.token;
        return csrfToken;
      })
      .catch(() => null)
      .finally(() => {
        csrfFetch = null;
      });
  }
  return csrfFetch;
}

const MUTATING_METHODS = ['post', 'put', 'delete', 'patch'];

// Request interceptor — attach CSRF token to state-changing requests
api.interceptors.request.use(async (config) => {
  const method = (config.method || 'get').toLowerCase();
  if (MUTATING_METHODS.includes(method)) {
    if (!csrfToken) {
      await fetchCsrfToken();
    }
    if (csrfToken) {
      config.headers['X-CSRF-Token'] = csrfToken;
    }
  }
  return config;
});

// Response interceptor - handle auth errors
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    // CSRF token missing/invalid (e.g. session rotated) — refresh token and retry once
    if (
      error.response?.status === 403 &&
      typeof error.response?.data?.error === 'string' &&
      error.response.data.error.toLowerCase().includes('csrf') &&
      !error.config?._csrfRetried
    ) {
      csrfToken = null;
      const token = await fetchCsrfToken();
      if (token) {
        error.config._csrfRetried = true;
        error.config.headers['X-CSRF-Token'] = token;
        return api.request(error.config);
      }
    }
    if (error.response?.status === 401) {
      const url = error.config?.url || '';
      // Don't intercept auth endpoint errors — let the login page handle them.
      if (!url.includes('/auth/') && !url.includes('/coaching/')) {
        // Prevent multiple interceptors from firing simultaneously.
        if (window.location.pathname !== '/auth/login' && window.location.pathname !== '/auth/signup') {
          // Await logout to actually clear the session cookie before redirecting.
          try {
            await fetch('/api/auth/logout', { method: 'POST', credentials: 'include' });
          } catch {
            // Ignore — session might already be invalid.
          }
          // Use replace instead of href to avoid the user hitting "back" into a broken state.
          window.location.replace('/auth/login');
        }
      }
    }
    return Promise.reject(error);
  }
);

export default api;
export const axiosInstance = api;