<script lang="ts">
	import { api } from '@sgse-app/backend/convex/_generated/api';
	import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
	import { useQuery } from 'convex-svelte';
	import { SvelteSet } from 'svelte/reactivity';
	import {
		abrirChat,
		abrirConversa,
		chatAberto,
		chatMinimizado,
		conversaAtiva,
		fecharChat,
		maximizarChat,
		minimizarChat,
		notificacaoAtiva
	} from '$lib/stores/chatStore';
	import ChatList from './ChatList.svelte';
	import ChatWindow from './ChatWindow.svelte';
	import { MessageSquare, Minus, Maximize2, X, Bell } from 'lucide-svelte';
	import { obterCoresDoTema, obterTemaPersistidoNoLocalStorage } from '$lib/utils/temas';

	const count = useQuery(api.chat.contarNotificacoesNaoLidas, {});

	// Query otimizada: usar apenas uma query para obter usuário atual
	// Priorizar obterPerfil pois retorna mais informações úteis
	const meuPerfilQuery = useQuery(api.usuarios.obterPerfil, {});
	const currentUser = useQuery(api.auth.getCurrentUser, {});

	// Derivar ID do usuário de forma otimizada (usar perfil primeiro, fallback para currentUser)
	const meuId = $derived(() => {
		if (meuPerfilQuery?.data?._id) {
			return String(meuPerfilQuery.data._id).trim();
		}
		if (currentUser?.data?._id) {
			return String(currentUser.data._id).trim();
		}
		return null;
	});

	let isOpen = $derived(false);
	let isMinimized = $derived(false);
	let activeConversation = $state<string | null>(null);

	// Função para obter a URL do avatar/foto do usuário logado (otimizada)
	let avatarUrlDoUsuario = $derived(() => {
		// Priorizar perfil (tem mais informações)
		const perfil = meuPerfilQuery?.data;
		if (perfil?.fotoPerfilUrl) {
			return perfil.fotoPerfilUrl;
		}

		// Fallback para currentUser
		const usuario = currentUser?.data;
		if (usuario?.fotoPerfilUrl) {
			return usuario.fotoPerfilUrl;
		}

		// Fallback: retornar null para usar o ícone User do Lucide
		return null;
	});

	// Posição do widget (arrastável)
	// Inicializar posição como null para indicar que precisa ser calculada
	let position = $state<{ x: number; y: number } | null>(null);
	let isDragging = $state(false);
	let dragStart = $state({ x: 0, y: 0 });
	let isAnimating = $state(false);
	let dragThreshold = $state(5); // Distância mínima em pixels para considerar arrastar
	let hasMoved = $state(false); // Flag para verificar se houve movimento durante o arrastar
	let shouldPreventClick = $state(false); // Flag para prevenir clique após arrastar
	let isDoubleClicking = $state(false); // Flag para prevenir clique simples após duplo clique

	// Suporte a gestos touch (swipe)
	let touchStart = $state<{ x: number; y: number; time: number } | null>(null);
	let touchCurrent = $state<{ x: number; y: number } | null>(null);
	let isTouching = $state(false);
	let swipeVelocity = $state(0); // Velocidade do swipe para animação

	// Tamanho da janela (redimensionável)
	const MIN_WIDTH = 300;
	const MAX_WIDTH = 1200;
	const MIN_HEIGHT = 400;
	const MAX_HEIGHT = 900;
	const DEFAULT_WIDTH = 440;
	const DEFAULT_HEIGHT = 680;

	// Carregar tamanho salvo do localStorage ou usar padrão
	function getSavedSize() {
		if (typeof window === 'undefined') return { width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT };
		const saved = localStorage.getItem('chat-window-size');
		if (saved) {
			try {
				const parsed = JSON.parse(saved);
				return {
					width: Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, parsed.width || DEFAULT_WIDTH)),
					height: Math.max(MIN_HEIGHT, Math.min(MAX_HEIGHT, parsed.height || DEFAULT_HEIGHT))
				};
			} catch {
				return { width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT };
			}
		}
		return { width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT };
	}

	let windowSize = $state(getSavedSize());
	let isMaximized = $state(false);
	let previousSize = $state({ width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT });
	let previousPosition = $state<{ x: number; y: number } | null>(null);

	// Dimensões da janela (reativo)
	let windowDimensions = $state({ width: 0, height: 0 });

	// Atualizar dimensões da janela
	function updateWindowDimensions() {
		if (typeof window !== 'undefined') {
			windowDimensions = {
				width: window.innerWidth,
				height: window.innerHeight
			};
		}
	}

	// Inicializar e atualizar dimensões da janela
	$effect(() => {
		if (typeof window === 'undefined') return;

		updateWindowDimensions();

		// Inicializar posição apenas uma vez quando as dimensões estiverem disponíveis
		if (position === null) {
			const saved = localStorage.getItem('chat-widget-position');
			if (saved) {
				try {
					const parsed = JSON.parse(saved);
					position = parsed;
				} catch {
					// Se falhar ao parsear, usar posição padrão no canto inferior direito
					position = {
						x: window.innerWidth - 72 - 24,
						y: window.innerHeight - 72 - 24
					};
				}
			} else {
				// Posição padrão: canto inferior direito
				position = {
					x: window.innerWidth - 72 - 24,
					y: window.innerHeight - 72 - 24
				};
			}
			savePosition(); // Salvar posição inicial
		}

		const handleResize = () => {
			updateWindowDimensions();
			// Ajustar posição quando a janela redimensionar
			if (position) {
				ajustarPosicao();
			}
		};

		window.addEventListener('resize', handleResize);

		return () => {
			window.removeEventListener('resize', handleResize);
		};
	});

	// Salvar posição no localStorage
	function savePosition() {
		if (typeof window !== 'undefined' && position) {
			localStorage.setItem('chat-widget-position', JSON.stringify(position));
		}
	}

	// Salvar tamanho no localStorage
	function saveSize() {
		if (typeof window !== 'undefined') {
			localStorage.setItem('chat-window-size', JSON.stringify(windowSize));
		}
	}

	// Redimensionamento
	let isResizing = $state(false);
	let resizeStart = $state({ x: 0, y: 0, width: 0, height: 0 });
	let resizeDirection = $state<string | null>(null); // 'n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'

	function handleResizeStart(e: MouseEvent | KeyboardEvent, direction: string) {
		if (!(e instanceof MouseEvent) || e.button !== 0) return;
		e.preventDefault();
		e.stopPropagation();
		isResizing = true;
		resizeDirection = direction;
		resizeStart = {
			x: e.clientX,
			y: e.clientY,
			width: windowSize.width,
			height: windowSize.height
		};
		document.body.classList.add('resizing');
	}

	function handleResizeMove(e: MouseEvent) {
		if (!isResizing || !resizeDirection || !position) return;

		const deltaX = e.clientX - resizeStart.x;
		const deltaY = e.clientY - resizeStart.y;

		let newWidth = resizeStart.width;
		let newHeight = resizeStart.height;
		let newX = position.x;
		let newY = position.y;

		// Redimensionar baseado na direção
		if (resizeDirection.includes('e')) {
			newWidth = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, resizeStart.width + deltaX));
		}
		if (resizeDirection.includes('w')) {
			const calculatedWidth = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, resizeStart.width - deltaX));
			const widthDelta = resizeStart.width - calculatedWidth;
			newWidth = calculatedWidth;
			newX = position.x + widthDelta;
		}
		if (resizeDirection.includes('s')) {
			newHeight = Math.max(MIN_HEIGHT, Math.min(MAX_HEIGHT, resizeStart.height + deltaY));
		}
		if (resizeDirection.includes('n')) {
			const calculatedHeight = Math.max(
				MIN_HEIGHT,
				Math.min(MAX_HEIGHT, resizeStart.height - deltaY)
			);
			const heightDelta = resizeStart.height - calculatedHeight;
			newHeight = calculatedHeight;
			newY = position.y + heightDelta;
		}

		windowSize = { width: newWidth, height: newHeight };
		position = { x: newX, y: newY };
	}

	function handleResizeEnd() {
		if (isResizing) {
			isResizing = false;
			resizeDirection = null;
			document.body.classList.remove('resizing');
			saveSize();
			ajustarPosicao();
		}
	}

	// Sincronizar com stores
	$effect(() => {
		isOpen = $chatAberto;
	});

	$effect(() => {
		isMinimized = $chatMinimizado;
	});

	$effect(() => {
		activeConversation = $conversaAtiva;

		// Quando uma conversa é aberta, marcar suas mensagens como visualizadas
		// para evitar notificações repetidas quando a conversa já está aberta
		if (activeConversation && todasConversas?.data && currentUser?.data?._id) {
			const conversas = todasConversas.data as ConversaComTimestamp[];
			const conversaAberta = conversas.find((c) => String(c._id) === String(activeConversation));

			if (conversaAberta && conversaAberta.ultimaMensagemTimestamp) {
				const mensagemId = `${conversaAberta._id}-${conversaAberta.ultimaMensagemTimestamp}`;
				if (!mensagensNotificadasGlobal.has(mensagemId)) {
					mensagensNotificadasGlobal.add(mensagemId);
					salvarMensagensNotificadasGlobal();
				}
			}
		}
	});

	// Ajustar posição quando a janela é aberta pela primeira vez
	let wasPreviouslyClosed = $state(true);
	$effect(() => {
		if (isOpen && !isMinimized && position && wasPreviouslyClosed) {
			// Quando a janela é aberta, recalcular posição para garantir que fique visível
			const winHeight =
				windowDimensions.height || (typeof window !== 'undefined' ? window.innerHeight : 0);
			const winWidth =
				windowDimensions.width || (typeof window !== 'undefined' ? window.innerWidth : 0);
			const widgetHeight = windowSize.height;
			const widgetWidth = windowSize.width;

			// Calcular limites válidos para a janela grande
			const minY = -(widgetHeight - 100);
			const maxY = Math.max(0, winHeight - 100);
			const minX = -(widgetWidth - 100);
			const maxX = Math.max(0, winWidth - 100);

			// Recalcular posição Y: tentar manter próximo ao canto inferior direito mas ajustar se necessário
			let newY = position.y;
			// Se a posição Y estava calculada para um botão pequeno (72px), ajustar para janela grande
			// Ajustar para manter aproximadamente a mesma distância do canto inferior
			if (position.y > maxY || position.y < minY) {
				// Se estava muito baixo (valor grande), ajustar para uma posição válida
				newY = Math.max(minY, Math.min(maxY, winHeight - widgetHeight - 24));
			}

			// Garantir que X também está dentro dos limites
			const newX = Math.max(minX, Math.min(maxX, position.x));

			// Aplicar novos valores apenas se necessário
			if (newX !== position.x || newY !== position.y) {
				position = { x: newX, y: newY };
				savePosition();
				// Forçar ajuste imediatamente
				ajustarPosicao();
			}

			wasPreviouslyClosed = false;
		} else if (!isOpen || isMinimized) {
			wasPreviouslyClosed = true;
		}
	});

	// Tipos para conversas
	type ConversaComTimestamp = {
		_id: string;
		ultimaMensagemTimestamp?: number;
		ultimaMensagemRemetenteId?: string; // ID do remetente da última mensagem
		ultimaMensagem?: string;
		nome?: string;
		outroUsuario?: { nome: string };
	};

	// Detectar novas mensagens globalmente (mesmo quando chat está fechado/minimizado)
	const todasConversas = useQuery(api.chat.listarConversas, {});
	let mensagensNotificadasGlobal = new SvelteSet<string>();
	let showGlobalNotificationPopup = $state(false);
	let globalNotificationMessage = $state<{
		remetente: string;
		conteudo: string;
		conversaId: string;
	} | null>(null);
	let globalNotificationTimeout: ReturnType<typeof setTimeout> | null = null;

	// Carregar mensagens já notificadas do localStorage ao montar
	let mensagensCarregadasGlobal = $state(false);

	$effect(() => {
		if (typeof window !== 'undefined' && !mensagensCarregadasGlobal) {
			const saved = localStorage.getItem('chat-mensagens-notificadas-global');
			if (saved) {
				try {
					const ids = JSON.parse(saved) as string[];
					mensagensNotificadasGlobal = new SvelteSet(ids);
				} catch {
					mensagensNotificadasGlobal = new SvelteSet();
				}
			}
			mensagensCarregadasGlobal = true;

			// Marcar todas as mensagens atuais como já visualizadas (não tocar beep ao abrir)
			if (todasConversas?.data) {
				const conversas = todasConversas.data as ConversaComTimestamp[];
				conversas.forEach((conv) => {
					if (conv.ultimaMensagemTimestamp) {
						const mensagemId = `${conv._id}-${conv.ultimaMensagemTimestamp}`;
						mensagensNotificadasGlobal.add(mensagemId);
					}
				});
				salvarMensagensNotificadasGlobal();
			}
		}
	});

	// Salvar mensagens notificadas no localStorage
	function salvarMensagensNotificadasGlobal() {
		if (typeof window !== 'undefined') {
			const ids = Array.from(mensagensNotificadasGlobal);
			// Limitar a 1000 IDs para não encher o localStorage
			const idsLimitados = ids.slice(-1000);
			localStorage.setItem('chat-mensagens-notificadas-global', JSON.stringify(idsLimitados));
		}
	}

	// Função para tocar som de notificação
	function tocarSomNotificacaoGlobal() {
		try {
			const AudioContextClass =
				window.AudioContext ||
				(window as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;
			if (!AudioContextClass) return;

			const audioContext = new AudioContextClass();
			if (audioContext.state === 'suspended') {
				audioContext
					.resume()
					.then(() => {
						const oscillator = audioContext.createOscillator();
						const gainNode = audioContext.createGain();
						oscillator.connect(gainNode);
						gainNode.connect(audioContext.destination);
						oscillator.frequency.value = 800;
						oscillator.type = 'sine';
						gainNode.gain.setValueAtTime(0.2, audioContext.currentTime);
						gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3);
						oscillator.start(audioContext.currentTime);
						oscillator.stop(audioContext.currentTime + 0.3);
					})
					.catch(() => {});
			} else {
				const oscillator = audioContext.createOscillator();
				const gainNode = audioContext.createGain();
				oscillator.connect(gainNode);
				gainNode.connect(audioContext.destination);
				oscillator.frequency.value = 800;
				oscillator.type = 'sine';
				gainNode.gain.setValueAtTime(0.2, audioContext.currentTime);
				gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3);
				oscillator.start(audioContext.currentTime);
				oscillator.stop(audioContext.currentTime + 0.3);
			}
		} catch {
			// Ignorar erro de áudio
		}
	}

	// Throttle para evitar execuções muito frequentes do effect
	let ultimaExecucaoNotificacao = $state(0);
	const THROTTLE_NOTIFICACAO_MS = 1000; // 1 segundo entre execuções

	$effect(() => {
		const agora = Date.now();
		const tempoDesdeUltimaExecucao = agora - ultimaExecucaoNotificacao;

		// Throttle: só executar se passou tempo suficiente
		if (tempoDesdeUltimaExecucao < THROTTLE_NOTIFICACAO_MS && ultimaExecucaoNotificacao > 0) {
			return;
		}

		if (todasConversas?.data && meuId()) {
			ultimaExecucaoNotificacao = agora;
			const conversas = todasConversas.data as ConversaComTimestamp[];
			const meuIdAtual = meuId();

			if (!meuIdAtual) {
				console.warn('⚠️ [ChatWidget] Não foi possível identificar o ID do usuário logado');
				return;
			}

			conversas.forEach((conv) => {
				if (!conv.ultimaMensagemTimestamp) return;

				// Verificar se a última mensagem foi enviada pelo usuário atual
				// Comparação mais robusta: normalizar ambos os IDs para string e comparar
				const remetenteIdStr = conv.ultimaMensagemRemetenteId
					? String(conv.ultimaMensagemRemetenteId).trim()
					: null;

				// Se a mensagem foi enviada pelo próprio usuário, ignorar completamente
				if (remetenteIdStr && remetenteIdStr === meuIdAtual) {
					// Mensagem enviada pelo próprio usuário - não tocar beep nem mostrar notificação
					// Marcar como notificada para evitar processamento futuro
					const mensagemId = `${conv._id}-${conv.ultimaMensagemTimestamp}`;
					if (!mensagensNotificadasGlobal.has(mensagemId)) {
						mensagensNotificadasGlobal.add(mensagemId);
						salvarMensagensNotificadasGlobal();
					}
					return;
				}

				// Criar ID único para esta mensagem: conversaId-timestamp
				const mensagemId = `${conv._id}-${conv.ultimaMensagemTimestamp}`;

				// Verificar se já foi notificada
				if (mensagensNotificadasGlobal.has(mensagemId)) return;

				const conversaAtivaId = activeConversation ? String(activeConversation).trim() : null;
				const conversaIdStr = String(conv._id).trim();
				const estaConversaEstaAberta = conversaAtivaId === conversaIdStr;

				// Verificar se outra notificação já está ativa para esta mensagem
				const notificacaoAtual = $notificacaoAtiva;
				const jaTemNotificacaoAtiva =
					notificacaoAtual &&
					notificacaoAtual.conversaId === conversaIdStr &&
					notificacaoAtual.mensagemId === mensagemId;

				// Só mostrar notificação se:
				// 1. O chat não está aberto OU
				// 2. O chat está aberto mas não estamos vendo essa conversa específica
				// 3. E não há outra notificação ativa para esta mensagem
				if ((!isOpen || !estaConversaEstaAberta) && !jaTemNotificacaoAtiva) {
					// Marcar como notificada ANTES de mostrar notificação (evita duplicação)
					mensagensNotificadasGlobal.add(mensagemId);
					salvarMensagensNotificadasGlobal();

					// Registrar notificação ativa no store global
					notificacaoAtiva.set({
						conversaId: conversaIdStr,
						mensagemId,
						componente: 'widget'
					});

					// Tocar som de notificação (apenas uma vez)
					tocarSomNotificacaoGlobal();

					// Mostrar popup de notificação
					globalNotificationMessage = {
						remetente: conv.outroUsuario?.nome || conv.nome || 'Usuário',
						conteudo: conv.ultimaMensagem || '',
						conversaId: conv._id
					};
					showGlobalNotificationPopup = true;

					// Ocultar popup após 5 segundos - garantir limpeza
					if (globalNotificationTimeout) {
						clearTimeout(globalNotificationTimeout);
						globalNotificationTimeout = null;
					}
					globalNotificationTimeout = setTimeout(() => {
						showGlobalNotificationPopup = false;
						globalNotificationMessage = null;
						globalNotificationTimeout = null;
						// Limpar notificação ativa do store
						notificacaoAtiva.set(null);
					}, 5000);
				} else {
					// Chat está aberto e estamos vendo essa conversa - marcar como visualizada
					// mas não mostrar notificação nem tocar beep
					mensagensNotificadasGlobal.add(mensagemId);
					salvarMensagensNotificadasGlobal();
				}
			});
		}

		// Cleanup: limpar timeout quando o effect for desmontado
		return () => {
			if (globalNotificationTimeout) {
				clearTimeout(globalNotificationTimeout);
				globalNotificationTimeout = null;
			}
		};
	});

	function handleToggle() {
		if (isOpen && !isMinimized) {
			minimizarChat();
		} else {
			abrirChat();
		}
	}

	function handleClose() {
		fecharChat();
	}

	function handleMinimize() {
		minimizarChat();
	}

	function handleMaximize() {
		if (!position) return;

		if (isMaximized) {
			// Restaurar tamanho anterior
			windowSize = previousSize;
			if (previousPosition) {
				position = previousPosition;
			}
			isMaximized = false;
			saveSize();
			ajustarPosicao();
		} else {
			// Salvar tamanho e posição atuais
			previousSize = { ...windowSize };
			previousPosition = { ...position };

			// Maximizar completamente: usar toda a largura e altura da tela
			const winWidth =
				windowDimensions.width ||
				(typeof window !== 'undefined' ? window.innerWidth : DEFAULT_WIDTH);
			const winHeight =
				windowDimensions.height ||
				(typeof window !== 'undefined' ? window.innerHeight : DEFAULT_HEIGHT);

			windowSize = {
				width: winWidth,
				height: winHeight
			};
			position = {
				x: 0,
				y: 0
			};
			isMaximized = true;
			saveSize();
			ajustarPosicao();
		}
		maximizarChat();
	}

	// Handler para duplo clique no botão flutuante - abre e maximiza
	function handleDoubleClick() {
		// Marcar que estamos processando um duplo clique
		isDoubleClicking = true;

		// Se o chat estiver fechado ou minimizado, abrir e maximizar
		if (!isOpen || isMinimized) {
			abrirChat();
			// Aguardar um pouco para garantir que o chat foi aberto antes de maximizar
			setTimeout(() => {
				if (position) {
					// Salvar tamanho e posição atuais antes de maximizar
					previousSize = { ...windowSize };
					previousPosition = { ...position };

					// Maximizar completamente
					const winWidth =
						windowDimensions.width ||
						(typeof window !== 'undefined' ? window.innerWidth : DEFAULT_WIDTH);
					const winHeight =
						windowDimensions.height ||
						(typeof window !== 'undefined' ? window.innerHeight : DEFAULT_HEIGHT);

					windowSize = {
						width: winWidth,
						height: winHeight
					};
					position = {
						x: 0,
						y: 0
					};
					isMaximized = true;
					saveSize();
					ajustarPosicao();
					maximizarChat();
				}
				// Resetar flag após processar
				setTimeout(() => {
					isDoubleClicking = false;
				}, 300);
			}, 50);
		} else {
			// Se já estiver aberto, apenas maximizar
			handleMaximize();
			setTimeout(() => {
				isDoubleClicking = false;
			}, 300);
		}
	}

	// Funcionalidade de arrastar
	function handleMouseDown(e: MouseEvent) {
		if (e.button !== 0 || !position) return; // Apenas botão esquerdo
		hasMoved = false;
		shouldPreventClick = false;
		isDragging = true;

		// Calcular offset do clique dentro do elemento (considerando a posição atual)
		// Isso garante que o arrasto comece exatamente onde o usuário clicou
		dragStart = {
			x: e.clientX - position.x,
			y: e.clientY - position.y
		};

		document.body.classList.add('dragging');
		e.preventDefault();
	}

	// Handler específico para o botão flutuante (evita conflito com clique)
	function handleButtonMouseDown(e: MouseEvent) {
		if (e.button !== 0 || !position) return;
		// Resetar flags de movimento e clique
		hasMoved = false;
		shouldPreventClick = false;
		isDragging = true;

		// Calcular offset do clique exatamente onde o mouse está
		dragStart = {
			x: e.clientX - position.x,
			y: e.clientY - position.y
		};

		document.body.classList.add('dragging');
		// Não prevenir default para permitir clique funcionar se não houver movimento
	}

	// Handlers para gestos touch (swipe)
	function handleTouchStart(e: TouchEvent) {
		if (!position || e.touches.length !== 1) return;
		const touch = e.touches[0];
		touchStart = {
			x: touch.clientX,
			y: touch.clientY,
			time: Date.now()
		};
		touchCurrent = { x: touch.clientX, y: touch.clientY };
		isTouching = true;
		isDragging = true;
		dragStart = {
			x: touch.clientX - position.x,
			y: touch.clientY - position.y
		};
		hasMoved = false;
		shouldPreventClick = false;
		document.body.classList.add('dragging');
	}

	function handleTouchMove(e: TouchEvent) {
		if (!isTouching || !touchStart || !position || e.touches.length !== 1) return;
		const touch = e.touches[0];
		touchCurrent = { x: touch.clientX, y: touch.clientY };

		// Calcular velocidade do swipe
		const deltaTime = Date.now() - touchStart.time;
		const deltaX = touch.clientX - touchStart.x;
		const deltaY = touch.clientY - touchStart.y;
		const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

		if (deltaTime > 0) {
			swipeVelocity = distance / deltaTime; // pixels por ms
		}

		// Calcular nova posição
		const newX = touch.clientX - dragStart.x;
		const newY = touch.clientY - dragStart.y;

		// Verificar se houve movimento significativo
		const deltaXAbs = Math.abs(newX - position.x);
		const deltaYAbs = Math.abs(newY - position.y);

		if (deltaXAbs > dragThreshold || deltaYAbs > dragThreshold) {
			hasMoved = true;
			shouldPreventClick = true;
		}

		// Dimensões do widget
		const widgetWidth = isOpen && !isMinimized ? windowSize.width : 72;
		const widgetHeight = isOpen && !isMinimized ? windowSize.height : 72;

		const winWidth =
			windowDimensions.width || (typeof window !== 'undefined' ? window.innerWidth : 0);
		const winHeight =
			windowDimensions.height || (typeof window !== 'undefined' ? window.innerHeight : 0);

		const minX = -(widgetWidth - 100);
		const maxX = Math.max(0, winWidth - 100);
		const minY = -(widgetHeight - 100);
		const maxY = Math.max(0, winHeight - 100);

		position = {
			x: Math.max(minX, Math.min(newX, maxX)),
			y: Math.max(minY, Math.min(newY, maxY))
		};
	}

	function handleTouchEnd(e: TouchEvent) {
		if (!isTouching || !touchStart || !position) return;

		const hadMoved = hasMoved;

		// Aplicar momentum se houver velocidade suficiente
		if (swipeVelocity > 0.5 && hadMoved) {
			const deltaX = touchCurrent ? touchCurrent.x - touchStart.x : 0;
			const deltaY = touchCurrent ? touchCurrent.y - touchStart.y : 0;
			const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

			if (distance > 10) {
				// Aplicar momentum suave
				const momentum = Math.min(swipeVelocity * 50, 200); // Limitar momentum
				const angle = Math.atan2(deltaY, deltaX);

				let momentumX = position.x + Math.cos(angle) * momentum;
				let momentumY = position.y + Math.sin(angle) * momentum;

				// Limitar dentro dos bounds
				const widgetWidth = isOpen && !isMinimized ? windowSize.width : 72;
				const widgetHeight = isOpen && !isMinimized ? windowSize.height : 72;
				const winWidth =
					windowDimensions.width || (typeof window !== 'undefined' ? window.innerWidth : 0);
				const winHeight =
					windowDimensions.height || (typeof window !== 'undefined' ? window.innerHeight : 0);
				const minX = -(widgetWidth - 100);
				const maxX = Math.max(0, winWidth - 100);
				const minY = -(widgetHeight - 100);
				const maxY = Math.max(0, winHeight - 100);

				momentumX = Math.max(minX, Math.min(momentumX, maxX));
				momentumY = Math.max(minY, Math.min(momentumY, maxY));

				position = { x: momentumX, y: momentumY };
				isAnimating = true;

				setTimeout(() => {
					isAnimating = false;
					ajustarPosicao();
				}, 300);
			}
		} else {
			ajustarPosicao();
		}

		isDragging = false;
		isTouching = false;
		touchStart = null;
		touchCurrent = null;
		swipeVelocity = 0;
		document.body.classList.remove('dragging');

		setTimeout(() => {
			hasMoved = false;
			shouldPreventClick = false;
		}, 100);

		savePosition();
	}

	function handleMouseMove(e: MouseEvent) {
		if (isResizing) {
			handleResizeMove(e);
			return;
		}

		if (!isDragging || !position) return;

		// Calcular nova posição baseada no offset do clique
		const newX = e.clientX - dragStart.x;
		const newY = e.clientY - dragStart.y;

		// Verificar se houve movimento significativo desde o último frame
		const deltaX = Math.abs(newX - position.x);
		const deltaY = Math.abs(newY - position.y);

		// Se houve qualquer movimento (mesmo pequeno), marcar como movido
		if (deltaX > 0 || deltaY > 0) {
			// Marcar como movido se passar do threshold
			if (deltaX > dragThreshold || deltaY > dragThreshold) {
				hasMoved = true;
				shouldPreventClick = true; // Prevenir clique se houve movimento
			}

			// Dimensões do widget
			const widgetWidth = isOpen && !isMinimized ? windowSize.width : 72;
			const widgetHeight = isOpen && !isMinimized ? windowSize.height : 72;

			// Usar dimensões reativas da janela
			const winWidth =
				windowDimensions.width || (typeof window !== 'undefined' ? window.innerWidth : 0);
			const winHeight =
				windowDimensions.height || (typeof window !== 'undefined' ? window.innerHeight : 0);

			// Limites da tela com margem de segurança
			const minX = -(widgetWidth - 100); // Permitir até 100px visíveis
			const maxX = Math.max(0, winWidth - 100); // Manter 100px dentro da tela
			const minY = -(widgetHeight - 100);
			const maxY = Math.max(0, winHeight - 100);

			// Atualizar posição imediatamente - garantir suavidade
			position = {
				x: Math.max(minX, Math.min(newX, maxX)),
				y: Math.max(minY, Math.min(newY, maxY))
			};
		}
	}

	function handleMouseUp(e?: MouseEvent) {
		const hadMoved = hasMoved;

		if (isDragging) {
			isDragging = false;

			// Se estava arrastando e houve movimento, prevenir clique
			if (hadMoved && e) {
				e.preventDefault();
				e.stopPropagation();
			}

			// Garantir que está dentro dos limites ao soltar
			ajustarPosicao();

			// Salvar posição após arrastar
			savePosition();

			// Aguardar um pouco antes de resetar as flags para garantir que o onclick não seja executado
			setTimeout(() => {
				hasMoved = false;
				shouldPreventClick = false;
			}, 100);

			document.body.classList.remove('dragging');
		}
		handleResizeEnd();

		return !hadMoved; // Retorna true se não houve movimento (permite clique)
	}

	function ajustarPosicao() {
		if (!position) return;

		isAnimating = true;

		// Dimensões do widget
		const widgetWidth = isOpen && !isMinimized ? windowSize.width : 72;
		const widgetHeight = isOpen && !isMinimized ? windowSize.height : 72;

		// Usar dimensões reativas da janela
		const winWidth =
			windowDimensions.width || (typeof window !== 'undefined' ? window.innerWidth : 0);
		const winHeight =
			windowDimensions.height || (typeof window !== 'undefined' ? window.innerHeight : 0);

		// Verificar se está fora dos limites
		let newX = position.x;
		let newY = position.y;

		// Ajustar X - garantir que pelo menos 100px fiquem visíveis
		const minX = -(widgetWidth - 100);
		const maxX = Math.max(0, winWidth - 100);

		if (newX < minX) {
			newX = minX;
		} else if (newX > maxX) {
			newX = maxX;
		}

		// Ajustar Y - garantir que pelo menos 100px fiquem visíveis
		const minY = -(widgetHeight - 100);
		const maxY = Math.max(0, winHeight - 100);

		if (newY < minY) {
			newY = minY;
		} else if (newY > maxY) {
			newY = maxY;
		}

		position = { x: newX, y: newY };

		// Salvar posição após ajuste
		savePosition();

		setTimeout(() => {
			isAnimating = false;
		}, 300);
	}

	// Event listeners globais com cleanup adequado
	$effect(() => {
		if (typeof window === 'undefined') return;

		window.addEventListener('mousemove', handleMouseMove);
		window.addEventListener('mouseup', handleMouseUp);
		window.addEventListener('touchmove', handleTouchMove, { passive: false });
		window.addEventListener('touchend', handleTouchEnd);

		return () => {
			window.removeEventListener('mousemove', handleMouseMove);
			window.removeEventListener('mouseup', handleMouseUp);
			window.removeEventListener('touchmove', handleTouchMove);
			window.removeEventListener('touchend', handleTouchEnd);
		};
	});

	// Obter cores do tema atual (reativo)
	let coresTema = $state(obterCoresDoTema());
	
	// Atualizar cores quando o tema mudar
	$effect(() => {
		if (typeof window === 'undefined') return;
		
		const atualizarCores = () => {
			coresTema = obterCoresDoTema();
		};
		
		// Atualizar cores inicialmente
		atualizarCores();
		
		// Escutar mudanças de tema
		window.addEventListener('themechange', atualizarCores);
		
		// Observar mudanças no atributo data-theme do HTML
		const observer = new MutationObserver(atualizarCores);
		const htmlElement = document.documentElement;
		observer.observe(htmlElement, {
			attributes: true,
			attributeFilter: ['data-theme']
		});
		
		return () => {
			window.removeEventListener('themechange', atualizarCores);
			observer.disconnect();
		};
	});
	
	// Função para obter gradiente do tema
	function obterGradienteTema() {
		const primary = coresTema.primary;
		// Criar variações da cor primária para o gradiente
		return `linear-gradient(135deg, ${primary} 0%, ${primary}dd 50%, ${primary}bb 100%)`;
	}
	
	// Função para obter rgba da cor primária
	function obterPrimariaRgba(alpha: number = 1) {
		const primary = coresTema.primary.trim();
		// Se já for rgba, extrair os valores
		if (primary.startsWith('rgba')) {
			const match = primary.match(/rgba?\(([^)]+)\)/);
			if (match) {
				const values = match[1].split(',').map(v => v.trim());
				if (values.length >= 3) {
					return `rgba(${values[0]}, ${values[1]}, ${values[2]}, ${alpha})`;
				}
			}
		}
		// Se for hex, converter
		if (primary.startsWith('#')) {
			const hex = primary.replace('#', '');
			if (hex.length === 6) {
				const r = parseInt(hex.substring(0, 2), 16);
				const g = parseInt(hex.substring(2, 4), 16);
				const b = parseInt(hex.substring(4, 6), 16);
				return `rgba(${r}, ${g}, ${b}, ${alpha})`;
			}
		}
		// Se for hsl, converter para hsla
		if (primary.startsWith('hsl')) {
			const match = primary.match(/hsl\(([^)]+)\)/);
			if (match) {
				return `hsla(${match[1]}, ${alpha})`;
			}
			// Fallback: tentar adicionar alpha
			return primary.replace(/\)$/, `, ${alpha})`).replace('hsl', 'hsla');
		}
		// Fallback padrão
		return `rgba(102, 126, 234, ${alpha})`;
	}
</script>

<!-- Botão flutuante MODERNO E ARRASTÁVEL -->
{#if (!isOpen || isMinimized) && position}
	{@const winWidth =
		windowDimensions.width || (typeof window !== 'undefined' ? window.innerWidth : 0)}
	{@const winHeight =
		windowDimensions.height || (typeof window !== 'undefined' ? window.innerHeight : 0)}
	{@const bottomPos = `${Math.max(0, winHeight - position.y - 72)}px`}
	{@const rightPos = `${Math.max(0, winWidth - position.x - 72)}px`}
	<button
		type="button"
		class="group fixed border-0 backdrop-blur-xl"
		style="
      z-index: 99999 !important; 
      width: 4.5rem; 
      height: 4.5rem; 
      bottom: {bottomPos};
      right: {rightPos};
      position: fixed !important;
      background: {obterGradienteTema()};
      box-shadow: 
        0 20px 60px -10px {obterPrimariaRgba(0.5)},
        0 10px 30px -5px {obterPrimariaRgba(0.4)},
        0 0 0 1px rgba(255, 255, 255, 0.1) inset;
      border-radius: 50%;
      cursor: {isDragging ? 'grabbing' : 'grab'};
      transform: {isDragging ? 'scale(1.05)' : 'scale(1)'};
      transition: {isAnimating
			? 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
			: 'transform 0.2s, box-shadow 0.3s'};
    "
		onmousedown={handleButtonMouseDown}
		onmouseup={(e) => {
			handleMouseUp(e);
		}}
		ontouchstart={handleTouchStart}
		onclick={(e) => {
			// Prevenir clique simples se estamos processando um duplo clique
			if (isDoubleClicking) {
				e.preventDefault();
				e.stopPropagation();
				return;
			}
			// Só executar toggle se não houve movimento durante o arrastar
			if (!shouldPreventClick && !hasMoved && !isTouching) {
				handleToggle();
			} else {
				// Prevenir clique se houve movimento
				e.preventDefault();
				e.stopPropagation();
				shouldPreventClick = false; // Resetar após prevenir
			}
		}}
		ondblclick={(e) => {
			// Prevenir que o clique simples seja executado após o duplo clique
			e.preventDefault();
			e.stopPropagation();
			// Executar maximização apenas se não houve movimento
			if (!shouldPreventClick && !hasMoved && !isTouching) {
				handleDoubleClick();
			}
		}}
		aria-label="Abrir chat (duplo clique para maximizar)"
	>
		<!-- Anel de brilho rotativo melhorado com múltiplas camadas -->
		<div
			class="absolute inset-0 rounded-full opacity-0 transition-opacity duration-500 group-hover:opacity-100"
			style="background: conic-gradient(from 0deg, transparent 0%, rgba(255,255,255,0.4) 25%, rgba(255,255,255,0.6) 50%, rgba(255,255,255,0.4) 75%, transparent 100%); animation: rotate 3s linear infinite; transform-origin: center;"
		></div>
		<!-- Segunda camada para efeito de profundidade -->
		<div
			class="absolute inset-0 cursor-pointer rounded-lg opacity-0 transition-opacity duration-700 group-hover:opacity-60"
			style="background: conic-gradient(from 180deg, transparent 0%, rgba(255,255,255,0.2) 30%, transparent 60%); animation: rotate 4s linear infinite reverse; transform-origin: center;"
			onclick={(e) => {
				// Propagar o clique para o elemento pai
				e.stopPropagation();
				if (!isDoubleClicking && !shouldPreventClick && !hasMoved && !isTouching) {
					handleToggle();
				}
			}}
			ondblclick={(e) => {
				e.stopPropagation();
				if (!shouldPreventClick && !hasMoved && !isTouching) {
					handleDoubleClick();
				}
			}}
		></div>
		<!-- Efeito de brilho pulsante durante arrasto -->
		{#if isDragging || isTouching}
			<div
				class="absolute inset-0 animate-pulse rounded-full opacity-30"
				style="background: radial-gradient(circle at center, rgba(255,255,255,0.4) 0%, transparent 70%); animation: pulse-glow 1.5s ease-in-out infinite;"
			></div>
		{/if}

		<!-- Ícone de chat moderno com efeito 3D -->
		<MessageSquare
			class="relative z-10 h-10 w-10 text-white transition-all duration-500 group-hover:scale-110"
			style="filter: drop-shadow(0 4px 12px rgba(0,0,0,0.4));"
			strokeWidth={2}
		/>

		<!-- Badge ULTRA PREMIUM com gradiente e brilho usando cores do tema -->
		{#if count?.data && count.data > 0}
			<span
				class="absolute -top-1 -right-1 z-20 flex h-8 w-8 items-center justify-center rounded-full text-xs font-black text-white"
				style="
          background: {coresTema.error ? `linear-gradient(135deg, ${coresTema.error}, ${coresTema.error}dd)` : 'linear-gradient(135deg, #ff416c, #ff4b2b)'};
          box-shadow: 
            0 8px 24px -4px {coresTema.error ? obterPrimariaRgba(0.6).replace(coresTema.primary, coresTema.error) : 'rgba(255, 65, 108, 0.6)'},
            0 4px 12px -2px {coresTema.error ? obterPrimariaRgba(0.4).replace(coresTema.primary, coresTema.error) : 'rgba(255, 75, 43, 0.4)'},
            0 0 0 3px rgba(255, 255, 255, 0.3),
            0 0 0 5px {coresTema.error ? obterPrimariaRgba(0.2).replace(coresTema.primary, coresTema.error) : 'rgba(255, 65, 108, 0.2)'};
          animation: badge-bounce 2s ease-in-out infinite;
        "
			>
				{count.data > 9 ? '9+' : count.data}
			</span>
		{/if}

		<!-- Indicador de arrastável -->
		<div
			class="absolute -bottom-2 left-1/2 flex -translate-x-1/2 transform gap-1 opacity-50 transition-opacity group-hover:opacity-100"
		>
			<div class="h-1 w-1 rounded-full bg-white"></div>
			<div class="h-1 w-1 rounded-full bg-white"></div>
			<div class="h-1 w-1 rounded-full bg-white"></div>
		</div>
	</button>
{/if}

<!-- Janela do Chat ULTRA MODERNA E ARRASTÁVEL -->
{#if isOpen && !isMinimized && position}
	{@const winWidth =
		windowDimensions.width || (typeof window !== 'undefined' ? window.innerWidth : 0)}
	{@const winHeight =
		windowDimensions.height || (typeof window !== 'undefined' ? window.innerHeight : 0)}
	{@const bottomPos = `${Math.max(0, winHeight - position.y - windowSize.height)}px`}
	{@const rightPos = `${Math.max(0, winWidth - position.x - windowSize.width)}px`}
	<div
		class="fixed flex flex-col overflow-hidden backdrop-blur-2xl"
		style="
      z-index: 99999 !important;
      bottom: {bottomPos};
      right: {rightPos};
      width: {windowSize.width}px;
      height: {windowSize.height}px;
      max-width: calc(100vw - 3rem);
      max-height: calc(100vh - 3rem);
      position: fixed !important;
      background: linear-gradient(135deg, rgba(255,255,255,0.95) 0%, rgba(249,250,251,0.98) 100%);
      border-radius: 24px;
      box-shadow: 
        0 32px 64px -12px rgba(0, 0, 0, 0.15),
        0 16px 32px -8px rgba(0, 0, 0, 0.1),
        0 0 0 1px rgba(0, 0, 0, 0.05),
        0 0 0 1px rgba(255, 255, 255, 0.5) inset;
      animation: slideInScale 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
      transition: {isAnimating ? 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)' : 'none'};
    "
	>
		<!-- Header ULTRA PREMIUM com gradiente glassmorphism -->
		<div
			class="relative flex items-center justify-between overflow-hidden px-6 py-5 text-white"
			style="
        background: {obterGradienteTema()};
        box-shadow: 0 8px 32px -4px {obterPrimariaRgba(0.3)};
        cursor: {isDragging ? 'grabbing' : 'grab'};
      "
			onmousedown={handleMouseDown}
			role="button"
			tabindex="0"
			aria-label="Arrastar janela do chat"
		>
			<!-- Efeitos de fundo animados -->
			<div
				class="absolute inset-0 opacity-30"
				style="background: radial-gradient(circle at 20% 50%, rgba(255,255,255,0.3) 0%, transparent 50%);"
			></div>
			<div
				class="absolute inset-0 opacity-20"
				style="background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.1) 50%, transparent 70%); animation: shimmer 3s infinite;"
			></div>
			<!-- Título com avatar/foto do usuário logado -->
			<h2 class="relative z-10 flex items-center gap-3 text-xl font-bold">
				<!-- Avatar/Foto do usuário logado com efeito glassmorphism -->
				<div
					class="relative flex h-10 w-10 items-center justify-center overflow-hidden rounded-xl"
					style="background: rgba(255,255,255,0.2); backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0,0,0,0.1), 0 0 0 1px rgba(255,255,255,0.2) inset;"
				>
					{#if avatarUrlDoUsuario()}
						<img
							src={avatarUrlDoUsuario()}
							alt={meuPerfilQuery?.data?.nome || currentUser?.data?.nome || 'Usuário'}
							class="h-full w-full object-cover"
						/>
					{:else}
						<!-- Fallback: ícone de chat genérico -->
						<MessageSquare
							class="h-5 w-5"
							style="filter: drop-shadow(0 2px 6px rgba(0,0,0,0.2));"
							strokeWidth={2}
						/>
					{/if}
				</div>
				<span
					class="font-extrabold tracking-wide"
					style="text-shadow: 0 2px 8px rgba(0,0,0,0.3); letter-spacing: 0.02em;">Mensagens</span
				>
			</h2>

			<!-- Botões de controle modernos -->
			<div class="relative z-10 flex items-center gap-2">
				<!-- Botão minimizar MODERNO -->
				<button
					type="button"
					class="group relative flex h-10 w-10 items-center justify-center overflow-hidden rounded-xl transition-all duration-300"
					style="background: rgba(255,255,255,0.15); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.2);"
					onclick={handleMinimize}
					aria-label="Minimizar"
				>
					<div
						class="absolute inset-0 bg-white/0 transition-colors duration-300 group-hover:bg-white/20"
					></div>
					<Minus
						class="relative z-10 h-5 w-5 transition-transform duration-300 group-hover:scale-110"
						style="filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));"
						strokeWidth={2.5}
					/>
				</button>

				<!-- Botão maximizar MODERNO -->
				<button
					type="button"
					class="group relative flex h-10 w-10 items-center justify-center overflow-hidden rounded-xl transition-all duration-300"
					style="background: rgba(255,255,255,0.15); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.2);"
					onclick={handleMaximize}
					aria-label="Maximizar"
				>
					<div
						class="absolute inset-0 bg-white/0 transition-colors duration-300 group-hover:bg-white/20"
					></div>
					<Maximize2
						class="relative z-10 h-5 w-5 transition-transform duration-300 group-hover:scale-110"
						style="filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));"
						strokeWidth={2.5}
					/>
				</button>

				<!-- Botão fechar MODERNO -->
				<button
					type="button"
					class="group relative flex h-10 w-10 items-center justify-center overflow-hidden rounded-xl transition-all duration-300"
					style="background: rgba(255,255,255,0.15); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.2);"
					onclick={handleClose}
					aria-label="Fechar"
				>
					<div
						class="absolute inset-0 bg-red-500/0 transition-colors duration-300 group-hover:bg-red-500/30"
					></div>
					<X
						class="relative z-10 h-5 w-5 transition-all duration-300 group-hover:scale-110 group-hover:rotate-90"
						style="filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));"
						strokeWidth={2.5}
					/>
				</button>
			</div>
		</div>

		<!-- Conteúdo -->
		<div class="relative flex-1 overflow-hidden">
			{#if !activeConversation}
				<ChatList />
			{:else}
				<ChatWindow conversaId={activeConversation} />
			{/if}

			<!-- Resize Handles -->
			<!-- Top -->
			<div
				role="button"
				tabindex="0"
				aria-label="Redimensionar janela pela borda superior"
				class="absolute top-0 right-0 left-0 z-50 h-2 cursor-ns-resize transition-colors"
				style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 24px 24px 0 0;"
				onmousedown={(e) => handleResizeStart(e, 'n')}
				onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'n')}
			></div>
			<!-- Bottom -->
			<div
				role="button"
				tabindex="0"
				aria-label="Redimensionar janela pela borda inferior"
				class="absolute right-0 bottom-0 left-0 z-50 h-2 cursor-ns-resize transition-colors"
				style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 0 0 24px 24px;"
				onmousedown={(e) => handleResizeStart(e, 's')}
				onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 's')}
			></div>
			<!-- Left -->
			<div
				role="button"
				tabindex="0"
				aria-label="Redimensionar janela pela borda esquerda"
				class="absolute top-0 bottom-0 left-0 z-50 w-2 cursor-ew-resize transition-colors"
				style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 24px 0 0 24px;"
				onmousedown={(e) => handleResizeStart(e, 'w')}
				onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'w')}
			></div>
			<!-- Right -->
			<div
				role="button"
				tabindex="0"
				aria-label="Redimensionar janela pela borda direita"
				class="absolute top-0 right-0 bottom-0 z-50 w-2 cursor-ew-resize transition-colors"
				style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 0 24px 24px 0;"
				onmousedown={(e) => handleResizeStart(e, 'e')}
				onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'e')}
			></div>
			<!-- Corners -->
			<div
				role="button"
				tabindex="0"
				aria-label="Redimensionar janela pelo canto superior esquerdo"
				class="absolute top-0 left-0 z-50 h-4 w-4 cursor-nwse-resize transition-colors"
				style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 24px 0 0 0;"
				onmousedown={(e) => handleResizeStart(e, 'nw')}
				onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'nw')}
			></div>
			<div
				role="button"
				tabindex="0"
				aria-label="Redimensionar janela pelo canto superior direito"
				class="absolute top-0 right-0 z-50 h-4 w-4 cursor-nesw-resize transition-colors"
				style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 0 24px 0 0;"
				onmousedown={(e) => handleResizeStart(e, 'ne')}
				onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'ne')}
			></div>
			<div
				role="button"
				tabindex="0"
				aria-label="Redimensionar janela pelo canto inferior esquerdo"
				class="absolute bottom-0 left-0 z-50 h-4 w-4 cursor-nesw-resize transition-colors"
				style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 0 0 0 24px;"
				onmousedown={(e) => handleResizeStart(e, 'sw')}
				onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'sw')}
			></div>
			<div
				role="button"
				tabindex="0"
				aria-label="Redimensionar janela pelo canto inferior direito"
				class="absolute right-0 bottom-0 z-50 h-4 w-4 cursor-nwse-resize transition-colors"
				style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 0 0 24px 0;"
				onmousedown={(e) => handleResizeStart(e, 'se')}
				onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'se')}
			></div>
		</div>
	</div>
{/if}

<!-- Indicador de Conexão -->

<!-- Popup Global de Notificação de Nova Mensagem (quando chat está fechado/minimizado) -->
{#if showGlobalNotificationPopup && globalNotificationMessage}
	{@const notificationMsg = globalNotificationMessage}
	<div
		role="button"
		tabindex="0"
		aria-label="Abrir conversa: Nova mensagem de {notificationMsg.remetente}"
		class="bg-base-100 fixed top-4 right-4 z-1000 max-w-sm cursor-pointer rounded-lg border p-4 shadow-2xl"
		style="border-color: {obterPrimariaRgba(0.2)}; box-shadow: 0 10px 40px -10px rgba(0,0,0,0.3); animation: slideInRight 0.3s ease-out;"
		onclick={() => {
			const conversaIdToOpen = notificationMsg?.conversaId;
			showGlobalNotificationPopup = false;
			globalNotificationMessage = null;
			if (globalNotificationTimeout) {
				clearTimeout(globalNotificationTimeout);
			}
			// Abrir chat e conversa ao clicar
			if (conversaIdToOpen) {
				abrirChat();
				abrirConversa(conversaIdToOpen as Id<'conversas'>);
			}
		}}
		onkeydown={(e) => {
			if (e.key === 'Enter' || e.key === ' ') {
				e.preventDefault();
				const conversaIdToOpen = notificationMsg?.conversaId;
				showGlobalNotificationPopup = false;
				globalNotificationMessage = null;
				if (globalNotificationTimeout) {
					clearTimeout(globalNotificationTimeout);
				}
				if (conversaIdToOpen) {
					abrirChat();
					abrirConversa(conversaIdToOpen as Id<'conversas'>);
				}
			}
		}}
	>
		<div class="flex items-start gap-3">
			<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full" style="background-color: {obterPrimariaRgba(0.2)}">
				<Bell class="h-5 w-5" style="color: {coresTema.primary}" strokeWidth={2} />
			</div>
			<div class="min-w-0 flex-1">
				<p class="text-base-content mb-1 text-sm font-semibold">
					Nova mensagem de {notificationMsg.remetente}
				</p>
				<p class="text-base-content/70 line-clamp-2 text-xs">
					{notificationMsg.conteudo}
				</p>
				<p class="mt-1 text-xs" style="color: {coresTema.primary}">Clique para abrir</p>
			</div>
			<button
				type="button"
				aria-label="Fechar notificação"
				class="hover:bg-base-200 flex h-6 w-6 shrink-0 items-center justify-center rounded-full transition-colors"
				onclick={(e) => {
					e.stopPropagation();
					showGlobalNotificationPopup = false;
					globalNotificationMessage = null;
					if (globalNotificationTimeout) {
						clearTimeout(globalNotificationTimeout);
					}
				}}
			>
				<X class="h-4 w-4" strokeWidth={2} />
			</button>
		</div>
	</div>
{/if}

<style>
	/* Animação do badge com bounce suave */
	@keyframes badge-bounce {
		0%,
		100% {
			transform: scale(1) translateY(0);
		}
		50% {
			transform: scale(1.08) translateY(-2px);
		}
	}

	/* Animação de entrada da janela com escala e bounce */
	@keyframes slideInScale {
		0% {
			opacity: 0;
			transform: translateY(30px) scale(0.9);
		}
		60% {
			transform: translateY(-5px) scale(1.02);
		}
		100% {
			opacity: 1;
			transform: translateY(0) scale(1);
		}
	}

	/* Ondas de pulso para o botão flutuante - cores dinâmicas */
	@keyframes pulse-ring {
		0% {
			box-shadow: 0 0 0 0 var(--pulse-color, rgba(102, 126, 234, 0.5));
		}
		50% {
			box-shadow: 0 0 0 15px transparent;
		}
		100% {
			box-shadow: 0 0 0 0 var(--pulse-color, rgba(102, 126, 234, 0.5));
		}
	}
	
	/* Estilos para handles de redimensionamento com hover dinâmico */
	[style*="--hover-bg"]:hover {
		background-color: var(--hover-bg) !important;
	}

	/* Rotação para anel de brilho - suavizada */
	@keyframes rotate {
		from {
			transform: rotate(0deg);
		}
		to {
			transform: rotate(360deg);
		}
	}

	/* Efeito de pulso de brilho durante arrasto */
	@keyframes pulse-glow {
		0%,
		100% {
			opacity: 0.2;
			transform: scale(1);
		}
		50% {
			opacity: 0.4;
			transform: scale(1.05);
		}
	}

	/* Efeito shimmer para o header */
	@keyframes shimmer {
		0% {
			transform: translateX(-100%);
		}
		100% {
			transform: translateX(100%);
		}
	}

	/* Suavizar transições */
	* {
		-webkit-font-smoothing: antialiased;
		-moz-osx-font-smoothing: grayscale;
	}
</style>
