import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { API_CONFIG } from '../config/api';
import { keycloak } from '../config/keycloak';
import { KEYCLOAK_TIMEOUTS } from '../config/keycloak';

// Créer une instance axios avec configuration par défaut depuis API_CONFIG
const axiosInstance: AxiosInstance = axios.create({
  baseURL: API_CONFIG.baseURL,
  timeout: API_CONFIG.timeout,
  headers: API_CONFIG.headers,
});

// Intercepteur pour ajouter le token d'authentification
axiosInstance.interceptors.request.use(
  async (config) => {
    // Vérifier si nous avons un token d'accès stocké
    if (typeof window !== 'undefined') {
      const accessToken = localStorage.getItem('accessToken');

      if (accessToken) {
        // Ajouter le token Bearer à l'en-tête Authorization
        config.headers.Authorization = `Bearer ${accessToken}`;
        console.log('🔐 API Request avec token:', config.method?.toUpperCase(), config.url);
      } else {
        console.log('⚠️ API Request sans token:', config.method?.toUpperCase(), config.url);
      }
    } else {
      // Fallback vers l'ancien système pour la rétrocompatibilité
      if (typeof window !== 'undefined') {
        const token = localStorage.getItem('accessToken') || localStorage.getItem('token');
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }
      }
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// Intercepteur pour gérer les réponses et erreurs
axiosInstance.interceptors.response.use(
  (response: AxiosResponse) => {
    return response;
  },
  (error) => {
    // Gérer les erreurs d'authentification et d'autorisation
    if (error.response?.status === 401 || error.response?.status === 403) {
      // Ne pas rediriger si on est en train de traiter un code d'autorisation
      if (typeof window !== 'undefined') {
        const currentUrl = window.location.href;
        const hasAuthCode = currentUrl.includes('code=') && currentUrl.includes('/dashboard');

        console.log(`🔍 API Client ${error.response?.status}:`, { currentUrl, hasAuthCode });

        if (!hasAuthCode) {
          // Token expiré, invalide ou permissions insuffisantes - sauvegarder la page actuelle et rediriger
          console.log(`🔄 API Client: Erreur ${error.response?.status}, redirection vers Keycloak...`);

          // Sauvegarder la page actuelle pour y revenir après reconnexion
          const currentPath = window.location.pathname + window.location.search;
          localStorage.setItem('returnUrl', currentPath);

          // Nettoyer les anciens tokens
          localStorage.removeItem('accessToken');
          localStorage.removeItem('refreshToken');
          localStorage.removeItem('idToken');

          // Rediriger vers Keycloak pour reconnexion
          window.location.href = '/api/auth/login';
        } else {
          console.log(`🔄 API Client: Erreur ${error.response?.status} ignorée car authentification en cours...`);
        }
      }
    }
    
    // Gérer les erreurs serveur
    if (error.response?.status >= 500) {
      console.error('Erreur serveur:', error.response?.data || error.message);
    }
    
    return Promise.reject(error);
  }
);

// Interface pour les réponses API standardisées
export interface ApiResponse<T = any> {
  data: T;
  message?: string;
  success?: boolean;
}

// Interface pour les erreurs API
export interface ApiError {
  message: string;
  code?: string;
  details?: any;
}

// Client API avec méthodes utilitaires
export class ApiClient {
  private instance: AxiosInstance;

  constructor(baseURL?: string) {
    this.instance = baseURL ? axios.create({ baseURL }) : axiosInstance;
  }

  // GET request
  async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.get<T>(url, config);
  }

  // POST request
  async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.post<T>(url, data, config);
  }

  // PUT request
  async put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.put<T>(url, data, config);
  }

  // DELETE request
  async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.delete<T>(url, config);
  }

  // PATCH request
  async patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    return this.instance.patch<T>(url, data, config);
  }

  // Upload file
  async upload<T = any>(url: string, file: File, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    const formData = new FormData();
    formData.append('file', file);
    
    return this.instance.post<T>(url, formData, {
      ...config,
      headers: {
        ...config?.headers,
        'Content-Type': 'multipart/form-data',
      },
    });
  }

  // Upload multiple files
  async uploadMultiple<T = any>(url: string, files: File[], config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    const formData = new FormData();
    files.forEach((file, index) => {
      formData.append(`files[${index}]`, file);
    });
    
    return this.instance.post<T>(url, formData, {
      ...config,
      headers: {
        ...config?.headers,
        'Content-Type': 'multipart/form-data',
      },
    });
  }

  // Download file
  async download(url: string, filename?: string, config?: AxiosRequestConfig): Promise<void> {
    const response = await this.instance.get(url, {
      ...config,
      responseType: 'blob',
    });

    // Créer un lien de téléchargement
    const blob = new Blob([response.data]);
    const downloadUrl = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = downloadUrl;
    link.download = filename || 'download';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(downloadUrl);
  }

  // Set auth token
  setAuthToken(token: string): void {
    this.instance.defaults.headers.common['Authorization'] = `Bearer ${token}`;
  }

  // Remove auth token
  removeAuthToken(): void {
    delete this.instance.defaults.headers.common['Authorization'];
  }
}

// Instance par défaut exportée
export const apiClient = new ApiClient();

// Export de l'instance axios brute pour les cas particuliers
export { axiosInstance };

// Utilitaires pour gérer les erreurs
export const handleApiError = (error: any): ApiError => {
  if (error.response) {
    // Erreur de réponse du serveur
    return {
      message: error.response.data?.message || error.response.statusText || 'Erreur serveur',
      code: error.response.status.toString(),
      details: error.response.data,
    };
  } else if (error.request) {
    // Erreur de réseau
    return {
      message: 'Impossible de se connecter au serveur',
      code: 'NETWORK_ERROR',
      details: error.request,
    };
  } else {
    // Autre erreur
    return {
      message: error.message || 'Une erreur inattendue est survenue',
      code: 'UNKNOWN_ERROR',
      details: error,
    };
  }
};

// Type guards pour vérifier les réponses API
export const isApiResponse = <T>(response: any): response is ApiResponse<T> => {
  return response && typeof response === 'object' && 'data' in response;
};

export const isApiError = (error: any): error is ApiError => {
  return error && typeof error === 'object' && 'message' in error;
};