import axios, { AxiosError } from 'axios';

const TOKEN_STORAGE_KEY = 'mimic.token';

let memoryToken: string | null = null;

export function setToken(token: string | null): void {
  memoryToken = token;
  if (token) {
    localStorage.setItem(TOKEN_STORAGE_KEY, token);
  } else {
    localStorage.removeItem(TOKEN_STORAGE_KEY);
  }
}

export function getToken(): string | null {
  if (memoryToken) return memoryToken;
  memoryToken = localStorage.getItem(TOKEN_STORAGE_KEY);
  return memoryToken;
}

/**
 * Callbacks the auth/toast layer registers so the interceptor can react
 * to 401 (purge + redirect to /login + toast).
 */
type UnauthorizedHandler = () => void;
let onUnauthorized: UnauthorizedHandler | null = null;

export function registerUnauthorizedHandler(handler: UnauthorizedHandler): void {
  onUnauthorized = handler;
}

export const apiClient = axios.create({
  baseURL: '/api',
  headers: { 'Content-Type': 'application/json' },
});

apiClient.interceptors.request.use((config) => {
  const token = getToken();
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

apiClient.interceptors.response.use(
  (response) => response,
  (error: AxiosError) => {
    if (error.response?.status === 401) {
      setToken(null);
      onUnauthorized?.();
    }
    return Promise.reject(error);
  },
);

/**
 * Extract a user-facing message from a thrown axios error.
 * Backend uses {error: "<message>"} shape.
 */
export function extractApiError(err: unknown, fallback = 'Une erreur est survenue'): string {
  if (axios.isAxiosError(err)) {
    const data = err.response?.data as { error?: string } | undefined;
    if (data?.error) return data.error;
    if (err.message) return err.message;
  }
  if (err instanceof Error) return err.message;
  return fallback;
}
