/**
 * Client API avec Axios pour COOP-CA AMIFOND
 *
 * V2 - Configuration pour l'authentification par cookies HttpOnly.
 */

import axios, { AxiosInstance, AxiosResponse, AxiosError } from "axios";
import { API_CONFIG, HTTP_STATUS, ERROR_MESSAGES, createHttpError, type HttpError, apiEndpoints } from "./api-config";
import { useAuthStore } from "@/stores/auth/auth-store";

class ApiClient {
  private readonly client: AxiosInstance;

  constructor() {
    this.client = axios.create({
      baseURL: API_CONFIG.baseURL,
      timeout: API_CONFIG.timeout,
      headers: API_CONFIG.defaultHeaders,
      withCredentials: true, // <-- TRÈS IMPORTANT
    });

    this.setupResponseInterceptor();
  }

  private setupResponseInterceptor() {
    this.client.interceptors.response.use(
      (response: AxiosResponse) => response,
      (error: AxiosError) => {
        // Si l'erreur est 401, déconnecter l'utilisateur
        if (error.response?.status === HTTP_STATUS.UNAUTHORIZED) {
          // Vérifier que l'URL n'est pas celle du login pour éviter une boucle
          if (!error.config?.url?.includes(apiEndpoints.auth.login) && 
              !error.config?.url?.includes(apiEndpoints.auth.register)) {
            console.log("401 Unauthorized detected, logging out user");
            useAuthStore.getState().logout();
          }
        }
        return Promise.reject(this.transformError(error));
      },
    );
  }

  private transformError(error: AxiosError): HttpError {
    if (!error.response) {
      return createHttpError(0, ERROR_MESSAGES.NETWORK_ERROR);
    }

    const { status, data } = error.response;
    let message: string;

    switch (status) {
      case HTTP_STATUS.UNAUTHORIZED:
        message = ERROR_MESSAGES.UNAUTHORIZED;
        break;
      case HTTP_STATUS.FORBIDDEN:
        message = ERROR_MESSAGES.FORBIDDEN;
        break;
      case HTTP_STATUS.NOT_FOUND:
        message = ERROR_MESSAGES.NOT_FOUND;
        break;
      case HTTP_STATUS.BAD_REQUEST:
      case HTTP_STATUS.UNPROCESSABLE_ENTITY:
        message = ERROR_MESSAGES.VALIDATION_ERROR;
        break;
      case HTTP_STATUS.INTERNAL_SERVER_ERROR:
        message = ERROR_MESSAGES.SERVER_ERROR;
        break;
      default:
        message = ERROR_MESSAGES.UNKNOWN_ERROR;
    }
    
    if (data && typeof data === "object") {
      const dataObject = data as Record<string, any>;
      if (dataObject.detail) {
        message = dataObject.detail;
      } else if (dataObject.message) {
        message = dataObject.message;
      } else if (dataObject.error) {
        message = dataObject.error;
      }
    }

    return createHttpError(status, message, data);
  }

  public async get<T = any>(url: string, config?: any): Promise<T> {
    const response = await this.client.get<T>(url, config);
    return response.data;
  }

  public async post<T = any>(url: string, data?: any, config?: any): Promise<T> {
    const response = await this.client.post<T>(url, data, config);
    return response.data;
  }

  public async put<T = any>(url: string, data?: any, config?: any): Promise<T> {
    const response = await this.client.put<T>(url, data, config);
    return response.data;
  }

  public async patch<T = any>(url: string, data?: any, config?: any): Promise<T> {
    const response = await this.client.patch<T>(url, data, config);
    return response.data;
  }

  public async delete<T = any>(url: string, config?: any): Promise<T> {
    const response = await this.client.delete<T>(url, config);
    return response.data;
  }

  public getAxiosInstance(): AxiosInstance {
    return this.client;
  }
}

export const apiClient = new ApiClient();
export type { HttpError };
export { createHttpError, HTTP_STATUS, ERROR_MESSAGES };
