'use client';

import { useState } from 'react';
import {
    BookOpen, AlertCircle, CalendarDays, Wrench, FileText,
    Building2, BarChart, ChevronRight, CheckCircle2, Info, Clock
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';

const MOCK_CHAPTERS = [
    { id: 'inicio', icon: BookOpen, title: 'Introducción' },
    { id: 'avisos', icon: AlertCircle, title: '1. Gestión de Avisos' },
    { id: 'agenda', icon: CalendarDays, title: '2. Agenda y Planificación' },
    { id: 'partes', icon: Wrench, title: '3. Partes de Trabajo' },
    { id: 'presupuestos', icon: FileText, title: '4. Área Comercial' },
    { id: 'clientes', icon: Building2, title: '5. Clientes y Contratos' },
    { id: 'estadisticas', icon: BarChart, title: '6. Estadísticas Avanzadas' },
    { id: 'fichaje', icon: Clock, title: '7. Control Horario y Ausencias' },
];

export default function ManualClient() {
    const [activeChapter, setActiveChapter] = useState('inicio');

    const renderContent = () => {
        switch (activeChapter) {
            case 'inicio': return <IntroSection />;
            case 'avisos': return <AvisosSection />;
            case 'agenda': return <AgendaSection />;
            case 'partes': return <PartesSection />;
            case 'presupuestos': return <PresupuestosSection />;
            case 'clientes': return <ClientesSection />;
            case 'estadisticas': return <EstadisticasSection />;
            case 'fichaje': return <FichajeSection />;
            default: return <IntroSection />;
        }
    };

    return (
        <div className="flex flex-col lg:flex-row gap-6 min-h-[calc(100vh-6rem)] pb-10">
            {/* Sidebar de Navegación del Manual */}
            <div className="w-full lg:w-72 flex-shrink-0">
                <div className="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden sticky top-24">
                    <div className="p-4 border-b border-gray-100 bg-gray-50/50">
                        <h2 className="font-bold text-gray-900 flex items-center gap-2">
                            <BookOpen className="w-5 h-5 text-blue-600" />
                            Índice Temático
                        </h2>
                    </div>
                    <nav className="p-2 space-y-1">
                        {MOCK_CHAPTERS.map(chapter => {
                            const Icon = chapter.icon;
                            const isActive = activeChapter === chapter.id;
                            return (
                                <button
                                    key={chapter.id}
                                    onClick={() => setActiveChapter(chapter.id)}
                                    className={`w-full flex items-center justify-between px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200 ${isActive
                                        ? 'bg-blue-50 text-blue-700'
                                        : 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'
                                        }`}
                                >
                                    <div className="flex items-center gap-3">
                                        <Icon className={`w-4 h-4 ${isActive ? 'text-blue-600' : 'text-gray-400'}`} />
                                        {chapter.title}
                                    </div>
                                    {isActive && <ChevronRight className="w-4 h-4 text-blue-600" />}
                                </button>
                            );
                        })}
                    </nav>
                </div>
            </div>

            {/* Área de Contenido Principal */}
            <div className="flex-1 bg-white rounded-2xl shadow-sm border border-gray-200 p-6 lg:p-10 relative overflow-hidden">
                <AnimatePresence mode="wait">
                    <motion.div
                        key={activeChapter}
                        initial={{ opacity: 0, y: 10 }}
                        animate={{ opacity: 1, y: 0 }}
                        exit={{ opacity: 0, y: -10 }}
                        transition={{ duration: 0.2 }}
                        className="prose prose-blue max-w-none"
                    >
                        {renderContent()}
                    </motion.div>
                </AnimatePresence>
            </div>
        </div>
    );
}

// ------ COMPONENTES DE SECCIONES ------

function IntroSection() {
    return (
        <div className="space-y-6">
            <h1 className="text-3xl font-bold text-gray-900 mb-2">Bienvenido a ClimaSan Docs</h1>
            <p className="text-gray-600 text-lg leading-relaxed">
                Este es el manual avanzado de operaciones del ERP <strong>ClimaSan</strong>. A diferencia de una guía básica, este documento detalla las <strong>reglas de negocio internas</strong>, las automatizaciones silenciosas y la lógica de fondo que gobierna cada módulo que hemos desarrollado a medida para ti.
            </p>
            <div className="bg-blue-50 border border-blue-100 p-5 rounded-xl flex gap-4 mt-8">
                <Info className="w-6 h-6 text-blue-600 flex-shrink-0" />
                <div>
                    <h3 className="text-blue-900 font-bold mb-1">Arquitectura de la Información</h3>
                    <p className="text-blue-800 text-sm">
                        El sistema está diseñado de forma modular pero interconectada. Lo que empieza como un simple "Aviso" telefónico, fluye automáticamente hacia la "Agenda" del operario, se materializa en un "Parte de Trabajo" físico, puede transformarse en un "Presupuesto" formal en PDF, y termina impactando en las gráficas globales de "Business Intelligence". Entender este flujo es vital para dominar la plataforma.
                    </p>
                </div>
            </div>
        </div>
    );
}

function AvisosSection() {
    return (
        <div className="space-y-6">
            <div className="flex items-center gap-3 border-b border-gray-100 pb-4 mb-6">
                <div className="p-3 bg-red-100 text-red-600 rounded-xl"><AlertCircle className="w-6 h-6" /></div>
                <h1 className="text-2xl font-bold text-gray-900 m-0">Gestión de Avisos (Incidencias)</h1>
            </div>

            <p className="text-gray-700 leading-relaxed text-sm">
                El <strong>Aviso</strong> es la entidad raíz ("Punto Cero"). Representa el contacto inicial del cliente reportando una avería. Su objetivo no es contener detalles técnicos profundos, sino capturar el problema rápidamente para su posterior delegación.
            </p>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">Lógica de Estados y Transiciones</h3>
            <p className="text-gray-700 text-sm mb-4">
                Los avisos no se borran; mutan de estado para mantener un registro histórico perfecto en la base de datos de Prisma:
            </p>
            <ul className="space-y-4 text-gray-700 text-sm">
                <li className="flex gap-3 bg-gray-50 p-3 rounded-lg border border-gray-100">
                    <CheckCircle2 className="w-5 h-5 text-amber-500 flex-shrink-0 mt-0.5" />
                    <div>
                        <strong className="text-gray-900 block mb-1">PENDIENTE (Estado Inicial)</strong>
                        Aplica en el momento exacto en que administración guarda el aviso. Implica que la información está en el sistema pero <strong>ningún técnico ha sido movilizado</strong>. En este estado, el aviso resalta visualmente para exigir atención.
                    </div>
                </li>
                <li className="flex gap-3 bg-gray-50 p-3 rounded-lg border border-gray-100">
                    <CheckCircle2 className="w-5 h-5 text-blue-500 flex-shrink-0 mt-0.5" />
                    <div>
                        <strong className="text-gray-900 block mb-1">EN PROCESO (Estado Transitorio)</strong>
                        Se activa manualmente cuando un técnico ya ha realizado una primera visita (generando un Parte de Trabajo) pero <strong>el problema no está resuelto</strong>. Generalmente indica que se está a la espera de recibir piezas de repuesto, aprobación de un presupuesto, o coordinación de andamios/grúas. Mantiene la alerta activa en el panel sin saturar la bandeja de urgencias.
                    </div>
                </li>
                <li className="flex gap-3 bg-gray-50 p-3 rounded-lg border border-gray-100">
                    <CheckCircle2 className="w-5 h-5 text-emerald-500 flex-shrink-0 mt-0.5" />
                    <div>
                        <strong className="text-gray-900 block mb-1">CERRADO (Estado Terminal)</strong>
                        El trabajo técnico ha concluido satisfactoriamente y el cliente ha firmado el parte. Al pasar a este estado, el aviso se oculta de las vistas operativas diarias para limpiar el estrés visual, pero vivirá para siempre en la ficha del Cliente y sumará a la métrica de "Avisos Solucionados" del técnico en la ventana de Estadísticas.
                    </div>
                </li>
            </ul>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-3">Motor de Filtrado Automático (30 Días)</h3>
            <p className="text-gray-700 text-sm leading-relaxed">
                Por desarrollo a nivel de Servidor, la carga inicial de la pantalla de Avisos aplica un <strong>Filtro de Rendimiento</strong>. La consulta a la base de datos restringe la búsqueda usando `gte` (Greater Than or Equal) sobre los últimos 30 días naturales a partir de las `00:00:00`. <br />
                <em>¿Por qué?</em> Si en 3 años tienes 15,000 avisos, descargar todos a la vez congelaría el navegador de la administración. Esto asegura que la APP cargue en milisegundos. Para consultar historiales, usa el Selector de Fechas.
            </p>
        </div>
    );
}

function AgendaSection() {
    return (
        <div className="space-y-6">
            <div className="flex items-center gap-3 border-b border-gray-100 pb-4 mb-6">
                <div className="p-3 bg-indigo-100 text-indigo-600 rounded-xl"><CalendarDays className="w-6 h-6" /></div>
                <h1 className="text-2xl font-bold text-gray-900 m-0">Agenda Multidimensional</h1>
            </div>

            <p className="text-gray-700 leading-relaxed text-sm">
                La Agenda no es solo un calendario pasivo; es un <strong>motor de asignación de recursos</strong>. Controla la tabla `EventoAgenda` y se encarga de resolver choques de horarios y diferenciar las prioridades.
            </p>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">Taxonomía de Eventos</h3>
            <p className="text-gray-700 text-sm mb-4">
                A nivel de programación, existen 3 tipos fijos de intervenciones, cada una con un impacto visual distinto para que el coordinador no deba leer el texto para entender la prioridad:
            </p>
            <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
                <div className="border border-gray-200 bg-red-50/30 rounded-xl p-4 shadow-sm border-t-4 border-t-red-500">
                    <h4 className="font-bold text-sm text-gray-900 flex items-center gap-2"><AlertCircle className="w-4 h-4 text-red-500" /> VINCULADO A AVISO</h4>
                    <p className="text-xs text-gray-600 mt-2">
                        Alta prioridad (Averías). Solo se pueden crear si previamente existe un ID de Aviso registrado. Tienen trazabilidad directa de vuelta al origen del problema.
                    </p>
                </div>
                <div className="border border-gray-200 bg-blue-50/30 rounded-xl p-4 shadow-sm border-t-4 border-t-blue-500">
                    <h4 className="font-bold text-sm text-gray-900 flex items-center gap-2"><Building2 className="w-4 h-4 text-blue-500" /> MANTENIMIENTO</h4>
                    <p className="text-xs text-gray-600 mt-2">
                        Trabajo preventivo (Revisiones). Creados en lote por el algoritmo de periodicidad. Permiten organizar las rutas de las furgonetas con semanas de antelación.
                    </p>
                </div>
                <div className="border border-gray-200 bg-gray-50/50 rounded-xl p-4 shadow-sm border-t-4 border-t-gray-500">
                    <h4 className="font-bold text-sm text-gray-900 flex items-center gap-2"><Wrench className="w-4 h-4 text-gray-500" /> TAREA INTERNA</h4>
                    <p className="text-xs text-gray-600 mt-2">
                        Reservas de tiempo cajón de sastre (Inventario en Nave, Recogida de Repuestos, Descansos médicos). Bloquean a un técnico para que no se le asigne trabajo externo.
                    </p>
                </div>
            </div>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-3">Motor de Recalculado en Cascada (Reprogramación Inteligente)</h3>
            <p className="text-gray-700 text-sm leading-relaxed mb-4">
                El sistema ya no arroja "errores de solapamiento" que bloqueen la gestión. Se ha creado un algoritmo de reajuste automático que detecta el <strong>Efecto Dominó</strong>:
            </p>
            <ul className="list-disc pl-5 space-y-3 text-gray-600 text-sm">
                <li><strong>Cascada por Empuje (Hacia el futuro):</strong> Si la visita a las 10:00 se complica y la alargas hasta las 12:00, las dos citas de la tarde <strong>no se borrarán</strong>, sino que serán arrastradas hacia adelante respetando los tiempos de conducción configurados.</li>
                <li><strong>Compactación (Hacia el presente):</strong> Si re-asignas, acortas o borras una cita de un trabajador, vas a dejarle un agujero o un descanso inútil. El sistema entonces "tirará" hacia arriba de todas sus reservas de la tarde y compactará el día.</li>
                <li><strong>Citas Fijas (Inamovibles) 📌:</strong> Para frenar este empuje elástico, al editar una cita puedes activar el marcador de "Cita Inamovible". Tanto el algoritmo de Empuje como el de Compactación rodearán esta franja horaria respetando el pacto cerrado con el cliente impidiendo que se mueva autónomamente.</li>
                <li><strong>Tope de Jornada Laboral (20:00):</strong> Si un efecto dominó aplasta las citas contra el fin de la tarde y superan la frontera de las 20:00, el sistema corta radicalmente: <strong>desasigna al operario</strong> y devuelve la cita caída a la lista de "Avisos Pendientes de programar", avisándote en color rojo.</li>
            </ul>
        </div>
    );
}

function PartesSection() {
    return (
        <div className="space-y-6">
            <div className="flex items-center gap-3 border-b border-gray-100 pb-4 mb-6">
                <div className="p-3 bg-amber-100 text-amber-600 rounded-xl"><Wrench className="w-6 h-6" /></div>
                <h1 className="text-2xl font-bold text-gray-900 m-0">Partes de Trabajo (El taller)</h1>
            </div>

            <p className="text-gray-700 leading-relaxed text-sm">
                El <strong>Parte de Trabajo</strong> es el documento con valor legal y económico fundamental del ERP. Detalla los operarios implicados, materiales utilizados, horas invertidas y funciona como albarán para facturación.
            </p>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">Arquitectura Local de Archivos Adjuntos (Local Storage)</h3>
            <p className="text-gray-700 text-sm mb-4">
                Petición de Desarrollo: Se eliminó Amazon S3 (AWS) del proyecto para evitar dependencias, costes recurrentes y problemas de firmas criptográficas.
            </p>
            <div className="bg-gray-800 text-gray-300 p-5 rounded-xl text-sm font-mono leading-relaxed mb-6">
                // Funcionamiento del Upload Server-Side <br />
                1. El navegador del operario recolecta las Fotos (.jpg, .png) o PDFs y crea un `FormData` múltiple. <br />
                2. Un `POST` masivo envía los datos a la ruta `/api/partes/[id]/adjuntos`. <br />
                3. Node.js transforma cada archivo recibido en un `Buffer` binario en memoria RAM. <br />
                4. Node.js verifica que exista la carpeta `/public/uploads/partes/` ejecutando un comando de sistema operativo (`fs.mkdir`). Si no, la crea silenciosamente. <br />
                5. Finalmente, usa `fs.writeFile` para volcar permanentemente la memoria al Disco Duro del Servidor. <br />
                6. Se inyecta la URL relativa en la Base de Datos Prisma (`/uploads/partes/filename.jpg`) para su rápida recuperación por HTTP.
            </div>
            <p className="text-gray-700 text-sm">
                <strong>¿La ventaja?</strong> Todo queda en "casa". La velocidad de carga de fotos al abrir un parte es casi instantánea en red local y estás libre de políticas de datos corporativas ajenas. Al borrar un Parte, el sistema hace limpieza profunda e invoca `fs.unlink` para evitar el almacenamiento de archivos "huérfanos".
            </p>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">El Switch "Facturable" y el Motor de Estadísticas</h3>
            <p className="text-gray-700 text-sm">
                El campo <strong>Importe Estimado / Coste</strong> no es solo texto. Existe una regla de negocio programada en el módulo de Business Intelligence: <br /><br />
                El sistema de Estadísticas ejecuta un `groupBy` en la base de datos sumando todos los euros de los Partes, <strong>PERO</strong> solo si se cumplen dos condiciones booleanas estrictas de forma simultánea: <code className="bg-gray-100 px-2 py-0.5 rounded text-blue-800">parte.facturable === true</code> y <code className="bg-gray-100 px-2 py-0.5 rounded text-emerald-800">parte.estado === FINALIZADO</code>.<br /><br />
                Si un técnico invirtió horas pero el parte está en garantía (No Facturable), esos euros quedarán a 0 en el computo de facturación de la empresa para que las cuentas de la analítica sean siempre reales.
            </p>
        </div>
    );
}

function PresupuestosSection() {
    return (
        <div className="space-y-6">
            <div className="flex items-center gap-3 border-b border-gray-100 pb-4 mb-6">
                <div className="p-3 bg-emerald-100 text-emerald-600 rounded-xl"><FileText className="w-6 h-6" /></div>
                <h1 className="text-2xl font-bold text-gray-900 m-0">El Ecosistema Comercial (Presupuestos, PDFs y Email)</h1>
            </div>

            <p className="text-gray-700 leading-relaxed text-sm">
                El módulo Comercial transforma meros textos informáticos en Documentos Corporativos formales y comunicaciones automáticas al cliente, convirtiendo el ERP en un verdadero CRM de ventas.
            </p>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">Motor de Generación de Documentos (PDF y DOCX)</h3>
            <p className="text-gray-700 text-sm mb-4">
                El sistema de renderizado no usa herramientas frágiles que intentan transformar el HTML superficial de la web a PDF. Se han programado dos motores 100% nativos e invisibles en el Backend:
            </p>
            <ul className="list-disc pl-5 mt-2 space-y-3 text-gray-600 text-sm">
                <li><strong>Motor PDF (`pdfmake` con Virtual File System):</strong> El diseño del lienzo (Cabecera, logotipo base64, columnas fiscales, tabla de importes desglosados y cajetines de firma oficial) está definido vectorialmente en Javascript. <i>Para solucionar fallos de tipografías (`ENOENT`) en Next.js, hemos empaquetado toda la familia de fuentes "Roboto" en código base64 e inyectado en el PDF para garantizar el renderizado sin importar el servidor donde alojes la App.</i></li>
                <li><strong>Motor Word (`docx`):</strong> Utilizado por el botón "Descargar Word". Genera internamente XMLs de Microsoft Office puros, creando párrafos nativos y tablas nativas, no texto plano. Permitiendo que administración altere cláusulas extrañas fácilmente antes de entregarlo.</li>
                <li><strong>Sistema de Empaquetado de Ficheros (Filenames):</strong> A través de la API, se inyectan Cabeceras HTTP `Content-Disposition`. Esto fuerza al navegador a bajarse el documento con variables automáticas usando `date-fns` para garantizar que la descarga siempre ofrezca un nombre limpio: <code>20261108_Presupuesto_005.pdf</code> en lugar del clásico <code>download(1).pdf</code>.</li>
            </ul>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">La Arquitectura Fantasma: Prospectos / No-Clientes</h3>
            <p className="text-gray-700 text-sm mb-4">
                <strong>¿Por qué crear presupuestos para desconocidos?</strong> En el mundo real, llegan peticiones de precio rápido de alguien por teléfono que quizá no vuelva jamás. Obligar a administración a ir a la pestaña "Clientes - Nuevo" antes de poder darle un presupuesto destruye la productividad.
            </p>
            <div className="bg-emerald-50 border border-emerald-200 p-5 rounded-xl text-sm text-gray-700 leading-relaxed">
                <strong>Solución Implementada: Campo Nombre Flexible.</strong><br />
                El campo de Cliente en el Modal de 'Nuevo Presupuesto' acepta que escribas texto plano (ej. "Comunidad de Vecinos Portal 1"). Al guardarse, Prisma almacena el ID del cliente como `null`, pero almacena el string "Comunidad de Vecinos Portal 1" en un sub-campo `nombreProspecto`.<br /><br />

                <i>¿Qué pasa al intentar mandar esto por email Automático?</i><br />
                La API intercepta la orden de envío y analiza: <code>if (!presupuesto.clienteId)</code>. Al resultar verdadero, sabemos que la base de datos no tiene un archivo de este señor. En ese instante, Next.js cancela temporalmente el envío de correos estandar, abre un modal `Prompt` en pantalla indicando: <strong>"Este individuo es un prospecto. Dame el correo manualmente, por favor"</strong>. Al introducirlo en el Prompt, NodeJS reanuda la acción, compila el PDF en RAM, y dispara (mediante Nodemailer HTTP Auth) un correo profesional al destinatario sin haber contaminado tu base de datos de Clientes estables.
            </div>
        </div>
    );
}

function ClientesSection() {
    return (
        <div className="space-y-6">
            <div className="flex items-center gap-3 border-b border-gray-100 pb-4 mb-6">
                <div className="p-3 bg-purple-100 text-purple-600 rounded-xl"><Building2 className="w-6 h-6" /></div>
                <h1 className="text-2xl font-bold text-gray-900 m-0">Clientes, Fichas y Mantenimientos</h1>
            </div>

            <p className="text-gray-700 leading-relaxed text-sm">
                La Ficha de cliente actúa como concentrador temporal (CRM): agrupa sus Partes, sus Presupuestos, Direcciones y, exclusivamente para clientes tipificados como "EMPRESA", despliega el módulo secreto de Contratos de Mantenimiento B2B.
            </p>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">Lógica de Generación Algorítmica de Visitas</h3>
            <p className="text-gray-700 text-sm mb-4">
                Tener registrado un Contrato (Ej. de 01 Enero a 31 Diciembre, Bimensual) no sirve de nada si depende de la memoria humana. Por ello, se programó el botón verde <strong>"Generar Visitas para este Contrato"</strong>, que dispara el script nativo situado en `generar-visitas/route.ts`.
            </p>

            <div className="bg-gray-800 text-gray-300 p-5 rounded-xl text-sm font-mono leading-relaxed mb-6 whitespace-pre-line">
                {'// Lógica Funcional del Algoritmo:\n'}
                {'1. variables = FechaInicio(Enero), FechaFin(Diciembre), Salto(2 meses).\n'}
                {'2. PunteroFecha = FechaInicio\n'}
                {'3. Bucle Iterativo `while (PunteroFecha <= FechaFin)`:\n'}
                {'    a) Construye Evento (`MANTENIMIENTO`, titulo="Revisión").\n'}
                {'    b) Se inyecta a Prisma DB apuntando a la agenda.\n'}
                {'    c) PunteroFecha = date-fns.addMonths(PunteroFecha, Salto).\n'}
                {'4. Fin del script. (Retorna éxito).'}
            </div>

            <p className="text-gray-700 text-sm">
                <strong>Impacto Real:</strong> Ese solo clic ha orquestado múltiples eventos perfectos (Enero, Marzo, Mayo, Julio, Septiembre, Noviembre) en el calendario general de la empresa. Además, el script utiliza el método `startOfDay(addHours(8))` para evitar asignar mantenimientos a la 1 de la madrugada, fijándolos siempre en el rango de horario laboral matutino, garantizando que cuando llegue el mes objetivo tu equipo verá la cita y acudirá a la planta industrial sin depender de recordatorios físicos.
            </p>
        </div>
    );
}

function EstadisticasSection() {
    return (
        <div className="space-y-6">
            <div className="flex items-center gap-3 border-b border-gray-100 pb-4 mb-6">
                <div className="p-3 bg-teal-100 text-teal-600 rounded-xl"><BarChart className="w-6 h-6" /></div>
                <h1 className="text-2xl font-bold text-gray-900 m-0">Business Intelligence y Analítica Flexible</h1>
            </div>

            <p className="text-gray-700 leading-relaxed text-sm">
                La pestaña "Estadísticas" ha sido rediseñada para ser un motor analítico avanzado (`BI / V2`), que manipula a nivel de consultas SQL profundas los datos insertados en toda la plataforma para arrojar radiografías financieras precisas.
            </p>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">Refactorización: Filtros de Reactividad Extrema</h3>
            <p className="text-gray-700 text-sm mb-4">
                Originalmente, las estadísticas cargaban el "total histórico", que sirve de poco a final de mes. La gran mejora arquitectónica introducida es el enrutador paramétrico superior (Rango "Desde" y "Hasta"):
            </p>
            <ul className="list-disc pl-5 mt-2 space-y-3 text-gray-600 text-sm mb-6">
                <li>Al establecer un límite temporal en los inputs, Next.js reconstruye la petición HTTP al vuelo: <code>/api/estadisticas?fechaInicio=2026-10-01&fechaFin=2026-10-31</code></li>
                <li>Por detrás, el Prisma ORM recibe estos parámetros y acopla cláusulas destructivas a los cálculos: <code>where: &#123; createdAt: &#123; gte: inicio, lte: fin &#125;&#125;</code>.</li>
                <li>Esto afecta radicalmente al gráfico de Técnicos, descartando matemáticamente aquellos partes cobrados la semana anterior al filtro. La gráfica resultante te da, al céntimo, el balance del mes.</li>
            </ul>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">Librería XLSX Integrada (SheetJS)</h3>
            <div className="bg-teal-50 border-l-4 border-teal-500 p-4 rounded-r-lg text-sm text-gray-700">
                A diferencia de los engorrosos `.CSV` básicos o reportes en PDF irreutilizables, el Dashboard tiene cargada en Memoria la robusta librería nativa de manipulación contable `xlsx` de SheetJS.<br /><br />
                Cuando pulsas "Exportar a Excel", la aplicación realiza un volcado literal de la memoria RAM del navegador (usando la abstracción `json_to_sheet`) transformando todo lo que ha procesado el Filtro de Fecha actual en hojas (`Worksheets`) independientes. Archiva lo visual en Tablas con formato nativo de MS Excel (<strong>.xlsx</strong>). El nombre del archivo descargado reaccionará dinámicamente también a tu filtro, ejemplo: <code>BI_Climasan_Desde_2026-05_Hasta_2026-06.xlsx</code>.
            </div>
        </div>
    );
}

function FichajeSection() {
    return (
        <div className="space-y-6">
            <div className="flex items-center gap-3 border-b border-gray-100 pb-4 mb-6">
                <div className="p-3 bg-indigo-100 text-indigo-600 rounded-xl"><Clock className="w-6 h-6" /></div>
                <h1 className="text-2xl font-bold text-gray-900 m-0">Control Horario y Gestión de Ausencias</h1>
            </div>

            <p className="text-gray-700 leading-relaxed text-sm">
                El módulo de Fichaje permite a los empleados registrar su jornada laboral (entradas, pausas y salidas) desde cualquier lugar. Asimismo, facilita la gestión centralizada de vacaciones, bajas y ausencias, previniendo la asignación de partes a operarios no disponibles.
            </p>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">1. El Widget de Fichaje (Reloj Flotante)</h3>
            <p className="text-gray-700 text-sm mb-4">
                Ubicado permanentemente en la esquina superior derecha del Dashboard, este widget es el punto de interacción principal para el empleado.
            </p>
            <ul className="list-disc pl-5 mt-2 space-y-3 text-gray-600 text-sm mb-6">
                <li><strong>Estados:</strong> Soporta múltiples estados asíncronos (`NO_INICIADA`, `ACTIVO`, `EN_PAUSA`, `FINALIZADO`).</li>
                <li><strong>Cálculo en Tiempo Real:</strong> El cronómetro no es un simple temporizador local; deduce el tiempo real descontando las pausas activas basándose directamente en los timestamps del servidor (Prisma ORM). Si recargas la página, el reloj conservará los minutos trabajados con exactitud.</li>
                <li><strong>Límite Defensivo (10 horas):</strong> El sistema (`api/control-horario/route.ts`) cuenta con una rutina de seguridad que fuerza el 'Auto-Logout'. Si un operario olvida cerrar su jornada, el sistema la finalizará automáticamente transcurridas 10 horas de tiempo de trabajo *efectivo*.</li>
            </ul>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">2. Extracción de Informes en PDF</h3>
            <p className="text-gray-700 text-sm mb-4">
                El registro histórico está disponible para descarga tanto desde el propio Widget (icono de descarga circular) como desde la pestaña de <strong>Configuración &gt; Extracción Fichaje</strong>.
            </p>
            <div className="bg-indigo-50 border-l-4 border-indigo-500 p-4 rounded-r-lg text-sm text-gray-700 mb-6">
                El sistema de informes genera documentos <strong>.PDF listos para imprimir</strong> utilizando `pdfmake`.<br /><br />
                La lógica del lado del servidor itera sobre cada día del mes, extrayendo las horas de entrada, pausas y salidas, calculando el sumatorio exacto de <code>Horas Efectivas Tabuladas</code> al céntimo. El PDF incorpora automáticamente el logo de ClimaSan y campos para la firma de conformidad del trabajador para inspecciones de trabajo y nóminas.
            </div>

            <h3 className="text-lg font-bold text-gray-800 mt-8 mb-4">3. Ausencias y Bloqueos en Agenda</h3>
            <p className="text-gray-700 text-sm mb-4">
                Desde <strong>Configuración &gt; Ausencias y Vacaciones</strong> puedes registrar cuándo un trabajador no está disponible.
            </p>
            <ul className="list-disc pl-5 mt-2 space-y-3 text-gray-600 text-sm mb-6">
                <li><strong>Integración en Arquitectura Cascada:</strong> A diferencia de las tarjetas de mantenimiento que se re-apilan o pueden ser editadas, las Ausencias se inyectan en la capa base de la Agenda de Cascada.</li>
                <li><strong>Inmutabilidad Visual:</strong> Las ausencias aparecen como bloques inamovibles cruzando todas las horas correspondientes en la Agenda Diaria y Semanal del trabajador impedido, impidiendo arrastrar (`drag and drop`) Partes de Trabajo encima.</li>
                <li><strong>Estados Persistentes:</strong> Las ausencias soportan modalidades (Vacaciones o Baja Médica) y son computadas visualmente antes de la superposición paramétrica de los partes normales.</li>
            </ul>
        </div>
    );
}
