<?php
/**
 * Buscador y Editor de Productos Robusto (Dual DB) - Edición en Línea Instantánea
 * 
 * Permite buscar productos con paginación avanzada y editar sus datos generales 
 * y presentaciones directamente en la misma celda de la tabla (estilo hoja de cálculo).
 * Los cambios se guardan automáticamente al salir del campo (evento blur) o presionar Enter.
 * Portabilidad: Funciona tanto localmente (SufarmaERP) como en el Hosting (SISTEMA1WEB).
 */

// 1. Cargar Configuración de Base de Datos y Conexión Dual
$configPath = file_exists(__DIR__ . '/db_config.php') ? __DIR__ . '/db_config.php' : __DIR__ . '/../db_config.php';
$dualPdoPath = file_exists(__DIR__ . '/dual_pdo.php') ? __DIR__ . '/dual_pdo.php' : __DIR__ . '/../dual_pdo.php';

if (!file_exists($configPath) || !file_exists($dualPdoPath)) {
    die(json_encode([
        'success' => false,
        'error' => 'Error de configuración: No se encontraron los archivos db_config.php o dual_pdo.php.'
    ]));
}

$config = require $configPath;
require_once $dualPdoPath;

// Instanciar la conexión dual
$pdo = getDualConnection($config);

// Definir nombres de bases de datos para visualización
$db_principal = $config['db1']['dbname'] ?? 'Principal';
$db_secundaria = $config['db2']['dbname'] ?? 'Secundaria';

// 2. Rutas de API internas
$action = $_GET['action'] ?? '';

// API: Buscar productos con paginación y filtros
if ($action === 'search') {
    header('Content-Type: application/json; charset=utf-8');
    
    $q = trim($_GET['q'] ?? '');
    $filter = trim($_GET['filter'] ?? 'all');
    $page = max(1, intval($_GET['page'] ?? 1));
    $limit = max(5, min(100, intval($_GET['limit'] ?? 15)));
    $offset = ($page - 1) * $limit;

    try {
        $where = [];
        $params = [];

        if (!empty($q)) {
            if ($filter === 'name') {
                $where[] = "(p.NombreComercial LIKE ? OR p.NombreGenerico LIKE ?)";
                $params[] = "%$q%";
                $params[] = "%$q%";
            } elseif ($filter === 'code') {
                $where[] = "(p.CodigoInterno LIKE ? OR p.CodigoBarra LIKE ?)";
                $params[] = "%$q%";
                $params[] = "%$q%";
            } elseif ($filter === 'lab') {
                $where[] = "p.laboratorio LIKE ?";
                $params[] = "%$q%";
            } else {
                $where[] = "(p.NombreComercial LIKE ? OR p.NombreGenerico LIKE ? OR p.CodigoInterno LIKE ? OR p.CodigoBarra LIKE ? OR p.laboratorio LIKE ?)";
                $params[] = "%$q%";
                $params[] = "%$q%";
                $params[] = "%$q%";
                $params[] = "%$q%";
                $params[] = "%$q%";
            }
        }

        $whereSql = !empty($where) ? "WHERE " . implode(" AND ", $where) : "";
        
        $sql = "SELECT SQL_CALC_FOUND_ROWS p.* FROM `productos` p $whereSql ORDER BY p.id DESC LIMIT $offset, $limit";
        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        $productos = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Obtener total de registros
        $total = $pdo->query("SELECT FOUND_ROWS()")->fetchColumn();
        $totalPages = ceil($total / $limit);

        // Obtener presentaciones activas de cada producto
        $stmtPres = $pdo->prepare("
            SELECT pp.*, pr.nombre AS presentacion_nombre 
            FROM `producto_presentaciones` pp
            INNER JOIN `presentaciones` pr ON pp.presentacion_id = pr.id
            WHERE pp.producto_id = ? AND pp.activo = 1
            ORDER BY pp.orden ASC
        ");

        foreach ($productos as &$p) {
            $stmtPres->execute([$p['id']]);
            $p['presentaciones'] = $stmtPres->fetchAll(PDO::FETCH_ASSOC);
        }

        echo json_encode([
            'success' => true,
            'data' => $productos,
            'pagination' => [
                'total' => $total,
                'page' => $page,
                'limit' => $limit,
                'total_pages' => $totalPages
            ]
        ]);
        exit;
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['success' => false, 'error' => $e->getMessage()]);
        exit;
    }
}

// API: Guardar edición de producto y presentaciones
if ($action === 'save' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    header('Content-Type: application/json; charset=utf-8');
    
    $input = json_decode(file_get_contents('php://input'), true);
    
    $id = intval($input['id'] ?? 0);
    $nombreComercial = trim($input['NombreComercial'] ?? '');
    $nombreGenerico = trim($input['NombreGenerico'] ?? '');
    $laboratorio = trim($input['laboratorio'] ?? '');
    $codigoInterno = trim($input['CodigoInterno'] ?? '');
    $codigoBarra = trim($input['CodigoBarra'] ?? '');
    $presentaciones = $input['presentaciones'] ?? [];

    if ($id <= 0 || empty($nombreComercial)) {
        echo json_encode(['success' => false, 'error' => 'Datos inválidos. El Nombre Comercial es obligatorio.']);
        exit;
    }

    try {
        $pdo->beginTransaction();

        // 1. Actualizar datos generales del producto
        $sql = "UPDATE `productos` SET 
                `NombreComercial` = ?, 
                `NombreGenerico` = ?, 
                `laboratorio` = ?, 
                `CodigoInterno` = ?, 
                `CodigoBarra` = ? 
                WHERE `id` = ?";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([$nombreComercial, $nombreGenerico, $laboratorio, $codigoInterno, $codigoBarra, $id]);

        // 2. Procesar las presentaciones usando ON DUPLICATE KEY UPDATE
        // Esto evita depender de IDs auto-incrementales que puedan diferir entre las dos bases de datos.
        $stmtUpsert = $pdo->prepare("
            INSERT INTO `producto_presentaciones` 
            (`producto_id`, `presentacion_id`, `factor_conversion`, `precio_venta`, `activo`, `es_facturable`, `es_comprable`, `es_vendible`, `orden`) 
            VALUES (?, ?, ?, ?, ?, 1, 1, 1, ?)
            ON DUPLICATE KEY UPDATE 
            `factor_conversion` = VALUES(`factor_conversion`),
            `precio_venta` = VALUES(`precio_venta`),
            `activo` = VALUES(`activo`),
            `orden` = VALUES(`orden`)
        ");

        $orden = 0;
        foreach ($presentaciones as $pres) {
            $presId = intval($pres['presentacion_id']);
            $activo = intval($pres['activo']);
            $factor = intval($pres['factor_conversion']);
            $precio = floatval($pres['precio_venta']);

            $stmtUpsert->execute([$id, $presId, $factor, $precio, $activo, $orden]);
            $orden++;
        }

        $pdo->commit();
        echo json_encode(['success' => true, 'message' => 'Producto y presentaciones actualizados exitosamente.']);
        exit;
    } catch (Exception $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        http_response_code(500);
        echo json_encode(['success' => false, 'error' => $e->getMessage()]);
        exit;
    }
}

// Obtener todas las presentaciones maestras
$presentacionesMaestras = [];
try {
    $presentacionesMaestras = $pdo->query("SELECT * FROM `presentaciones` WHERE `activo` = 1 ORDER BY `id` ASC")->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
    $presentacionesMaestras = [
        ['id' => 1, 'nombre' => 'UNIDAD'],
        ['id' => 2, 'nombre' => 'BLISTER'],
        ['id' => 3, 'nombre' => 'CAJA'],
        ['id' => 4, 'nombre' => 'BOTE'],
        ['id' => 5, 'nombre' => 'PAQUETE'],
        ['id' => 6, 'nombre' => 'FARDO'],
        ['id' => 7, 'nombre' => 'BOLSA'],
        ['id' => 8, 'nombre' => 'GALON'],
        ['id' => 9, 'nombre' => 'MIXTO'],
        ['id' => 10, 'nombre' => 'OCTAVO']
    ];
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Buscador y Editor de Productos (Edición Directa)</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
    <style>
        :root {
            --primary: #0b0f19;
            --primary-light: #151f32;
            --accent: #3b82f6;
            --accent-hover: #2563eb;
            --surface: rgba(21, 31, 50, 0.85);
            --border: rgba(255, 255, 255, 0.12);
            --text: #ffffff;
            --text-secondary: #cbd5e1;
            --borderless-bg: rgba(15, 23, 42, 0.55);
        }

        body {
            background-color: var(--primary);
            background-image: 
                radial-gradient(circle at 10% 20%, rgba(59, 130, 246, 0.1) 0%, transparent 40%),
                radial-gradient(circle at 90% 80%, rgba(16, 185, 129, 0.08) 0%, transparent 40%);
            color: var(--text);
            font-family: 'Plus Jakarta Sans', sans-serif;
            min-height: 100vh;
        }

        .glass-card {
            background: var(--surface);
            backdrop-filter: blur(20px);
            border: 1px solid var(--border);
            border-radius: 1.25rem;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
        }

        .search-input {
            background: rgba(15, 23, 42, 0.7) !important;
            border: 1px solid var(--border) !important;
            color: white !important;
            border-radius: 0.75rem !important;
            padding: 0.75rem 1.25rem !important;
            font-weight: 500;
        }

        .search-input:focus {
            border-color: var(--accent) !important;
            box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.25) !important;
        }

        .filter-select {
            background: rgba(15, 23, 42, 0.7) !important;
            border: 1px solid var(--border) !important;
            color: white !important;
            border-radius: 0.75rem !important;
            padding: 0.75rem 1.25rem !important;
            font-weight: 600;
            cursor: pointer;
        }

        .table-custom {
            --bs-table-bg: transparent;
            --bs-table-color: var(--text);
            --bs-table-border-color: var(--border);
            margin-bottom: 0;
        }

        .table-custom th {
            font-weight: 700;
            text-transform: uppercase;
            font-size: 0.8rem;
            letter-spacing: 0.75px;
            color: #94a3b8;
            padding: 1.2rem 1rem;
            background: rgba(15, 23, 42, 0.3);
        }

        .table-custom td {
            padding: 0.8rem 1rem;
            vertical-align: middle;
            border-bottom: 1px solid var(--border);
        }

        .tr-product {
            transition: background-color 0.2s;
        }

        .tr-product:hover {
            background-color: rgba(255, 255, 255, 0.02);
        }

        .pagination-custom .page-link {
            background: rgba(21, 31, 50, 0.7);
            border: 1px solid var(--border);
            color: var(--text-secondary);
            padding: 0.6rem 1rem;
            transition: all 0.2s;
        }

        .pagination-custom .page-item.active .page-link {
            background: var(--accent);
            border-color: var(--accent);
            color: white;
            font-weight: 700;
        }

        .pagination-custom .page-link:hover {
            background: rgba(59, 130, 246, 0.2);
            color: white;
            border-color: var(--accent);
        }

        /* Inputs Editables con Excelente Contraste */
        .borderless-input {
            background: var(--borderless-bg);
            border: 1px solid rgba(255, 255, 255, 0.15);
            border-radius: 0.5rem;
            padding: 0.45rem 0.65rem;
            transition: all 0.15s;
            width: 100%;
        }

        .borderless-input:hover {
            background: rgba(255, 255, 255, 0.08);
            border-color: rgba(255, 255, 255, 0.3);
        }

        .borderless-input:focus {
            background: #0f172a;
            border-color: var(--accent);
            box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
            outline: none;
        }

        /* Colores de alto contraste por tipo de dato */
        .input-nombre-comercial {
            color: #ffffff !important;
            font-weight: 700 !important;
            font-size: 1rem !important;
        }
        .input-nombre-generico {
            color: #cbd5e1 !important; /* slate-300 */
            font-size: 0.85rem !important;
        }
        .input-laboratorio {
            color: #fbbf24 !important; /* amber-400 */
            font-weight: 700 !important;
            font-size: 0.775rem !important;
            text-transform: uppercase !important;
        }
        .input-codigo-interno {
            color: #38bdf8 !important; /* sky-400 */
            font-weight: 700 !important;
            font-size: 0.875rem !important;
        }
        .input-codigo-barra {
            color: #e2e8f0 !important; /* slate-200 */
            font-size: 0.8rem !important;
        }

        /* Contenedor y Botón de Presentación */
        .inline-pres-box {
            background: rgba(15, 23, 42, 0.6);
            border: 1px solid rgba(255, 255, 255, 0.15);
            border-radius: 0.6rem;
            padding: 0.45rem 0.65rem;
            display: flex;
            align-items: center;
            gap: 0.5rem;
            margin-bottom: 0.4rem;
        }

        /* Selector de presentación estilo Badge */
        .select-badge {
            background: #334155; /* slate-700 */
            color: #ffffff;
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 0.4rem;
            font-size: 0.75rem;
            font-weight: 700;
            padding: 0.15rem 0.45rem;
            cursor: pointer;
            text-transform: uppercase;
            outline: none;
            transition: all 0.15s;
        }

        .select-badge:hover {
            background: #475569; /* slate-600 */
            border-color: rgba(255, 255, 255, 0.4);
        }

        .btn-inline-remove {
            background: rgba(239, 68, 68, 0.15);
            color: #f87171;
            border: 1px solid rgba(239, 68, 68, 0.25);
            border-radius: 0.35rem;
            padding: 0.15rem 0.35rem;
            font-size: 0.75rem;
            transition: all 0.15s;
        }

        .btn-inline-remove:hover {
            background: #ef4444;
            color: white;
            border-color: #ef4444;
        }

        .select-inline-add {
            background: rgba(59, 130, 246, 0.15) !important;
            border: 1px solid rgba(59, 130, 246, 0.35) !important;
            color: #60a5fa !important;
            border-radius: 0.5rem !important;
            font-size: 0.8rem;
            font-weight: 700;
            padding: 0.35rem 0.65rem;
            cursor: pointer;
            text-transform: uppercase;
            outline: none;
            transition: all 0.15s;
        }

        .select-inline-add:hover {
            background: rgba(59, 130, 246, 0.25) !important;
            border-color: rgba(59, 130, 246, 0.5) !important;
        }

        /* Forzar que la lista de opciones tenga fondo oscuro y texto blanco de alto contraste */
        .select-inline-add option,
        .select-badge option {
            background-color: #151f32 !important; /* fondo azul oscuro/slate */
            color: #ffffff !important; /* texto blanco puro */
            font-weight: 600 !important;
        }
    </style>
</head>
<body class="py-5">

<div class="container">
    <!-- Header -->
    <div class="glass-card p-4 mb-4 text-center">
        <h2 class="fw-bold text-white mb-2"><i class="fa-solid fa-pen-to-square text-primary me-2"></i> Buscador y Editor de Productos en Línea</h2>
        <p class="text-secondary mb-0"><span class="badge bg-success me-1">Dual DB</span> Haz clic en cualquier campo para editar. Al salir del campo se guardará de forma automática en <code><?= htmlspecialchars($db_principal) ?></code> y <code><?= htmlspecialchars($db_secundaria) ?></code></p>
    </div>

    <!-- Buscador y Filtros -->
    <div class="glass-card p-4 mb-4">
        <div class="row g-3">
            <div class="col-md-7">
                <input type="text" id="searchInput" class="form-control search-input" placeholder="Escriba para buscar por nombre, código o laboratorio...">
            </div>
            <div class="col-md-3">
                <select id="filterSelect" class="form-select filter-select">
                    <option value="all">🔍 Buscar en Todo</option>
                    <option value="name">📦 Nombre Comercial/Genérico</option>
                    <option value="code">🔑 Código Interno/Barras</option>
                    <option value="lab">🧪 Laboratorio</option>
                </select>
            </div>
            <div class="col-md-2">
                <button id="btnSearch" class="btn btn-primary w-100 py-3 rounded-3 fw-bold"><i class="fa-solid fa-magnifying-glass me-2"></i> Buscar</button>
            </div>
        </div>
    </div>

    <!-- Grid / Resultados -->
    <div class="glass-card p-4 mb-4">
        <div class="table-responsive">
            <table class="table table-custom align-middle">
                <thead>
                    <tr>
                        <th style="width: 15%">Códigos</th>
                        <th style="width: 35%">Producto / Laboratorio</th>
                        <th style="width: 40%">Presentaciones Activas</th>
                        <th style="width: 10%" class="text-center">Estado</th>
                    </tr>
                </thead>
                <tbody id="productsTableBody">
                    <tr>
                        <td colspan="4" class="text-center py-5 text-secondary">
                            <div class="spinner-border text-primary mb-3" role="status"></div>
                            <div>Cargando catálogo de productos...</div>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>

        <!-- Paginación -->
        <div class="d-flex justify-content-between align-items-center mt-4 flex-wrap gap-3">
            <div class="text-secondary small" id="paginationInfo">Mostrando 0 de 0 productos</div>
            <nav>
                <ul class="pagination pagination-custom mb-0" id="paginationList">
                    <!-- Dinámico -->
                </ul>
            </nav>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

<script>
    // Variables globales
    const masterPresentaciones = <?= json_encode($presentacionesMaestras) ?>;
    let productsData = []; // Caché de productos en pantalla

    let currentPage = 1;
    let currentLimit = 15;
    let searchDebounceTimeout = null;

    document.addEventListener('DOMContentLoaded', () => {
        loadProducts(1);

        // Búsqueda en tiempo real (debounced)
        document.getElementById('searchInput').addEventListener('input', () => {
            clearTimeout(searchDebounceTimeout);
            searchDebounceTimeout = setTimeout(() => {
                loadProducts(1);
            }, 300);
        });

        document.getElementById('filterSelect').addEventListener('change', () => {
            loadProducts(1);
        });

        document.getElementById('btnSearch').addEventListener('click', () => {
            loadProducts(1);
        });
    });

    // Cargar productos
    async function loadProducts(page = 1) {
        currentPage = page;
        const q = document.getElementById('searchInput').value.trim();
        const filter = document.getElementById('filterSelect').value;
        const tbody = document.getElementById('productsTableBody');

        try {
            const res = await fetch(`?action=search&q=${encodeURIComponent(q)}&filter=${filter}&page=${page}&limit=${currentLimit}`);
            const json = await res.json();

            if (!json.success) {
                tbody.innerHTML = `<tr><td colspan="4" class="text-center text-danger py-4"><i class="fa-solid fa-circle-exclamation me-2"></i> Error: ${json.error}</td></tr>`;
                return;
            }

            productsData = json.data;
            renderProductsTable();
            renderPagination(json.pagination);
        } catch (err) {
            tbody.innerHTML = `<tr><td colspan="4" class="text-center text-danger py-4"><i class="fa-solid fa-circle-exclamation me-2"></i> Error: ${err.message}</td></tr>`;
        }
    }

    // Renderizar tabla
    function renderProductsTable() {
        const tbody = document.getElementById('productsTableBody');
        tbody.innerHTML = '';

        if (productsData.length === 0) {
            tbody.innerHTML = '<tr><td colspan="4" class="text-center py-5 text-secondary">No se encontraron productos.</td></tr>';
            return;
        }

        productsData.forEach(p => {
            const tr = document.createElement('tr');
            tr.id = `row_${p.id}`;
            tr.className = 'tr-product';
            
            // Creamos las 4 celdas vacías
            tr.innerHTML = '<td></td><td></td><td></td><td></td>';
            tbody.appendChild(tr);
            renderRowHTML(p.id);
        });
    }

    // Renderizar una fila individual con sus inputs editables
    function renderRowHTML(productId) {
        const tr = document.getElementById(`row_${productId}`);
        if (!tr) return;

        const p = productsData.find(prod => prod.id === productId);
        if (!p) return;

        // Celda 1: Códigos
        const cellCodigos = `
            <div class="mb-2">
                <input type="text" class="borderless-input input-codigo-interno font-monospace"
                       placeholder="Código Interno" value="${escapeHtml(p.CodigoInterno || '')}" 
                       onblur="saveField(${p.id}, 'CodigoInterno', this.value)"
                       onkeydown="if(event.key === 'Enter') { this.blur(); }">
            </div>
            <div>
                <input type="text" class="borderless-input input-codigo-barra font-monospace"
                       placeholder="Código Barras" value="${escapeHtml(p.CodigoBarra || '')}" 
                       onblur="saveField(${p.id}, 'CodigoBarra', this.value)"
                       onkeydown="if(event.key === 'Enter') { this.blur(); }">
            </div>
        `;

        // Celda 2: Producto y Laboratorio
        const cellProducto = `
            <div class="mb-1">
                <input type="text" class="borderless-input input-nombre-comercial" 
                       placeholder="Nombre Comercial" value="${escapeHtml(p.NombreComercial || '')}" 
                       onblur="saveField(${p.id}, 'NombreComercial', this.value)"
                       onkeydown="if(event.key === 'Enter') { this.blur(); }">
            </div>
            <div class="mb-1">
                <input type="text" class="borderless-input input-nombre-generico" 
                       placeholder="Nombre Genérico" value="${escapeHtml(p.NombreGenerico || '')}" 
                       onblur="saveField(${p.id}, 'NombreGenerico', this.value)"
                       onkeydown="if(event.key === 'Enter') { this.blur(); }">
            </div>
            <div>
                <input type="text" class="borderless-input input-laboratorio" 
                       placeholder="Laboratorio" value="${escapeHtml(p.laboratorio || '')}" 
                       onblur="saveField(${p.id}, 'laboratorio', this.value)"
                       onkeydown="if(event.key === 'Enter') { this.blur(); }">
            </div>
        `;

        // Celda 3: Presentaciones
        let presBoxes = '';
        let activeIds = [];
        if (p.presentaciones && p.presentaciones.length > 0) {
            p.presentaciones.forEach(pres => {
                if (pres.activo === 1) {
                    activeIds.push(pres.presentacion_id);

                    // Opciones para cambiar/swap la presentación
                    let swapOptions = '';
                    masterPresentaciones.forEach(master => {
                        if (master.id === pres.presentacion_id || !activeIds.includes(master.id)) {
                            const isSelected = (master.id === pres.presentacion_id) ? 'selected' : '';
                            swapOptions += `<option value="${master.id}" ${isSelected}>${master.nombre}</option>`;
                        }
                    });

                    // Si es "Unidad", no mostramos el factor de conversión ("de 1 unidades")
                    const isUnidad = pres.presentacion_nombre.trim().toLowerCase() === 'unidad';

                    let factorHtml = '';
                    if (isUnidad) {
                        // En "Unidad" sólo dejamos el basurero para quitarla
                        factorHtml = `
                            <button type="button" class="btn-inline-remove ms-2" onclick="removePresentation(${p.id}, ${pres.presentacion_id})">
                                <i class="fa-solid fa-trash-can"></i>
                            </button>
                        `;
                    } else {
                        // Presentación normal: mostramos el input del factor editable
                        factorHtml = `
                            <span class="small text-secondary" style="font-size: 0.7rem;">de:</span>
                            <input type="number" min="1" 
                                   class="form-control form-control-sm text-center py-0 px-1 font-weight-bold" 
                                   style="width: 50px; background: rgba(0,0,0,0.4); border: 1px solid var(--border); color: white; border-radius: 4px;" 
                                   value="${pres.factor_conversion}"
                                   onchange="updatePresentationFactor(${p.id}, ${pres.presentacion_id}, this.value)">
                            <span class="small text-secondary" style="font-size: 0.7rem; margin-right: 5px;">unidades</span>
                            <button type="button" class="btn-inline-remove" onclick="removePresentation(${p.id}, ${pres.presentacion_id})">
                                <i class="fa-solid fa-trash-can"></i>
                            </button>
                        `;
                    }

                    presBoxes += `
                        <div class="inline-pres-box justify-content-between">
                            <div class="d-flex align-items-center">
                                <select class="select-badge" onchange="swapPresentation(${p.id}, ${pres.presentacion_id}, this.value)">
                                    ${swapOptions}
                                </select>
                            </div>
                            <div class="d-flex align-items-center gap-2">
                                <div class="d-flex align-items-center gap-1">
                                    ${factorHtml}
                                </div>
                            </div>
                        </div>
                    `;
                }
            });
        }

        if (presBoxes === '') {
            presBoxes = '<span class="text-secondary small d-block my-2">Ninguna presentación activa</span>';
        }

        // Selector para agregar (diseñado como selector tipo Badge sin botón adicional)
        let selectOptions = '<option value="" disabled selected>+ Agregar Presentación</option>';
        masterPresentaciones.forEach(master => {
            if (!activeIds.includes(master.id)) {
                selectOptions += `<option value="${master.id}">${master.nombre}</option>`;
            }
        });

        const cellPresentaciones = `
            <div id="pres_list_${p.id}">
                ${presBoxes}
            </div>
            <div class="d-flex align-items-center gap-2 mt-2 pt-2 border-top border-secondary">
                <select class="select-inline-add" onchange="addPresentation(${p.id}, this.value); this.value = '';">
                    ${selectOptions}
                </select>
            </div>
        `;

        // Celda 4: Estado
        const cellAcciones = `
            <div class="text-center" id="status_${p.id}">
                <span class="text-secondary small" style="opacity: 0.4;"><i class="fa-solid fa-check"></i> Sincronizado</span>
            </div>
        `;

        tr.cells[0].innerHTML = cellCodigos;
        tr.cells[1].innerHTML = cellProducto;
        tr.cells[2].innerHTML = cellPresentaciones;
        tr.cells[3].innerHTML = cellAcciones;
    }

    // Guardar cambio en campo de texto
    async function saveField(productId, fieldName, value) {
        const p = productsData.find(prod => prod.id === productId);
        if (!p) return;

        const trimmedValue = value.trim();
        if (p[fieldName] === trimmedValue) return;

        const oldValue = p[fieldName];
        p[fieldName] = trimmedValue;

        const success = await persistProductToServer(p);
        if (!success) {
            p[fieldName] = oldValue;
            renderRowHTML(productId);
        }
    }

    // Guardar cambio en el factor
    async function updatePresentationFactor(productId, presId, value) {
        const p = productsData.find(prod => prod.id === productId);
        if (!p) return;

        const factor = parseInt(value) || 1;
        const pres = p.presentaciones.find(pr => pr.presentacion_id === presId);
        if (!pres) return;

        if (pres.factor_conversion === factor) return;

        const oldFactor = pres.factor_conversion;
        pres.factor_conversion = factor;

        const success = await persistProductToServer(p);
        if (!success) {
            pres.factor_conversion = oldFactor;
            renderRowHTML(productId);
        }
    }

    // Reemplazar / Cambiar tipo de presentación inline (select-badge)
    async function swapPresentation(productId, oldPresId, newPresId) {
        const p = productsData.find(prod => prod.id === productId);
        if (!p) return;

        const newId = parseInt(newPresId);
        const oldId = parseInt(oldPresId);
        if (newId === oldId) return;

        const presIndex = p.presentaciones.findIndex(pr => pr.presentacion_id === oldId);
        if (presIndex === -1) return;

        const master = masterPresentaciones.find(m => m.id === newId);
        if (!master) return;

        // Registrar la desactivación explícita del ID viejo
        if (!p.deactivatedPresIds) {
            p.deactivatedPresIds = [];
        }
        if (!p.deactivatedPresIds.includes(oldId)) {
            p.deactivatedPresIds.push(oldId);
        }

        // Guardar respaldos locales
        const backupPresId = p.presentaciones[presIndex].presentacion_id;
        const backupPresNombre = p.presentaciones[presIndex].presentacion_nombre;

        // Actualizar temporalmente en memoria local al nuevo tipo de presentación
        p.presentaciones[presIndex].presentacion_id = newId;
        p.presentaciones[presIndex].presentacion_nombre = master.nombre;

        const success = await persistProductToServer(p);
        if (success) {
            p.deactivatedPresIds = [];
            renderRowHTML(productId);
        } else {
            p.presentaciones[presIndex].presentacion_id = backupPresId;
            p.presentaciones[presIndex].presentacion_nombre = backupPresNombre;
            const devIdx = p.deactivatedPresIds.indexOf(oldId);
            if (devIdx !== -1) p.deactivatedPresIds.splice(devIdx, 1);
            renderRowHTML(productId);
        }
    }

    // Remover presentación
    async function removePresentation(productId, presId) {
        const p = productsData.find(prod => prod.id === productId);
        if (!p) return;

        const presIndex = p.presentaciones.findIndex(pr => pr.presentacion_id === presId);
        if (presIndex === -1) return;

        const backupPres = { ...p.presentaciones[presIndex] };
        p.presentaciones[presIndex].activo = 0;

        const success = await persistProductToServer(p);
        if (success) {
            p.presentaciones.splice(presIndex, 1);
            renderRowHTML(productId);
        } else {
            p.presentaciones[presIndex] = backupPres;
            renderRowHTML(productId);
        }
    }

    // Agregar presentación
    async function addPresentation(productId, presIdStr) {
        const presId = parseInt(presIdStr);
        if (isNaN(presId)) return;

        const master = masterPresentaciones.find(m => m.id === presId);
        if (!master) return;

        const p = productsData.find(prod => prod.id === productId);
        if (!p) return;

        const existingIndex = p.presentaciones.findIndex(pr => pr.presentacion_id === presId);
        if (existingIndex !== -1) {
            p.presentaciones[existingIndex].activo = 1;
            p.presentaciones[existingIndex].factor_conversion = 1;
        } else {
            p.presentaciones.push({
                presentacion_id: master.id,
                presentacion_nombre: master.nombre,
                factor_conversion: 1,
                precio_venta: 0.00,
                activo: 1
            });
        }

        const success = await persistProductToServer(p);
        if (success) {
            renderRowHTML(productId);
        } else {
            if (existingIndex !== -1) {
                p.presentaciones[existingIndex].activo = 0;
            } else {
                p.presentaciones.pop();
            }
            renderRowHTML(productId);
        }
    }

    // Enviar cambios del producto completo al servidor
    async function persistProductToServer(product) {
        const statusEl = document.getElementById(`status_${product.id}`);
        statusEl.innerHTML = '<span class="text-info"><i class="fa-solid fa-spinner fa-spin"></i> Guardando...</span>';

        const presentacionPayload = [];
        
        // Agregar presentaciones locales activas o inactivas modificadas
        product.presentaciones.forEach(pres => {
            presentacionPayload.push({
                presentacion_id: pres.presentacion_id,
                activo: pres.activo,
                factor_conversion: pres.factor_conversion,
                precio_venta: pres.precio_venta || 0.00
            });
        });

        // Agregar desactivaciones por intercambio (swaps)
        if (product.deactivatedPresIds) {
            product.deactivatedPresIds.forEach(oldId => {
                presentacionPayload.push({
                    presentacion_id: oldId,
                    activo: 0,
                    factor_conversion: 1,
                    precio_venta: 0.00
                });
            });
        }

        // Asegurar desactivación de las que no están en memoria
        const processedIds = presentacionPayload.map(pr => pr.presentacion_id);
        masterPresentaciones.forEach(m => {
            if (!processedIds.includes(m.id)) {
                presentacionPayload.push({
                    presentacion_id: m.id,
                    activo: 0,
                    factor_conversion: 1,
                    precio_venta: 0.00
                });
            }
        });

        try {
            const res = await fetch('?action=save', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    id: product.id,
                    NombreComercial: product.NombreComercial,
                    NombreGenerico: product.NombreGenerico,
                    laboratorio: product.laboratorio,
                    CodigoInterno: product.CodigoInterno,
                    CodigoBarra: product.CodigoBarra,
                    presentaciones: presentacionPayload
                })
            });

            const data = await res.json();
            if (data.success) {
                statusEl.innerHTML = '<span class="text-success"><i class="fa-solid fa-cloud-arrow-up"></i> Guardado</span>';
                setTimeout(() => {
                    if (statusEl.innerHTML.includes('cloud-arrow-up')) {
                        statusEl.innerHTML = '<span class="text-secondary small" style="opacity: 0.4;"><i class="fa-solid fa-check"></i> Sincronizado</span>';
                    }
                }, 2000);
                return true;
            } else {
                statusEl.innerHTML = `<span class="text-danger" title="${escapeHtml(data.error)}"><i class="fa-solid fa-circle-exclamation"></i> Error</span>`;
                Swal.fire('Error al guardar', data.error || 'Ocurrió un error.', 'error');
                return false;
            }
        } catch (err) {
            statusEl.innerHTML = '<span class="text-danger"><i class="fa-solid fa-triangle-exclamation"></i> Error Red</span>';
            Swal.fire('Error de red', err.message, 'error');
            return false;
        }
    }

    // Renderizar paginador
    function renderPagination(info) {
        const infoSpan = document.getElementById('paginationInfo');
        const list = document.getElementById('paginationList');
        list.innerHTML = '';

        const start = (info.page - 1) * info.limit + 1;
        const end = Math.min(info.total, info.page * info.limit);
        infoSpan.textContent = `Mostrando ${info.total > 0 ? start : 0} a ${end} de ${info.total} productos`;

        if (info.total_pages <= 1) return;

        // Botón Anterior
        const prevLi = document.createElement('li');
        prevLi.className = `page-item ${info.page === 1 ? 'disabled' : ''}`;
        prevLi.innerHTML = `<a class="page-link" href="#" onclick="loadProducts(${info.page - 1}); return false;"><i class="fa-solid fa-chevron-left"></i></a>`;
        list.appendChild(prevLi);

        let startPage = Math.max(1, info.page - 2);
        let endPage = Math.min(info.total_pages, startPage + 4);
        if (endPage - startPage < 4) {
            startPage = Math.max(1, endPage - 4);
        }

        for (let i = startPage; i <= endPage; i++) {
            const li = document.createElement('li');
            li.className = `page-item ${info.page === i ? 'active' : ''}`;
            li.innerHTML = `<a class="page-link" href="#" onclick="loadProducts(${i}); return false;">${i}</a>`;
            list.appendChild(li);
        }

        // Botón Siguiente
        const nextLi = document.createElement('li');
        nextLi.className = `page-item ${info.page === info.total_pages ? 'disabled' : ''}`;
        nextLi.innerHTML = `<a class="page-link" href="#" onclick="loadProducts(${info.page + 1}); return false;"><i class="fa-solid fa-chevron-right"></i></a>`;
        list.appendChild(nextLi);
    }

    function escapeHtml(str) {
        if (!str) return '';
        return str
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }
</script>
</body>
</html>
