/**
 * products.js — Product table rendering and inline editing
 */

const Products = {
    /**
     * Render full product table from JSON data
     */
    render(data) {
        const container = document.getElementById('productTable');
        const products = data.products || [];
        const pagination = data.pagination || {};

        if (products.length === 0) {
            container.innerHTML = `
                <div class="empty-state">
                    <i class="fas fa-capsules"></i>
                    <p>No se encontraron productos</p>
                    <small>Intenta otra búsqueda o agrega un nuevo producto</small>
                </div>`;
            document.getElementById('pagination').innerHTML = '';
            return;
        }

        let html = `<table class="product-table">
            <thead><tr>
                <th class="col-codigo">Código</th>
                <th class="col-producto">Producto</th>
                <th class="col-pres">Presentaciones</th>
                <th class="col-costo bg-cost">Costo<br>Unid</th>
                <th class="col-costo bg-cost">Costo<br>Blist</th>
                <th class="col-costo bg-cost">Costo<br>Mayor</th>
                <th class="col-precio bg-price">Vta<br>Unid</th>
                <th class="col-precio bg-price">Vta<br>Blist</th>
                <th class="col-precio bg-price">Vta<br>Mayor</th>
                <th class="col-precio bg-price">Vta<br>Mixta</th>
                <th class="col-fecha">Costo / Venc.</th>
                <th class="col-iva">Exento</th>
                <th class="col-acc">Acción</th>
            </tr></thead>
            <tbody>`;

        for (const p of products) {
            html += this._renderRow(p, data);
        }

        html += '</tbody></table>';
        container.innerHTML = html;

        // Render pagination
        this._renderPagination(pagination);

        // Bind events
        this._bindEvents();
    },

    /**
     * Render a single product row
     */
    _renderRow(p, data) {
        const id = p.id;
        const specific = p.specific || null;
        const useSpecific = !!specific;

        // 1. Determine cost and date source (Priority: Specific > Absolute Latest > Master Table)
        const al = p.absolute_latest || null;
        
        let costoU = p.CostoUnidad || 0;
        let costoB = p.CostoBlister || 0;
        let costoM = p.CostoMayor || 0;
        let fechaIngreso = p.FechaIngreso || '';
        let fechaVenc = p.FechaVencimiento || '';

        if (useSpecific) {
            costoU = specific.costo_unidad || 0;
            costoB = specific.costo_blister || 0;
            costoM = specific.costo_mayor || 0;
            fechaIngreso = specific.fecha_ingreso || '';
            fechaVenc = specific.fecha_vencimiento || '';
        } else if (al) {
            costoU = al.costo_unidad || 0;
            costoB = al.costo_blister || 0;
            costoM = al.costo_mayor || 0;
            fechaIngreso = al.fecha || '';
            fechaVenc = al.fecha_vencimiento || '';
        }

        // 1.1 Context for Last Purchase (for sub-text/labels)
        const lastDate = al ? al.fecha : '';
        const lastLugar = al ? al.lugar_nombre : '';
        const isUsingGlobalLatest = !useSpecific && !!al;

        // Factors
        const factorCaja = parseFloat(p.FactorCaja) || 0;
        const factorBlister = parseFloat(p.FactorBlister) || 0;
        const activoBlister = parseInt(p.ActivoBlister) === 1;
        const activoCaja = parseInt(p.ActivoCaja) === 1;
        const facturableUnidad = parseInt(p.FacturableUnidad) === 1;
        const facturableBlister = parseInt(p.FacturableBlister) === 1;
        const facturableCaja = parseInt(p.FacturableCaja) === 1;

        // Auto-calculate blister/mayor if 0 + factor exists
        const displayCostoB = costoB > 0 ? costoB : (factorBlister > 0 && costoU > 0 ? costoU * factorBlister : 0);
        const displayCostoM = costoM > 0 ? costoM : (factorCaja > 0 && costoU > 0 ? costoU * factorCaja : 0);

        // Stock
        const stockFact = useSpecific ? (specific.stock_facturado || 0) : (al ? (al.stock_facturado || 0) : 0);
        const stockNoFact = useSpecific ? (specific.stock_no_facturado || 0) : (al ? (al.stock_no_facturado || 0) : 0);
        const stockTotal = p.stock_total || 0;

        // Dates cleanup
        const fechaAct = p.fecha_actualizacion || '';

        // Check if product has been updated recently (Ingreso or Actualizacion from 2025+)
        const checkYear = (d) => d ? parseInt(d.substring(0, 4)) : 0;
        const baseFechaIngreso = p.FechaIngreso || '';
        const isUpdated = checkYear(fechaIngreso) >= 2025 || checkYear(fechaAct) >= 2025 || checkYear(baseFechaIngreso) >= 2025;

        // IVA
        const isExento = useSpecific ? specific.exento_iva : (al ? al.exento_iva : (p.exento_iva || 0));

        // Locations HTML for sub-row
        const activeLugarId = useSpecific ? specific.lugar_compra_id : (al ? al.id : null);

        let lugaresHtml = '<span style="color:var(--text-muted);font-size:0.75rem">Sin lugares asignados</span>';
        if (p.lugares && p.lugares.length > 0) {
            lugaresHtml = p.lugares.map(l => {
                const shortName = truncate(l.nombre, 15);
                const isActive = activeLugarId == l.id;
                return `<div class="lugar-badge ${isActive ? 'active' : ''}" title="${escapeHtml(l.nombre)}" 
                             data-producto-id="${id}" data-lugar-id="${l.id}">
                    <span class="lugar-name">${escapeHtml(shortName)}</span>
                    <span class="lugar-remove" data-producto-id="${id}" data-lugar-id="${l.id}" title="Eliminar">×</span>
                </div>`;
            }).join('');
        }

        const rowClass = isUpdated ? 'row-updated' : 'row-not-updated';

        // CLIENT-SIDE FILTER (Safety second layer)
        const filter = App.currentUpdateFilter || 'all';
        if (filter === 'updated' && !isUpdated) return '';
        if (filter === 'not_updated' && isUpdated) return '';

        const totalCols = 13; // 14 - 1 (Costo Mixto removed)

        // Presentations content (Editable Factors and Facturabilidad)
        const presHtml = `
            <div class="pres-group" style="display:flex;align-items:center;gap:8px;width:100%">
                <span style="font-size:0.75rem;font-weight:600;min-width:45px">Unidad</span>
                <label class="checkbox-label" style="display:inline-flex;align-items:center;gap:4px;font-size:0.7rem;cursor:pointer;margin-left:auto" title="Facturar por defecto en POS">
                    <input type="checkbox" class="facturabilidad-toggle" data-presentation="unidad" ${facturableUnidad ? 'checked' : ''} style="width:12px;height:12px;cursor:pointer">
                    <span>Fact.</span>
                </label>
            </div>
            <div class="pres-group" style="display:flex;align-items:center;gap:8px;width:100%;margin-top:4px">
                <label class="checkbox-label" style="display:inline-flex;align-items:center;gap:4px;font-size:0.75rem;cursor:pointer;font-weight:600;min-width:45px">
                    <input type="checkbox" class="pres-toggle" data-presentation="blister" ${activoBlister ? 'checked' : ''} style="width:14px;height:14px;cursor:pointer">
                    <span>Blister</span>
                </label>
                <input type="number" step="0.01" class="units-input ${activoBlister ? '' : 'hidden'}" data-field="FactorBlister" value="${factorBlister || 0}" style="width:40px;height:20px;padding:2px;font-size:0.75rem;margin-left:auto">
                <label class="checkbox-label ${activoBlister ? '' : 'hidden'}" style="display:inline-flex;align-items:center;gap:4px;font-size:0.7rem;cursor:pointer" title="Facturar por defecto en POS">
                    <input type="checkbox" class="facturabilidad-toggle" data-presentation="blister" ${facturableBlister ? 'checked' : ''} style="width:12px;height:12px;cursor:pointer">
                    <span>Fact.</span>
                </label>
            </div>
            <div class="pres-group" style="display:flex;align-items:center;gap:8px;width:100%;margin-top:4px">
                <label class="checkbox-label" style="display:inline-flex;align-items:center;gap:4px;font-size:0.75rem;cursor:pointer;font-weight:600;min-width:45px">
                    <input type="checkbox" class="pres-toggle" data-presentation="caja" ${activoCaja ? 'checked' : ''} style="width:14px;height:14px;cursor:pointer">
                    <span>Caja</span>
                </label>
                <input type="number" step="0.01" class="units-input ${activoCaja ? '' : 'hidden'}" data-field="FactorCaja" value="${factorCaja || 0}" style="width:40px;height:20px;padding:2px;font-size:0.75rem;margin-left:auto">
                <label class="checkbox-label ${activoCaja ? '' : 'hidden'}" style="display:inline-flex;align-items:center;gap:4px;font-size:0.7rem;cursor:pointer" title="Facturar por defecto en POS">
                    <input type="checkbox" class="facturabilidad-toggle" data-presentation="caja" ${facturableCaja ? 'checked' : ''} style="width:12px;height:12px;cursor:pointer">
                    <span>Fact.</span>
                </label>
            </div>
        `;

        return `<tr data-id="${id}" data-latest-lugar-id="${al ? al.id : ''}" data-latest-purchase-id="${al ? al.purchase_id : ''}" class="${rowClass} product-main-row">
            <td>
                <div class="cell-editable" data-field="CodigoInterno"><strong>${escapeHtml(p.CodigoInterno)}</strong></div>
                <div class="cell-editable" data-field="CodigoBarra" style="font-size:0.72rem;color:var(--text-muted)">${escapeHtml(p.CodigoBarra)}</div>
            </td>
            <td style="white-space:normal">
                <div class="cell-editable product-name" data-field="NombreComercial">${escapeHtml(p.NombreComercial)}</div>
                <div class="cell-editable product-generic" data-field="NombreGenerico">${escapeHtml(p.NombreGenerico)}</div>
                <div class="cell-editable product-lab" data-field="laboratorio">${escapeHtml(p.laboratorio)}</div>
                ${p.FuncionMedica ? `<div class="cell-editable product-funcion" data-field="FuncionMedica" title="${escapeHtml(p.FuncionMedica)}">${escapeHtml(p.FuncionMedica)}</div>` : ''}
            </td>

            <!-- Presentations -->
            <td class="col-pres">
                <div class="product-pres-info">
                   ${presHtml}
                </div>
            </td>

            <!-- Costs -->
            <td class="bg-cost"><input type="number" step="0.01" class="table-input cost-input" data-field="CostoUnidad" value="${formatCurrency(costoU)}"></td>
            <td class="bg-cost"><input type="number" step="0.01" class="table-input cost-input" data-field="CostoBlister" value="${formatCurrency(displayCostoB)}"></td>
            <td class="bg-cost"><input type="number" step="0.01" class="table-input cost-input" data-field="CostoMayor" value="${formatCurrency(displayCostoM)}"></td>

            <!-- Prices -->
            <td class="bg-price"><input type="number" step="0.01" class="table-input price-input" data-field="PrecioVentaUnidad" value="${formatCurrency(p.PrecioVentaUnidad)}"></td>
            <td class="bg-price"><input type="number" step="0.01" class="table-input price-input" data-field="PrecioVentaBlister" value="${formatCurrency(p.PrecioVentaBlister)}"></td>
            <td class="bg-price"><input type="number" step="0.01" class="table-input price-input" data-field="PrecioVentaMayor" value="${formatCurrency(p.PrecioVentaMayor)}"></td>
            <td class="bg-price"><input type="number" step="0.01" class="table-input price-input" data-field="PrecioVentaMixto" value="${formatCurrency(p.PrecioVentaMixto)}"></td>

            <!-- Dates -->
            <td class="date-cell">
                <div class="date-info-group ${isUsingGlobalLatest ? 'is-latest' : ''}">
                    <span class="date-label">${isUsingGlobalLatest ? 'Últ. Ingreso' : 'Ingreso'}</span>
                    <div class="date-ingreso" data-field="FechaIngreso" data-original="${fechaIngreso}" title="Fecha de entrada de costos">
                        ${formatDate(fechaIngreso) || '---'}
                    </div>
                    ${lastLugar && isUsingGlobalLatest ? `<div class="date-lugar-tag">${escapeHtml(lastLugar)}</div>` : ''}
                </div>
                <div class="date-info-group venc-group">
                    <span class="date-label">Venc.</span>
                    <div class="date-vencimiento" data-field="FechaVencimiento" data-original="${fechaVenc}">
                        ${formatDate(fechaVenc) || '---'}
                    </div>
                </div>
            </td>

            <!-- IVA -->
            <td style="text-align:center">
                <input type="checkbox" class="iva-toggle" ${isExento ? 'checked' : ''} title="Exento IVA">
            </td>

            <!-- Actions -->
            <td style="text-align:center">
                <button class="btn btn-danger-ghost btn-delete" title="Eliminar"><i class="fas fa-trash-alt"></i></button>
            </td>
        </tr>
        <tr data-id="${id}" class="${rowClass} lugar-subrow">
            <td colspan="${totalCols}" class="lugar-subrow-cell">
                <div class="lugar-subrow-content">
                    <i class="fas fa-store lugar-subrow-icon"></i>
                    ${lugaresHtml}
                </div>
            </td>
        </tr>`;
    },

    /**
     * Render pagination controls
     */
    _renderPagination(p) {
        const container = document.getElementById('pagination');
        if (!p || p.total_pages <= 1) {
            container.innerHTML = p ? `<span class="page-info">${p.total} producto(s)</span>` : '';
            return;
        }

        let html = '';
        html += `<button class="page-btn" data-page="${p.page - 1}" ${p.page <= 1 ? 'disabled' : ''}><i class="fas fa-chevron-left"></i></button>`;

        const maxVisible = 7;
        let start = Math.max(1, p.page - Math.floor(maxVisible / 2));
        let end = Math.min(p.total_pages, start + maxVisible - 1);
        if (end - start < maxVisible - 1) start = Math.max(1, end - maxVisible + 1);

        if (start > 1) {
            html += `<button class="page-btn" data-page="1">1</button>`;
            if (start > 2) html += `<span class="page-info">…</span>`;
        }

        for (let i = start; i <= end; i++) {
            html += `<button class="page-btn ${i === p.page ? 'active' : ''}" data-page="${i}">${i}</button>`;
        }

        if (end < p.total_pages) {
            if (end < p.total_pages - 1) html += `<span class="page-info">…</span>`;
            html += `<button class="page-btn" data-page="${p.total_pages}">${p.total_pages}</button>`;
        }

        html += `<button class="page-btn" data-page="${p.page + 1}" ${p.page >= p.total_pages ? 'disabled' : ''}><i class="fas fa-chevron-right"></i></button>`;
        html += `<span class="page-info">${p.total} productos</span>`;

        container.innerHTML = html;

        // Bind pagination clicks
        container.querySelectorAll('.page-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                const pg = parseInt(btn.dataset.page);
                if (!isNaN(pg) && pg >= 1 && pg <= p.total_pages) {
                    App.currentPage = pg;
                    App.loadProducts();
                }
            });
        });
    },

    async refreshRow(id, oldRow) {
        try {
            const res = await API.getProduct(id, App.currentLugarId);
            if (res && res.data && res.data.products && res.data.products.length > 0) {
                const temp = document.createElement('tbody');
                temp.innerHTML = this._renderRow(res.data.products[0], res.data);
                // We now have two rows per product (main + lugar subrow)
                const mainRow = oldRow.classList.contains('product-main-row') ? oldRow : oldRow.previousElementSibling;
                const subRow = mainRow ? mainRow.nextElementSibling : null;
                const newMainRow = temp.querySelector('.product-main-row');
                const newSubRow = temp.querySelector('.lugar-subrow');
                if (mainRow && newMainRow) {
                    mainRow.replaceWith(newMainRow);
                    this._bindEvents(newMainRow);
                    newMainRow.classList.add('row-saved');
                    setTimeout(() => newMainRow.classList.remove('row-saved'), 600);
                }
                if (subRow && newSubRow) {
                    subRow.replaceWith(newSubRow);
                    this._bindEvents(newSubRow);
                }
            }
        } catch (err) {
            console.error('Error al refrescar fila:', err);
        }
    },

    /**
     * Bind all interactive events on the table
     */
    _bindEvents(container = null) {
        if (!container) container = document.querySelector('.product-table');
        const table = container;
        if (!table) return;

        // Inline text editing
        table.querySelectorAll('.cell-editable').forEach(cell => {
            cell.addEventListener('click', (e) => this._startInlineEdit(cell));
        });

        // Cost input: real-time recalculation on 'input', save on 'blur'
        table.querySelectorAll('.cost-input').forEach(input => {
            const original = input.value;
            input.dataset.original = original;
            input.addEventListener('focus', () => { input.dataset.original = input.value; });
            input.addEventListener('input', () => this._recalculateCosts(input));
            input.addEventListener('blur', () => this._saveCostPrice(input));
        });

        // Units/Factors input: real-time recal or save on blur
        table.querySelectorAll('.units-input').forEach(input => {
            input.addEventListener('input', () => this._recalculateCostsFromFactor(input));
            input.addEventListener('blur', () => this._saveFactor(input));
            // Prevent main row from getting focus or other issues
            input.addEventListener('click', (e) => e.stopPropagation());
        });

        // Price input: save on blur (no recalculation needed)
        table.querySelectorAll('.price-input').forEach(input => {
            const original = input.value;
            input.dataset.original = original;
            input.addEventListener('focus', () => { input.dataset.original = input.value; });
            input.addEventListener('blur', () => this._savePriceOnly(input));
        });


        // IVA toggles
        table.querySelectorAll('.iva-toggle').forEach(cb => {
            cb.addEventListener('change', () => this._toggleIva(cb));
        });

        // Presentation toggles
        table.querySelectorAll('.pres-toggle').forEach(cb => {
            cb.addEventListener('change', () => this._togglePresentation(cb));
        });

        // Facturabilidad toggles
        table.querySelectorAll('.facturabilidad-toggle').forEach(cb => {
            cb.addEventListener('change', () => this._toggleFacturabilidad(cb));
        });

        // Delete buttons
        table.querySelectorAll('.btn-delete').forEach(btn => {
            btn.addEventListener('click', () => this._deleteProduct(btn));
        });

        // Location badge clicks (load specific data) — listen to the badge itself
        table.querySelectorAll('.lugar-badge').forEach(el => {
            el.addEventListener('click', (e) => {
                if (e.target.classList.contains('lugar-remove')) return;
                this._clickLocation(el);
            });
        });

        // Location remove
        table.querySelectorAll('.lugar-remove').forEach(el => {
            el.addEventListener('click', (e) => {
                e.stopPropagation();
                this._removeLocation(el);
            });
        });

        // Date field clicks
        table.querySelectorAll('.date-ingreso, .date-vencimiento').forEach(el => {
            el.addEventListener('click', () => this._editDate(el));
        });
    },

    // === Inline text editing ===
    _startInlineEdit(cell) {
        if (cell.querySelector('.inline-input')) return;
        const field = cell.dataset.field;
        const currentText = cell.textContent.trim();
        const row = cell.closest('tr');
        const id = row.dataset.id;

        const input = document.createElement('input');
        input.type = 'text';
        input.className = 'inline-input';
        input.value = currentText;
        cell.textContent = '';
        cell.appendChild(input);
        input.focus();
        input.select();

        const save = async () => {
            const newVal = input.value.trim();
            cell.textContent = newVal || currentText;
            if (newVal && newVal !== currentText) {
                try {
                    await API.updateProduct(id, field, newVal);
                    await Products.refreshRow(id, row);
                } catch (err) {
                    showToast('Error: ' + err.message, 'error');
                    cell.textContent = currentText;
                }
            }
        };

        input.addEventListener('blur', save);
        input.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') input.blur();
            if (e.key === 'Escape') { input.value = currentText; input.blur(); }
        });
    },

    // === Real-time cost recalculation on input ===
    _recalculateCosts(changedInput) {
        const row = changedInput.closest('tr');
        const field = changedInput.dataset.field;
        const value = parseFloat(changedInput.value) || 0;

        // Get factors from the row
        const factorBlister = parseFloat(row.querySelector('.units-input[data-field="FactorBlister"]')?.value) || 0;
        const factorCaja = parseFloat(row.querySelector('.units-input[data-field="FactorCaja"]')?.value) || 0;

        // Helper to get/set cost input by field name
        const getCostInput = (f) => row.querySelector(`.cost-input[data-field="${f}"]`);
        const setCostValue = (f, val) => {
            const inp = getCostInput(f);
            if (inp && inp !== changedInput) {
                inp.value = formatCurrency(val);
            }
        };

        // Derive CostoUnidad from the changed field, then calculate all others
        let costoUnidad = 0;

        switch (field) {
            case 'CostoUnidad':
                costoUnidad = value;
                break;
            case 'CostoBlister':
                costoUnidad = factorBlister > 0 ? value / factorBlister : value;
                break;
            case 'CostoMayor':
                costoUnidad = factorCaja > 0 ? value / factorCaja : value;
                break;
        }

        // Forward-calculate all costs from CostoUnidad
        if (field !== 'CostoUnidad') setCostValue('CostoUnidad', costoUnidad);
        if (field !== 'CostoBlister' && factorBlister > 0) setCostValue('CostoBlister', costoUnidad * factorBlister);
        if (field !== 'CostoMayor' && factorCaja > 0) setCostValue('CostoMayor', costoUnidad * factorCaja);
    },

    // === Save Factor to database ===
    async _saveFactor(input) {
        const row = input.closest('tr');
        const id = row.dataset.id;
        const field = input.dataset.field;
        const value = parseFloat(input.value) || 0;

        try {
            await API.updateProduct(id, field, value);
            // After saving factor, trigger a save of costs to sync database if needed
            // (The UI already recalculated on 'input', but let's ensure costs are pushed)
            this._saveCostPrice(row.querySelector('.cost-input[data-field="CostoUnidad"]'));
        } catch (err) {
            showToast('Error guardando factor: ' + err.message, 'error');
        }
    },

    // === Recalculate costs when a factor (FactorBlister/FactorCaja) changes ===
    _recalculateCostsFromFactor(factorInput) {
        const row = factorInput.closest('tr');
        const costoUnidadInput = row.querySelector('.cost-input[data-field="CostoUnidad"]');
        if (!costoUnidadInput) return;
        const costoUnidad = parseFloat(costoUnidadInput.value) || 0;
        if (costoUnidad <= 0) return;

        const factorField = factorInput.dataset.field;
        const newFactor = parseFloat(factorInput.value) || 0;
        if (newFactor <= 0) return;

        if (factorField === 'FactorBlister') {
            const blisterInput = row.querySelector('.cost-input[data-field="CostoBlister"]');
            if (blisterInput) blisterInput.value = formatCurrency(costoUnidad * newFactor);
        } else if (factorField === 'FactorCaja') {
            const mayorInput = row.querySelector('.cost-input[data-field="CostoMayor"]');
            if (mayorInput) mayorInput.value = formatCurrency(costoUnidad * newFactor);
        }
    },

    // === Save ALL costs on blur (sends all 4 values via AJAX) ===
    async _saveCostPrice(input) {
        // If nothing changed in this specific input, skip
        if (input.value === input.dataset.original) return;
        const row = input.closest('tr');
        const id = row.dataset.id;

        // Collect ALL current cost values from the row (excluding Mixto already removed)
        const costoUnidad = parseFloat(row.querySelector('.cost-input[data-field="CostoUnidad"]')?.value) || 0;
        const costoBlister = parseFloat(row.querySelector('.cost-input[data-field="CostoBlister"]')?.value) || 0;
        const costoMayor = parseFloat(row.querySelector('.cost-input[data-field="CostoMayor"]')?.value) || 0;

        const lugarId = App.currentLugarId;
        try {
            const body = {
                producto_id: parseInt(id),
                lugar_compra_id: lugarId ? parseInt(lugarId) : null,
                costo_unidad: costoUnidad,
                costo_blister: costoBlister,
                costo_mayor: costoMayor,
                costo_mixto: costoUnidad, // Mixto is same as unit
            };
            if (App.currentFecha) body.fecha_ultima_compra = App.currentFecha;
            await API.upsertProductLocation(body);
            await Products.refreshRow(id, row);
        } catch (err) {
            showToast('Error guardando costos: ' + err.message, 'error');
        }

        // Update original values so blur doesn't re-save on no-change
        row.querySelectorAll('.cost-input').forEach(inp => {
            inp.dataset.original = inp.value;
        });
    },

    // === Save price only (individual field, no recalculation) ===
    async _savePriceOnly(input) {
        if (input.value === input.dataset.original) return;
        const row = input.closest('tr');
        const id = row.dataset.id;
        const field = input.dataset.field;
        const value = parseFloat(input.value) || 0;

        try {
            await API.updateProduct(id, field, value);
            await Products.refreshRow(id, row);
        } catch (err) {
            showToast('Error: ' + err.message, 'error');
        }
    },

    // === Presentation toggle ===
    async _togglePresentation(cb) {
        const row = cb.closest('tr');
        const id = row.dataset.id;
        const pres = cb.dataset.presentation;
        const activo = cb.checked;

        // Show/hide units input
        const unitsInput = cb.closest('.pres-group')?.querySelector('.units-input');
        if (unitsInput) {
            unitsInput.classList.toggle('hidden', !activo);
        }

        try {
            await API.updatePresentation(id, pres, activo);
            await Products.refreshRow(id, row);
        } catch (err) {
            showToast('Error: ' + err.message, 'error');
            cb.checked = !activo;
        }
    },

    // === Toggle presentation facturabilidad ===
    async _toggleFacturabilidad(cb) {
        const row = cb.closest('tr');
        const id = row.dataset.id;
        const pres = cb.dataset.presentation;
        const facturable = cb.checked;

        try {
            await API.updatePresentationFacturabilidad(id, pres, facturable);
            await Products.refreshRow(id, row);
        } catch (err) {
            showToast('Error: ' + err.message, 'error');
            cb.checked = !facturable;
        }
    },

    // === Save units factor ===
    async _saveUnitsFactor(input) {
        const row = input.closest('tr');
        const id = row.dataset.id;
        const field = input.dataset.field; // "FactorBlister" or "FactorCaja"
        const value = parseFloat(input.value) || 0;

        const presMap = { 'FactorBlister': 'blister', 'FactorCaja': 'caja' };
        const presName = presMap[field];

        try {
            // Need to know if it's active. We can check the checkbox
            const cb = row.querySelector(`.pres-toggle[data-presentation="${presName}"]`);
            const activo = cb ? cb.checked : true;

            await API.updatePresentation(id, presName, activo, value);
            await Products.refreshRow(id, row);
        } catch (err) {
            showToast('Error: ' + err.message, 'error');
        }
    },

    // === IVA toggle ===
    async _toggleIva(cb) {
        const row = cb.closest('tr');
        const id = row.dataset.id;
        const val = cb.checked;
        cb.disabled = true;

        try {
            await API.updateIva(id, val ? 1 : 0);
            await Products.refreshRow(id, row);
        } catch (err) {
            showToast('Error: ' + err.message, 'error');
            cb.checked = !val;
        } finally {
            cb.disabled = false;
        }
    },

    // === Delete product ===
    async _deleteProduct(btn) {
        const row = btn.closest('tr');
        const id = row.dataset.id;
        const name = row.querySelector('.product-name')?.textContent || '';

        if (!confirm(`¿Eliminar "${name}"?\nEsta acción no se puede deshacer.`)) return;

        try {
            await API.deleteProduct(id);
            // Also remove the lugar subrow
            const subRow = row.nextElementSibling;
            row.style.transition = 'opacity 300ms, transform 300ms';
            row.style.opacity = '0';
            row.style.transform = 'translateX(20px)';
            if (subRow && subRow.classList.contains('lugar-subrow')) {
                subRow.style.transition = 'opacity 300ms, transform 300ms';
                subRow.style.opacity = '0';
                subRow.style.transform = 'translateX(20px)';
                setTimeout(() => subRow.remove(), 300);
            }
            setTimeout(() => row.remove(), 300);
            showToast('Producto eliminado', 'success');
        } catch (err) {
            showToast('Error: ' + err.message, 'error');
        }
    },

    // === Click location badge ===
    async _clickLocation(el) {
        const productoId = el.dataset.productoId;
        const lugarId = el.dataset.lugarId;
        const subRow = el.closest('tr');
        // The main product row is the previous sibling of the lugar sub-row
        const row = subRow.classList.contains('lugar-subrow') ? subRow.previousElementSibling : subRow;

        // Highlight active badge
        subRow.querySelectorAll('.lugar-badge').forEach(b => b.classList.remove('active'));
        el.closest('.lugar-badge').classList.add('active');

        // --- Auto-sync: set globalLugar selector to this location ---
        const globalSelect = document.getElementById('globalLugar');
        if (globalSelect) {
            globalSelect.value = lugarId;
            App.currentLugarId = parseInt(lugarId);
        }

        // Enable cost editing since we now have a location
        this._setCostsEditable(true);

        try {
            const res = await API.getProductLocation(productoId, lugarId);
            if (res && res.data) {
                const d = res.data;
                // Update cost inputs (in main row)
                const setInput = (field, val) => {
                    const inp = row.querySelector(`.cost-input[data-field="${field}"]`);
                    if (inp) { inp.value = formatCurrency(val || 0); inp.dataset.original = inp.value; }
                };
                setInput('CostoUnidad', d.costo_unidad);
                setInput('CostoBlister', d.costo_blister);
                setInput('CostoMayor', d.costo_mayor);
                setInput('CostoMixto', d.costo_mixto);

                // Update dates
                const dateIng = row.querySelector('.date-ingreso');
                const dateVenc = row.querySelector('.date-vencimiento');
                if (dateIng) { dateIng.textContent = formatDate(d.fecha_ingreso); dateIng.dataset.original = d.fecha_ingreso || ''; }
                if (dateVenc) { dateVenc.textContent = formatDate(d.fecha_vencimiento); dateVenc.dataset.original = d.fecha_vencimiento || ''; }

                // --- Auto-sync: set globalFecha to this location's date ---
                const locationDate = d.fecha_ultima_compra || d.fecha_ingreso || '';
                if (locationDate) {
                    App.currentFecha = locationDate;
                    const fechaInput = document.getElementById('globalFecha');
                    if (fechaInput && fechaInput._flatpickr) {
                        fechaInput._flatpickr.setDate(locationDate, true);
                    }
                }

                // Update stock
                const stockCell = row.querySelector('.stock-cell');
                if (stockCell) {
                    const total = (parseInt(d.stock_facturado) || 0) + (parseInt(d.stock_no_facturado) || 0);
                    stockCell.innerHTML = `${total}<div class="stock-detail">${d.stock_facturado || 0}F/${d.stock_no_facturado || 0}NF</div>`;
                }

                // Update IVA
                const ivaCb = row.querySelector('.iva-toggle');
                if (ivaCb) ivaCb.checked = !!d.exento_iva;

                row.classList.add('row-saved');
                setTimeout(() => row.classList.remove('row-saved'), 600);
            }
        } catch (err) {
            showToast('Error cargando datos de lugar: ' + err.message, 'error');
        }
    },

    // === Remove location ===
    async _removeLocation(el) {
        const productoId = el.dataset.productoId;
        const lugarId = el.dataset.lugarId;
        const badge = el.closest('.lugar-badge');
        const lugarName = badge?.querySelector('.lugar-name')?.textContent || '';

        if (!confirm(`¿Eliminar lugar "${lugarName}" de este producto?`)) return;

        try {
            await API.deleteProductLocation(productoId, lugarId);
            await Products.refreshRow(productoId, badge.closest('tr'));
            showToast('Lugar eliminado', 'success');
        } catch (err) {
            showToast('Error: ' + err.message, 'error');
        }
    },

    // === Edit date with flatpickr ===
    _editDate(el) {
        if (el.querySelector('input')) return;
        const row = el.closest('tr');
        const id = row.dataset.id;
        const field = el.dataset.field;
        const original = el.dataset.original || '';

        const input = document.createElement('input');
        input.type = 'text';
        input.className = 'inline-input';
        input.style.width = '80px';
        input.style.fontSize = '0.75rem';
        el.textContent = '';
        el.appendChild(input);

        const fp = flatpickr(input, {
            dateFormat: 'Y-m-d',
            altInput: true,
            altFormat: 'd/m/y',
            defaultDate: original || undefined,
            locale: 'es',
            onClose: async (dates, dateStr) => {
                const finalDate = dateStr || original;
                el.textContent = formatDate(finalDate) || '---';
                el.dataset.original = finalDate || '';
                if (dateStr && dateStr !== original) {
                    try {
                        // 1. Update the base product table (for general consistency)
                        await API.updateProduct(id, field, dateStr);

                        const globalLugarId = App.currentLugarId;
                        const latestLugarId = row.dataset.latestLugarId;
                        const latestPurchaseId = row.dataset.latestPurchaseId;
                        const targetLugarId = globalLugarId || latestLugarId;

                        const body = {
                            id: globalLugarId ? null : (latestPurchaseId || null),
                            producto_id: parseInt(id),
                            lugar_compra_id: targetLugarId ? parseInt(targetLugarId) : null,
                        };
                        if (field === 'FechaIngreso') body.fecha_ingreso = dateStr;
                        else body.fecha_vencimiento = dateStr;
                        await API.upsertProductLocation(body);

                        await Products.refreshRow(id, row);
                    } catch (err) {
                        showToast('Error: ' + err.message, 'error');
                    }
                }
                fp.destroy();
            }
        });
        fp.open();
    },

    // === Enable/Disable all cost inputs ===
    _setCostsEditable(enabled) {
        const table = document.querySelector('.product-table');
        if (!table) return;
        table.querySelectorAll('.cost-input').forEach(inp => {
            inp.disabled = false; // Always enabled to allow editing without selecting location
        });
    },
};

// Helper: hidden class
document.head.insertAdjacentHTML('beforeend', '<style>.hidden{display:none!important}</style>');
