import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';

// Función para unir clases de Tailwind
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

// Configuración base de la API
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000';

// Interceptor para manejar errores comunes
async function handleApiError(response: Response) {
  if (!response.ok) {
    const errorData = await response.json().catch(() => ({}));

    // Manejar errores de autenticación
    if (response.status === 401) {
      throw new Error('No autorizado. Por favor inicia sesión.');
    }

    // Manejar errores de validación
    if (response.status === 422) {
      const fieldErrors = errorData.errors || {};
      const errorMessage = Object.entries(fieldErrors)
        .map(([field, errors]) => `${field}: ${Array.isArray(errors) ? errors.join(', ') : errors}`)
        .join('; ');
      throw new Error(errorMessage || 'Error de validación');
    }

    // Manejar errores de servidor
    if (response.status >= 500) {
      throw new Error('Error del servidor. Por favor intenta de nuevo más tarde.');
    }

    // Manejar otros errores
    throw new Error(errorData.message || 'Error en la solicitud');
  }

  return response;
}

// Función genérica para peticiones GET
export async function apiGet<T>(endpoint: string, params?: Record<string, any>): Promise<T> {
  const url = new URL(`${API_BASE_URL}${endpoint}`);

  if (params) {
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        url.searchParams.append(key, String(value));
      }
    });
  }

  const response = await fetch(url.toString(), {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    },
  });

  await handleApiError(response);
  return response.json();
}

// Función genérica para peticiones POST
export async function apiPost<T>(endpoint: string, data: any): Promise<T> {
  const response = await fetch(`${API_BASE_URL}${endpoint}`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
  });

  await handleApiError(response);
  return response.json();
}

// Función genérica para peticiones PUT
export async function apiPut<T>(endpoint: string, data: any): Promise<T> {
  const response = await fetch(`${API_BASE_URL}${endpoint}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
  });

  await handleApiError(response);
  return response.json();
}

// Función genérica para peticiones DELETE
export async function apiDelete<T>(endpoint: string): Promise<T> {
  const response = await fetch(`${API_BASE_URL}${endpoint}`, {
    method: 'DELETE',
    headers: {
      'Content-Type': 'application/json',
    },
  });

  await handleApiError(response);
  return response.json();
}

// Función para subir archivos
export async function apiUpload<T>(
  endpoint: string,
  file: File,
  additionalData?: Record<string, any>
): Promise<T> {
  const formData = new FormData();
  formData.append('file', file);

  if (additionalData) {
    Object.entries(additionalData).forEach(([key, value]) => {
      formData.append(key, String(value));
    });
  }

  const response = await fetch(`${API_BASE_URL}${endpoint}`, {
    method: 'POST',
    body: formData,
  });

  await handleApiError(response);
  return response.json();
}

// Función para peticiones con paginación
export async function apiGetPaginated<T>(
  endpoint: string,
  page: number = 1,
  limit: number = 10,
  filters?: Record<string, any>
): Promise<{
  data: T[];
  pagination: {
    page: number;
    limit: number;
    total: number;
    totalPages: number;
  };
}> {
  const params = {
    page,
    limit,
    ...filters,
  };

  return apiGet(endpoint, params);
}

// Función para buscar
export async function apiSearch<T>(
  endpoint: string,
  query: string,
  filters?: Record<string, any>
): Promise<T[]> {
  return apiGet(endpoint, {
    search: query,
    ...filters,
  });
}
