/**
 * Cliente API para comunicación con el backend
 */
import { getToken } from './auth';
import { browser } from '$app/environment';
import { toast } from 'svelte-sonner';
import { clearAccessTokenOnDocument, setAccessTokenOnDocument } from '$lib/access-token-cookie-browser';

/** Base URL absoluta para fetch; corrige `http:host` sin `//` y añade `http://` si no hay esquema. */
function normalizeAbsoluteApiBaseUrl(raw: string): string {
	let s = (raw ?? '').trim().replace(/\/+$/, '');
	if (!s) return '';
	if (s.startsWith('http:') && !s.startsWith('http://')) {
		s = 'http://' + s.slice('http:'.length).replace(/^\/+/, '');
	}
	if (s.startsWith('https:') && !s.startsWith('https://')) {
		s = 'https://' + s.slice('https:'.length).replace(/^\/+/, '');
	}
	if (s.startsWith('/')) return s;
	if (/^https?:\/\//i.test(s)) return s;
	return `http://${s.replace(/^\/+/, '')}`;
}

const API_BASE_URL = normalizeAbsoluteApiBaseUrl(String(import.meta.env.VITE_API_URL ?? ''));

export interface ApiResponse<T = any> {
	data?: T;
	error?: string;
	validationErrors?: Array<{
		field: string;
		message: string;
		code?: string;
		solution?: string[];
		value?: any;
	}>;
	status: number;
}

/** Reemplaza referencias técnicas `line[n]` por texto más claro para el usuario. */
export function humanizeLineReferences(text: string): string {
	return text.replace(/\bline\[(\d+)\]/gi, 'partida $1');
}

function humanizeFieldPath(field: string): string {
	const rawField = (field || '').trim();
	if (!rawField) return 'campo';

	const lineMatch = rawField.match(/^line\[(\d+)\]\.(.+)$/i);
	const fieldPath = lineMatch?.[2] || rawField;
	const label = fieldPath
		.replace(/^body\./i, '')
		.replace(/\./g, ' → ')
		.replace(/_/g, ' ');

	if (lineMatch) {
		return `Partida ${lineMatch[1]} - ${label}`;
	}

	return label;
}

function humanizeValidationMessage(message: string): string {
	const rawMessage = (message || '').trim();
	if (!rawMessage) return 'error de validación';

	return rawMessage
		.replace(/\b(field required|is required)\b/gi, 'es obligatorio')
		.replace(/\b(value is not a valid decimal)\b/gi, 'debe ser un número válido')
		.replace(/\b(value is not a valid integer)\b/gi, 'debe ser un número entero válido');
}

function formatValidationHint(field: string, message: string, code?: string): string {
	const fieldLabel = humanizeFieldPath(field);
	const normalizedMessage = humanizeValidationMessage(message);

	if (code === 'REQUIRED' || code === 'REQUIRED_FIELD' || /es obligatorio|es requerido/i.test(normalizedMessage)) {
		return `Completa ${fieldLabel}.`;
	}

	if (code === 'AMERICAN_FRACTION_NOT_FOUND') {
		return 'La fracción americana seleccionada no existe. Elige una opción del catálogo.';
	}

	if (code === 'UNIT_OF_MEASURE_NOT_FOUND') {
		return 'La unidad de medida seleccionada no existe. Elige una opción del catálogo.';
	}

	if (code === 'ORIGIN_COUNTRY_NOT_FOUND') {
		return 'El país de origen seleccionado no existe. Elige una opción del catálogo.';
	}

	if (code === 'CLASS_NOT_FOUND') {
		return 'La clase seleccionada no existe. Elige una opción del catálogo.';
	}

	if (code === 'FRACTION_TYPE_INVALID') {
		return 'Selecciona un tipo de tarifa válido.';
	}

	return normalizedMessage;
}

/**
 * Título y descripción listos para toasts / alertas a partir de ApiResponse.
 * Prioriza los mensajes que ya envía el backend y evita duplicar rutas técnicas.
 */
export function friendlyApiErrorParts(res: ApiResponse): { title: string; description: string } {
	const validationErrors = res.validationErrors;
	if (validationErrors?.length) {
		const blocks = validationErrors.map((e) => {
			const base = formatValidationHint(e.field || '', e.message || '', e.code);
			const hints = e.solution?.filter(Boolean).length
				? '\n' + e.solution!.map((s) => `• ${humanizeLineReferences(s)}`).join('\n')
				: '';
			return base + hints;
		});
		const description = blocks.join('\n\n').trim();
		const rawTitle = (res.error || '').trim();
		const title =
			rawTitle &&
			!rawTitle.startsWith('Error de validación') &&
			rawTitle !== 'Error de validación'
				? rawTitle
				: 'Revisa los datos de la partida';
		return { title, description: description || rawTitle || 'Corrige los datos e intenta de nuevo.' };
	}

	if (res.error) {
		const err = humanizeValidationMessage(humanizeLineReferences(res.error.trim()));
		if (err.startsWith('Error de validación:')) {
			return {
				title: 'Revisa los datos ingresados',
				description: err.replace(/^Error de validación:\s*/i, '').trim() || err
			};
		}
		return { title: 'No se pudo completar la acción', description: err };
	}

	return {
		title: 'Error',
		description: 'Ocurrió un error inesperado. Intenta de nuevo o contacta a soporte si continúa.'
	};
}

let isRefreshing = false;
let refreshSubscribers: ((token: string) => void)[] = [];

/**
 * Agrega una petición a la cola de espera mientras se refresca el token
 */
function subscribeTokenRefresh(callback: (token: string) => void) {
	refreshSubscribers.push(callback);
}

/**
 * Notifica a todas las peticiones en espera que el token se ha refrescado
 */
function onTokenRefreshed(token: string) {
	refreshSubscribers.forEach((callback) => callback(token));
	refreshSubscribers = [];
}

/**
 * Refresca el token silenciosamente usando el endpoint server-side.
 *
 * El servidor lee el refresh_token desde la cookie HttpOnly,
 * llama a Keycloak, actualiza las cookies y devuelve el nuevo access_token.
 * El refresh_token NUNCA es leído por este código JavaScript.
 */
async function refreshToken(): Promise<string | null> {
	if (!browser) return null;

	try {
		const response = await fetch('/api-sveltekit/auth/silent-refresh', {
			method: 'POST',
			credentials: 'include', // Envía cookies HttpOnly automáticamente
			headers: { 'Content-Type': 'application/json' }
		});

		if (!response.ok) {
			console.error('❌ [API] Silent refresh falló, status:', response.status);
			clearAccessTokenOnDocument();
			const hubBase = (import.meta.env.VITE_HUB_URL || 'https://workspace.aduanasoft.com').replace(/\/+$/, '');
			setTimeout(() => {
				window.location.href = `${hubBase}/login?return_to=${encodeURIComponent(window.location.origin + '/login?sso_verified=1')}`;
			}, 1500);
			return null;
		}

		const data = await response.json() as { access_token?: string };

		if (data.access_token) {
			setAccessTokenOnDocument(data.access_token);

			// Actualizar authStore en memoria
			try {
				const { authStore } = await import('./auth');
				authStore.setToken(data.access_token);
			} catch {}

			return data.access_token;
		}

		return null;
	} catch (error) {
		console.error('❌ [API] Error en silent refresh:', error);
		return null;
	}
}

/**
 * Construye los headers de autenticación (Bearer + X-Tenant-Override SSO multi-tenant).
 * Compartido por fetchApi y fetchBlob para garantizar trato uniforme.
 */
function buildAuthHeaders(baseHeaders: Record<string, string> = {}): Record<string, string> {
	const headers: Record<string, string> = { ...baseHeaders };
	const token = getToken();

	if (token) {
		headers['Authorization'] = `Bearer ${token}`;
	}

	// sso_tenant_pub es una cookie no-HttpOnly que el servidor setea junto con sso_tenant_id.
	if (browser) {
		const tenantPub = document.cookie
			.split('; ')
			.find((c) => c.startsWith('sso_tenant_pub='))
			?.split('=')[1];
		if (tenantPub) {
			headers['X-Tenant-Override'] = tenantPub;
		}

		// active_system (SCAF/SCAII): cookie no-HttpOnly → header explícito para el backend.
		const activeSystem = document.cookie
			.split('; ')
			.find((c) => c.startsWith('active_system='))
			?.split('=')[1];
		if (activeSystem) {
			headers['X-Active-System'] = activeSystem;
		}
	}

	return headers;
}

/**
 * Realiza una petición al API con manejo automático de refresh token
 */
async function fetchApi<T = any>(
	endpoint: string,
	options: RequestInit = {},
	retryCount = 0
): Promise<ApiResponse<T>> {
	// Si ya estamos refrescando el token, esperar
	if (isRefreshing && retryCount === 0) {
		return new Promise((resolve) => {
			subscribeTokenRefresh((newToken) => {
				resolve(fetchApi<T>(endpoint, options, 1));
			});
		});
	}

	const token = getToken();

	if (!token && !endpoint.includes('/auth/login')) {
		console.warn('⚠️ [API] No hay token disponible para', endpoint);
	}

	const baseHeaders: Record<string, string> = {
		...((options.headers as Record<string, string>) || {})
	};

	// Only set Content-Type to application/json if not already set and body is not FormData
	if (!baseHeaders['Content-Type'] && !(options.body instanceof FormData)) {
		baseHeaders['Content-Type'] = 'application/json';
	}

	const headers = buildAuthHeaders(baseHeaders);

	try {
		const response = await fetch(`${API_BASE_URL}${endpoint}`, {
			...options,
			headers,
			credentials: 'include' // Importante: envía cookies con cada request
		});

		// 403 = permisos, no autenticación: nunca intentar refresh.
		if (response.status === 403 && !endpoint.includes('/auth/refresh') && retryCount === 0) {
			if (browser) {
				toast.error('No tienes permisos para realizar esta acción', {
					duration: 4000,
					description: 'Contacta a tu administrador si crees que esto es un error'
				});
			}
			const data = await response.json();
			return {
				error: data.detail || 'No tienes permisos para realizar esta acción',
				status: 403
			};
		}

		// 402 = licencia inválida/expirada: no intentar refresh.
		if (response.status === 402 && !endpoint.includes('/auth/refresh') && retryCount === 0) {
			const data = await response.json().catch(() => ({}));
			return {
				error: data.message || data.detail || 'Licencia inválida o expirada',
				status: 402
			};
		}

		// Solo 401 dispara silent refresh.
		if (response.status === 401 && !endpoint.includes('/auth/refresh') && retryCount === 0) {
			// Si es 401, intentar refrescar el token
			isRefreshing = true;

			try {
				const newToken = await refreshToken();

				if (newToken) {
					// Token refrescado exitosamente					
					onTokenRefreshed(newToken);
					isRefreshing = false;
					// Reintentar la petición original con el nuevo token
					return await fetchApi<T>(endpoint, options, 1);
				} else {
					console.error('❌ [API] No se pudo refrescar el token');
					isRefreshing = false;
					// Retornar error 401 para que la capa superior lo maneje
					return {
						error: 'Sesión expirada. Por favor, inicia sesión nuevamente.',
						status: 401
					};
				}
			} catch (refreshError) {
				console.error('❌ [API] Error al refrescar:', refreshError);
				isRefreshing = false;
				return {
					error: 'Error al refrescar la sesión',
					status: 401
				};
			}
		}

		// Manejar respuestas sin contenido (204 No Content)
		if (response.status === 204) {
			return {
				data: null as T,
				status: response.status
			};
		}

		const data = await response.json();

		if (!response.ok) {
			// Manejo especial para errores 422 (validation error)
			if (response.status === 422) {
				// HTTPException(detail={ message, errors }) — catálogo / CSV parity
				const det = data.detail || (typeof data.message === 'object' ? data.message : null);
				if (
					det &&
					typeof det === "object" &&
					!Array.isArray(det) &&
					Array.isArray((det as { errors?: unknown }).errors)
				) {
					const d = det as {
						message?: string;
						errors: Array<{ col?: string; msg?: string; field?: string; message?: string }>;
					};

					// Mapping for catalog column names to DTO field names
					const colToField: Record<string, string> = {
						"CLAVE TRANSPORTISTA": "transporter_key",
						NOMBRE: "name",
						"NOMBRE CORTO": "short_name",
						RESPONSABLE: "responsible",
						RFC: "rfc",
						CALLES: "streets",
						"CODIGO POSTAL": "postal_code",
						CIUDAD: "city",
						ESTADO: "state",
						PAIS: "country",
						"CODIGO CARGADOR": "loader_code",
						"CODIGO CAAT": "caat_code",
						"CODIGO TRANS": "transport_code",
						"TIPO INTERFASE TRANS": "transport_interface_type",
						"SERVIDOR FTP": "ftp_server",
						"USUARIO FTP": "ftp_user",
						"CLAVE ACCESO FTP": "ftp_password",
						"DIRECTORIO FTP": "ftp_directory",
						// Vehicles
						CLAVE: "vehicle_key",
						"CLAVE ACE": "ace_vehicle_key", // Fallback for vehicles
						"CLAVE TRANSPORTE": "transporter_key",
						VIN: "series",
						"TIPO TRANSPORTE": "transport_type",
						"CODIGO DE ENTIDAD": "entity_code",
						TRANSPONDEDOR: "transponder_number",
						"NUMERO DOT": "dot_number",
						PLACAS: "plate_number",
						PRECINTO: "seal",
						"EMPRESA ASEGURADORA": "insurance_company_name",
						"NUM. ASEGURADORA": "insurance_number",
						"MONTO ASEGURADO": "insurance_amount",
						"FECHA DE ASEGURADORA": "insurance_date",
						// Trailers
						"NUMERO TRAILER": "trailer_number",
						"TIPO TRAILER": "trailer_type_key",
						"CODIGO ENTIDAD": "entity_code",
						"CLAVE CONTENEDOR": "container_key"
					};

					const normalizedErrors = d.errors.map((err) => ({
						field: err.field || (err.col ? colToField[err.col] || err.col : ""),
						message: err.message || err.msg || "Error de validación"
					}));

					return {
						error: d.message || (typeof data.message === 'string' ? data.message : 'Error de validación'),
						validationErrors: normalizedErrors,
						status: response.status
					};
				}
				// Errores de validación personalizados (con array errors en raíz)
				if (data.errors && Array.isArray(data.errors)) {
					return {
						error: data.message || 'Error de validación',
						validationErrors: data.errors as NonNullable<ApiResponse['validationErrors']>,
						status: response.status
					};
				}
				// Errores de validación de FastAPI (con detail)
				else if (data.detail) {
					let errorMessage = 'Error de validación: ';
					const vErrors: NonNullable<ApiResponse['validationErrors']> = [];

					// FastAPI devuelve errores de validación en data.detail como array
					if (Array.isArray(data.detail)) {
						data.detail.forEach((err: any) => {
							const fieldPath = err.loc ? err.loc.filter((l: any) => l !== 'body').join('.') : 'campo';
							const msg = humanizeValidationMessage(err.msg || 'error de validación');
							
							vErrors.push({
								field: err.loc ? String(err.loc[err.loc.length - 1]) : 'campo',
								message: msg
							});
						});
						
						errorMessage += data.detail.map((err: any) => {
							const field = err.loc ? err.loc.join('.') : 'campo desconocido';
							return `${field}: ${err.msg}`;
						}).join(', ');
					} else if (typeof data.detail === 'string') {
						errorMessage = data.detail;
					} else {
						errorMessage += JSON.stringify(data.detail);
					}

					return {
						error: errorMessage,
						validationErrors: vErrors.length ? vErrors : undefined,
						status: response.status
					};
				}
			}

			return {
				error: data.message || (typeof data.detail === 'string' ? data.detail : JSON.stringify(data.detail)) || 'Error en la petición',
				status: response.status
			};
		}

		return {
			data,
			status: response.status
		};
	} catch (error) {
		console.error(`❌ [API] Error de conexión en ${endpoint}:`, error);
		return {
			error: 'Error de conexión con el servidor',
			status: 0
		};
	}
}

/** Opciones para subidas CSV (FormData) con progreso de red. */
export type CsvFormDataUploadOptions = {
	onUploadProgress?: (e: { loaded: number; total: number }) => void;
};

/**
 * POST multipart/form-data con XMLHttpRequest para exponer progreso de subida.
 * Misma semántica de auth/401/403/422 que fetchApi.
 */
async function fetchApiFormDataPost<T = any>(
	endpoint: string,
	formData: FormData,
	opts: CsvFormDataUploadOptions & { retryCount?: number } = {}
): Promise<ApiResponse<T>> {
	const retryCount = opts.retryCount ?? 0;

	if (isRefreshing && retryCount === 0) {
		return new Promise((resolve) => {
			subscribeTokenRefresh(() => {
				resolve(fetchApiFormDataPost<T>(endpoint, formData, { ...opts, retryCount: 1 }));
			});
		});
	}

	return new Promise((resolve) => {
		const token = getToken();
		const xhr = new XMLHttpRequest();
		xhr.open('POST', `${API_BASE_URL}${endpoint}`);
		xhr.withCredentials = true;
		if (token) {
			xhr.setRequestHeader('Authorization', `Bearer ${token}`);
		}

		xhr.upload.onprogress = (ev) => {
			if (!opts.onUploadProgress) return;
			if (ev.lengthComputable) {
				opts.onUploadProgress({ loaded: ev.loaded, total: ev.total });
			} else {
				opts.onUploadProgress({ loaded: ev.loaded, total: 0 });
			}
		};

		xhr.onload = () => {
			void (async () => {
				const status = xhr.status;
				let data: any = null;
				if (xhr.responseText) {
					try {
						data = JSON.parse(xhr.responseText) as any;
					} catch {
						data = null;
					}
				}

				if ((status === 401 || status === 403) && !endpoint.includes('/auth/refresh') && retryCount === 0) {
					if (status === 403) {
						if (browser) {
							toast.error('No tienes permisos para realizar esta acción', {
								duration: 4000,
								description: 'Contacta a tu administrador si crees que esto es un error'
							});
						}
						resolve({
							error: data?.detail || 'No tienes permisos para realizar esta acción',
							status: 403
						});
						return;
					}

					isRefreshing = true;
					try {
						const newToken = await refreshToken();
						if (newToken) {
							onTokenRefreshed(newToken);
							isRefreshing = false;
							resolve(await fetchApiFormDataPost<T>(endpoint, formData, { ...opts, retryCount: 1 }));
						} else {
							console.error('❌ [API] No se pudo refrescar el token');
							isRefreshing = false;
							resolve({
								error: 'Sesión expirada. Por favor, inicia sesión nuevamente.',
								status: 401
							});
						}
					} catch (refreshError) {
						console.error('❌ [API] Error al refrescar:', refreshError);
						isRefreshing = false;
						resolve({
							error: 'Error al refrescar la sesión',
							status: 401
						});
					}
					return;
				}

				if (status === 204) {
					resolve({
						data: null as T,
						status
					});
					return;
				}

				if (status === 0) {
					resolve({
						error: 'Error de conexión con el servidor',
						status: 0
					});
					return;
				}

				if (status < 200 || status >= 300) {
					if (status === 422 && data) {
						if (data.errors && Array.isArray(data.errors)) {
							resolve({
								error: data.message || 'Error de validación',
								validationErrors: data.errors as NonNullable<ApiResponse['validationErrors']>,
								status: 422
							});
							return;
						}
						if (data.detail) {
							let errorMessage = 'Error de validación: ';
							if (Array.isArray(data.detail)) {
								const errors = data.detail
									.map((err: any) => {
										const field = err.loc ? err.loc.filter((loc: string) => loc !== 'body').join('.') : 'campo desconocido';
										return `${humanizeFieldPath(field)}: ${humanizeValidationMessage(err.msg || 'error de validación')}`;
									})
									.join(', ');
								errorMessage += errors;
							} else if (typeof data.detail === 'string') {
								errorMessage = data.detail;
							} else {
								errorMessage += JSON.stringify(data.detail);
							}
							resolve({
								error: errorMessage,
								status: 422
							});
							return;
						}
					}
					resolve({
						error:
							data?.message ||
							(typeof data?.detail === 'string' ? data.detail : JSON.stringify(data?.detail)) ||
							'Error en la petición',
						status
					});
					return;
				}

				if (data === null && xhr.responseText) {
					resolve({
						error: 'Respuesta inválida del servidor',
						status
					});
					return;
				}

				resolve({
					data,
					status
				});
			})();
		};

		xhr.onerror = () => {
			resolve({
				error: 'Error de conexión con el servidor',
				status: 0
			});
		};

		try {
			xhr.send(formData);
		} catch (error) {
			console.error(`❌ [API] Error al enviar ${endpoint}:`, error);
			resolve({
				error: 'Error de conexión con el servidor',
				status: 0
			});
		}
	});
}

/**
 * Convierte cuerpos de error (JSON o texto) en un mensaje legible para toasts/UX.
 * Evita mostrar JSON crudo p. ej. `{"error":"HTTP_ERROR","message":"..."}`.
 */
function messageFromBlobErrorResponse(text: string, status: number): string {
	const raw = (text || '').trim();
	if (!raw) {
		return status === 404
			? 'No se encontró el recurso. Prueba otro rango o vuelve a intentar.'
			: `Error ${status} al descargar el archivo.`;
	}
	try {
		const data = JSON.parse(raw) as Record<string, unknown>;
		if (typeof data.message === 'string' && data.message.trim()) {
			return data.message.trim();
		}
		const d = data.detail;
		if (typeof d === 'string' && d.trim()) {
			return d.trim();
		}
		if (Array.isArray(d) && d[0] && typeof (d[0] as { msg?: string }).msg === 'string') {
			return String((d[0] as { msg: string }).msg).trim();
		}
	} catch {
		// no es JSON: usar texto plano si es corto y legible
	}
	if (raw.length < 500 && !raw.startsWith('{')) {
		return raw;
	}
	if (raw.startsWith('{')) {
		return status === 404
			? 'No se encontró información para exportar. Prueba otras fechas o amplía el rango.'
			: `Error ${status} al descargar el archivo.`;
	}
	return raw;
}

async function fetchBlob(
	endpoint: string,
	options: RequestInit = {},
	retryCount = 0
): Promise<Blob> {
	// Si ya estamos refrescando el token, esperar a que termine antes de pegar.
	if (isRefreshing && retryCount === 0) {
		return new Promise((resolve, reject) => {
			subscribeTokenRefresh(() => {
				fetchBlob(endpoint, options, 1).then(resolve).catch(reject);
			});
		});
	}

	const headers = buildAuthHeaders((options.headers as Record<string, string>) || {});

	const response = await fetch(`${API_BASE_URL}${endpoint}`, {
		...options,
		headers,
		credentials: 'include'
	});

	// 401: intentar silent refresh y reintentar una vez (mismo flujo que fetchApi).
	if (response.status === 401 && !endpoint.includes('/auth/refresh') && retryCount === 0) {
		isRefreshing = true;
		try {
			const newToken = await refreshToken();
			if (newToken) {
				onTokenRefreshed(newToken);
				isRefreshing = false;
				return await fetchBlob(endpoint, options, 1);
			}
			isRefreshing = false;
			throw new Error('Sesión expirada. Por favor, inicia sesión nuevamente.');
		} catch (refreshError) {
			isRefreshing = false;
			if (refreshError instanceof Error) throw refreshError;
			throw new Error('Error al refrescar la sesión');
		}
	}

	// 403: notificar permisos de manera consistente con fetchApi.
	if (response.status === 403) {
		if (browser) {
			toast.error('No tienes permisos para realizar esta acción', {
				duration: 4000,
				description: 'Contacta a tu administrador si crees que esto es un error'
			});
		}
		const text = await response.text().catch(() => '');
		throw new Error(messageFromBlobErrorResponse(text, response.status));
	}

	if (!response.ok) {
		const text = await response.text().catch(() => '');
		throw new Error(messageFromBlobErrorResponse(text, response.status));
	}
	return await response.blob();
}

// Métodos HTTP
export const api = {
	get: <T = any>(endpoint: string) => fetchApi<T>(endpoint, { method: 'GET' }),
	getBlob: (endpoint: string) => fetchBlob(endpoint, { method: 'GET' }),
	postBlob: (endpoint: string, body: any) =>
		fetchBlob(endpoint, {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
			body: JSON.stringify(body)
		}),

	post: <T = any>(endpoint: string, body: any, options: RequestInit = {}) =>
		fetchApi<T>(endpoint, {
			method: 'POST',
			body: JSON.stringify(body),
			...options
		}),

	put: <T = any>(endpoint: string, body: any, options: RequestInit = {}) =>
		fetchApi<T>(endpoint, {
			method: 'PUT',
			body: JSON.stringify(body),
			...options
		}),

	patch: <T = any>(endpoint: string, body: any, options: RequestInit = {}) =>
		fetchApi<T>(endpoint, {
			method: 'PATCH',
			body: JSON.stringify(body),
			...options
		}),

	delete: <T = any>(endpoint: string, options: RequestInit = {}) => fetchApi<T>(endpoint, { method: 'DELETE', ...options }),

	auth: {
		login: (credentials: { username: string; password: string; tenant_slug: string }) =>
			api.post('/v1/auth/login/', credentials),
		refresh: (refreshToken: string) =>
			api.post('/v1/auth/refresh/', { refresh_token: refreshToken }),
		logout: (data: { refresh_token: string, username?: string }) => api.post('/v1/auth/logout', data, { keepalive: true }),
		me: () => api.get('/v1/auth/me/'),
		health: () => api.get('/health'),
		register: (data: {
			username: string;
			email: string;
			password: string;
			first_name: string;
			last_name: string;
			tenant_slug: string;
			invite_token?: string;
		}) => api.post('/v1/auth/register', data),
	},

	tenants: {
		list: (page = 1, pageSize = 50) =>
			api.get(`/v1/tenants/?page=${page}&page_size=${pageSize}`),
		get: (id: number) => api.get(`/v1/tenants/${id}/`),
		create: (data: any) => api.post('/v1/tenants/', data),
		update: (id: number, data: any) => api.put(`/v1/tenants/${id}/`, data)
	},

	licenses: {
		get: (tenantId: number) => api.get(`/v1/licenses/tenant/${tenantId}/`),
		myLicense: () => api.get('/v1/licenses/my-license/'),
		usage: (tenantId: number) => api.get(`/v1/licenses/usage/${tenantId}/`),
		validate: (tenantId: number) => api.get(`/v1/licenses/validate/${tenantId}/`)
	},

	// Agrega aquí los endpoints específicos de tu proyecto.

	// Implementa aquí tus endpoints de importación CSV si los necesitas.

	// Generic request for custom needs (like file uploads)
	request: <T = any>(endpoint: string, options: RequestInit = {}) => fetchApi<T>(endpoint, options)
};
