<script lang="ts">
	import { api } from '@sgse-app/backend/convex/_generated/api';
	import { useConvexClient } from 'convex-svelte';
	import { AlertCircle, CheckCircle2, Clock } from 'lucide-svelte';
	import { onDestroy, onMount } from 'svelte';
	import { obterTempoPC, obterTempoServidor } from '$lib/utils/sincronizacaoTempo';

	const client = useConvexClient();

	let tempoAtual = $state<Date>(new Date());
	let sincronizado = $state(false);
	let sincronizando = $state(false);
	let usandoServidorExterno = $state(false);
	let offsetSegundos = $state(0);
	let erro = $state<string | null>(null);
	let intervalId: ReturnType<typeof setInterval> | null = null;
	let intervaloSincronizacao: ReturnType<typeof setInterval> | null = null;
	let sincronizacaoEmAndamento = $state(false); // Flag para evitar múltiplas sincronizações simultâneas

	async function atualizarTempo() {
		// Evitar múltiplas sincronizações simultâneas
		if (sincronizacaoEmAndamento) {
			return;
		}
		sincronizacaoEmAndamento = true;
		sincronizando = true;
		try {
			const config = await client.query(api.configuracaoRelogio.obterConfiguracao, {});
			// Usar gmtOffset da configuração, sem valor padrão, pois 0 é um valor válido
			// Se não estiver configurado, usar null e tratar como 0
			const gmtOffset = config.gmtOffset ?? 0;

			let timestampBase: number;

			if (config.usarServidorExterno) {
				try {
					// Adicionar timeout de 10 segundos para sincronização
					const sincronizacaoPromise = client.action(api.configuracaoRelogio.sincronizarTempo, {});
					const timeoutPromise = new Promise<never>((_, reject) => 
						setTimeout(() => reject(new Error('Timeout na sincronização (10s)')), 10000)
					);
					const resultado = await Promise.race([sincronizacaoPromise, timeoutPromise]);
					if (resultado.sucesso && resultado.timestamp) {
						timestampBase = resultado.timestamp;
						sincronizado = true;
						usandoServidorExterno = resultado.usandoServidorExterno || false;
						offsetSegundos = resultado.offsetSegundos || 0;
						erro = null;
					} else {
						throw new Error('Falha ao sincronizar');
					}
				} catch (error) {
					console.warn('Erro ao sincronizar:', error);
					if (config.fallbackParaPC) {
						timestampBase = obterTempoPC();
						sincronizado = false;
						usandoServidorExterno = false;
						erro = 'Usando relógio do PC (falha na sincronização)';
					} else {
						// Mesmo sem fallback configurado, usar PC como última opção
						timestampBase = obterTempoPC();
						sincronizado = false;
						usandoServidorExterno = false;
						erro = 'Usando relógio do PC (servidor indisponível)';
					}
				}
			} else {
				// Usar relógio do PC (sem sincronização com servidor)
				timestampBase = obterTempoPC();
				sincronizado = false;
				usandoServidorExterno = false;
				erro = 'Usando relógio do PC';
			}

			// Aplicar GMT offset ao timestamp UTC
			// O offset é aplicado manualmente, então usamos UTC como base para evitar conversão dupla
			let timestampAjustado: number;
			if (gmtOffset !== 0) {
				// Aplicar offset configurado ao timestamp UTC
				timestampAjustado = timestampBase + gmtOffset * 60 * 60 * 1000;
			} else {
				// Quando GMT = 0, manter timestamp UTC puro
				timestampAjustado = timestampBase;
			}
			// Armazenar o timestamp ajustado (não o Date, para evitar problemas de timezone)
			tempoAtual = new Date(timestampAjustado);
		} catch (error) {
			console.error('Erro ao obter tempo:', error);
			tempoAtual = new Date(obterTempoPC());
			sincronizado = false;
			erro = 'Erro ao obter tempo do servidor';
		} finally {
			sincronizando = false;
			sincronizacaoEmAndamento = false;
		}
	}

	function atualizarRelogio() {
		// Atualizar segundo a segundo
		const agora = new Date(tempoAtual.getTime() + 1000);
		tempoAtual = agora;
	}

	onMount(async () => {
		// Inicializar com relógio do PC imediatamente para não bloquear a interface
		tempoAtual = new Date(obterTempoPC());
		sincronizado = false;
		erro = 'Usando relógio do PC';
		// Atualizar display a cada segundo
		intervalId = setInterval(atualizarRelogio, 1000);
		// Sincronizar em background (não bloquear) após um pequeno delay para garantir que a UI está renderizada
		setTimeout(() => {
			atualizarTempo().catch((error) => {
				console.error('Erro ao sincronizar tempo em background:', error);
			});
		}, 100);
		// Sincronizar a cada 30 segundos
		intervaloSincronizacao = setInterval(() => {
			atualizarTempo().catch((error) => {
				console.error('Erro ao sincronizar tempo periódico:', error);
			});
		}, 30000);
	});

	onDestroy(() => {
		if (intervalId) {
			clearInterval(intervalId);
		}
		if (intervaloSincronizacao) {
			clearInterval(intervaloSincronizacao);
		}
		sincronizacaoEmAndamento = false;
	});

	const horaFormatada = $derived.by(() => {
		// Usar UTC como base pois já aplicamos o offset manualmente no timestamp
		// Isso evita conversão dupla pelo navegador
		return tempoAtual.toLocaleTimeString('pt-BR', {
			hour: '2-digit',
			minute: '2-digit',
			second: '2-digit',
			timeZone: 'UTC' // Usar UTC como base pois já aplicamos o offset manualmente
		});
	});

	const dataFormatada = $derived.by(() => {
		// Usar UTC como base pois já aplicamos o offset manualmente no timestamp
		// Isso evita conversão dupla pelo navegador
		return tempoAtual.toLocaleDateString('pt-BR', {
			weekday: 'long',
			day: '2-digit',
			month: 'long',
			year: 'numeric',
			timeZone: 'UTC' // Usar UTC como base pois já aplicamos o offset manualmente
		});
	});
</script>

<div class="flex w-full flex-col items-center gap-4">
	<!-- Hora -->
	<div class="text-primary font-mono text-5xl font-black tracking-tight drop-shadow-sm">
		{horaFormatada}
	</div>

	<!-- Data -->
	<div class="text-base-content/80 text-base font-semibold capitalize">
		{dataFormatada}
	</div>

	<!-- Status de Sincronização -->
	<div
		class="flex items-center gap-2 rounded-full px-4 py-2 {sincronizando
			? 'bg-info/20 text-info border-info/30 border animate-pulse'
			: sincronizado
				? 'bg-success/20 text-success border-success/30 border'
				: erro
					? 'bg-warning/20 text-warning border-warning/30 border'
					: 'bg-base-300/50 text-base-content/60 border-base-300 border'}"
	>
		{#if sincronizando}
			<span class="loading loading-spinner loading-sm text-info"></span>
			<span class="text-sm font-semibold">Sincronizando com servidor...</span>
		{:else if sincronizado}
			<CheckCircle2 class="h-4 w-4" strokeWidth={2.5} />
			<span class="text-sm font-semibold">
				{#if usandoServidorExterno}
					Sincronizado com servidor NTP
				{:else}
					Sincronizado com servidor
				{/if}
			</span>
		{:else if erro}
			<AlertCircle class="h-4 w-4" strokeWidth={2.5} />
			<span class="text-sm font-semibold">{erro}</span>
		{:else}
			<Clock class="h-4 w-4" strokeWidth={2.5} />
			<span class="text-sm font-semibold">Usando relógio do PC</span>
		{/if}
	</div>
</div>
