<?php include 'files/guardiankey.php'; ?>
<?php
session_start();

// Configuración de errores (esto está perfecto como lo tenías)
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/../logs/php_errors.log');
error_reporting(E_ALL);

include_once 'db/db_connection.php';

// Variables con valores por defecto
$db_error_message = null;
$company_logo_url = 'img/placeholder-logo.png';
$company_name_from_db = 'Nombre de la Empresa';
$contact_name_from_db = 'Nombre de Contacto';
$contact_email_from_db = 'correo@ejemplo.com';
$contact_phone_from_db = 'N/A';

try {
    // Cambio 1: La consulta ahora apunta a la tabla 'business_info' para obtener todos los datos.
    $stmt_config = $pdo->query("SELECT * FROM business_info WHERE id = 1");
    $config = $stmt_config->fetch(PDO::FETCH_ASSOC);

    if ($config) {
        // Cambio 2: Mapeo de las nuevas columnas de 'business_info' a tus variables PHP.
        $company_name_from_db = htmlspecialchars($config['company_name'] ?? 'Nombre de la Empresa');
        $contact_name_from_db = htmlspecialchars($config['full_name'] ?? 'Nombre de Contacto'); // Usamos 'full_name'
        $contact_email_from_db = htmlspecialchars($config['site_email'] ?? 'correo@ejemplo.com'); // Usamos 'site_email'
        $contact_phone_from_db = htmlspecialchars($config['phone_primary'] ?? 'N/A');
        
        // El logo ahora viene de la misma tabla, no es necesaria una segunda consulta.
        if (!empty($config['logo_url'])) {
            $company_logo_url = htmlspecialchars($config['logo_url']);
        }

    } else {
        $db_error_message = 'No se encontró la configuración en la tabla business_info. Se usarán valores por defecto.';
    }
    
} catch (PDOException $e) {
    error_log("Error PDO al cargar configuración desde business_info: " . $e->getMessage());
    $db_error_message = 'Error de Base de Datos: ' . $e->getMessage();
} catch (Exception $e) {
    error_log("Error general al cargar configuración desde business_info: " . $e->getMessage());
    $db_error_message = 'Error inesperado: ' . $e->getMessage();
}

?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Centro De Facturas FlowCRM™  De OrozDesign Powered By OrozCO</title>
  <meta name="robots" content="noindex, nofollow">

    <link rel="icon" type="image/png" href="img/favicon.png">
    <link rel="apple-touch-icon" href="img/apple-touch-icon.png">

    <?php include 'files/gtm-head.php'; ?>
    
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Barlow:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">

    <script src="https://unpkg.com/lucide@latest"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>

    <script src="https://unpkg.com/imask"></script>

    <link rel="stylesheet" href="style.css">
    <script src="files/header-manager.js"></script>
    
    <style>
        .interactive-module { background-color: #f7fafc; padding: 2rem; border-radius: 0.75rem; border: 1px solid #e2e8f0; }
        .stat-card { background-color: white; padding: 1.5rem; border-radius: 0.75rem; box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); border-left: 5px solid #FFC107; display: flex; align-items: center; gap: 1rem; }
        .stat-card .icon { color: #FFC107; }
        .stat-card .value { color: #98012E; font-weight: 800; font-size: 2.5rem; line-height: 1; }
        .stat-card .title { font-weight: 700; text-transform: uppercase; color: #4A5568; }
        .stat-card .subtitle { font-size: 0.8rem; text-transform: uppercase; color: #A0AEC0; }
        .input-with-icon { position: relative; }
        .input-with-icon input { padding-left: 2.5rem; }
        .input-with-icon .search-icon {
            position: absolute;
            left: 0.75rem;
            top: 50%;
            transform: translateY(-50%);
            color: #A0AEC0;
            pointer-events: none;
        }
        .status-modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            visibility: hidden;
            opacity: 0;
            transition: opacity 0.3s ease-in-out, visibility 0s 0.3s; /* Corregido */
        }
        .status-modal-overlay.active {
            visibility: visible;
            opacity: 1;
            transition: opacity 0.3s ease-in-out; /* Corregido */
        }
        .status-modal {
            background-color: white;
            padding: 2rem;
            border-radius: 0.75rem;
            box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -2px rgb(0 0 0 / 0.1);
            width: 90%;
            max-width: 400px;
            transform: translateY(-20px);
            transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; /* Corregido */
            opacity: 0; /* Añadido */
        }
        .status-modal-overlay.active .status-modal {
            transform: translateY(0); /* Corregido */
            opacity: 1; /* Añadido */
        }

        /* === REGLAS PARA TABLAS RESPONSIVAS === */
        @media (max-width: 767px) {
            .responsive-table-stack tbody,
            .responsive-table-stack tr,
            .responsive-table-stack td {
                display: block;
                width: 100%;
            }
            .responsive-table-stack thead {
                display: none;
            }
            .responsive-table-stack tr {
                margin-bottom: 1rem;
                border: 1px solid #e2e8f0;
                border-radius: 0.5rem;
                padding: 0.5rem;
                background-color: white;
                box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
            }
            .responsive-table-stack td {
                text-align: right !important;
                padding-left: 50% !important;
                position: relative;
                border-bottom: 1px solid #edf2f7;
                padding-top: 0.75rem;
                padding-bottom: 0.75rem;
                white-space: normal;
                word-break: break-word;
            }
            .responsive-table-stack td:last-child {
                border-bottom: 0;
            }
            .responsive-table-stack td::before {
                content: attr(data-label);
                position: absolute;
                left: 0.75rem;
                width: calc(50% - 1.5rem);
                padding-right: 1rem;
                white-space: nowrap;
                text-align: left;
                font-weight: bold;
                text-transform: uppercase;
                color: #4a5568;
                flex-shrink: 0;
            }
            .responsive-table-stack td.actions-cell {
                text-align: center !important;
                padding-left: 0 !important;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;
                gap: 0.75rem;
                min-height: 48px;
                flex-wrap: wrap;
            }
            .responsive-table-stack td.actions-cell::before {
                content: none;
            }
            .responsive-table-stack td.actions-cell button {
                width: 100%;
                flex-grow: 0;
                min-width: 80px;
            }
        }
    </style>
</head>
<body data-page-title="Centro De Control De Facturación"
      data-page-subtitle="Administra, Crea Y Organiza Los Cobros Por Tus Servicios"
      data-page-icon="wallet">

    <div id="toast-container" class="toast-container"></div>
    
<?php include 'files/gtm-body.php'; ?>

<div class="relative min-h-screen md:flex">

    <div id="sidebar-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-30 hidden md:hidden"></div>
    <div id="task-panel-overlay" class="off-canvas-overlay"></div> 
    
    <?php include 'menu.php'; ?>

    <main class="flex-1 overflow-y-auto">
        <header class="bg-white shadow-sm p-4 flex justify-between items-center sticky top-0 z-20">
            <button id="mobile-menu-button" class="md:hidden text-gray-600 hover:text-gray-800">
                <i data-lucide="menu" class="w-6 h-6"></i>
            </button>
            <div class="page-header-container">
                <h2 id="page-title"></h2>
                <p id="page-subtitle"></p>
            </div>
        </header>

        <div id="content-area" class="p-4 md:p-8 space-y-8">
           <section id="dashboard-stats-section">
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
        <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-primary)]">
            <i data-lucide="users" class="w-12 h-12 text-gray-700"></i>
            <div>
                <h3 class="text-lg font-extrabold text-gray-500 mb-1 uppercase">Facturas de Clientes</h3>
                <p id="stats-clients-count" class="text-5xl font-bold text-[var(--color-secondary)] uppercase">0</p>
                <p class="text-sm text-gray-400 mt-1 uppercase">En el mes seleccionado</p>
            </div>
        </div>

        <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-highlight)]">
            <i data-lucide="wallet" class="w-12 h-12 text-gray-700"></i>
            <div>
                <h3 class="text-lg font-extrabold text-gray-500 mb-1 uppercase">Valor Total Facturado</h3>
                <p id="stats-month-total" class="text-5xl font-bold text-[var(--color-secondary)] uppercase">$0</p>
                <p class="text-sm text-gray-400 mt-1 uppercase">Del mes seleccionado</p>
            </div>
        </div>

        <div class="stat-card bg-white p-6 rounded-xl shadow-md flex items-center space-x-4 border-l-4 border-[var(--color-secondary)]">
            <i data-lucide="bell" class="w-12 h-12 text-gray-700"></i>
            <div>
                <h3 class="text-lg font-extrabold text-gray-500 mb-1 uppercase">Facturas Pendientes</h3>
                <p id="stats-pending-count" class="text-5xl font-bold text-[var(--color-secondary)] uppercase">0</p>
                <p class="text-sm text-gray-400 mt-1 uppercase">Enviadas y Atrasadas</p>
            </div>
        </div>
    </div>
</section>

            <section id="list-view-section">
                <div class="bg-white p-6 rounded-xl shadow-md">
                    <div class="flex flex-col md:flex-row justify-between items-center mb-6 gap-4">
                        <h3 class="text-2xl font-extrabold text-gray-800 flex items-center gap-2"><i data-lucide="banknote" class="w-7 h-7 text-[var(--color-primary)]"></i> TODAS LAS FACTURAS</h3>
                        <button id="show-generator-btn" class="btn-primary py-2 px-4 rounded-lg flex items-center justify-center w-full md:w-auto uppercase"><i data-lucide="plus" class="w-5 h-5 mr-2"></i> Nueva Factura</button>
                    </div>
                    <div class="flex flex-col md:flex-row gap-4 mb-6">
                        <div class="input-with-icon w-full">
                            <i data-lucide="search" class="search-icon w-5 h-5"></i>
                            <input type="text" id="list-search" placeholder="Buscar Por Nombre..." class="w-full p-3 border border-gray-300 rounded-lg">
                        </div>
                        <select id="month-filter" class="w-full md:w-auto p-3 border border-gray-300 rounded-lg bg-white"></select>
                        <select id="list-filter-status" class="w-full md:w-auto p-3 border border-gray-300 rounded-lg bg-white"></select>
                    </div>
                    <div class="overflow-x-auto pt-4">
                        <table class="min-w-full bg-white responsive-table-stack">
                            <thead class="bg-gray-50">
                                <tr class="text-left text-gray-500 uppercase text-sm">
                                    <th class="py-3 px-6 font-semibold">Fecha</th>
                                    <th class="py-3 px-6 font-semibold">Cliente</th>
                                    <th class="py-3 px-6 font-semibold">Servicio</th>
                                    <th class="py-3 px-6 font-semibold">Monto</th>
                                    <th class="py-3 px-6 font-semibold">Estado</th>
                                    <th class="py-3 px-6 font-semibold text-center">Acciones</th>
                                </tr>
                            </thead>
                            <tbody id="invoicesTableBody"></tbody>
                        </table>
                        <p id="no-invoices-msg" class="text-center text-gray-500 py-8 hidden">AÚN NO HAS GENERADO NINGUNA FACTURA</p>
                    </div>
                </div>
            </section>
        </div>
    </main>
</div>

<section id="generator-view-section" class="hidden">
    <div id="generator-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-40"></div>
    <div id="generator-panel" class="fixed inset-y-0 right-0 w-full max-w-6xl bg-gray-100 shadow-xl z-50 transform translate-x-full transition-transform duration-300 ease-in-out">
        <div class="grid grid-cols-1 lg:grid-cols-5 h-full">
            <div class="lg:col-span-2 bg-gray-100 p-6 overflow-y-auto space-y-6 h-full">
                <h1 id="generator-title" class="text-3xl font-black text-gray-800 text-center uppercase">Crear Factura</h1>
                <input type="hidden" id="editing-invoice-id">

                <div class="space-y-4">
                    <h2 class="text-lg font-black text-[var(--color-primary)] flex items-center gap-2 uppercase"><i data-lucide="user-check"></i> Información del Cliente</h2>

                    <div id="contact-selection-area">
                        <div class="space-y-2">
                            <label for="clientSearch" class="text-sm font-semibold text-gray-700">Buscar Cliente</label>
                            <div class="relative input-with-icon">
                                <i data-lucide="search" class="search-icon w-5 h-5"></i>
                                <input type="text" id="clientSearch" placeholder="Nombre Del Cliente..." autocomplete="off" class="w-full p-2.5 border border-gray-300 rounded-lg">
                                <div id="client-suggestions" class="absolute w-full bg-white border rounded-md mt-1 shadow-lg z-20 hidden"></div>
                            </div>
                        </div>
                    </div>

                    <div id="selected-contact-display" class="hidden items-center justify-between p-3 bg-blue-50 border border-blue-200 rounded-lg">
                        <div class="flex items-center gap-3">
                            <i data-lucide="user-check" class="w-6 h-6 text-blue-800"></i>
                            <div>
                                <p class="font-bold text-blue-800" id="selected-contact-name"></p>
                                <p class="text-xs text-blue-600" id="selected-contact-email"></p>
                            </div>
                        </div>
                        <button id="change-contact-btn" class="text-sm text-blue-600 hover:underline">Cambiar</button>
                    </div>
                </div>

                <div class="space-y-4">
                    <h2 class="text-lg font-black text-[var(--color-primary)] flex items-center gap-2 uppercase"><i data-lucide="clipboard-list"></i> Detalles Del Servicio</h2>
                    <select id="tipoServicio" class="w-full p-2.5 border border-gray-300 rounded-lg"></select>
                </div>
                <div class="space-y-4">
                    <h2 class="text-lg font-black text-[var(--color-primary)] flex items-center gap-2 uppercase"><i data-lucide="percent"></i> Impuestos (Taxes)</h2>
                    <input type="number" id="tax-rate" value="0" min="0" step="0.1" class="w-full p-2.5 border border-gray-300 rounded-lg">
                </div>
                <div class="flex flex-col space-y-3 pt-4"> 
                    <button id="save-invoice-btn" class="btn-secondary w-full p-3 rounded-lg text-lg uppercase font-black flex items-center justify-center"><i data-lucide="save" class="w-6 h-6 mr-2"></i> Guardar Cambios</button>
                    <button id="download-pdf-btn" class="btn-primary w-full p-3 rounded-lg text-lg uppercase font-black flex items-center justify-center"><i data-lucide="download" class="w-6 h-6 mr-2"></i> Descargar Digital</button>
                    <button id="back-to-list-btn" class="bg-gray-300 hover:bg-gray-400 text-gray-800 w-full p-3 rounded-lg uppercase font-bold flex items-center justify-center"><i data-lucide="arrow-left" class="w-6 h-6 mr-2"></i> Cancelar</button>
                </div>
            </div>
            <div class="lg:col-span-3 bg-white p-2 overflow-y-auto h-full">
                <div id="pdf-preview" class="p-8"><div id="invoice-content"></div></div>
            </div>
        </div>
    </div>
</section>

<div id="status-modal-overlay" class="status-modal-overlay">
    <div id="status-modal" class="status-modal">
        <h3 class="text-xl font-bold mb-4 text-gray-800">CAMBIAR ESTADO DE LA FACTURA</h3>
        <input type="hidden" id="modal-invoice-id">
        <div class="mb-4">
            <label for="modal-status-select" class="block text-gray-700 text-sm font-semibold mb-2">Selecciona Un Nuevo Estado:</label>
            <select id="modal-status-select" class="w-full p-2.5 border border-gray-300 rounded-lg bg-white">
            </select>
        </div>
        <div class="flex flex-col sm:flex-row justify-end space-y-2 sm:space-y-0 sm:space-x-3"> <button id="modal-cancel-btn" class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-4 py-2 rounded-lg font-semibold w-full sm:w-auto">CANCELAR</button>
            <button id="modal-save-status-btn" class="btn-primary px-4 py-2 rounded-lg font-semibold w-full sm:w-auto">GUARDAR</button>
        </div>
    </div>
</div>

<div id="confirmDeleteModal" class="fixed inset-0 bg-gray-900 bg-opacity-75 flex items-center justify-center hidden z-50">
    <div class="bg-white p-8 rounded-xl shadow-2xl w-full max-w-sm m-4 transform transition-all duration-300 scale-95 opacity-0 text-center">
        <div class="flex justify-center mb-4">
            <i data-lucide="alert-triangle" class="w-16 h-16 text-[var(--color-secondary)]"></i>
        </div>
        <h3 class="text-2xl font-bold text-[var(--color-primary)] mb-4 uppercase">CONFIRMAR ELIMINACIÓN</h3>
        <p class="text-gray-700 mb-6 uppercase">¿ESTÁS SEGURO DE QUE DESEAS ELIMINAR ESTA <span id="confirm-item-type" class="font-semibold">ELEMENTO</span>? ESTA ACCIÓN NO SE PUEDE DESHACER.</p>
        <div class="flex flex-col sm:flex-row justify-center space-y-2 sm:space-y-0 sm:space-x-4"> <button type="button" class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded-lg uppercase w-full sm:w-auto" id="cancel-delete-btn">CANCELAR</button>
            <button type="button" class="btn-secondary font-bold py-2 px-4 rounded-lg uppercase w-full sm:w-auto" id="confirm-delete-button">CONFIRMAR</button>
        </div>
    </div>
</div>

<script>
    document.addEventListener('DOMContentLoaded', function() {

        // =================================================================
        // INICIALIZACIÓN DE LIBRERÍAS
        // =================================================================
        if (window.jspdf) {
            window.jsPDF = window.jspdf.jsPDF;
        }

        // =================================================================
        // VARIABLES GLOBALES DE DATOS Y ESTADO
        // =================================================================
        let allClients = [];
        let allServices = [];
        let allInvoices = {};
        let nextAvailableInvoiceNumber = 1;
        let selectedContact = null;

        const invoiceTemplateHTML = `<div class="flex justify-between items-start mb-10"><div><img src="<?php echo $company_logo_url; ?>" alt="Logo" class="h-16 mb-4"><h2 class="text-2xl font-black text-gray-800"><?php echo $company_name_from_db; ?></h2><p class="text-gray-600"><?php echo $contact_name_from_db; ?></p><p class="text-gray-600"><?php echo $contact_email_from_db; ?></p><p class="text-gray-600"><?php echo $contact_phone_from_db; ?></p></div><div class="text-right"><h1 class="text-5xl font-black text-gray-300 tracking-wider">INVOICE</h1><p><strong>Date:</strong> <span id="previewDate"></span></p><p><strong>Invoice No.:</strong> <span id="previewInvoiceId"></span></p></div></div><div class="bg-gray-50 p-4 rounded-lg mb-8"><h3 class="font-bold text-gray-500 text-sm tracking-wider">INVOICE TO:</h3><p id="previewContactName" contenteditable="true"></p><p id="previewContactAddress" contenteditable="true"></p><p id="previewContactEmail" contenteditable="true"></p><p id="previewContactPhone" contenteditable="true"></p></div><table class="w-full mb-8"><thead class="bg-gray-800 text-white"><tr><th class="text-left p-3 rounded-tl-md">DESCRIPTION</th><th class="text-right p-3">QTY.</th><th class="text-right p-3">UNIT PRICE</th><th class="text-right p-3 rounded-tr-md">TOTAL</th><th class="p-3 rounded-tr-md"></th></tr></thead><tbody id="invoice-items"></tbody></table><button id="addItemBtn" class="bg-gray-100 border w-full p-2.5 rounded-lg text-sm mb-6 flex items-center justify-center"><i data-lucide="plus-circle" class="w-5 h-5 mr-2"></i> AGREGAR ADICIONAL</button><div class="flex justify-end mt-4"><div class="w-full md:w-1/2"><div class="flex justify-between p-2"><span>Subtotal</span><span id="previewSubtotal"></span></div><div class="flex justify-between p-2 border-b"><span>Tax (<span id="previewTaxRate">0</span>%)</span><span id="previewTaxAmount"></span></div><div class="flex justify-between font-bold text-xl bg-yellow-300 p-3 rounded-md"><span>TOTAL</span><span id="previewTotal"></span></div></div></div><div class="mt-16 text-xs text-gray-500"><h4 class="font-bold mb-1">Terms and Conditions</h4><p contenteditable="true">This invoice is due upon receipt.</p></div>`;


        // =================================================================
        // CACHÉ DE ELEMENTOS DEL DOM
        // =================================================================
        const elements = {
            // Vistas principales
            generatorView: document.getElementById('generator-view-section'),
            generatorPanel: document.getElementById('generator-panel'),
            generatorOverlay: document.getElementById('generator-overlay'),
            invoicesTableBody: document.getElementById('invoicesTableBody'),
            noInvoicesMsg: document.getElementById('no-invoices-msg'),
            
            // Botones
            showGeneratorBtn: document.getElementById('show-generator-btn'),
            saveInvoiceBtn: document.getElementById('save-invoice-btn'),
            downloadPdfBtn: document.getElementById('download-pdf-btn'),
            backToListBtn: document.getElementById('back-to-list-btn'),
            
            // Filtros y búsqueda
            listSearch: document.getElementById('list-search'),
            monthFilter: document.getElementById('month-filter'),
            listFilterStatus: document.getElementById('list-filter-status'),
            
            // Elementos del generador de facturas
            generatorTitle: document.getElementById('generator-title'),
            editingInvoiceId: document.getElementById('editing-invoice-id'),
            clientSearch: document.getElementById('clientSearch'),
            clientSuggestions: document.getElementById('client-suggestions'),
            contactSelectionArea: document.getElementById('contact-selection-area'),
            selectedContactDisplay: document.getElementById('selected-contact-display'),
            selectedContactName: document.getElementById('selected-contact-name'),
            selectedContactEmail: document.getElementById('selected-contact-email'),
            changeContactBtn: document.getElementById('change-contact-btn'),
            tipoServicio: document.getElementById('tipoServicio'),
            taxRate: document.getElementById('tax-rate'),
            invoiceContent: document.getElementById('invoice-content'),
            
            // Estadísticas
            statsClientsCount: document.getElementById('stats-clients-count'),
            statsMonthTotal: document.getElementById('stats-month-total'),
            statsPendingCount: document.getElementById('stats-pending-count'),
            
            // Modales
            statusModalOverlay: document.getElementById('status-modal-overlay'),
            statusModal: document.getElementById('status-modal'),
            modalInvoiceId: document.getElementById('modal-invoice-id'),
            modalStatusSelect: document.getElementById('modal-status-select'),
            modalCancelBtn: document.getElementById('modal-cancel-btn'),
            modalSaveStatusBtn: document.getElementById('modal-save-status-btn'),
            confirmDeleteModal: document.getElementById('confirmDeleteModal'),
            confirmDeleteButton: document.getElementById('confirm-delete-button'),
            confirmItemTypeSpan: document.getElementById('confirm-item-type'),
            cancelDeleteBtn: document.getElementById('cancel-delete-btn'),

            // Mobile Menu
            mobileMenuButton: document.getElementById('mobile-menu-button'),
            sidebar: document.getElementById('sidebar'),
            sidebarOverlay: document.getElementById('sidebar-overlay'),
            phoneInput: document.getElementById('contact_phone')
        };
        let dynamicElements = {};
        
        // =================================================================
        // FUNCIONES DE UI Y LÓGICA DE NEGOCIO
        // =================================================================

        const showGeneratorView = (externalId = null) => {
            elements.generatorView.classList.remove('hidden');
            setTimeout(() => { elements.generatorPanel.classList.remove('translate-x-full'); }, 10);
            elements.invoiceContent.innerHTML = invoiceTemplateHTML;
            
            bindDynamicElements(); // Primero vincula, luego resetea
            resetGeneratorForm();

            if (externalId && allInvoices[externalId]) {
                const invoice = allInvoices[externalId];
                elements.generatorTitle.textContent = `Editando Factura #${invoice.id.replace('inv-', '')}`;
                elements.editingInvoiceId.value = externalId;
                if (invoice.contact) handleContactSelection(invoice.contact);
                elements.taxRate.value = invoice.taxRate || 0;
                
                dynamicElements.invoiceItemsBody.innerHTML = '';
                invoice.items.forEach(([desc, price, quantity = 1]) => dynamicElements.invoiceItemsBody.appendChild(createItemRow(desc, price, quantity)));
                
                if (invoice.items.length > 0) {
                    const firstItemDesc = invoice.items[0][0];
                    const matchingService = allServices.find(s => s.name === firstItemDesc);
                    if (matchingService) elements.tipoServicio.value = matchingService.id;
                    else elements.tipoServicio.value = '';
                }
            } else {
                dynamicElements.invoiceItemsBody.appendChild(createItemRow("Nuevo Ítem", 0.00, 1)); 
                elements.generatorTitle.textContent = 'Crear Nueva Factura';
                elements.editingInvoiceId.value = '';
            }
            updatePreview();

            if (typeof lucide !== 'undefined') {
                lucide.createIcons({ container: elements.generatorPanel });
            }
        };


        const hideGeneratorView = () => {
            elements.generatorPanel.classList.add('translate-x-full');
            setTimeout(() => { elements.generatorView.classList.add('hidden'); }, 300);
        };

        const bindDynamicElements = () => {
            dynamicElements = {
                invoiceItemsBody: document.getElementById('invoice-items'),
                addItemBtn: document.getElementById('addItemBtn'),
                previewContactName: document.getElementById('previewContactName'),
                previewContactAddress: document.getElementById('previewContactAddress'),
                previewContactEmail: document.getElementById('previewContactEmail'),
                previewContactPhone: document.getElementById('previewContactPhone'),
                previewDate: document.getElementById('previewDate'),
                previewInvoiceId: document.getElementById('previewInvoiceId'),
                previewSubtotal: document.getElementById('previewSubtotal'),
                previewTaxRate: document.getElementById('previewTaxRate'),
                previewTaxAmount: document.getElementById('previewTaxAmount'),
                previewTotal: document.getElementById('previewTotal')
            };

            if (dynamicElements.addItemBtn) {
                // *** CORRECCIÓN 1 (Botón Borrar) ***
                dynamicElements.addItemBtn.addEventListener('click', () => {
                    dynamicElements.invoiceItemsBody.appendChild(createItemRow());
                    if (typeof lucide !== 'undefined') {
                        lucide.createIcons(); // Vuelve a dibujar íconos
                    }
                });
            }
            if (dynamicElements.invoiceItemsBody) {
                dynamicElements.invoiceItemsBody.addEventListener('input', recalculateTotal);
                dynamicElements.invoiceItemsBody.addEventListener('blur', (e) => {
                    if (e.target.matches('.item-unit-price')) {
                        e.target.textContent = `$${(parseFloat(e.target.textContent.replace(/[^\d.]/g, '')) || 0).toFixed(2)}`;
                    } else if (e.target.matches('.item-qty')) {
                        e.target.textContent = `${(parseInt(e.target.textContent) || 1)}`;
                    }
                }, true);
            }
            if (elements.taxRate) elements.taxRate.addEventListener('input', recalculateTotal);
        };

        const formatStatusText = (status) => (status ? status.replace(/_/g, ' ').toUpperCase() : '');
        
        const getStatusClass = (status) => {
            const s = status.toLowerCase();
            if (s === 'pagada') return 'bg-green-100 text-green-800';
            if (s === 'enviada') return 'bg-blue-100 text-blue-800';
            if (s === 'cancelada') return 'bg-[var(--color-secondary)] text-white';
            if (s === 'atrasada') return 'bg-orange-200 text-orange-800';
            if (s === 'generada') return 'bg-gray-300 text-gray-800';
            return 'bg-gray-100 text-gray-800';
        };

        const updateDisplay = () => {
            const monthFilterValue = elements.monthFilter.value;
            renderTable(monthFilterValue);
            updateDashboardStats(monthFilterValue);
        };

        const renderTable = (monthFilterValue) => {
            const filters = {
                term: elements.listSearch.value.toLowerCase(),
                status: elements.listFilterStatus.value
            };

            const filteredData = Object.values(allInvoices).filter(doc => {
                const matchesTerm = doc.cliente.toLowerCase().includes(filters.term);
                const matchesStatus = (filters.status === 'all' || doc.estado === filters.status);
                const matchesMonth = (monthFilterValue === 'all') || (doc.fechaSolicitud.startsWith(monthFilterValue));
                return matchesTerm && matchesStatus && matchesMonth;
            });
            
            elements.invoicesTableBody.innerHTML = '';
            elements.noInvoicesMsg.classList.toggle('hidden', filteredData.length > 0);
            
            filteredData.forEach(doc => {
                const row = elements.invoicesTableBody.insertRow();
                row.className = 'border-b hover:bg-gray-50';
                row.innerHTML = `
                    <td class="py-4 px-6" data-label="FECHA">${doc.fechaSolicitud}</td>
                    <td class="py-4 px-6" data-label="CLIENTE">${doc.cliente}</td>
                    <td class="py-4 px-6" data-label="SERVICIO">${doc.servicio}</td>
                    <td class="py-4 px-6" data-label="MONTO">$${parseFloat(doc.montoFacturado).toFixed(2)}</td>
                    <td class="py-4 px-6" data-label="ESTADO">
                        <span class="${getStatusClass(doc.estado)} py-1 px-3 rounded-full text-xs font-bold">${formatStatusText(doc.estado)}</span>
                    </td>
                    <td class="py-4 px-6 text-center actions-cell" data-label="ACCIONES">
                        <div class="flex flex-col sm:flex-row items-center justify-center space-y-2 sm:space-y-0 sm:space-x-3">
                            ${doc.estado !== 'pagada' ? `
                                <button class="text-gray-500 hover:text-gray-700 change-status-btn w-full sm:w-auto" data-invoice-id="${doc.id}" data-current-status="${doc.estado}" title="Cambiar Estado">
                                    <i data-lucide="edit-3" class="w-5 h-5"></i>
                                </button>
                                <button class="text-blue-600 hover:text-blue-800 edit-invoice-btn w-full sm:w-auto" data-invoice-id="${doc.id}" title="Ver/Editar">
                                    <i data-lucide="eye" class="w-5 h-5"></i>
                                </button>
                            ` : `
                                <span class="text-gray-400 w-full sm:w-auto" title="Factura Pagada"><i data-lucide="check-circle" class="w-5 h-5"></i> Pagada</span>
                            `}
                            <button class="text-[var(--color-secondary)] hover:text-[var(--color-secondary)] delete-invoice-btn w-full sm:w-auto" data-invoice-id="${doc.id}" title="Eliminar">
                                <i data-lucide="trash-2" class="w-5 h-5"></i>
                            </button>
                        </div>
                    </td>`;
            });

            if (typeof lucide !== 'undefined') lucide.createIcons();
            setupActionListeners();
        };
        
        const setupActionListeners = () => {
            document.querySelectorAll('.change-status-btn').forEach(button => {
                button.onclick = null; // Prevenir múltiples listeners
                button.addEventListener('click', (event) => {
                    const { invoiceId, currentStatus } = event.currentTarget.dataset;
                    showStatusModal(invoiceId, currentStatus);
                    event.stopPropagation();
                });
            });

            document.querySelectorAll('.edit-invoice-btn').forEach(button => {
                button.onclick = null; // Prevenir múltiples listeners
                button.addEventListener('click', (event) => {
                    const { invoiceId } = event.currentTarget.dataset;
                    showGeneratorView(invoiceId);
                    event.stopPropagation();
                });
            });

            document.querySelectorAll('.delete-invoice-btn').forEach(button => {
                button.onclick = null; // Prevenir múltiples listeners
                button.addEventListener('click', (event) => {
                    const { invoiceId } = event.currentTarget.dataset;
                    openConfirmDeleteModal(invoiceId, 'factura');
                    event.stopPropagation();
                });
            });
        };

        const showStatusModal = (externalId, currentStatus) => {
            elements.modalInvoiceId.value = externalId;
            const statuses = ['generada', 'enviada', 'cancelada', 'atrasada', 'pagada'];
            elements.modalStatusSelect.innerHTML = statuses.map(s => `
                <option value="${s}" ${s === currentStatus ? 'selected' : ''}>${formatStatusText(s)}</option>
            `).join('');
            elements.statusModalOverlay.classList.add('active');
        };

        const hideStatusModal = () => elements.statusModalOverlay.classList.remove('active');

        const openModal = (modalId) => {
            const modal = document.getElementById(modalId);
            if (!modal) return;
            const modalBox = modal.querySelector('div:first-of-type');
            modal.classList.remove('hidden');
            if (modalBox) setTimeout(() => { modalBox.classList.remove('scale-95', 'opacity-0'); }, 50);
        };
        
        const closeModal = (modalId) => {
            const modal = document.getElementById(modalId);
            if (!modal) return;
            const modalBox = modal.querySelector('div:first-of-type');
            if (modalBox) modalBox.classList.add('scale-95', 'opacity-0');
            setTimeout(() => { modal.classList.add('hidden'); }, 300);
        };
        
        const openConfirmDeleteModal = (itemId, itemType) => {
            if (!elements.confirmDeleteButton || !elements.confirmItemTypeSpan) return;
            elements.confirmDeleteButton.dataset.itemId = itemId;
            elements.confirmDeleteButton.dataset.itemType = itemType;
            elements.confirmItemTypeSpan.textContent = itemType.toUpperCase();
            openModal('confirmDeleteModal');
        };

        const updateInvoiceStatus = async (externalId, newStatus) => {
            const invoice = allInvoices[externalId];
            if (!invoice || !invoice.db_id) {
                showToast('Error: Datos de la factura no encontrados.', 'error');
                return;
            }
            try {
                const response = await fetch('db/invoice-status-update.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: invoice.db_id, status: newStatus }) });
                const result = await response.json();
                if (result.success) {
                    hideStatusModal();
                    showToast(`Estado de la factura actualizado.`, 'success');
                    location.reload();
                } else {
                    showToast(`Error al actualizar estado: ${result.message}`, 'error');
                }
            } catch (error) {
                console.error('Error de conexión al actualizar estado:', error);
                showToast('Error de conexión al actualizar el estado.', 'error');
            }
        };

        const formatToK = (num) => {
            if (num === 0) return '0';
            return Math.abs(num) > 999 ? (Math.sign(num)*((Math.abs(num)/1000).toFixed(1))) + 'k' : Math.sign(num)*Math.abs(num);
        };

        const updateDashboardStats = (monthFilterValue) => {
            let clientsCount = 0, monthTotal = 0, pendingCount = 0;
            const dataToProcess = Object.values(allInvoices).filter(doc => (monthFilterValue === 'all') || doc.fechaSolicitud.startsWith(monthFilterValue));
            
            const clientIds = new Set();
            dataToProcess.forEach(invoice => {
                if (invoice.contactType === 'client') {
                    clientIds.add(invoice.contact.id);
                }
                monthTotal += parseFloat(invoice.montoFacturado) || 0;
                if (['enviada', 'atrasada'].includes(invoice.estado)) pendingCount++;
            });
            clientsCount = clientIds.size; // Contar clientes únicos

            if (elements.statsClientsCount) elements.statsClientsCount.textContent = clientsCount;
            if (elements.statsMonthTotal) elements.statsMonthTotal.textContent = `$${formatToK(monthTotal)}`;
            if (elements.statsPendingCount) elements.statsPendingCount.textContent = pendingCount;
        };

        const generatePDF = () => {
            const invoiceElement = document.getElementById('pdf-preview');
            const addItemBtn = invoiceElement?.querySelector('#addItemBtn');
            const removeBtns = invoiceElement?.querySelectorAll('.remove-item-btn');
            
            // Ocultar botones y ajustar estilos para la generación del PDF
            const togglePdfStyles = (hide = true) => {
                if (addItemBtn) addItemBtn.style.display = hide ? 'none' : '';
                if (removeBtns) removeBtns.forEach(btn => btn.style.display = hide ? 'none' : '');
                const invoiceItemsBody = invoiceElement?.querySelector('#invoice-items');
                if (invoiceItemsBody) invoiceItemsBody.style.marginBottom = hide ? '20px' : '';
                if (invoiceElement) {
                    invoiceElement.style.width = hide ? '816px' : '';
                    invoiceElement.style.margin = hide ? '0 auto' : '';
                    invoiceElement.style.padding = hide ? '32px' : '';
                    invoiceElement.style.boxSizing = hide ? 'border-box' : '';
                }
            };
            
            togglePdfStyles(true);

            html2canvas(invoiceElement, { scale: 2, useCORS: true, width: 816 }).then(canvas => {
                togglePdfStyles(false);
                const imgData = canvas.toDataURL('image/png');
                const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'letter' });
                const pdfWidth = pdf.internal.pageSize.getWidth();
                const pdfHeight = pdf.internal.pageSize.getHeight();
                const imgHeight = (canvas.height * pdfWidth) / canvas.width;
                let heightLeft = imgHeight;
                let position = 0;

                pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight);
                heightLeft -= pdfHeight;

                while (heightLeft >= 0) {
                    position = heightLeft - imgHeight;
                    pdf.addPage();
                    pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight);
                    heightLeft -= pdfHeight;
                }

                pdf.save(`Factura-${dynamicElements.previewInvoiceId.textContent}-${dynamicElements.previewContactName.textContent.replace(/\s+/g, '_')}.pdf`);
            }).catch(err => {
                togglePdfStyles(false);
                console.error("Error al generar PDF:", err);
                showToast('Error al generar el PDF de la factura.', 'error');
            });
        };
        
        const createItemRow = (desc = "Nuevo Ítem", unitPrice = 0.00, qty = 1) => {
            const row = document.createElement('tr');
            row.innerHTML = `
                <td class="p-3 border-b" contenteditable="true">${desc}</td>
                <td class="text-right p-3 item-qty border-b" contenteditable="true">${qty}</td>
                <td class="text-right p-3 item-unit-price border-b" contenteditable="true">$${parseFloat(unitPrice).toFixed(2)}</td>
                <td class="text-right p-3 item-total-price border-b">$${(unitPrice * qty).toFixed(2)}</td>
                <td class="p-3 border-b text-center">
                    <button type="button" class="text-[var(--color-secondary)] hover:text-[var(--color-secondary)] remove-item-btn font-bold text-lg" title="Remove Item">
                        <i data-lucide="x" class="w-5 h-5"></i>
                    </button>
                </td>
            `;
            const removeButton = row.querySelector('.remove-item-btn');
            if (removeButton) {
                removeButton.addEventListener('click', () => {
                    row.remove();
                    recalculateTotal();
                });
            }
            return row;
        };

        const recalculateTotal = () => {
            if (!dynamicElements.invoiceItemsBody) return;
            let subtotal = 0;
            dynamicElements.invoiceItemsBody.querySelectorAll('tr').forEach(row => {
                const qty = parseInt(row.cells[1].textContent) || 0;
                const unitPrice = parseFloat(row.cells[2].textContent.replace(/[$,]/g, '')) || 0;
                const itemTotal = qty * unitPrice;
                row.cells[3].textContent = `$${itemTotal.toFixed(2)}`;
                subtotal += itemTotal;
            });
            const taxRate = parseFloat(elements.taxRate.value) || 0;
            const taxAmount = subtotal * (taxRate / 100);
            const total = subtotal + taxAmount;
            if (dynamicElements.previewSubtotal) dynamicElements.previewSubtotal.textContent = `$${subtotal.toFixed(2)}`;
            if (dynamicElements.previewTaxRate) dynamicElements.previewTaxRate.textContent = taxRate.toFixed(2);
            if (dynamicElements.previewTaxAmount) dynamicElements.previewTaxAmount.textContent = `$${taxAmount.toFixed(2)}`;
            if (dynamicElements.previewTotal) dynamicElements.previewTotal.textContent = `$${total.toFixed(2)}`;
        };

        const resetGeneratorForm = () => {
            selectedContact = null;
            elements.editingInvoiceId.value = '';
            elements.contactSelectionArea.classList.remove('hidden');
            elements.selectedContactDisplay.classList.add('hidden');
            elements.clientSearch.value = '';
            elements.tipoServicio.value = '';
            elements.taxRate.value = 0;
            if (dynamicElements.invoiceItemsBody) dynamicElements.invoiceItemsBody.innerHTML = '';
            updatePreview();
        };

        const handleContactSelection = (contact) => {
            selectedContact = contact;
            elements.contactSelectionArea.classList.add('hidden');
            elements.selectedContactName.textContent = contact.name;
            elements.selectedContactEmail.textContent = contact.email;
            elements.selectedContactDisplay.classList.remove('hidden');
            elements.clientSuggestions.classList.add('hidden');
            elements.clientSearch.value = '';
            updatePreview();
        };
        
        // *** INICIO DE CORRECCIÓN 2 (Ocultar campos vacíos) ***
        const updatePreview = () => {
            if (!dynamicElements.previewContactName) return;

            // --- NOMBRE (Siempre se muestra) ---
            dynamicElements.previewContactName.textContent = selectedContact?.name || "Nombre del Contacto";
            dynamicElements.previewContactName.style.display = ''; // 'block' por defecto

            // --- DIRECCIÓN (Se oculta si está vacía) ---
            const address = selectedContact?.street_address || selectedContact?.address;
            if (address) {
                dynamicElements.previewContactAddress.textContent = address;
                dynamicElements.previewContactAddress.style.display = ''; // 'block' por defecto
            } else {
                dynamicElements.previewContactAddress.textContent = '';
                dynamicElements.previewContactAddress.style.display = 'none'; // Ocultar
            }

            // --- EMAIL (Se oculta si está vacío) ---
            const email = selectedContact?.email;
            if (email) {
                dynamicElements.previewContactEmail.textContent = email;
                dynamicElements.previewContactEmail.style.display = ''; // 'block' por defecto
            } else {
                dynamicElements.previewContactEmail.textContent = '';
                dynamicElements.previewContactEmail.style.display = 'none'; // Ocultar
            }

            // --- TELÉFONO (Se oculta si está vacío) ---
            const phone = selectedContact?.phone || selectedContact?.mobile;
            if (phone) {
                dynamicElements.previewContactPhone.textContent = phone;
                dynamicElements.previewContactPhone.style.display = ''; // 'block' por defecto
            } else {
                dynamicElements.previewContactPhone.textContent = '';
                dynamicElements.previewContactPhone.style.display = 'none'; // Ocultar
            }

            // --- Resto de la función (Números de factura y fecha) ---
            dynamicElements.previewDate.textContent = new Date().toLocaleDateString('es-ES');

            let invoiceNumberDisplay = 'NUEVO';
            if (elements.editingInvoiceId.value) {
                const externalIdKey = elements.editingInvoiceId.value;
                if (allInvoices[externalIdKey] && allInvoices[externalIdKey].db_id !== undefined) {
                    const numericId = allInvoices[externalIdKey].db_id;
                    if (!isNaN(numericId)) {
                        invoiceNumberDisplay = String(numericId).padStart(3, '0');
                    }
                }
            } else {
                invoiceNumberDisplay = String(nextAvailableInvoiceNumber).padStart(3, '0');
            }
            dynamicElements.previewInvoiceId.textContent = invoiceNumberDisplay;
            recalculateTotal();
        };
        // *** FIN DE CORRECCIÓN 2 ***

        const saveInvoice = async () => {
            if (!selectedContact || selectedContact.type !== 'client') {
                showToast("Por favor, selecciona un cliente.", 'warning');
                return;
            }

            const itemsData = Array.from(dynamicElements.invoiceItemsBody.querySelectorAll('tr')).map(row => {
                const [desc, qty, unitPrice] = [row.cells[0].textContent, parseInt(row.cells[1].textContent) || 1, parseFloat(row.cells[2].textContent.replace(/[$,]/g, '')) || 0];
                return [desc, unitPrice, qty];
            }).filter(([desc, unitPrice, qty]) => desc.trim() !== '' && (unitPrice > 0 || qty > 0) && desc.trim() !== 'Nuevo Ítem'); // Filtro mejorado

            if (itemsData.length === 0) {
                showToast("Por favor, agrega al menos un ítem válido.", 'warning');
                return;
            }

            const isEditing = elements.editingInvoiceId.value !== '';
            const invoiceData = {
                id: isEditing ? allInvoices[elements.editingInvoiceId.value]?.db_id : null,
                invoice_date: new Date().toISOString().split('T')[0],
                status: isEditing ? allInvoices[elements.editingInvoiceId.value]?.estado : 'generada',
                tax_rate: parseFloat(elements.taxRate.value) || 0,
                items: itemsData,
                client_id: selectedContact.id,
                lead_id: null,
            };

            const apiUrl = isEditing ? 'db/invoice-update.php' : 'db/invoice-create.php';

            try {
                const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(invoiceData) });
                const result = await response.json();
                if (result.success) {
                    showToast(`Factura guardada correctamente.`, 'success');
                    hideGeneratorView();
                    location.reload();
                } else {
                    showToast(`Error al guardar: ${result.message}`, 'error');
                }
            } catch (error) {
                console.error('Error al guardar:', error);
                showToast('Error de conexión al guardar.', 'error');
            }
        };

        const executeDeleteInvoice = async (externalId) => {
            const invoiceToDelete = allInvoices[externalId];
            if (!invoiceToDelete || !invoiceToDelete.db_id) {
                showToast('Error: ID de factura no encontrado.', 'error');
                return;
            }
            try {
                const response = await fetch('db/invoice-delete.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: invoiceToDelete.db_id }) });
                const result = await response.json();
                if (result.success) {
                    showToast('Factura eliminada con éxito.', 'success');
                    closeModal('confirmDeleteModal');
                    location.reload();
                } else {
                    showToast(`Error al eliminar: ${result.message}`, 'error');
                }
            } catch (error) {
                console.error('Error al eliminar:', error);
                showToast('Error de conexión al eliminar.', 'error');
            }
        };

        const setupSearch = (inputEl, suggestionEl) => {
            let searchTimeout;
            inputEl.addEventListener('input', () => {
                clearTimeout(searchTimeout);
                const searchTerm = inputEl.value.toLowerCase();
                suggestionEl.innerHTML = '';
                if (!searchTerm || searchTerm.length < 2) { 
                    suggestionEl.classList.add('hidden'); 
                    return; 
                }
                searchTimeout = setTimeout(() => {
                    const matches = allClients.filter(c => 
                        (c.name?.toLowerCase().includes(searchTerm)) || 
                        (c.email?.toLowerCase().includes(searchTerm))
                    );
                    if (matches.length > 0) {
                        suggestionEl.innerHTML = matches.map(contact => `
                            <div class="p-2 hover:bg-gray-100 cursor-pointer text-sm border-b last:border-b-0" data-client-id="${contact.id}">
                                ${contact.name} (${contact.email || 'Sin email'})
                            </div>
                        `).join('');
                        suggestionEl.classList.remove('hidden');
                    } else {
                        suggestionEl.classList.add('hidden');
                    }
                }, 300);
            });
            inputEl.addEventListener('blur', () => {
                setTimeout(() => { if (!suggestionEl.matches(':hover')) suggestionEl.classList.add('hidden'); }, 200);
            });
            suggestionEl.addEventListener('mousedown', (e) => { // 'mousedown' es mejor que 'click' para 'blur'
                e.preventDefault();
                const clientItem = e.target.closest('[data-client-id]');
                if (clientItem) {
                    const contactId = clientItem.dataset.clientId;
                    const contact = allClients.find(c => c.id == contactId);
                    if (contact) {
                        handleContactSelection(contact);
                        suggestionEl.classList.add('hidden');
                    }
                }
            });
        };

        const populateServiceDropdown = () => {
            const { tipoServicio } = elements;
            tipoServicio.innerHTML = '<option value="">-- Selecciona Un Servicio --</option>';
            const servicesByCategory = allServices.reduce((acc, service) => {
                const category = service.category || 'Sin Categoría';
                if (!acc[category]) acc[category] = [];
                acc[category].push(service);
                return acc;
            }, {});

            for (const category in servicesByCategory) {
                const optgroup = document.createElement('optgroup');
                optgroup.label = category;
                servicesByCategory[category].forEach(service => {
                    const option = new Option(`${service.name} ($${service.price.toFixed(2)})`, service.id);
                    optgroup.appendChild(option);
                });
                tipoServicio.appendChild(optgroup);
            }
        };

        const fetchAndDisplayInvoices = async () => {
            try {
                const response = await fetch('db/invoice-read.php');
                const result = await response.json();
                if (result.success) {
                    allInvoices = {};
                    let currentMaxDbId = 0;
                    result.data.forEach(invoice => {
                        allInvoices[invoice.id] = invoice;
                        if (parseInt(invoice.db_id) > currentMaxDbId) currentMaxDbId = parseInt(invoice.db_id);
                    });
                    nextAvailableInvoiceNumber = currentMaxDbId + 1;
                    updateMonthFilterOptions();
                } else {
                    showToast('Error al cargar facturas: ' + (result.message || 'Error desconocido.'), 'error');
                }
            } catch (error) {
                showToast('Error de conexión al cargar facturas.', 'error');
            }
        };

        const updateMonthFilterOptions = () => {
            const months = [...new Set(Object.values(allInvoices).map(q => q.fechaSolicitud.substring(0, 7)))].sort().reverse();
            const currentMonthYear = new Date().toISOString().substring(0, 7);
            
            elements.monthFilter.innerHTML = `<option value="all">TODOS LOS MESES</option>` + months.map(m => {
                const date = new Date(`${m}-02T12:00:00`); // Usar UTC para evitar problemas de zona
                const monthName = date.toLocaleString('es-ES', { month: 'long', timeZone: 'UTC' });
                return `<option value="${m}">${monthName.charAt(0).toUpperCase() + monthName.slice(1).toUpperCase()} ${date.getUTCFullYear()}</option>`;
            }).join('');
            
            if (months.includes(currentMonthYear)) {
                elements.monthFilter.value = currentMonthYear;
            } else if (months.length > 0) {
                elements.monthFilter.value = months[0];
            } else {
                elements.monthFilter.value = 'all';
            }
        };

        // =================================================================
        // EVENT LISTENERS E INICIALIZACIÓN
        // =================================================================
        (async function init() {
            // Manejo de notificaciones globales
            const urlParams = new URLSearchParams(window.location.search);
            const notificationType = urlParams.get('notification_type');
            const notificationMessage = urlParams.get('notification_message');
            if (notificationType && notificationMessage) {
                if (typeof showToast === 'function') {
                    showToast(notificationMessage, notificationType);
                }
            }

            // Manejo del menú móvil
            elements.mobileMenuButton?.addEventListener('click', () => { elements.sidebar.classList.toggle('-translate-x-full'); elements.sidebarOverlay.classList.toggle('hidden'); });
            elements.sidebarOverlay?.addEventListener('click', () => { elements.sidebar.classList.add('-translate-x-full'); elements.sidebarOverlay.classList.add('hidden'); });
            if (elements.phoneInput) IMask(elements.phoneInput, { mask: '(000) 000-0000' });
            
            // Carga de datos iniciales
            const [clientsResponse, servicesResponse] = await Promise.all([
                fetch('db/clients-read-contact-data.php'),
                fetch('db/services-read-all.php')
            ]);
            const [clientsResult, servicesResult] = await Promise.all([clientsResponse.json(), servicesResponse.json()]);

            if (clientsResult.success) { allClients = clientsResult.data; setupSearch(elements.clientSearch, elements.clientSuggestions); }
            else { showToast('Error al cargar clientes: ' + (clientsResult.message || 'Error desconocido.'), 'error'); }

            if (servicesResult.success) { allServices = servicesResult.data; populateServiceDropdown(); }
            else { showToast('Error al cargar servicios: ' + (servicesResult.message || 'Error desconocido.'), 'error'); }

            await fetchAndDisplayInvoices();

            if (elements.listFilterStatus) {
                elements.listFilterStatus.innerHTML = '<option value="all">TODOS LOS ESTADOS</option>';
                ['generada', 'enviada', 'cancelada', 'atrasada', 'pagada'].forEach(s => elements.listFilterStatus.add(new Option(formatStatusText(s), s)));
            }
            
            updateDisplay(); // Llamada inicial para renderizar la tabla

            // Event Listeners principales
            [elements.listSearch, elements.listFilterStatus].forEach(el => el?.addEventListener('input', updateDisplay));
            elements.monthFilter?.addEventListener('change', updateDisplay);
            elements.showGeneratorBtn?.addEventListener('click', () => showGeneratorView());
            elements.backToListBtn?.addEventListener('click', hideGeneratorView);
            elements.generatorOverlay?.addEventListener('click', hideGeneratorView);
            elements.saveInvoiceBtn?.addEventListener('click', saveInvoice);
            elements.downloadPdfBtn?.addEventListener('click', generatePDF);
            elements.changeContactBtn?.addEventListener('click', () => {
                resetGeneratorForm();
                dynamicElements.invoiceItemsBody.appendChild(createItemRow("Nuevo Ítem", 0.00, 1));
                if (typeof lucide !== 'undefined') {
                    lucide.createIcons();
                }
            });
            elements.taxRate?.addEventListener('input', recalculateTotal);
            
            elements.tipoServicio?.addEventListener('change', () => {
                const selectedServiceId = elements.tipoServicio.value;
                if (selectedServiceId) {
                    const service = allServices.find(s => s.id == selectedServiceId);
                    if (service && dynamicElements.invoiceItemsBody) {
                        
                        // Lógica para reemplazar o añadir item
                        const firstRow = dynamicElements.invoiceItemsBody.querySelector('tr');
                        const isDefaultRow = firstRow && firstRow.cells[0].textContent.trim() === 'Nuevo Ítem' && parseFloat(firstRow.cells[2].textContent.replace(/[$,]/g, '')) === 0;

                        if (isDefaultRow) {
                            firstRow.remove(); // Quita el item por defecto
                        }

                        dynamicElements.invoiceItemsBody.appendChild(createItemRow(service.name, service.price, 1));
                        recalculateTotal();
                        
                        if (typeof lucide !== 'undefined') {
                            lucide.createIcons(); // Vuelve a dibujar íconos
                        }
                    }
                }
            });

            elements.modalCancelBtn?.addEventListener('click', hideStatusModal);
            elements.statusModalOverlay?.addEventListener('click', (event) => { if (event.target === elements.statusModalOverlay) hideStatusModal(); });
            elements.modalSaveStatusBtn?.addEventListener('click', () => {
                const externalId = elements.modalInvoiceId.value;
                const newStatus = elements.modalStatusSelect.value;
                updateInvoiceStatus(externalId, newStatus);
            });
            elements.confirmDeleteButton?.addEventListener('click', function() { executeDeleteInvoice(this.dataset.itemId); });
            elements.cancelDeleteBtn?.addEventListener('click', () => closeModal('confirmDeleteModal'));

            if (typeof lucide !== 'undefined') lucide.createIcons();
        })();
    });
</script>


</body>
</html>