'use client'; import { useState } from 'react'; import { useSearchParams } from 'next/navigation'; import { useQuery } from '@tanstack/react-query'; import { DashboardShell } from '@/components/layouts/dashboard-shell'; import { Card, CardContent, Button, SortableHeader, cn } from '@horux/shared-ui'; import { apiClient } from '@/lib/api/client'; import { useContribuyenteStore } from '@/stores/contribuyente-store'; import { formatCurrency, toCfdiDate } from '@/lib/utils'; import { exportToExcel } from '@/lib/export-excel'; import { useTableSort } from '@horux/shared-ui'; import { CfdiViewerModal } from '@/components/cfdi/cfdi-viewer-modal'; import { getCfdiById } from '@/lib/api/cfdi'; import { Eye, Download } from 'lucide-react'; import type { Cfdi } from '@horux/shared'; const EXCEL_COLUMNS = [ { header: 'UUID', key: 'uuid', width: 40 }, { header: 'Comprobante', key: 'tipoComprobante', width: 12 }, { header: 'Fecha Emision', key: '_fecha', width: 15 }, { header: 'RFC Emisor', key: 'rfcEmisor', width: 15 }, { header: 'Nombre Emisor', key: 'nombreEmisor', width: 30 }, { header: 'RFC Receptor', key: 'rfcReceptor', width: 15 }, { header: 'Nombre Receptor', key: 'nombreReceptor', width: 30 }, { header: 'Total MXN', key: '_totalMxn', width: 15 }, { header: 'Monto Pago MXN', key: '_montoPagoMxn', width: 15 }, { header: 'IVA Trasladado MXN', key: '_ivaMxn', width: 18 }, { header: 'Metodo Pago', key: 'metodoPago', width: 12 }, { header: 'Regimen Emisor', key: 'regimenEmisor', width: 15 }, { header: 'Regimen Receptor', key: 'regimenReceptor', width: 15 }, ]; function prepareRows(data: any[]) { return data.map((c) => ({ ...c, _fecha: toCfdiDate(c.fechaEmision).toLocaleDateString('es-MX'), _totalMxn: Number(c.totalMxn || 0), _montoPagoMxn: Number(c.montoPagoMxn || 0), _ivaMxn: Number(c.ivaTrasladoMxn || 0), })); } export default function DrillDownPage() { const searchParams = useSearchParams(); const titulo = searchParams.get('titulo') || 'Detalle de CFDIs'; const [selectedCfdi, setSelectedCfdi] = useState(null); const [loadingCfdiId, setLoadingCfdiId] = useState(null); const { selectedContribuyenteId } = useContribuyenteStore(); const params = new URLSearchParams(); for (const [key, value] of searchParams.entries()) { if (key !== 'titulo') params.set(key, value); } // Respetar contribuyente seleccionado globalmente — así cualquier drillUrl // construido desde dashboard/impuestos/etc queda automáticamente filtrado // sin tener que acordarse de pasarlo en cada call-site. El URLSearchParams // de entrada gana si el caller sí lo pasó explícitamente. if (selectedContribuyenteId && !params.has('contribuyenteId')) { params.set('contribuyenteId', selectedContribuyenteId); } const { data, isLoading } = useQuery({ queryKey: ['drill-down', params.toString()], queryFn: async () => { const res = await apiClient.get(`/cfdi/drill-down?${params}`); return res.data; }, }); const { sortedData, toggleSort, getSortIndicator } = useTableSort( data, { fecha: (c) => toCfdiDate(c.fechaEmision).getTime(), total: (c) => Number(c.totalMxn || 0), pago: (c) => Number(c.montoPagoMxn || 0), iva: (c) => Number(c.ivaTrasladoMxn || 0), }, 'fecha', ); // Total con signo: tipo E resta (es una nota de crédito que reduce el bucket). // Tipo I/N suman total_mxn; tipo P suma monto_pago_mxn (su total es 0 por convención // del complemento). Así el total del header coincide con los KPIs del dashboard. const totalMxn = data?.reduce((s, r) => { const sign = r.tipoComprobante === 'E' ? -1 : 1; const amount = r.tipoComprobante === 'P' ? Number(r.montoPagoMxn || 0) : Number(r.totalMxn || 0); return s + sign * amount; }, 0) || 0; const totalPagos = data?.reduce((s, r) => s + Number(r.montoPagoMxn || 0), 0) || 0; const handleExport = () => { if (!sortedData || sortedData.length === 0) return; exportToExcel(prepareRows(sortedData), EXCEL_COLUMNS, 'drill-down-cfdis'); }; return ( {isLoading ? (
Cargando...
) : !data || data.length === 0 ? (
No hay CFDIs que coincidan con los filtros
) : ( <>

{data.length} CFDIs encontrados

Total MXN: {formatCurrency(totalMxn)} {totalPagos > 0 && Pagos MXN: {formatCurrency(totalPagos)}}
toggleSort('fecha')} /> toggleSort('total')} /> toggleSort('pago')} /> toggleSort('iva')} /> {(sortedData || []).map((cfdi: any) => { const isNC = cfdi.tipoComprobante === 'E'; return ( ); })}
UUID Comp. RFC Emisor Nombre Emisor RFC Receptor Nombre Receptor M. Pago Reg. E Reg. R
{cfdi.uuid?.substring(0, 8)} {cfdi.tipoComprobante} {toCfdiDate(cfdi.fechaEmision).toLocaleDateString('es-MX')} {cfdi.rfcEmisor} {cfdi.nombreEmisor} {cfdi.rfcReceptor} {cfdi.nombreReceptor} {isNC ? '−' : ''}{formatCurrency(Number(cfdi.totalMxn))} {cfdi.tipoComprobante === 'P' && cfdi.montoPagoMxn ? formatCurrency(Number(cfdi.montoPagoMxn)) : '-'} {cfdi.ivaTrasladoMxn ? formatCurrency(Number(cfdi.ivaTrasladoMxn)) : '-'} {cfdi.metodoPago || '-'} {cfdi.regimenEmisor || '-'} {cfdi.regimenReceptor || '-'}
)}
setSelectedCfdi(null)} />
); }