import Axios from "axios";
import type { AxiosRequestConfig } from "axios";
import { keysToCamel, keysToSnake } from "@/shared/utils/case-converter";

/**
 * Axios instance for Orval-generated API client
 * 
 * Features:
 * - Configurable baseURL from environment variable
 * - Auth token management
 * - Request cancellation support
 */
const FALLBACK_API_BASE = '/api/v1';
const configuredBaseUrl = import.meta.env.VITE_API_BASE_URL?.trim();

export const AXIOS_INSTANCE = Axios.create({
  // Default to /api/v1 so local dev still hits the proxy when no env is provided
  baseURL: configuredBaseUrl && configuredBaseUrl.length > 0 ? configuredBaseUrl : FALLBACK_API_BASE,
});

const isTransformablePayload = (payload: unknown) => {
  if (payload === null || payload === undefined) {
    return false;
  }
  if (payload instanceof FormData || payload instanceof Blob || payload instanceof ArrayBuffer) {
    return false;
  }
  return typeof payload === "object";
};

const SKIP_RECURSE_KEYS = new Set(["values", "valuesYaml"]);

AXIOS_INSTANCE.interceptors.request.use((config) => {
  if (isTransformablePayload(config.data)) {
    config.data = keysToSnake(config.data, SKIP_RECURSE_KEYS);
  }
  if (isTransformablePayload(config.params)) {
    config.params = keysToSnake(config.params);
  }
  return config;
});

AXIOS_INSTANCE.interceptors.response.use(
  (response) => {
    if (isTransformablePayload(response?.data)) {
      response.data = keysToCamel(response.data);
    }
    return response;
  },
  (error) => {
    if (isTransformablePayload(error?.response?.data)) {
      error.response.data = keysToCamel(error.response.data);
    }
    return Promise.reject(error);
  }
);

/**
 * Custom axios instance for Orval
 * Provides request cancellation support
 */
export const customAxiosInstance = <T>(
  config: AxiosRequestConfig,
  options?: AxiosRequestConfig
): Promise<T> => {
  const source = Axios.CancelToken.source();
  const promise = AXIOS_INSTANCE({
    ...config,
    ...options,
    cancelToken: source.token,
  }).then(({ data }) => data);

  // @ts-ignore
  promise.cancel = () => {
    source.cancel('Query was cancelled');
  };

  return promise as any;
};

/**
 * Set authentication token for all requests
 * 
 * @param token JWT token or null to remove
 * 
 * @example
 * import { setAuthToken } from '@/api/axios-mutator';
 * 
 * // Set token
 * setAuthToken('your-jwt-token');
 * 
 * // Remove token
 * setAuthToken(null);
 */
export function setAuthToken(token: string | null) {
  if (token) {
    AXIOS_INSTANCE.defaults.headers.common['Authorization'] = `Bearer ${token}`;
  } else {
    delete AXIOS_INSTANCE.defaults.headers.common['Authorization'];
  }
}
