import axios, { AxiosError, type AxiosInstance } from 'axios';
import { ApiClientError, apiBaseUrl, handlers } from './base';

export const http: AxiosInstance = axios.create({
  baseURL: apiBaseUrl,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
  },
});

function extractMessage(details: unknown, fallback: string): string {
  if (
    typeof details === 'object' &&
    details &&
    'message' in details &&
    typeof details.message === 'string'
  ) {
    return details.message;
  }
  return fallback;
}

function normalizeError(error: unknown): ApiClientError {
  if (error instanceof ApiClientError) return error;

  if (axios.isAxiosError(error)) {
    const status = error.response?.status;
    const details = error.response?.data;

    return new ApiClientError(extractMessage(details, error.message || 'Request failed'), {
      status,
      details,
      causeError: error,
    });
  }

  if (error instanceof Error) {
    return new ApiClientError(error.message, { causeError: error });
  }

  return new ApiClientError('Error inesperado.', { causeError: error });
}

http.interceptors.response.use(
  (response) => response,
  async (error: AxiosError) => {
    const normalized = normalizeError(error);

    if (normalized.status === 403 && handlers.onForbidden) {
      await handlers.onForbidden(normalized);
    }

    if (handlers.onError) {
      await handlers.onError(normalized);
    }

    return Promise.reject(normalized);
  }
);
