/**
 * Utilitários para criar janela flutuante redimensionável e arrastável
 */

export interface PosicaoJanela {
	x: number;
	y: number;
	width: number;
	height: number;
}

export interface LimitesJanela {
	minWidth: number;
	minHeight: number;
	maxWidth?: number;
	maxHeight?: number;
}

function getDefaultLimits(): LimitesJanela {
	if (typeof window === 'undefined') {
		return {
			minWidth: 400,
			minHeight: 300,
			maxWidth: 1920,
			maxHeight: 1080
		};
	}
	return {
		minWidth: 400,
		minHeight: 300,
		maxWidth: window.innerWidth,
		maxHeight: window.innerHeight
	};
}

const DEFAULT_LIMITS: LimitesJanela = getDefaultLimits();

/**
 * Salvar posição da janela no localStorage
 */
export function salvarPosicaoJanela(
	id: string,
	posicao: PosicaoJanela
): void {
	if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
		return;
	}
	try {
		const key = `floating-window-${id}`;
		localStorage.setItem(key, JSON.stringify(posicao));
	} catch (error) {
		console.warn('Erro ao salvar posição da janela:', error);
	}
}

/**
 * Restaurar posição da janela do localStorage
 */
export function restaurarPosicaoJanela(id: string): PosicaoJanela | null {
	if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
		return null;
	}
	try {
		const key = `floating-window-${id}`;
		const saved = localStorage.getItem(key);
		if (!saved) return null;
		
		const posicao = JSON.parse(saved) as PosicaoJanela;
		
		// Validar se a posição ainda é válida (dentro da tela)
		if (
			posicao.x >= 0 &&
			posicao.y >= 0 &&
			posicao.x + posicao.width <= window.innerWidth + 100 &&
			posicao.y + posicao.height <= window.innerHeight + 100 &&
			posicao.width >= DEFAULT_LIMITS.minWidth &&
			posicao.height >= DEFAULT_LIMITS.minHeight
		) {
			return posicao;
		}
		
		return null;
	} catch (error) {
		console.warn('Erro ao restaurar posição da janela:', error);
		return null;
	}
}

/**
 * Obter posição inicial da janela (centralizada)
 */
export function obterPosicaoInicial(
	width: number = 800,
	height: number = 600
): PosicaoJanela {
	if (typeof window === 'undefined') {
		return {
			x: 100,
			y: 100,
			width,
			height
		};
	}
	return {
		x: (window.innerWidth - width) / 2,
		y: (window.innerHeight - height) / 2,
		width,
		height
	};
}

/**
 * Criar handler de arrastar para janela
 */
export function criarDragHandler(
	element: HTMLElement,
	handle: HTMLElement,
	onPositionChange?: (x: number, y: number) => void
): () => void {
	let isDragging = false;
	let startX = 0;
	let startY = 0;
	let initialX = 0;
	let initialY = 0;

	function handleMouseDown(e: MouseEvent): void {
		if (e.button !== 0) return; // Apenas botão esquerdo
		
		isDragging = true;
		startX = e.clientX;
		startY = e.clientY;
		
		const rect = element.getBoundingClientRect();
		initialX = rect.left;
		initialY = rect.top;

		document.addEventListener('mousemove', handleMouseMove);
		document.addEventListener('mouseup', handleMouseUp);
		
		e.preventDefault();
	}

	function handleMouseMove(e: MouseEvent): void {
		if (!isDragging) return;

		const deltaX = e.clientX - startX;
		const deltaY = e.clientY - startY;

		let newX = initialX + deltaX;
		let newY = initialY + deltaY;

		// Limitar movimento dentro da tela
		if (typeof window === 'undefined') return;
		const maxX = window.innerWidth - element.offsetWidth;
		const maxY = window.innerHeight - element.offsetHeight;

		newX = Math.max(0, Math.min(newX, maxX));
		newY = Math.max(0, Math.min(newY, maxY));

		element.style.left = `${newX}px`;
		element.style.top = `${newY}px`;

		if (onPositionChange) {
			onPositionChange(newX, newY);
		}
	}

	function handleMouseUp(): void {
		isDragging = false;
		document.removeEventListener('mousemove', handleMouseMove);
		document.removeEventListener('mouseup', handleMouseUp);
	}

	// Suporte para touch (mobile)
	function handleTouchStart(e: TouchEvent): void {
		if (e.touches.length !== 1) return;
		
		isDragging = true;
		const touch = e.touches[0];
		startX = touch.clientX;
		startY = touch.clientY;
		
		const rect = element.getBoundingClientRect();
		initialX = rect.left;
		initialY = rect.top;

		document.addEventListener('touchmove', handleTouchMove, { passive: false });
		document.addEventListener('touchend', handleTouchEnd);
		
		e.preventDefault();
	}

	function handleTouchMove(e: TouchEvent): void {
		if (!isDragging || e.touches.length !== 1) return;

		const touch = e.touches[0];
		const deltaX = touch.clientX - startX;
		const deltaY = touch.clientY - startY;

		let newX = initialX + deltaX;
		let newY = initialY + deltaY;

		if (typeof window === 'undefined') return;
		const maxX = window.innerWidth - element.offsetWidth;
		const maxY = window.innerHeight - element.offsetHeight;

		newX = Math.max(0, Math.min(newX, maxX));
		newY = Math.max(0, Math.min(newY, maxY));

		element.style.left = `${newX}px`;
		element.style.top = `${newY}px`;

		if (onPositionChange) {
			onPositionChange(newX, newY);
		}

		e.preventDefault();
	}

	function handleTouchEnd(): void {
		isDragging = false;
		document.removeEventListener('touchmove', handleTouchMove);
		document.removeEventListener('touchend', handleTouchEnd);
	}

	handle.addEventListener('mousedown', handleMouseDown);
	handle.addEventListener('touchstart', handleTouchStart, { passive: false });

	// Retornar função de cleanup
	return () => {
		handle.removeEventListener('mousedown', handleMouseDown);
		handle.removeEventListener('touchstart', handleTouchStart);
		document.removeEventListener('mousemove', handleMouseMove);
		document.removeEventListener('mouseup', handleMouseUp);
		document.removeEventListener('touchmove', handleTouchMove);
		document.removeEventListener('touchend', handleTouchEnd);
	};
}

/**
 * Criar handler de redimensionar para janela
 */
export function criarResizeHandler(
	element: HTMLElement,
	handles: HTMLElement[],
	limites: LimitesJanela = DEFAULT_LIMITS,
	onSizeChange?: (width: number, height: number) => void
): () => void {
	let isResizing = false;
	let currentHandle: HTMLElement | null = null;
	let startX = 0;
	let startY = 0;
	let startWidth = 0;
	let startHeight = 0;
	let startLeft = 0;
	let startTop = 0;

	function handleMouseDown(e: MouseEvent, handle: HTMLElement): void {
		if (e.button !== 0) return;
		
		isResizing = true;
		currentHandle = handle;
		startX = e.clientX;
		startY = e.clientY;
		
		const rect = element.getBoundingClientRect();
		startWidth = rect.width;
		startHeight = rect.height;
		startLeft = rect.left;
		startTop = rect.top;

		document.addEventListener('mousemove', handleMouseMove);
		document.addEventListener('mouseup', handleMouseUp);
		
		e.preventDefault();
		e.stopPropagation();
	}

	function handleMouseMove(e: MouseEvent): void {
		if (!isResizing || !currentHandle) return;

		const deltaX = e.clientX - startX;
		const deltaY = e.clientY - startY;

		let newWidth = startWidth;
		let newHeight = startHeight;
		let newLeft = startLeft;
		let newTop = startTop;

		// Determinar direção do resize baseado na classe do handle
		const classes = currentHandle.className;
		
		// Right
		if (classes.includes('resize-right') || classes.includes('resize-e')) {
			newWidth = startWidth + deltaX;
		}
		
		// Bottom
		if (classes.includes('resize-bottom') || classes.includes('resize-s')) {
			newHeight = startHeight + deltaY;
		}
		
		// Left
		if (classes.includes('resize-left') || classes.includes('resize-w')) {
			newWidth = startWidth - deltaX;
			newLeft = startLeft + deltaX;
		}
		
		// Top
		if (classes.includes('resize-top') || classes.includes('resize-n')) {
			newHeight = startHeight - deltaY;
			newTop = startTop + deltaY;
		}
		
		// Corner handles
		if (classes.includes('resize-se')) {
			newWidth = startWidth + deltaX;
			newHeight = startHeight + deltaY;
		}
		if (classes.includes('resize-sw')) {
			newWidth = startWidth - deltaX;
			newHeight = startHeight + deltaY;
			newLeft = startLeft + deltaX;
		}
		if (classes.includes('resize-ne')) {
			newWidth = startWidth + deltaX;
			newHeight = startHeight - deltaY;
			newTop = startTop + deltaY;
		}
		if (classes.includes('resize-nw')) {
			newWidth = startWidth - deltaX;
			newHeight = startHeight - deltaY;
			newLeft = startLeft + deltaX;
			newTop = startTop + deltaY;
		}

		if (typeof window === 'undefined') return;
		
		// Aplicar limites
		const maxWidth = limites.maxWidth || window.innerWidth - newLeft;
		const maxHeight = limites.maxHeight || window.innerHeight - newTop;

		newWidth = Math.max(limites.minWidth, Math.min(newWidth, maxWidth));
		newHeight = Math.max(limites.minHeight, Math.min(newHeight, maxHeight));

		// Ajustar posição se necessário
		if (newLeft + newWidth > window.innerWidth) {
			newLeft = window.innerWidth - newWidth;
		}
		if (newTop + newHeight > window.innerHeight) {
			newTop = window.innerHeight - newHeight;
		}

		if (newLeft < 0) {
			newLeft = 0;
			newWidth = Math.min(newWidth, window.innerWidth);
		}
		if (newTop < 0) {
			newTop = 0;
			newHeight = Math.min(newHeight, window.innerHeight);
		}

		element.style.width = `${newWidth}px`;
		element.style.height = `${newHeight}px`;
		element.style.left = `${newLeft}px`;
		element.style.top = `${newTop}px`;

		if (onSizeChange) {
			onSizeChange(newWidth, newHeight);
		}
	}

	function handleMouseUp(): void {
		isResizing = false;
		currentHandle = null;
		document.removeEventListener('mousemove', handleMouseMove);
		document.removeEventListener('mouseup', handleMouseUp);
	}

	const cleanupFunctions: (() => void)[] = [];

	// Adicionar listeners para cada handle
	for (const handle of handles) {
		const handler = (e: MouseEvent) => handleMouseDown(e, handle);
		handle.addEventListener('mousedown', handler);
		cleanupFunctions.push(() => handle.removeEventListener('mousedown', handler));
	}

	// Retornar função de cleanup
	return () => {
		cleanupFunctions.forEach((cleanup) => cleanup());
		document.removeEventListener('mousemove', handleMouseMove);
		document.removeEventListener('mouseup', handleMouseUp);
	};
}


