<script lang="ts">
	import { onMount, onDestroy } from 'svelte';
	import { useQuery, useConvexClient } from 'convex-svelte';
	import { api } from '@sgse-app/backend/convex/_generated/api';
	import { Clock, Filter, Download, Printer, BarChart3, Users, CheckCircle2, XCircle, TrendingUp, TrendingDown, FileText } from 'lucide-svelte';
	import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
	import { formatarHoraPonto, getTipoRegistroLabel } from '$lib/utils/ponto';
	import jsPDF from 'jspdf';
	import autoTable from 'jspdf-autotable';
	import logoGovPE from '$lib/assets/logo_governo_PE.png';
	import PrintPontoModal from '$lib/components/ponto/PrintPontoModal.svelte';
	import { toast } from 'svelte-sonner';
	import { Chart, registerables } from 'chart.js';
	
	Chart.register(...registerables);

	const client = useConvexClient();

	// Estados
	let dataInicio = $state(new Date().toISOString().split('T')[0]!);
	let dataFim = $state(new Date().toISOString().split('T')[0]!);
	let funcionarioIdFiltro = $state<Id<'funcionarios'> | ''>('');
	let carregando = $state(false);
	let mostrarModalImpressao = $state(false);
	let funcionarioParaImprimir = $state<Id<'funcionarios'> | ''>('');
	let chartCanvas: HTMLCanvasElement;
	let chartInstance: Chart | null = null;

	// Parâmetros reativos para queries
	const registrosParams = $derived({
		funcionarioId: funcionarioIdFiltro || undefined,
		dataInicio,
		dataFim,
	});
	const estatisticasParams = $derived({
		dataInicio,
		dataFim,
	});

	// Queries
	const funcionariosQuery = useQuery(api.funcionarios.getAll, {});
	const registrosQuery = useQuery(api.pontos.listarRegistrosPeriodo, registrosParams);
	const estatisticasQuery = useQuery(api.pontos.obterEstatisticas, estatisticasParams);
	const configQuery = useQuery(api.configuracaoPonto.obterConfiguracao, {});

	const funcionarios = $derived(funcionariosQuery?.data || []);
	const registros = $derived(registrosQuery?.data || []);
	const estatisticas = $derived(estatisticasQuery?.data);
	const config = $derived(configQuery?.data);


	// Dados do gráfico baseados nas estatísticas
	const chartData = $derived.by(() => {
		if (!estatisticas) return null;
		
		return {
			labels: ['Estatísticas de Registros'],
			datasets: [
				{
					label: 'Dentro do Prazo',
					data: [estatisticas.dentroDoPrazo || 0],
					backgroundColor: 'rgba(34, 197, 94, 0.8)',
					borderColor: 'rgba(34, 197, 94, 1)',
					borderWidth: 2,
				},
				{
					label: 'Fora do Prazo',
					data: [estatisticas.foraDoPrazo || 0],
					backgroundColor: 'rgba(239, 68, 68, 0.8)',
					borderColor: 'rgba(239, 68, 68, 1)',
					borderWidth: 2,
				}
			]
		};
	});

	// Função para criar/atualizar o gráfico
	function criarGrafico() {
		if (!chartCanvas || !estatisticas || !chartData) {
			return;
		}

		const ctx = chartCanvas.getContext('2d');
		if (!ctx) {
			return;
		}

		// Destruir gráfico anterior se existir
		if (chartInstance) {
			chartInstance.destroy();
			chartInstance = null;
		}

		try {
			chartInstance = new Chart(ctx, {
				type: 'bar',
				data: chartData,
				options: {
					responsive: true,
					maintainAspectRatio: false,
					plugins: {
						legend: {
							display: true,
							position: 'top',
							labels: {
								color: 'hsl(var(--bc))',
								font: {
									size: 12,
									family: "'Inter', sans-serif",
								},
								usePointStyle: true,
								padding: 15,
							}
						},
						tooltip: {
							backgroundColor: 'rgba(0, 0, 0, 0.85)',
							titleColor: '#fff',
							bodyColor: '#fff',
							borderColor: 'hsl(var(--p))',
							borderWidth: 1,
							padding: 12,
							callbacks: {
								label: function(context) {
									const label = context.dataset.label || '';
									const value = context.parsed.y;
									const total = estatisticas.totalRegistros;
									const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : '0.0';
									return `${label}: ${value} (${percentage}%)`;
								}
							}
						}
					},
					scales: {
						x: {
							stacked: true,
							grid: {
								display: false,
							},
							ticks: {
								color: 'hsl(var(--bc))',
								font: {
									size: 12,
								}
							}
						},
						y: {
							stacked: true,
							beginAtZero: true,
							grid: {
								color: 'rgba(0, 0, 0, 0.05)',
							},
							ticks: {
								color: 'hsl(var(--bc))',
								font: {
									size: 11,
								},
								stepSize: 1,
							}
						}
					},
					animation: {
						duration: 1000,
						easing: 'easeInOutQuart'
					},
					interaction: {
						mode: 'index',
						intersect: false,
					}
				}
			});
		} catch (error) {
			console.error('Erro ao criar gráfico:', error);
		}
	}

	// Inicializar gráfico quando canvas e dados estiverem disponíveis
	$effect(() => {
		if (chartCanvas && estatisticas && chartData) {
			// Aguardar um pouco para garantir que o canvas está renderizado
			const timeoutId = setTimeout(() => {
				criarGrafico();
			}, 100);

			return () => {
				clearTimeout(timeoutId);
			};
		}
	});

	// Também tentar criar quando o canvas for montado
	onMount(() => {
		if (chartCanvas && estatisticas && chartData) {
			setTimeout(() => {
				criarGrafico();
			}, 200);
		}
	});

	onDestroy(() => {
		if (chartInstance) {
			chartInstance.destroy();
		}
	});

	// Agrupar registros por funcionário e data
	const registrosAgrupados = $derived.by(() => {
		const agrupados: Record<
			string,
			{
				funcionario: { nome: string; matricula?: string; descricaoCargo?: string } | null;
				funcionarioId: Id<'funcionarios'>;
				registrosPorData: Record<
					string,
					{
						data: string;
						registros: Array<typeof registros[number]>;
						saldoDiario?: { saldoMinutos: number; horas: number; minutos: number; positivo: boolean };
					}
				>;
			}
		> = {};

		// Usar Set para evitar registros duplicados
		const registrosProcessados = new Set<string>();

		// Verificar se registros é um array válido
		if (!Array.isArray(registros) || registros.length === 0) {
			return [];
		}

		for (const registro of registros) {
			// Verificar se o registro tem os campos necessários
			if (!registro || !registro._id || !registro.funcionarioId || !registro.data) {
				console.warn('⚠️ [DEBUG] Registro inválido ignorado:', registro);
				continue;
			}

			// Criar chave única para evitar duplicatas
			const chaveUnica = `${registro._id}`;
			if (registrosProcessados.has(chaveUnica)) {
				continue; // Pular se já foi processado
			}
			registrosProcessados.add(chaveUnica);

			const key = registro.funcionarioId;
			if (!agrupados[key]) {
				agrupados[key] = {
					funcionario: registro.funcionario,
					funcionarioId: registro.funcionarioId,
					registrosPorData: {},
				};
			}

			const dataKey = registro.data;
			if (!agrupados[key]!.registrosPorData[dataKey]) {
				agrupados[key]!.registrosPorData[dataKey] = {
					data: dataKey,
					registros: [],
					saldoDiario: undefined,
				};
			}
			
			// Verificar se o registro já não está no array antes de adicionar
			const jaExiste = agrupados[key]!.registrosPorData[dataKey]!.registros.some(
				(r) => r._id === registro._id
			);
			if (!jaExiste) {
				agrupados[key]!.registrosPorData[dataKey]!.registros.push(registro);
			}
		}

		// Ordenar registros por data e hora dentro de cada grupo e usar saldo diário da query
		const resultado = Object.values(agrupados);
		
		// Ordenar grupos por nome do funcionário
		resultado.sort((a, b) => {
			const nomeA = a.funcionario?.nome || '';
			const nomeB = b.funcionario?.nome || '';
			return nomeA.localeCompare(nomeB, 'pt-BR');
		});

		for (const grupo of resultado) {
			// Ordenar datas dentro de cada grupo (mais recente primeiro)
			const datasOrdenadas = Object.keys(grupo.registrosPorData).sort((a, b) => {
				return new Date(b).getTime() - new Date(a).getTime();
			});

			// Criar novo objeto com datas ordenadas
			const registrosPorDataOrdenado: Record<string, typeof grupo.registrosPorData[string]> = {};
			for (const dataKey of datasOrdenadas) {
				registrosPorDataOrdenado[dataKey] = grupo.registrosPorData[dataKey]!;
			}
			grupo.registrosPorData = registrosPorDataOrdenado;

			for (const dataKey in grupo.registrosPorData) {
				const grupoData = grupo.registrosPorData[dataKey];
				if (grupoData && grupoData.registros.length > 0) {
					// Ordenar por hora e minuto
					grupoData.registros.sort((a, b) => {
						if (a.hora !== b.hora) {
							return a.hora - b.hora;
						}
						return a.minuto - b.minuto;
					});

					// Usar saldo diário da query se disponível, senão calcular
					const primeiroRegistro = grupoData.registros[0];
					if (primeiroRegistro && 'saldoDiario' in primeiroRegistro && primeiroRegistro.saldoDiario) {
						grupoData.saldoDiario = primeiroRegistro.saldoDiario;
					} else {
						// Calcular saldo diário como diferença entre saída e entrada
						grupoData.saldoDiario = calcularSaldoDiario(grupoData.registros);
					}
				}
			}
		}

		return resultado;
	});

	// Query para banco de horas de cada funcionário
	const funcionariosComBancoHoras = $derived.by(() => {
		return registrosAgrupados.map((grupo) => grupo.funcionarioId);
	});

	// Função para formatar saldo de horas
	function formatarSaldoHoras(minutos: number): string {
		const horas = Math.floor(Math.abs(minutos) / 60);
		const mins = Math.abs(minutos) % 60;
		const sinal = minutos >= 0 ? '+' : '-';
		return `${sinal}${horas}h ${mins}min`;
	}

	// Função para formatar saldo diário
	function formatarSaldoDiario(saldo?: { saldoMinutos: number; horas: number; minutos: number; positivo: boolean }): string {
		if (!saldo) return '-';
		const sinal = saldo.positivo ? '+' : '-';
		return `${sinal}${saldo.horas}h ${saldo.minutos}min`;
	}

	// Função para formatar data em português
	function formatarData(data: string): string {
		if (!data) return '';
		const dataObj = new Date(data + 'T00:00:00');
		return dataObj.toLocaleDateString('pt-BR', {
			day: '2-digit',
			month: '2-digit',
			year: 'numeric'
		});
	}

	// Obter nome do funcionário selecionado
	const funcionarioSelecionadoNome = $derived.by(() => {
		if (!funcionarioIdFiltro) return null;
		return funcionarios.find(f => f._id === funcionarioIdFiltro)?.nome || null;
	});

	// Função para calcular saldo diário como diferença entre saída e entrada
	function calcularSaldoDiario(registros: Array<{ tipo: string; hora: number; minuto: number }>): { saldoMinutos: number; horas: number; minutos: number; positivo: boolean } | null {
		if (registros.length === 0) return null;

		// Ordenar registros por hora e minuto
		const registrosOrdenados = [...registros].sort((a, b) => {
			if (a.hora !== b.hora) {
				return a.hora - b.hora;
			}
			return a.minuto - b.minuto;
		});

		// Buscar entrada (primeiro registro do tipo 'entrada')
		const entrada = registrosOrdenados.find((r) => r.tipo === 'entrada');
		// Buscar saída (último registro do tipo 'saida')
		const saida = registrosOrdenados.filter((r) => r.tipo === 'saida').pop();

		if (!entrada || !saida) return null;

		// Calcular diferença em minutos
		const minutosEntrada = entrada.hora * 60 + entrada.minuto;
		const minutosSaida = saida.hora * 60 + saida.minuto;
		
		// Se a saída for no dia seguinte (após meia-noite), adicionar 24 horas
		let saldoMinutos = minutosSaida - minutosEntrada;
		if (saldoMinutos < 0) {
			saldoMinutos += 24 * 60; // Adicionar um dia em minutos
		}

		const horas = Math.floor(saldoMinutos / 60);
		const minutos = saldoMinutos % 60;

		return {
			saldoMinutos,
			horas,
			minutos,
			positivo: true, // Sempre positivo, pois é tempo trabalhado
		};
	}

	function abrirModalImpressao(funcionarioId: Id<'funcionarios'>) {
		funcionarioParaImprimir = funcionarioId;
		mostrarModalImpressao = true;
	}

	async function gerarPDFComSelecao(sections: {
		dadosFuncionario: boolean;
		registrosPonto: boolean;
		saldoDiario: boolean;
		bancoHoras: boolean;
		alteracoesGestor: boolean;
		dispensasRegistro: boolean;
	}) {
		if (!funcionarioParaImprimir) return;

		const funcionarioId = funcionarioParaImprimir;
		
		// Verificar se pelo menos uma seção foi selecionada
		if (!Object.values(sections).some((v) => v)) {
			toast.error('Selecione pelo menos uma seção para imprimir');
			return;
		}

		const funcionario = funcionarios.find((f) => f._id === funcionarioId);
		if (!funcionario) {
			toast.error('Funcionário não encontrado');
			return;
		}

		// Buscar registros do funcionário no período selecionado
		const registrosFuncionario = await client.query(api.pontos.listarRegistrosPeriodo, {
			funcionarioId,
			dataInicio,
			dataFim,
		});

		if (!registrosFuncionario || registrosFuncionario.length === 0) {
			toast.error('Nenhum registro encontrado para este funcionário no período selecionado');
			return;
		}

		try {
			const doc = new jsPDF();

			// Logo
			let yPosition = 20;
			try {
				const logoImg = new Image();
				logoImg.src = logoGovPE;
				await new Promise<void>((resolve, reject) => {
					logoImg.onload = () => resolve();
					logoImg.onerror = () => reject();
					setTimeout(() => reject(), 3000);
				});

				const logoWidth = 25;
				const aspectRatio = logoImg.height / logoImg.width;
				const logoHeight = logoWidth * aspectRatio;

				doc.addImage(logoImg, 'PNG', 15, 10, logoWidth, logoHeight);
				yPosition = Math.max(20, 10 + logoHeight / 2);
			} catch (err) {
				console.warn('Não foi possível carregar a logo:', err);
			}

			// Cabeçalho
			doc.setFontSize(16);
			doc.setTextColor(41, 128, 185);
			doc.text('FICHA DE PONTO', 105, yPosition, { align: 'center' });

			yPosition += 10;

			// Dados do Funcionário
			if (sections.dadosFuncionario) {
				doc.setFontSize(12);
				doc.setTextColor(0, 0, 0);
				doc.setFont('helvetica', 'bold');
				doc.text('DADOS DO FUNCIONÁRIO', 15, yPosition);
				doc.setFont('helvetica', 'normal');

				yPosition += 8;
				doc.setFontSize(10);

				if (funcionario.matricula) {
					doc.text(`Matrícula: ${funcionario.matricula}`, 15, yPosition);
					yPosition += 6;
				}
				doc.text(`Nome: ${funcionario.nome}`, 15, yPosition);
				yPosition += 6;
				if (funcionario.descricaoCargo) {
					doc.text(`Cargo/Função: ${funcionario.descricaoCargo}`, 15, yPosition);
					yPosition += 6;
				}

				yPosition += 5;
				// Formatar período para exibição
				const dataInicioParts = dataInicio.split('-');
				const dataFimParts = dataFim.split('-');
				const periodoFormatado = `${dataInicioParts[2]}/${dataInicioParts[1]}/${dataInicioParts[0]} a ${dataFimParts[2]}/${dataFimParts[1]}/${dataFimParts[0]}`;
				doc.text(`Período: ${periodoFormatado}`, 15, yPosition);
				yPosition += 10;
			}

			// Buscar homologações e dispensas
			let homologacoes: Array<{
				_id: Id<'homologacoesPonto'>;
				criadoEm: number;
				registroId?: Id<'registrosPonto'>;
				horaAnterior?: number;
				minutoAnterior?: number;
				horaNova?: number;
				minutoNova?: number;
				tipoAjuste?: 'compensar' | 'abonar' | 'descontar';
				periodoDias?: number;
				periodoHoras?: number;
				periodoMinutos?: number;
				motivoDescricao?: string;
				motivoTipo?: string;
				observacoes?: string;
			}> = [];
			
			let dispensas: Array<{
				dataInicio: string;
				dataFim: string;
				horaInicio: number;
				minutoInicio: number;
				horaFim: number;
				minutoFim: number;
				motivo: string;
				isento: boolean;
			}> = [];

			if (sections.alteracoesGestor) {
				try {
					homologacoes = await client.query(api.pontos.listarHomologacoes, {
						funcionarioId,
					}) || [];
				} catch (error) {
					console.warn('Erro ao buscar homologações:', error);
					// Continuar mesmo se houver erro ao buscar homologações
				}
			}

			if (sections.dispensasRegistro) {
				try {
					dispensas = await client.query(api.pontos.listarDispensas, {
						funcionarioId,
						apenasAtivas: false,
					}) || [];
				} catch (error) {
					console.warn('Erro ao buscar dispensas:', error);
					// Continuar mesmo se houver erro ao buscar dispensas
				}
			}

			// Tabela de registros
			if (sections.registrosPonto) {
				const config = await client.query(api.configuracaoPonto.obterConfiguracao, {});
				const tableData: string[][] = [];

				// Agrupar por data para incluir saldo diário
				const registrosPorData: Record<
					string,
					Array<{
						data: string;
						tipo: string;
						hora: number;
						minuto: number;
						dentroDoPrazo: boolean;
					}>
				> = {};

				for (const r of registrosFuncionario) {
					const dataKey = r.data;
					if (!registrosPorData[dataKey]) {
						registrosPorData[dataKey] = [];
					}
					registrosPorData[dataKey]!.push({
						data: r.data,
						tipo: r.tipo,
						hora: r.hora,
						minuto: r.minuto,
						dentroDoPrazo: r.dentroDoPrazo,
					});
				}

				// Criar dados da tabela com saldo diário
				for (const [data, regs] of Object.entries(registrosPorData)) {
					// Formatar data para exibição (DD/MM/YYYY)
					const dataParts = data.split('-');
					const dataFormatada = `${dataParts[2]}/${dataParts[1]}/${dataParts[0]}`;
					
					// Calcular saldo diário como diferença entre saída e entrada
					const saldoDiarioDia = calcularSaldoDiario(regs);
					
					for (const reg of regs) {
						const linha: string[] = [
							dataFormatada,
							config
								? getTipoRegistroLabel(reg.tipo as 'entrada' | 'saida_almoco' | 'retorno_almoco' | 'saida', {
										nomeEntrada: config.nomeEntrada,
										nomeSaidaAlmoco: config.nomeSaidaAlmoco,
										nomeRetornoAlmoco: config.nomeRetornoAlmoco,
										nomeSaida: config.nomeSaida,
									})
								: getTipoRegistroLabel(reg.tipo as 'entrada' | 'saida_almoco' | 'retorno_almoco' | 'saida'),
							formatarHoraPonto(reg.hora, reg.minuto),
						];

						// Saldo Diário sempre após Horário
						if (sections.saldoDiario) {
							if (saldoDiarioDia) {
								const sinal = saldoDiarioDia.positivo ? '+' : '-';
								linha.push(`${sinal}${saldoDiarioDia.horas}h ${saldoDiarioDia.minutos}min`);
							} else {
								linha.push('-');
							}
						}

						linha.push(reg.dentroDoPrazo ? 'Sim' : 'Não');

						tableData.push(linha);
					}
				}

				const headers = ['Data', 'Tipo', 'Horário'];
				if (sections.saldoDiario) {
					headers.push('Saldo Diário');
				}
				headers.push('Dentro do Prazo');

				// Salvar a posição Y antes da tabela
				const yPosAntesTabela = yPosition;

				autoTable(doc, {
					startY: yPosition,
					head: [headers],
					body: tableData,
					theme: 'grid',
					headStyles: { fillColor: [41, 128, 185], fontStyle: 'bold' },
					styles: { fontSize: 9 },
				});

				// Calcular posição Y após a tabela
				const lastPage = doc.getNumberOfPages();
				doc.setPage(lastPage);
				const finalY = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY;

				if (finalY) {
					yPosition = finalY;
				} else {
					const linhasTabela = tableData.length + 1;
					yPosition = yPosAntesTabela + linhasTabela * 7 + 10;
				}
				yPosition += 10;
			}

			// Banco de Horas
			if (sections.bancoHoras) {
				if (yPosition > doc.internal.pageSize.getHeight() - 60) {
					doc.addPage();
					yPosition = 20;
				}

				const bancoHoras = await client.query(api.pontos.obterBancoHorasFuncionario, {
					funcionarioId,
				});

				doc.setFontSize(12);
				doc.setFont('helvetica', 'bold');
				doc.setTextColor(41, 128, 185);
				doc.text('RESUMO DO BANCO DE HORAS', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				doc.setTextColor(0, 0, 0);

				yPosition += 10;
				doc.setFontSize(10);

				if (bancoHoras) {
					const saldoMinutos = bancoHoras.saldoAcumuladoMinutos;
					const horas = Math.floor(Math.abs(saldoMinutos) / 60);
					const minutos = Math.abs(saldoMinutos) % 60;
					const sinal = saldoMinutos >= 0 ? '+' : '-';
					const saldoFormatado = `${sinal}${horas}h ${minutos}min`;

					doc.setFont('helvetica', 'bold');
					doc.text('Saldo Atual:', 15, yPosition);
					doc.setFont('helvetica', 'normal');
					doc.text(saldoFormatado, 60, yPosition);
					yPosition += 8;

					if (saldoMinutos > 0) {
						doc.setFont('helvetica', 'bold');
						doc.setTextColor(0, 128, 0);
						doc.text('Horas Excedentes:', 15, yPosition);
						doc.setFont('helvetica', 'normal');
						doc.text(`${horas}h ${minutos}min`, 75, yPosition);
						doc.setTextColor(0, 0, 0);
						yPosition += 8;
					}

					if (saldoMinutos < 0) {
						doc.setFont('helvetica', 'bold');
						doc.setTextColor(200, 0, 0);
						doc.text('Horas a Pagar:', 15, yPosition);
						doc.setFont('helvetica', 'normal');
						doc.text(`${horas}h ${minutos}min`, 70, yPosition);
						doc.setTextColor(0, 0, 0);
						yPosition += 8;
					}

					doc.setFont('helvetica', 'bold');
					doc.text('Total de Dias com Registro:', 15, yPosition);
					doc.setFont('helvetica', 'normal');
					doc.text(`${bancoHoras.totalDias} dias`, 95, yPosition);
					yPosition += 10;
				} else {
					doc.text('Banco de horas não disponível', 15, yPosition);
					yPosition += 10;
				}
			}

			// Alterações pelo Gestor
			if (sections.alteracoesGestor && homologacoes.length > 0) {
				if (yPosition > doc.internal.pageSize.getHeight() - 60) {
					doc.addPage();
					yPosition = 20;
				}

				doc.setFontSize(12);
				doc.setFont('helvetica', 'bold');
				doc.setTextColor(41, 128, 185);
				doc.text('ALTERAÇÕES PELO GESTOR', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				doc.setTextColor(0, 0, 0);
				yPosition += 10;

				const homologacoesData = homologacoes.map((h) => {
					// Formatar data de criação
					const dataCriacao = new Date(h.criadoEm);
					const dataFormatada = `${dataCriacao.getDate().toString().padStart(2, '0')}/${(dataCriacao.getMonth() + 1).toString().padStart(2, '0')}/${dataCriacao.getFullYear()}`;
					
					if (h.registroId && h.horaAnterior !== undefined) {
						return [
							dataFormatada,
							'Edição de Registro',
							h.horaAnterior !== undefined
								? `${formatarHoraPonto(h.horaAnterior, h.minutoAnterior || 0)} → ${formatarHoraPonto(h.horaNova || 0, h.minutoNova || 0)}`
								: '-',
							h.motivoDescricao || h.motivoTipo || '-',
							h.observacoes || '-',
						];
					} else if (h.tipoAjuste) {
						const tipoAjusteLabel = h.tipoAjuste === 'compensar' ? 'Compensar' : h.tipoAjuste === 'abonar' ? 'Abonar' : 'Descontar';
						return [
							dataFormatada,
							`Ajuste: ${tipoAjusteLabel}`,
							`${h.periodoDias || 0}d ${h.periodoHoras || 0}h ${h.periodoMinutos || 0}min`,
							h.motivoDescricao || h.motivoTipo || '-',
							h.observacoes || '-',
						];
					}
					return [];
				}).filter((row) => row.length > 0);

				if (homologacoesData.length > 0) {
					autoTable(doc, {
						startY: yPosition,
						head: [['Data', 'Tipo', 'Detalhes', 'Motivo', 'Observações']],
						body: homologacoesData,
						theme: 'grid',
						headStyles: { fillColor: [41, 128, 185], fontStyle: 'bold' },
						styles: { fontSize: 9 },
					});

					const lastPage = doc.getNumberOfPages();
					doc.setPage(lastPage);
					const finalY = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY;
					if (finalY) {
						yPosition = finalY + 10;
					} else {
						yPosition += homologacoesData.length * 7 + 10;
					}
				}
			}

			// Dispensas de Registro
			if (sections.dispensasRegistro && dispensas.length > 0) {
				if (yPosition > doc.internal.pageSize.getHeight() - 60) {
					doc.addPage();
					yPosition = 20;
				}

				doc.setFontSize(12);
				doc.setFont('helvetica', 'bold');
				doc.setTextColor(41, 128, 185);
				doc.text('DISPENSAS DE REGISTRO', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				doc.setTextColor(0, 0, 0);
				yPosition += 10;

				const dispensasData = dispensas.map((d) => {
					// Formatar data de início
					const dataInicioParts = d.dataInicio.split('-');
					const dataInicioFormatada = `${dataInicioParts[2]}/${dataInicioParts[1]}/${dataInicioParts[0]}`;
					
					// Formatar data de fim
					const dataFimParts = d.dataFim.split('-');
					const dataFimFormatada = `${dataFimParts[2]}/${dataFimParts[1]}/${dataFimParts[0]}`;
					
					return [
						`${dataInicioFormatada} ${d.horaInicio.toString().padStart(2, '0')}:${d.minutoInicio.toString().padStart(2, '0')}`,
						`${dataFimFormatada} ${d.horaFim.toString().padStart(2, '0')}:${d.minutoFim.toString().padStart(2, '0')}`,
						d.motivo,
						d.isento ? 'Isento (sem expiração)' : 'Temporária',
					];
				});

				autoTable(doc, {
					startY: yPosition,
					head: [['Início', 'Fim', 'Motivo', 'Tipo']],
					body: dispensasData,
					theme: 'grid',
					headStyles: { fillColor: [41, 128, 185], fontStyle: 'bold' },
					styles: { fontSize: 9 },
				});

				const lastPage = doc.getNumberOfPages();
				doc.setPage(lastPage);
				const finalY = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY;
				if (finalY) {
					yPosition = finalY + 10;
				} else {
					yPosition += dispensasData.length * 7 + 10;
				}
			}

			// Rodapé
			const pageCount = doc.getNumberOfPages();
			for (let i = 1; i <= pageCount; i++) {
				doc.setPage(i);
				doc.setFontSize(8);
				doc.setTextColor(128, 128, 128);
				doc.text(
					`SGSE - Sistema de Gerenciamento de Secretaria | Página ${i} de ${pageCount}`,
					doc.internal.pageSize.getWidth() / 2,
					doc.internal.pageSize.getHeight() - 10,
					{ align: 'center' }
				);
			}

			// Salvar
			const nomeArquivo = `ficha-ponto-${funcionario.matricula || funcionario.nome}-${dataInicio}-${dataFim}.pdf`;
			doc.save(nomeArquivo);
			
			// Fechar modal após gerar PDF
			mostrarModalImpressao = false;
			funcionarioParaImprimir = '';
			toast.success('PDF gerado com sucesso!');
		} catch (error) {
			console.error('Erro ao gerar PDF:', error);
			const errorMessage = error instanceof Error ? error.message : String(error);
			toast.error(`Erro ao gerar ficha de ponto: ${errorMessage}`);
		}
	}

	async function imprimirDetalhesRegistro(registroId: Id<'registrosPonto'>) {
		try {
			// Buscar dados completos do registro
			const registro = await client.query(api.pontos.obterRegistro, { registroId });
			
			if (!registro) {
				alert('Registro não encontrado');
				return;
			}

			const doc = new jsPDF();

			// Logo
			let yPosition = 20;
			try {
				const logoImg = new Image();
				logoImg.src = logoGovPE;
				await new Promise<void>((resolve, reject) => {
					logoImg.onload = () => resolve();
					logoImg.onerror = () => reject();
					setTimeout(() => reject(), 3000);
				});

				const logoWidth = 25;
				const aspectRatio = logoImg.height / logoImg.width;
				const logoHeight = logoWidth * aspectRatio;

				doc.addImage(logoImg, 'PNG', 15, 10, logoWidth, logoHeight);
				yPosition = Math.max(20, 10 + logoHeight / 2);
			} catch (err) {
				console.warn('Não foi possível carregar a logo:', err);
			}

			// Cabeçalho
			doc.setFontSize(16);
			doc.setTextColor(41, 128, 185);
			doc.text('DETALHES DO REGISTRO DE PONTO', 105, yPosition, { align: 'center' });

			yPosition += 15;

			// Informações do Funcionário
			doc.setFontSize(12);
			doc.setTextColor(0, 0, 0);
			doc.setFont('helvetica', 'bold');
			doc.text('DADOS DO FUNCIONÁRIO', 15, yPosition);
			doc.setFont('helvetica', 'normal');

			yPosition += 8;
			doc.setFontSize(10);

			if (registro.funcionario) {
				if (registro.funcionario.matricula) {
					doc.text(`Matrícula: ${registro.funcionario.matricula}`, 15, yPosition);
					yPosition += 6;
				}
				doc.text(`Nome: ${registro.funcionario.nome}`, 15, yPosition);
				yPosition += 6;
				if (registro.funcionario.descricaoCargo) {
					doc.text(`Cargo/Função: ${registro.funcionario.descricaoCargo}`, 15, yPosition);
					yPosition += 6;
				}
			}

			yPosition += 5;

			// Informações do Registro
			doc.setFont('helvetica', 'bold');
			doc.text('DADOS DO REGISTRO', 15, yPosition);
			doc.setFont('helvetica', 'normal');

			yPosition += 8;
			doc.setFontSize(10);

			const config = await client.query(api.configuracaoPonto.obterConfiguracao, {});
			const tipoLabel = config
				? getTipoRegistroLabel(registro.tipo, {
						nomeEntrada: config.nomeEntrada,
						nomeSaidaAlmoco: config.nomeSaidaAlmoco,
						nomeRetornoAlmoco: config.nomeRetornoAlmoco,
						nomeSaida: config.nomeSaida,
					})
				: getTipoRegistroLabel(registro.tipo);
			doc.text(`Tipo: ${tipoLabel}`, 15, yPosition);
			yPosition += 6;

			const dataHora = `${registro.data} ${registro.hora.toString().padStart(2, '0')}:${registro.minuto.toString().padStart(2, '0')}:${registro.segundo.toString().padStart(2, '0')}`;
			doc.text(`Data e Hora: ${dataHora}`, 15, yPosition);
			yPosition += 6;

			doc.text(`Status: ${registro.dentroDoPrazo ? 'Dentro do Prazo' : 'Fora do Prazo'}`, 15, yPosition);
			yPosition += 6;

			doc.text(`Tolerância: ${registro.toleranciaMinutos} minutos`, 15, yPosition);
			yPosition += 6;

			doc.text(
				`Sincronizado: ${registro.sincronizadoComServidor ? 'Sim (Servidor)' : 'Não (PC Local)'}`,
				15,
				yPosition
			);
			yPosition += 6;

			if (registro.justificativa) {
				doc.text(`Justificativa: ${registro.justificativa}`, 15, yPosition);
				yPosition += 6;
			}

			yPosition += 5;

			// Localização
			if (registro.latitude && registro.longitude) {
				// Verificar se precisa de nova página
				if (yPosition > 200) {
					doc.addPage();
					yPosition = 20;
				}

				doc.setFont('helvetica', 'bold');
				doc.text('LOCALIZAÇÃO', 15, yPosition);
				doc.setFont('helvetica', 'normal');

				yPosition += 8;
				doc.setFontSize(10);

				doc.text(`Latitude: ${registro.latitude.toFixed(6)}`, 15, yPosition);
				yPosition += 6;

				doc.text(`Longitude: ${registro.longitude.toFixed(6)}`, 15, yPosition);
				yPosition += 6;

				if (registro.precisao) {
					doc.text(`Precisão: ${registro.precisao.toFixed(2)} metros`, 15, yPosition);
					yPosition += 6;
				}

				if (registro.endereco) {
					doc.text(`Endereço: ${registro.endereco}`, 15, yPosition);
					yPosition += 6;
				}

				if (registro.cidade) {
					doc.text(`Cidade: ${registro.cidade}`, 15, yPosition);
					yPosition += 6;
				}

				if (registro.estado) {
					doc.text(`Estado: ${registro.estado}`, 15, yPosition);
					yPosition += 6;
				}

				if (registro.pais) {
					doc.text(`País: ${registro.pais}`, 15, yPosition);
					yPosition += 6;
				}

				if (registro.timezone) {
					doc.text(`Fuso Horário: ${registro.timezone}`, 15, yPosition);
					yPosition += 6;
				}

				yPosition += 5;
			}

			// Validação de GPS e Anti-Spoofing
			if (registro.latitude && registro.longitude) {
				// Verificar se precisa de nova página
				if (yPosition > 200) {
					doc.addPage();
					yPosition = 20;
				}

				doc.setFont('helvetica', 'bold');
				doc.setFontSize(12);
				doc.text('VALIDAÇÃO DE LOCALIZAÇÃO GPS', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				doc.setFontSize(10);
				yPosition += 10;

				// Informações detalhadas do GPS
				doc.setFont('helvetica', 'bold');
				doc.text('Dados do GPS:', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				yPosition += 6;

				if (registro.precisao !== null && registro.precisao !== undefined) {
					doc.text(`  Precisão: ${registro.precisao.toFixed(2)} metros`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.altitude !== null && registro.altitude !== undefined) {
					doc.text(`  Altitude: ${registro.altitude.toFixed(2)} metros`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.altitudeAccuracy !== null && registro.altitudeAccuracy !== undefined) {
					doc.text(`  Precisão da Altitude: ${registro.altitudeAccuracy.toFixed(2)} metros`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.heading !== null && registro.heading !== undefined) {
					doc.text(`  Direção (Heading): ${registro.heading.toFixed(2)}°`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.speed !== null && registro.speed !== undefined) {
					doc.text(`  Velocidade: ${(registro.speed * 3.6).toFixed(2)} km/h`, 20, yPosition);
					yPosition += 6;
				}

				yPosition += 3;

				// Confiabilidade e Scores
				doc.setFont('helvetica', 'bold');
				doc.text('Confiabilidade:', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				yPosition += 6;

				if (registro.confiabilidadeGPS !== null && registro.confiabilidadeGPS !== undefined) {
					const confiabilidadePercent = (registro.confiabilidadeGPS * 100).toFixed(1);
					const confiabilidadeCor = registro.confiabilidadeGPS >= 0.7 ? [0, 128, 0] : registro.confiabilidadeGPS >= 0.4 ? [255, 165, 0] : [255, 0, 0];
					doc.setTextColor(confiabilidadeCor[0], confiabilidadeCor[1], confiabilidadeCor[2]);
					doc.text(`  Confiabilidade GPS (Frontend): ${confiabilidadePercent}%`, 20, yPosition);
					doc.setTextColor(0, 0, 0);
					yPosition += 6;
				}

				if (registro.scoreConfiancaBackend !== null && registro.scoreConfiancaBackend !== undefined) {
					const scorePercent = (registro.scoreConfiancaBackend * 100).toFixed(1);
					const scoreCor = registro.scoreConfiancaBackend >= 0.7 ? [0, 128, 0] : registro.scoreConfiancaBackend >= 0.4 ? [255, 165, 0] : [255, 0, 0];
					doc.setTextColor(scoreCor[0], scoreCor[1], scoreCor[2]);
					doc.text(`  Score de Confiança (Backend): ${scorePercent}%`, 20, yPosition);
					doc.setTextColor(0, 0, 0);
					yPosition += 6;
				}

				yPosition += 3;

				// Status de Validação
				if (registro.suspeitaSpoofing !== null && registro.suspeitaSpoofing !== undefined) {
					doc.setFont('helvetica', 'bold');
					doc.text('Status de Validação:', 15, yPosition);
					doc.setFont('helvetica', 'normal');
					yPosition += 6;

					if (registro.suspeitaSpoofing) {
						doc.setTextColor(255, 0, 0);
						doc.setFont('helvetica', 'bold');
						doc.text('  ⚠️ MARCAÇÃO SUSPEITA DETECTADA', 20, yPosition);
						doc.setFont('helvetica', 'normal');
						doc.setTextColor(0, 0, 0);
						yPosition += 6;
					} else {
						doc.setTextColor(0, 128, 0);
						doc.setFont('helvetica', 'bold');
						doc.text('  ✓ Localização validada com sucesso', 20, yPosition);
						doc.setFont('helvetica', 'normal');
						doc.setTextColor(0, 0, 0);
						yPosition += 6;
					}

					if (registro.motivoSuspeita) {
						doc.setTextColor(255, 0, 0);
						const motivoLines = doc.splitTextToSize(`  Motivo: ${registro.motivoSuspeita}`, 170);
						doc.text(motivoLines, 20, yPosition);
						yPosition += motivoLines.length * 5;
						doc.setTextColor(0, 0, 0);
					}

					yPosition += 3;
				}

				// Avisos de Validação
				if (registro.avisosValidacao && registro.avisosValidacao.length > 0) {
					doc.setFont('helvetica', 'bold');
					doc.text('Avisos de Validação:', 15, yPosition);
					doc.setFont('helvetica', 'normal');
					yPosition += 6;

					registro.avisosValidacao.forEach((aviso: string) => {
						const avisoLines = doc.splitTextToSize(`  • ${aviso}`, 170);
						doc.text(avisoLines, 20, yPosition);
						yPosition += avisoLines.length * 5;
					});

					yPosition += 3;
				}

				// Análise de Propriedades GPS
				doc.setFont('helvetica', 'bold');
				doc.text('Análise de Propriedades GPS:', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				yPosition += 6;

				let propriedadesGPS = 0;
				let propriedadesTotais = 5;

				if (registro.altitude !== null && registro.altitude !== undefined && registro.altitude !== 0) {
					doc.text('  ✓ Altitude disponível', 20, yPosition);
					propriedadesGPS++;
				} else {
					doc.text('  ✗ Altitude não disponível', 20, yPosition);
				}
				yPosition += 5;

				if (registro.altitudeAccuracy !== null && registro.altitudeAccuracy !== undefined && registro.altitudeAccuracy > 0) {
					doc.text('  ✓ Precisão de altitude disponível', 20, yPosition);
					propriedadesGPS++;
				} else {
					doc.text('  ✗ Precisão de altitude não disponível', 20, yPosition);
				}
				yPosition += 5;

				if (registro.heading !== null && registro.heading !== undefined && !isNaN(registro.heading)) {
					doc.text('  ✓ Direção (heading) disponível', 20, yPosition);
					propriedadesGPS++;
				} else {
					doc.text('  ✗ Direção (heading) não disponível', 20, yPosition);
				}
				yPosition += 5;

				if (registro.speed !== null && registro.speed !== undefined && !isNaN(registro.speed)) {
					doc.text('  ✓ Velocidade disponível', 20, yPosition);
					propriedadesGPS++;
				} else {
					doc.text('  ✗ Velocidade não disponível', 20, yPosition);
				}
				yPosition += 5;

				if (registro.precisao !== null && registro.precisao !== undefined && registro.precisao < 20) {
					doc.text('  ✓ Alta precisão GPS (< 20m)', 20, yPosition);
					propriedadesGPS++;
				} else if (registro.precisao !== null && registro.precisao !== undefined && registro.precisao >= 20 && registro.precisao < 100) {
					doc.text('  ⚠ Precisão média GPS (20-100m)', 20, yPosition);
					propriedadesGPS += 0.5;
				} else {
					doc.text('  ✗ Baixa precisão GPS (> 100m)', 20, yPosition);
				}
				yPosition += 5;

				// Indicador de qualidade GPS
				const qualidadeGPS = (propriedadesGPS / propriedadesTotais) * 100;
				const qualidadeTexto = qualidadeGPS >= 80 ? 'Alta qualidade (GPS real)' : qualidadeGPS >= 50 ? 'Qualidade média' : 'Baixa qualidade (possível spoofing)';
				const qualidadeCor = qualidadeGPS >= 80 ? [0, 128, 0] : qualidadeGPS >= 50 ? [255, 165, 0] : [255, 0, 0];

				doc.setFont('helvetica', 'bold');
				doc.setTextColor(qualidadeCor[0], qualidadeCor[1], qualidadeCor[2]);
				doc.text(`Qualidade GPS: ${qualidadeTexto} (${qualidadeGPS.toFixed(0)}% das propriedades)`, 20, yPosition);
				doc.setFont('helvetica', 'normal');
				doc.setTextColor(0, 0, 0);
				yPosition += 8;
			}

			// Validação de Geofencing (Localização Permitida)
			if (registro.latitude && registro.longitude) {
				// Verificar se precisa de nova página
				if (yPosition > 200) {
					doc.addPage();
					yPosition = 20;
				}

				doc.setFont('helvetica', 'bold');
				doc.setFontSize(12);
				doc.text('VALIDAÇÃO DE LOCALIZAÇÃO PERMITIDA', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				doc.setFontSize(10);
				yPosition += 10;

				if (registro.enderecoMarcacaoEsperado || registro.dentroRaioPermitido !== undefined) {
					// Buscar dados do endereço esperado se houver ID
					let enderecoEsperadoNome = 'Não configurado';
					let enderecoEsperadoEndereco = 'Não configurado';
					let enderecoEsperadoLatitude: number | null = null;
					let enderecoEsperadoLongitude: number | null = null;

					if (registro.enderecoMarcacaoEsperado) {
						try {
							const enderecoEsperado = await client.query(
								api.enderecosMarcacao.obterEndereco,
								{ enderecoId: registro.enderecoMarcacaoEsperado }
							);
							if (enderecoEsperado) {
								enderecoEsperadoNome = enderecoEsperado.nome;
								enderecoEsperadoEndereco = `${enderecoEsperado.endereco}, ${enderecoEsperado.cidade}/${enderecoEsperado.estado}`;
								enderecoEsperadoLatitude = enderecoEsperado.latitude;
								enderecoEsperadoLongitude = enderecoEsperado.longitude;
							}
						} catch (error) {
							console.warn('Erro ao buscar endereço esperado:', error);
						}
					}

					doc.setFont('helvetica', 'bold');
					doc.text('Endereço Esperado:', 15, yPosition);
					doc.setFont('helvetica', 'normal');
					yPosition += 6;

					doc.text(`  Nome: ${enderecoEsperadoNome}`, 20, yPosition);
					yPosition += 6;

					const enderecoLines = doc.splitTextToSize(`  Endereço: ${enderecoEsperadoEndereco}`, 170);
					doc.text(enderecoLines, 20, yPosition);
					yPosition += enderecoLines.length * 5 + 3;

					if (enderecoEsperadoLatitude !== null && enderecoEsperadoLongitude !== null) {
						doc.text(`  Coordenadas: ${enderecoEsperadoLatitude.toFixed(6)}, ${enderecoEsperadoLongitude.toFixed(6)}`, 20, yPosition);
						yPosition += 6;
					}

					yPosition += 3;

					doc.setFont('helvetica', 'bold');
					doc.text('Localização do Registro:', 15, yPosition);
					doc.setFont('helvetica', 'normal');
					yPosition += 6;

					doc.text(`  Coordenadas: ${registro.latitude.toFixed(6)}, ${registro.longitude.toFixed(6)}`, 20, yPosition);
					yPosition += 6;

					if (registro.distanciaEnderecoEsperado !== null && registro.distanciaEnderecoEsperado !== undefined) {
						const distanciaKm = (registro.distanciaEnderecoEsperado / 1000).toFixed(2);
						const distanciaMetros = registro.distanciaEnderecoEsperado.toFixed(0);
						
						if (registro.distanciaEnderecoEsperado >= 1000) {
							doc.text(`  Distância: ${distanciaKm} km (${distanciaMetros} metros)`, 20, yPosition);
						} else {
							doc.text(`  Distância: ${distanciaMetros} metros`, 20, yPosition);
						}
						yPosition += 6;
					}

					yPosition += 3;

					doc.setFont('helvetica', 'bold');
					doc.text('Raio Permitido:', 15, yPosition);
					doc.setFont('helvetica', 'normal');
					yPosition += 6;

					if (registro.raioToleranciaUsado !== null && registro.raioToleranciaUsado !== undefined) {
						const raioKm = (registro.raioToleranciaUsado / 1000).toFixed(2);
						const raioMetros = registro.raioToleranciaUsado.toFixed(0);
						
						if (registro.raioToleranciaUsado >= 1000) {
							doc.text(`  ${raioKm} km (${raioMetros} metros)`, 20, yPosition);
						} else {
							doc.text(`  ${raioMetros} metros`, 20, yPosition);
						}
						yPosition += 6;
					} else {
						doc.text('  Não configurado', 20, yPosition);
						yPosition += 6;
					}

					yPosition += 3;

					// Status da validação
					doc.setFont('helvetica', 'bold');
					doc.text('Status:', 15, yPosition);
					doc.setFont('helvetica', 'normal');
					yPosition += 6;

					if (registro.dentroRaioPermitido === true) {
						doc.setTextColor(0, 128, 0);
						doc.setFont('helvetica', 'bold');
						doc.text('  ✓ DENTRO DO RAIO PERMITIDO', 20, yPosition);
						doc.setFont('helvetica', 'normal');
						doc.setTextColor(0, 0, 0);
					} else if (registro.dentroRaioPermitido === false) {
						doc.setTextColor(255, 0, 0);
						doc.setFont('helvetica', 'bold');
						doc.text('  ⚠️ FORA DO RAIO PERMITIDO', 20, yPosition);
						doc.setFont('helvetica', 'normal');
						doc.setTextColor(0, 0, 0);
						yPosition += 6;

						if (
							registro.distanciaEnderecoEsperado !== null &&
							registro.distanciaEnderecoEsperado !== undefined &&
							registro.raioToleranciaUsado !== null &&
							registro.raioToleranciaUsado !== undefined
						) {
							const distanciaExcedente = registro.distanciaEnderecoEsperado - registro.raioToleranciaUsado;
							const distanciaExcedenteKm = (distanciaExcedente / 1000).toFixed(2);
							const distanciaExcedenteMetros = distanciaExcedente.toFixed(0);

							if (distanciaExcedente >= 1000) {
								doc.text(`  ${distanciaExcedenteKm} km além do permitido`, 20, yPosition);
							} else {
								doc.text(`  ${distanciaExcedenteMetros} metros além do permitido`, 20, yPosition);
							}
						}

						yPosition += 6;

						doc.setFont('helvetica', 'normal');
						doc.setTextColor(0, 0, 0);
						doc.setFontSize(9);
						const observacaoLines = doc.splitTextToSize(
							'O registro foi realizado fora da área permitida de marcação de ponto. Verifique se o funcionário possui autorização para trabalho remoto ou deslocamento.',
							170
						);
						doc.text(observacaoLines, 20, yPosition);
						yPosition += observacaoLines.length * 4;
						doc.setFontSize(10);
					} else {
						doc.text('  Não validado', 20, yPosition);
					}

					yPosition += 8;
				} else {
					doc.text('Validação de localização permitida não configurada para este registro.', 15, yPosition);
					yPosition += 8;
				}
			}

			// Dados Técnicos
			// Verificar se precisa de nova página
			if (yPosition > 200) {
				doc.addPage();
				yPosition = 20;
			}

			doc.setFont('helvetica', 'bold');
			doc.text('DADOS TÉCNICOS', 15, yPosition);
			doc.setFont('helvetica', 'normal');

			yPosition += 8;
			doc.setFontSize(10);

			// Informações de Rede
			if (registro.ipAddress || registro.ipPublico || registro.ipLocal) {
				doc.setFont('helvetica', 'bold');
				doc.text('Rede:', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				yPosition += 6;

				if (registro.ipAddress) {
					doc.text(`  IP: ${registro.ipAddress}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.ipPublico) {
					doc.text(`  IP Público: ${registro.ipPublico}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.ipLocal) {
					doc.text(`  IP Local: ${registro.ipLocal}`, 20, yPosition);
					yPosition += 6;
				}

				yPosition += 3;
			}

			// Informações do Navegador
			if (registro.browser || registro.userAgent) {
				doc.setFont('helvetica', 'bold');
				doc.text('Navegador:', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				yPosition += 6;

				if (registro.browser) {
					doc.text(`  Navegador: ${registro.browser}${registro.browserVersion ? ` ${registro.browserVersion}` : ''}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.engine) {
					doc.text(`  Engine: ${registro.engine}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.userAgent) {
					// Quebrar user agent em múltiplas linhas se necessário
					const userAgentLines = doc.splitTextToSize(`  User Agent: ${registro.userAgent}`, 170);
					doc.text(userAgentLines, 20, yPosition);
					yPosition += userAgentLines.length * 6;
				}

				yPosition += 3;
			}

			// Informações do Sistema
			if (registro.sistemaOperacional || registro.arquitetura) {
				doc.setFont('helvetica', 'bold');
				doc.text('Sistema:', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				yPosition += 6;

				if (registro.sistemaOperacional) {
					doc.text(`  SO: ${registro.sistemaOperacional}${registro.osVersion ? ` ${registro.osVersion}` : ''}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.arquitetura) {
					doc.text(`  Arquitetura: ${registro.arquitetura}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.plataforma) {
					doc.text(`  Plataforma: ${registro.plataforma}`, 20, yPosition);
					yPosition += 6;
				}

				yPosition += 3;
			}

			// Informações do Dispositivo
			if (registro.deviceType || registro.screenResolution) {
				doc.setFont('helvetica', 'bold');
				doc.text('Dispositivo:', 15, yPosition);
				doc.setFont('helvetica', 'normal');
				yPosition += 6;

				if (registro.deviceType) {
					doc.text(`  Tipo: ${registro.deviceType}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.deviceModel) {
					doc.text(`  Modelo: ${registro.deviceModel}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.screenResolution) {
					doc.text(`  Resolução: ${registro.screenResolution}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.coresTela) {
					doc.text(`  Cores: ${registro.coresTela}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.isMobile || registro.isTablet || registro.isDesktop) {
					const tipoDispositivo = registro.isMobile ? 'Mobile' : registro.isTablet ? 'Tablet' : 'Desktop';
					doc.text(`  Categoria: ${tipoDispositivo}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.idioma) {
					doc.text(`  Idioma: ${registro.idioma}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.connectionType) {
					doc.text(`  Conexão: ${registro.connectionType}`, 20, yPosition);
					yPosition += 6;
				}

				if (registro.memoryInfo) {
					doc.text(`  Memória: ${registro.memoryInfo}`, 20, yPosition);
					yPosition += 6;
				}

				yPosition += 3;
			}

			// Imagem capturada (se disponível)
			if (registro.imagemUrl) {
				yPosition += 10;
				// Verificar se precisa de nova página
				if (yPosition > 200) {
					doc.addPage();
					yPosition = 20;
				}

				doc.setFont('helvetica', 'bold');
				doc.text('FOTO CAPTURADA', 105, yPosition, { align: 'center' });
				doc.setFont('helvetica', 'normal');
				yPosition += 10;

				try {
					// Carregar imagem usando fetch para evitar problemas de CORS
					const response = await fetch(registro.imagemUrl);
					if (!response.ok) {
						throw new Error('Erro ao carregar imagem');
					}
					
					const blob = await response.blob();
					const reader = new FileReader();
					
					// Converter blob para base64
					const base64 = await new Promise<string>((resolve, reject) => {
						reader.onloadend = () => {
							if (typeof reader.result === 'string') {
								resolve(reader.result);
							} else {
								reject(new Error('Erro ao converter imagem'));
							}
						};
						reader.onerror = () => reject(new Error('Erro ao ler imagem'));
						reader.readAsDataURL(blob);
					});

					// Criar elemento de imagem para obter dimensões
					const img = new Image();
					await new Promise<void>((resolve, reject) => {
						img.onload = () => resolve();
						img.onerror = () => reject(new Error('Erro ao processar imagem'));
						img.src = base64;
						setTimeout(() => reject(new Error('Timeout ao processar imagem')), 10000);
					});

					// Calcular dimensões para caber na página (largura máxima 80mm, manter proporção)
					const maxWidth = 80;
					const maxHeight = 60;
					let imgWidth = img.width;
					let imgHeight = img.height;
					const aspectRatio = imgWidth / imgHeight;

					if (imgWidth > maxWidth || imgHeight > maxHeight) {
						if (aspectRatio > 1) {
							// Imagem horizontal
							imgWidth = maxWidth;
							imgHeight = maxWidth / aspectRatio;
						} else {
							// Imagem vertical
							imgHeight = maxHeight;
							imgWidth = maxHeight * aspectRatio;
						}
					}

					// Centralizar imagem
					const xPosition = (doc.internal.pageSize.getWidth() - imgWidth) / 2;
					
					// Verificar se cabe na página atual
					if (yPosition + imgHeight > doc.internal.pageSize.getHeight() - 20) {
						doc.addPage();
						yPosition = 20;
					}

					// Adicionar imagem ao PDF usando base64
					doc.addImage(base64, 'JPEG', xPosition, yPosition, imgWidth, imgHeight);
					yPosition += imgHeight + 10;
				} catch (error) {
					console.warn('Erro ao adicionar imagem ao PDF:', error);
					doc.setFontSize(10);
					doc.text('Foto não disponível para impressão', 105, yPosition, { align: 'center' });
					yPosition += 6;
				}
			}

			// Rodapé
			const pageCount = doc.getNumberOfPages();
			for (let i = 1; i <= pageCount; i++) {
				doc.setPage(i);
				doc.setFontSize(8);
				doc.setTextColor(128, 128, 128);
				doc.text(
					`SGSE - Sistema de Gerenciamento de Secretaria | Página ${i} de ${pageCount}`,
					doc.internal.pageSize.getWidth() / 2,
					doc.internal.pageSize.getHeight() - 10,
					{ align: 'center' }
				);
			}

			// Salvar
			const nomeArquivo = `detalhes-ponto-${registro.data}-${registro.hora.toString().padStart(2, '0')}${registro.minuto.toString().padStart(2, '0')}.pdf`;
			doc.save(nomeArquivo);
		} catch (error) {
			console.error('Erro ao gerar PDF detalhado:', error);
			alert('Erro ao gerar relatório detalhado. Tente novamente.');
		}
	}
</script>

<div class="container mx-auto px-4 py-6 max-w-7xl">
	<!-- Header -->
	<section class="relative mb-8 overflow-hidden rounded-2xl border border-base-300 bg-gradient-to-br from-primary/10 via-base-100 to-secondary/10 p-8 shadow-lg">
		<div class="bg-primary/20 absolute top-10 -left-10 h-40 w-40 rounded-full blur-3xl"></div>
		<div class="bg-secondary/20 absolute right-0 -bottom-16 h-56 w-56 rounded-full blur-3xl"></div>
		<div class="relative z-10 flex flex-col gap-6 lg:flex-row lg:items-center lg:justify-between">
			<div class="flex items-center gap-4">
				<div class="p-4 bg-primary/20 rounded-2xl backdrop-blur-sm border border-primary/30 shadow-lg">
					<Clock class="h-10 w-10 text-primary" strokeWidth={2.5} />
				</div>
				<div class="max-w-3xl space-y-2">
					<h1 class="text-4xl font-black text-base-content leading-tight sm:text-5xl">
						Registro de Pontos
					</h1>
					<p class="text-base-content/70 text-base leading-relaxed sm:text-lg">
						Gerencie e visualize os registros de ponto dos funcionários com informações detalhadas e relatórios
					</p>
				</div>
			</div>
			{#if estatisticas}
				<div class="border-base-200/60 bg-base-100/70 grid grid-cols-2 gap-4 rounded-2xl border p-6 shadow-lg backdrop-blur sm:max-w-sm">
					<div>
						<p class="text-base-content/60 text-sm font-semibold">Total de Registros</p>
						<p class="text-base-content mt-2 text-2xl font-bold">{estatisticas.totalRegistros}</p>
					</div>
					<div class="text-right">
						<p class="text-base-content/60 text-sm font-semibold">Funcionários</p>
						<p class="text-base-content mt-2 text-xl font-bold">{estatisticas.totalFuncionarios}</p>
					</div>
					<div class="via-base-300 col-span-2 h-px bg-gradient-to-r from-transparent to-transparent"></div>
					<div class="text-base-content/70 col-span-2 flex items-center justify-between text-sm">
						<span>
							{estatisticas.totalRegistros > 0
								? ((estatisticas.dentroDoPrazo / estatisticas.totalRegistros) * 100).toFixed(1)
								: 0}% dentro do prazo
						</span>
						<span class="badge badge-primary badge-sm">Ativo</span>
					</div>
				</div>
			{/if}
		</div>
	</section>

	<!-- Cards de Estatísticas -->
	{#if estatisticas}
		<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
			<!-- Total de Registros -->
			<div class="card bg-gradient-to-br from-blue-500/10 to-blue-600/20 border border-blue-500/20 shadow-xl hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-1">
				<div class="card-body">
					<div class="flex items-center justify-between">
						<div class="flex-1">
							<p class="text-sm text-base-content/70 font-semibold mb-1">Total de Registros</p>
							<p class="text-3xl font-bold text-base-content">{estatisticas.totalRegistros}</p>
						</div>
						<div class="p-3 bg-blue-500/20 rounded-xl">
							<BarChart3 class="h-8 w-8 text-blue-600" strokeWidth={2.5} />
						</div>
					</div>
				</div>
			</div>

			<!-- Dentro do Prazo -->
			<div class="card bg-gradient-to-br from-green-500/10 to-green-600/20 border border-green-500/20 shadow-xl hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-1">
				<div class="card-body">
					<div class="flex items-center justify-between">
						<div class="flex-1">
							<p class="text-sm text-base-content/70 font-semibold mb-1">Dentro do Prazo</p>
							<p class="text-3xl font-bold text-green-600">{estatisticas.dentroDoPrazo}</p>
							<p class="text-xs text-base-content/60 mt-1">
								{estatisticas.totalRegistros > 0
									? ((estatisticas.dentroDoPrazo / estatisticas.totalRegistros) * 100).toFixed(1)
									: 0}% do total
							</p>
						</div>
						<div class="p-3 bg-green-500/20 rounded-xl">
							<CheckCircle2 class="h-8 w-8 text-green-600" strokeWidth={2.5} />
						</div>
					</div>
				</div>
			</div>

			<!-- Fora do Prazo -->
			<div class="card bg-gradient-to-br from-red-500/10 to-red-600/20 border border-red-500/20 shadow-xl hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-1">
				<div class="card-body">
					<div class="flex items-center justify-between">
						<div class="flex-1">
							<p class="text-sm text-base-content/70 font-semibold mb-1">Fora do Prazo</p>
							<p class="text-3xl font-bold text-red-600">{estatisticas.foraDoPrazo}</p>
							<p class="text-xs text-base-content/60 mt-1">
								{estatisticas.totalRegistros > 0
									? ((estatisticas.foraDoPrazo / estatisticas.totalRegistros) * 100).toFixed(1)
									: 0}% do total
							</p>
						</div>
						<div class="p-3 bg-red-500/20 rounded-xl">
							<XCircle class="h-8 w-8 text-red-600" strokeWidth={2.5} />
						</div>
					</div>
				</div>
			</div>

			<!-- Funcionários -->
			<div class="card bg-gradient-to-br from-purple-500/10 to-purple-600/20 border border-purple-500/20 shadow-xl hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-1">
				<div class="card-body">
					<div class="flex items-center justify-between">
						<div class="flex-1">
							<p class="text-sm text-base-content/70 font-semibold mb-1">Funcionários</p>
							<p class="text-3xl font-bold text-purple-600">{estatisticas.totalFuncionarios}</p>
							<p class="text-xs text-base-content/60 mt-1">
								{estatisticas.funcionariosDentroPrazo} dentro, {estatisticas.funcionariosForaPrazo} fora
							</p>
						</div>
						<div class="p-3 bg-purple-500/20 rounded-xl">
							<Users class="h-8 w-8 text-purple-600" strokeWidth={2.5} />
						</div>
					</div>
				</div>
			</div>
		</div>
	{/if}

	<!-- Gráfico de Estatísticas -->
	{#if estatisticas}
		<div class="card bg-base-100/90 backdrop-blur-sm border border-base-300 shadow-xl mb-8">
			<div class="card-body">
				<div class="flex items-center justify-between mb-6">
					<h2 class="card-title text-2xl">
						<div class="p-2 bg-primary/10 rounded-lg">
							<BarChart3 class="h-6 w-6 text-primary" strokeWidth={2.5} />
						</div>
						<span>Visão Geral das Estatísticas</span>
					</h2>
				</div>
				<div class="h-80 w-full relative rounded-xl bg-base-200/50 p-4 border border-base-300">
					<canvas bind:this={chartCanvas} class="w-full h-full"></canvas>
					{#if !chartInstance && estatisticas}
						<div class="absolute inset-0 flex items-center justify-center">
							<span class="loading loading-spinner loading-lg text-primary"></span>
						</div>
					{/if}
				</div>
			</div>
		</div>
	{/if}

	<!-- Filtros -->
	<div class="card bg-base-100/90 backdrop-blur-sm border border-base-300 shadow-xl mb-8">
		<div class="card-body">
			<div class="flex items-center gap-3 mb-6">
				<div class="p-2 bg-secondary/10 rounded-lg">
					<Filter class="h-5 w-5 text-secondary" strokeWidth={2.5} />
				</div>
				<h2 class="card-title text-2xl mb-0">Filtros de Busca</h2>
			</div>
			<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
				<div class="form-control">
					<label class="label" for="data-inicio">
						<span class="label-text font-semibold">Data Início</span>
					</label>
					<input
						id="data-inicio"
						type="date"
						bind:value={dataInicio}
						class="input input-bordered input-primary focus:input-primary focus:ring-2 focus:ring-primary/20"
					/>
				</div>

				<div class="form-control">
					<label class="label" for="data-fim">
						<span class="label-text font-semibold">Data Fim</span>
					</label>
					<input
						id="data-fim"
						type="date"
						bind:value={dataFim}
						class="input input-bordered input-primary focus:input-primary focus:ring-2 focus:ring-primary/20"
					/>
				</div>

				<div class="form-control">
					<label class="label" for="funcionario">
						<span class="label-text font-semibold">Funcionário</span>
					</label>
					<select
						id="funcionario"
						bind:value={funcionarioIdFiltro}
						class="select select-bordered select-primary focus:select-primary focus:ring-2 focus:ring-primary/20"
					>
						<option value="">Todos os funcionários</option>
						{#each funcionarios as funcionario}
							<option value={funcionario._id}>{funcionario.nome}</option>
						{/each}
					</select>
				</div>
			</div>
		</div>
	</div>

	<!-- Lista de Registros -->
	<div class="card bg-base-100/90 backdrop-blur-sm border border-base-300 shadow-xl">
		<div class="card-body">
			<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-6">
				<div class="flex items-center gap-3">
					<div class="p-2 bg-primary/10 rounded-lg">
						<Clock class="h-6 w-6 text-primary" strokeWidth={2.5} />
					</div>
					<h2 class="card-title text-2xl mb-0">Registros de Ponto</h2>
				</div>
				
				<!-- Exibição dos Filtros Selecionados -->
				{#if funcionarioIdFiltro || dataInicio || dataFim}
					<div class="flex items-center gap-2 flex-wrap">
						{#if funcionarioIdFiltro && funcionarioSelecionadoNome}
							<div class="badge badge-primary badge-lg gap-2 px-4 py-3">
								<Users class="h-4 w-4" />
								{funcionarioSelecionadoNome}
							</div>
						{/if}
						{#if dataInicio}
							<div class="badge badge-info badge-lg gap-2 px-4 py-3">
								<Clock class="h-4 w-4" />
								De: {formatarData(dataInicio)}
							</div>
						{/if}
						{#if dataFim}
							<div class="badge badge-info badge-lg gap-2 px-4 py-3">
								<Clock class="h-4 w-4" />
								Até: {formatarData(dataFim)}
							</div>
						{/if}
					</div>
				{/if}
			</div>

			{#if registrosQuery?.status === 'Loading'}
				<div class="flex flex-col items-center justify-center py-16 bg-base-200/50 rounded-xl border border-base-300">
					<span class="loading loading-spinner loading-lg text-primary mb-4"></span>
					<span class="text-base-content/70 font-medium">Carregando registros...</span>
					<span class="text-sm text-base-content/50 mt-2">Aguarde um momento</span>
				</div>
			{:else if registrosQuery?.error}
				<div class="alert alert-error shadow-lg border-2 border-error/50">
					<XCircle class="h-6 w-6" />
					<div>
						<h3 class="font-bold">Erro ao carregar registros</h3>
						<div class="text-sm mt-1">{registrosQuery.error.message || 'Erro desconhecido'}</div>
					</div>
				</div>
			{:else if !registrosQuery?.data}
				<div class="alert alert-warning shadow-lg border-2 border-warning/50">
					<Clock class="h-6 w-6" />
					<span class="font-medium">Aguardando dados da consulta...</span>
				</div>
			{:else if registros.length === 0}
				<div class="alert alert-info shadow-lg border-2 border-info/50 rounded-xl bg-gradient-to-r from-info/10 to-info/5">
					<FileText class="h-6 w-6 text-info" />
					<div class="flex-1">
						<h3 class="font-bold text-base-content">Nenhum registro encontrado</h3>
						<div class="text-sm mt-2 opacity-80">
							<p>Período: <span class="font-semibold">{formatarData(dataInicio)} até {formatarData(dataFim)}</span></p>
							{#if funcionarioIdFiltro && funcionarioSelecionadoNome}
								<p class="mt-1">Funcionário: <span class="font-semibold">{funcionarioSelecionadoNome}</span></p>
							{/if}
							<p class="mt-2 text-base-content/60">Tente ajustar os filtros para encontrar registros.</p>
						</div>
					</div>
				</div>
			{:else if registrosAgrupados.length === 0}
				<div class="alert alert-warning shadow-lg border-2 border-warning/50 rounded-xl bg-gradient-to-r from-warning/10 to-warning/5">
					<FileText class="h-6 w-6 text-warning" />
					<div class="flex-1">
						<h3 class="font-bold">Registros encontrados, mas não foi possível agrupá-los</h3>
						<div class="text-sm mt-2 opacity-80">
							Total de registros: <span class="font-semibold">{registros.length}</span>
						</div>
					</div>
				</div>
			{:else}
				<div class="space-y-6">
					{#each registrosAgrupados as grupo}
						<div class="card bg-gradient-to-br from-base-100 to-base-200/50 border border-base-300 shadow-lg hover:shadow-xl transition-all duration-300">
							<div class="card-body p-6">
								<div class="flex flex-col lg:flex-row items-start lg:items-center justify-between gap-4 mb-6">
									<div class="flex-1">
										<div class="flex items-center gap-3 mb-2">
											<div class="p-2 bg-primary/10 rounded-lg">
												<Users class="h-5 w-5 text-primary" strokeWidth={2.5} />
											</div>
											<h3 class="font-bold text-xl text-base-content">
												{grupo.funcionario?.nome || 'Funcionário não encontrado'}
											</h3>
										</div>
										{#if grupo.funcionario?.matricula}
											<p class="text-sm text-base-content/70 ml-11">
												Matrícula: <span class="font-semibold">{grupo.funcionario.matricula}</span>
											</p>
										{/if}
										{#if grupo.funcionario?.descricaoCargo}
											<p class="text-sm text-base-content/60 ml-11">
												{grupo.funcionario.descricaoCargo}
											</p>
										{/if}
									</div>
									
									<div class="flex items-center gap-3 flex-wrap">
										<!-- Banco de Horas -->
										{#key grupo.funcionarioId}
											{@const bancoHorasQuery = useQuery(
												api.pontos.obterBancoHorasFuncionario,
												{ funcionarioId: grupo.funcionarioId }
											)}
											{@const bancoHoras = bancoHorasQuery?.data}
											{@const saldoAcumulado = bancoHoras?.saldoAcumuladoMinutos ?? 0}
											{@const saldoPositivo = saldoAcumulado >= 0}
											
											{#if bancoHoras}
												<div class="rounded-xl border-2 p-4 shadow-md transition-all hover:scale-105 {saldoPositivo ? 'border-success/50 bg-gradient-to-br from-success/10 to-success/5' : 'border-error/50 bg-gradient-to-br from-error/10 to-error/5'}">
													<div class="flex items-center gap-3">
														<div class="p-2 {saldoPositivo ? 'bg-success/20' : 'bg-error/20'} rounded-lg">
															{#if saldoPositivo}
																<TrendingUp class="h-5 w-5 text-success" strokeWidth={2.5} />
															{:else}
																<TrendingDown class="h-5 w-5 text-error" strokeWidth={2.5} />
															{/if}
														</div>
														<div>
															<p class="text-xs font-semibold opacity-70 mb-1">Banco de Horas</p>
															<p class="text-xl font-bold {saldoPositivo ? 'text-success' : 'text-error'}">
																{formatarSaldoHoras(saldoAcumulado)}
															</p>
														</div>
													</div>
												</div>
											{/if}
										{/key}
										
										<button
											class="btn btn-primary gap-2 shadow-md hover:shadow-lg transition-all"
											onclick={() => abrirModalImpressao(grupo.funcionarioId)}
										>
											<Printer class="h-4 w-4" />
											Imprimir Ficha
										</button>
									</div>
								</div>

								<div class="overflow-x-auto max-h-[600px] overflow-y-auto border border-base-300 rounded-xl shadow-inner bg-base-100/50">
									<table class="table table-zebra">
										<thead class="sticky top-0 z-10 shadow-md bg-gradient-to-r from-base-300 to-base-200">
											<tr>
												<th class="whitespace-nowrap font-bold text-base-content border-b border-base-400">Data</th>
												<th class="whitespace-nowrap font-bold text-base-content border-b border-base-400">Tipo</th>
												<th class="whitespace-nowrap font-bold text-base-content border-b border-base-400">Horário</th>
												<th class="whitespace-nowrap font-bold text-base-content border-b border-base-400">Saldo Diário</th>
												<th class="whitespace-nowrap font-bold text-base-content border-b border-base-400">Status</th>
												<th class="whitespace-nowrap font-bold text-base-content border-b border-base-400">Ações</th>
											</tr>
										</thead>
										<tbody>
											{#each Object.values(grupo.registrosPorData) as grupoData}
												{@const totalRegistros = grupoData.registros.length}
												{@const dataParts = grupoData.data.split('-')}
												{@const dataFormatada = `${dataParts[2]}/${dataParts[1]}/${dataParts[0]}`}
												{#each grupoData.registros as registro, index}
													<tr>
														<td class="whitespace-nowrap">{dataFormatada}</td>
														<td class="whitespace-nowrap">
															{config
																? getTipoRegistroLabel(registro.tipo, {
																		nomeEntrada: config.nomeEntrada,
																		nomeSaidaAlmoco: config.nomeSaidaAlmoco,
																		nomeRetornoAlmoco: config.nomeRetornoAlmoco,
																		nomeSaida: config.nomeSaida,
																	})
																: getTipoRegistroLabel(registro.tipo)}
														</td>
														<td class="whitespace-nowrap">{formatarHoraPonto(registro.hora, registro.minuto)}</td>
														{#if index === 0}
															<td class="whitespace-nowrap" rowspan={totalRegistros}>
																{#if grupoData.saldoDiario}
																	<span
																		class="badge badge-lg font-semibold {grupoData.saldoDiario.positivo ? 'badge-success shadow-sm' : 'badge-error shadow-sm'}"
																	>
																		{formatarSaldoDiario(grupoData.saldoDiario)}
																	</span>
																{:else}
																	<span class="badge badge-ghost badge-lg">-</span>
																{/if}
															</td>
														{/if}
														<td class="whitespace-nowrap">
															<span
																class="badge badge-lg font-semibold {registro.dentroDoPrazo ? 'badge-success shadow-sm' : 'badge-error shadow-sm'}"
															>
																{registro.dentroDoPrazo ? '✓ Dentro do Prazo' : '✗ Fora do Prazo'}
															</span>
														</td>
														<td class="whitespace-nowrap">
															<button
																class="btn btn-sm btn-outline btn-primary gap-2 hover:btn-primary hover:shadow-md transition-all"
																onclick={() => imprimirDetalhesRegistro(registro._id)}
																title="Imprimir Detalhes"
															>
																<FileText class="h-4 w-4" />
																Detalhes
															</button>
														</td>
													</tr>
												{/each}
											{/each}
										</tbody>
									</table>
								</div>
							</div>
						</div>
					{/each}
				</div>
			{/if}
		</div>
	</div>
</div>

{#if mostrarModalImpressao && funcionarioParaImprimir}
	<PrintPontoModal
		funcionarioId={funcionarioParaImprimir}
		onClose={() => {
			mostrarModalImpressao = false;
			funcionarioParaImprimir = '';
		}}
		onGenerate={gerarPDFComSelecao}
	/>
{/if}

