import axios from 'axios';
import { setupCache } from 'axios-cache-interceptor';
import Cookies from 'js-cookie';

const TOKEN_COOKIE = 'auth_token';

type UnauthorizedCallback = () => void;
let onUnauthorized: UnauthorizedCallback | null = null;

export function setUnauthorizedCallback(cb: UnauthorizedCallback) {
  onUnauthorized = cb;
}

const axiosInstance = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_URL,
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Accept-Language': 'fr',
  },
});

const cachedAxios = setupCache(axiosInstance, { ttl: 5 * 60 * 1000 });

cachedAxios.interceptors.request.use((config) => {
  const token = Cookies.get(TOKEN_COOKIE);
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

cachedAxios.interceptors.response.use(
  (response) => response,
  (error) => {
    const status = error.response?.status;
    if (status === 401 || status === 419) {
      Cookies.remove(TOKEN_COOKIE);
      if (onUnauthorized) onUnauthorized();
    }
    return Promise.reject(error);
  }
);

const HttpClient = {
  // Caching is opt-in: dynamic data (installations) must always be fresh, so a
  // stale entry never survives a server-side change (e.g. a deleted record).
  // Static reference data opts back in by passing `{ cache: true }`.
  get<T>(url: string, config?: Parameters<typeof cachedAxios.get>[1]) {
    return cachedAxios
      .get<T>(url, { cache: false, ...config } as Parameters<typeof cachedAxios.get>[1])
      .then((r) => r.data);
  },
  post<T>(url: string, data?: unknown) {
    return cachedAxios.post<T>(url, data).then((r) => r.data);
  },
  put<T>(url: string, data?: unknown) {
    return cachedAxios.put<T>(url, data).then((r) => r.data);
  },
  patch<T>(url: string, data?: unknown) {
    return cachedAxios.patch<T>(url, data).then((r) => r.data);
  },
  delete<T>(url: string) {
    return cachedAxios.delete<T>(url).then((r) => r.data);
  },
  postForm<T>(url: string, formData: FormData) {
    return cachedAxios
      .post<T>(url, formData, { headers: { 'Content-Type': 'multipart/form-data' } })
      .then((r) => r.data);
  },
};

export { TOKEN_COOKIE };
export default HttpClient;
