/**
 * HTTP client configuration and instance.
 * @packageDocumentation
 */

import axios from 'axios';
import type { AxiosError, InternalAxiosRequestConfig, AxiosResponse } from 'axios';

/**
 * Token storage interface for flexibility
 */
interface TokenStorage {
  getToken(): string | null;
  setToken(token: string): void;
  removeToken(): void;
}

/**
 * Default token storage using localStorage
 */
const defaultTokenStorage: TokenStorage = {
  getToken: () => localStorage.getItem('auth_token'),
  setToken: (token: string) => localStorage.setItem('auth_token', token),
  removeToken: () => localStorage.removeItem('auth_token'),
};

/**
 * HTTP client configuration
 */
interface HttpClientConfig {
  baseURL?: string;
  timeout?: number;
  tokenStorage?: TokenStorage;
  onUnauthorized?: () => void;
}

/**
 * Create HTTP client with configuration
 */
export const createHttpClient = (config: HttpClientConfig = {}) => {
  const {
    baseURL = process.env.REACT_APP_API_URL || 'http://localhost:3000/api',
    timeout = 10000,
    tokenStorage = defaultTokenStorage,
    onUnauthorized,
  } = config;

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

  /**
   * Request interceptor for authentication
   */
  client.interceptors.request.use(
    (config: InternalAxiosRequestConfig) => {
      const token = tokenStorage.getToken();
      if (token && config.headers) {
        config.headers.Authorization = `Bearer ${token}`;
      }
      return config;
    },
    (error: AxiosError) => {
      console.error('Request interceptor error:', error);
      return Promise.reject(error);
    }
  );

  /**
   * Response interceptor for error handling
   */
  client.interceptors.response.use(
    (response: AxiosResponse) => response,
    (error: AxiosError) => {
      // Handle authentication errors
      if (error.response?.status === 401) {
        tokenStorage.removeToken();
        if (onUnauthorized) {
          onUnauthorized();
        } else {
          console.warn('Unauthorized access - token removed');
        }
      }

      // Log other errors for debugging
      if (error.response?.status && error.response.status >= 500) {
        console.error('Server error:', error.response.status, error.response.data);
      }

      return Promise.reject(error);
    }
  );

  return client;
};

/**
 * Default HTTP client instance
 */
export const httpClient = createHttpClient();

/**
 * Utility function to update token storage
 */
export const updateAuthToken = (token: string) => {
  defaultTokenStorage.setToken(token);
};

/**
 * Utility function to clear authentication
 */
export const clearAuth = () => {
  defaultTokenStorage.removeToken();
};