(function () {
    'use strict';
    if (window.__ICY_PRODUCT_COSTING_MODULE_ACTIVE) return;
    window.__ICY_PRODUCT_COSTING_MODULE_ACTIVE = true;
    const listenerController = new AbortController();
    const on = (target, eventName, handler) => target.addEventListener(eventName, handler, { signal: listenerController.signal });
    window.ICY_PAGE_CLEANUPS = window.ICY_PAGE_CLEANUPS || [];
    window.ICY_PAGE_CLEANUPS.push(() => {
        listenerController.abort();
        window.__ICY_PRODUCT_COSTING_MODULE_ACTIVE = false;
        document.body.classList.remove('is-modal-open');
    });

    const $ = (id) => document.getElementById(id);
    const initial = window.ICYLAB_PRODUCT_COSTING_INITIAL || {};
    const state = { from: initial.from || '', to: initial.to || '', data: null, product: null };

    function escapeHtml(value) {
        return String(value == null ? '' : value).replace(/[&<>'"]/g, (char) => ({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[char]));
    }
    function money(value) { return '$' + Math.round(Number(value || 0)).toLocaleString('es-CL'); }
    function number(value, digits) { return Number(value || 0).toLocaleString('es-CL', { minimumFractionDigits: digits || 0, maximumFractionDigits: digits || 0 }); }
    function pct(value) { return value === null || value === undefined || value === '' ? 'N/D' : number(value, 1) + '%'; }
    function today() { return new Date().toISOString().slice(0, 10); }
    function refreshIcons() { if (window.lucide && typeof window.lucide.createIcons === 'function') window.lucide.createIcons(); }

    async function request(url, options) {
        const response = await fetch(url, Object.assign({ credentials: 'same-origin', headers: { Accept: 'application/json' } }, options || {}));
        const text = await response.text();
        let payload = null;
        try { payload = text ? JSON.parse(text) : null; } catch (error) {}
        if (!response.ok || !payload || payload.success === false) throw new Error(payload && payload.message ? payload.message : 'No fue posible completar la operación.');
        return payload;
    }

    async function action(values) {
        const form = values instanceof HTMLFormElement ? new FormData(values) : new FormData();
        if (!(values instanceof HTMLFormElement)) Object.keys(values || {}).forEach((key) => form.append(key, values[key] == null ? '' : values[key]));
        const token = document.querySelector('meta[name="csrf-token"]');
        if (token && !form.has('_csrf_token')) form.append('_csrf_token', token.content);
        return request('/modules/costs/product_cost_action_ajax.php', { method: 'POST', body: form });
    }

    function notice(message, type) {
        const el = $('productCostNotice');
        if (!el) return;
        el.hidden = !message;
        el.textContent = message || '';
        el.className = 'product-cost-notice' + (type ? ' is-' + type : '');
    }

    async function loadWorkspace(successMessage) {
        state.from = $('marginFrom').value;
        state.to = $('marginTo').value;
        if (!state.from || !state.to || state.from > state.to) { notice('Revisa el rango de fechas.', 'error'); return; }
        notice('Actualizando costeo y cobertura…', '');
        try {
            const query = new URLSearchParams({ from: state.from, to: state.to });
            const payload = await request('/modules/costs/product_cost_data_ajax.php?' + query.toString());
            state.data = payload.data;
            renderAll();
            notice(successMessage || '', successMessage ? 'success' : '');
        } catch (error) {
            notice(error.message, 'error');
        }
    }

    function kpi(label, value, note) {
        return '<article class="product-cost-kpi"><span>' + escapeHtml(label) + '</span><strong>' + escapeHtml(value) + '</strong><small>' + escapeHtml(note || '') + '</small></article>';
    }

    function renderAll() {
        const data = state.data;
        if (!data) return;
        const metrics = data.metrics || {};
        $('productCostKpis').innerHTML = [
            kpi('Productos activos', number(metrics.active_products), 'Catálogo vigente'),
            kpi('Costo validado', number(metrics.approved_standard), 'Versiones estándar aprobadas'),
            kpi('Costo provisional', number(metrics.provisional_legacy), 'Heredado del catálogo'),
            kpi('Sin costo', number(metrics.without_cost), 'Requieren definición'),
            kpi('Borradores', number(metrics.drafts), 'Pendientes de aprobación')
        ].join('');
        renderProducts();
        renderCoverage();
        renderMargins();
        const marginAllowed = !!(data.permissions && data.permissions.margin_view);
        $('marginTab').hidden = !marginAllowed;
        refreshIcons();
    }

    function renderProducts() {
        if (!state.data) return;
        const search = ($('productCostSearch').value || '').trim().toLowerCase();
        const rows = (state.data.products || []).filter((product) => !search || [product.name, product.sku, product.category_name].join(' ').toLowerCase().includes(search));
        const canEdit = !!(state.data.permissions && state.data.permissions.edit);
        $('productCostBody').innerHTML = rows.length ? rows.map((product) => {
            let quality = 'missing', label = 'Sin costo';
            if (product.approved_version_id && product.costing_method === 'legacy') { quality = 'provisional'; label = 'Provisional'; }
            else if (product.approved_version_id) { quality = 'validated'; label = 'Aprobado'; }
            const unitCost = Number(product.unit_standard_cost || 0);
            const price = Number(product.price || 0);
            const listMargin = price > 0 && unitCost > 0 ? (price - unitCost) / price * 100 : null;
            const draft = product.draft_version_id ? '<small>Borrador v' + number(product.draft_version_number) + ' pendiente</small>' : '';
            return '<tr data-search="' + escapeHtml([product.name, product.sku].join(' ').toLowerCase()) + '">' +
                '<td><strong>' + escapeHtml(product.name) + '</strong><small>' + escapeHtml(product.sku || 'Sin SKU') + ' · ' + escapeHtml(product.category_name) + '</small></td>' +
                '<td><span class="cost-status ' + quality + '">' + label + '</span>' + draft + '</td>' +
                '<td>' + escapeHtml(product.effective_from || 'Sin vigencia') + '</td>' +
                '<td class="number">' + money(price) + '</td><td class="number">' + (unitCost > 0 ? money(unitCost) : 'N/D') + '</td><td class="number">' + pct(listMargin) + '</td>' +
                '<td class="number"><button class="btn btn-outline btn-sm" type="button" data-open-cost-product="' + escapeHtml(product.id) + '"><i data-lucide="' + (canEdit ? 'pencil' : 'eye') + '"></i><span>' + (canEdit ? 'Costear' : 'Ver') + '</span></button></td></tr>';
        }).join('') : '<tr><td class="empty-row" colspan="7">No hay productos para este filtro.</td></tr>';
        refreshIcons();
    }

    function renderCoverage() {
        const c = state.data.coverage || {};
        $('coverageGrid').innerHTML = [
            kpi('Documentos con líneas', number(c.documents_with_lines) + ' / ' + number(c.documents_total), pct(c.document_coverage_pct) + ' de cobertura'),
            kpi('Documentos sin líneas', number(c.documents_without_lines), 'Excepción histórica'),
            kpi('Líneas con costo', number(c.lines_costed) + ' / ' + number(c.lines_total), pct(c.cost_coverage_pct) + ' del ingreso'),
            kpi('Líneas pendientes', number(c.lines_missing), 'Producto o costo no identificado')
        ].join('').replace(/product-cost-kpi/g, 'coverage-item');
        const warning = $('coverageWarning');
        warning.className = 'coverage-warning ' + (c.reliable ? 'is-ready' : 'is-blocked');
        warning.textContent = c.reliable
            ? 'Cobertura suficiente: el margen del período puede utilizarse como indicador de gestión.'
            : 'Margen oficial bloqueado: faltan líneas históricas o costos identificables. Los datos parciales se muestran solo como referencia.';
        const canApprove = !!(state.data.permissions && state.data.permissions.approve);
        $('rebuildSnapshotsBtn').hidden = !canApprove;
    }

    function renderMargins() {
        const margins = state.data.margins || {};
        const s = margins.summary;
        if (!s) {
            $('marginSummary').innerHTML = kpi('Acceso restringido', '—', 'Solicita el permiso Ver márgenes.');
            $('marginProductBody').innerHTML = $('marginCustomerBody').innerHTML = '<tr><td class="empty-row" colspan="5">Sin permiso para visualizar márgenes.</td></tr>';
            return;
        }
        const reliable = !!s.reliable;
        $('marginSummary').innerHTML = [
            kpi('Venta neta cubierta', money(s.net_revenue), reliable ? 'Cobertura suficiente' : 'Muestra parcial'),
            kpi('Costo vendido', money(s.total_cost), 'Fotografías en CLP'),
            kpi('Contribución', money(s.contribution_margin), reliable ? 'Indicador habilitado' : 'Valor referencial'),
            kpi('Margen contribución', reliable ? pct(s.margin_percent) : 'N/D', reliable ? 'Publicable' : 'Bloqueado por cobertura'),
            kpi('Calidad del costo', s.quality === 'validated' ? 'Validada' : (s.quality === 'provisional' ? 'Provisional' : 'Insuficiente'), 'Según versión aplicada')
        ].join('');
        const marginRows = (rows) => rows.length ? rows.map((row) => '<tr><td><strong>' + escapeHtml(row.label) + '</strong>' + (row.sku ? '<small>' + escapeHtml(row.sku) + '</small>' : '') + '</td><td class="number">' + money(row.net_revenue) + '</td><td class="number">' + money(row.total_cost) + '</td><td class="number">' + money(row.contribution_margin) + '</td><td class="number">' + pct(row.margin_percent) + '</td></tr>').join('') : '<tr><td class="empty-row" colspan="5">Aún no hay líneas costeadas en este período.</td></tr>';
        $('marginProductBody').innerHTML = marginRows(margins.by_product || []);
        $('marginCustomerBody').innerHTML = marginRows(margins.by_customer || []);
    }

    async function openProduct(productId) {
        try {
            notice('Cargando versión de costo…', '');
            const payload = await request('/modules/costs/product_cost_data_ajax.php?product_id=' + encodeURIComponent(productId));
            state.product = payload.data;
            fillProductModal();
            $('productCostModal').classList.add('is-open');
            $('productCostModal').setAttribute('aria-hidden', 'false');
            document.body.classList.add('is-modal-open');
            notice('', '');
        } catch (error) { notice(error.message, 'error'); }
    }

    function fillProductModal() {
        const info = state.product;
        const product = info.product;
        const template = info.template;
        const isDraft = template && template.status === 'draft';
        const permissions = state.data.permissions || {};
        $('productCostModalSku').textContent = product.sku || 'SIN SKU';
        $('productCostModalTitle').textContent = product.name;
        $('productCostModalSubtitle').textContent = (product.category_name || '') + ' · costo catálogo ' + money(product.cost);
        $('costProductId').value = product.id;
        $('costVersionId').value = isDraft ? template.id : '';
        $('costEffectiveFrom').value = isDraft ? template.effective_from : today();
        $('costOutputQuantity').value = template ? template.output_quantity : 1;
        $('costOutputUnit').value = template ? template.output_unit : (product.unit || 'unidad');
        $('costYield').value = template ? template.yield_percent : 100;
        $('costNotes').value = template && template.costing_method !== 'legacy' ? (template.notes || '') : '';
        $('costComponentList').innerHTML = '';
        const components = template && Array.isArray(template.components) ? template.components : [];
        components.forEach(addComponent);
        if (!components.length && permissions.edit) addComponent({ component_type: 'material', description: '', quantity: 1, unit_measure: 'unidad', unit_cost: '', waste_percent: 0 });
        const canEdit = !!permissions.edit;
        Array.from($('productCostForm').querySelectorAll('input,select,textarea')).forEach((field) => { if (field.type !== 'hidden') field.disabled = !canEdit; });
        $('addCostComponentBtn').hidden = !canEdit;
        Array.from($('costComponentList').querySelectorAll('.component-remove')).forEach((button) => { button.hidden = !canEdit; });
        $('productCostForm').querySelector('button[type="submit"]');
        const submit = document.querySelector('button[form="productCostForm"]');
        if (submit) submit.hidden = !canEdit;
        $('approveCostVersionBtn').hidden = !(isDraft && permissions.approve);
        calculateCost();
        refreshIcons();
    }

    function addComponent(component) {
        component = component || { component_type: 'material', description: '', quantity: 1, unit_measure: 'unidad', unit_cost: 0, waste_percent: 0 };
        const types = (state.product && state.product.component_types) || (state.data && state.data.component_types) || {};
        const row = document.createElement('div');
        row.className = 'component-row';
        row.innerHTML = '<select class="select component-type">' + Object.keys(types).map((key) => '<option value="' + escapeHtml(key) + '"' + (key === component.component_type ? ' selected' : '') + '>' + escapeHtml(types[key]) + '</option>').join('') + '</select>' +
            '<input class="input component-description" placeholder="Descripción" maxlength="255" value="' + escapeHtml(component.description || '') + '">' +
            '<input class="input component-quantity cost-calc-input" type="number" min="0.0001" step="0.0001" title="Cantidad" value="' + escapeHtml(component.quantity == null ? 1 : component.quantity) + '">' +
            '<input class="input component-unit" maxlength="50" title="Unidad" value="' + escapeHtml(component.unit_measure || 'unidad') + '">' +
            '<input class="input component-unit-cost cost-calc-input" type="number" min="0" step="0.0001" title="Costo unitario neto" placeholder="Costo neto" value="' + escapeHtml(component.unit_cost == null ? 0 : component.unit_cost) + '">' +
            '<input class="input component-waste cost-calc-input" type="number" min="0" max="100" step="0.01" title="Merma %" value="' + escapeHtml(component.waste_percent == null ? 0 : component.waste_percent) + '">' +
            '<button class="btn btn-outline component-remove" type="button" title="Quitar"><i data-lucide="trash-2"></i></button>';
        $('costComponentList').appendChild(row);
        refreshIcons();
        calculateCost();
    }

    function componentsFromForm() {
        return Array.from($('costComponentList').querySelectorAll('.component-row')).map((row) => ({
            component_type: row.querySelector('.component-type').value,
            description: row.querySelector('.component-description').value.trim(),
            quantity: row.querySelector('.component-quantity').value,
            unit_measure: row.querySelector('.component-unit').value.trim(),
            unit_cost: row.querySelector('.component-unit-cost').value,
            waste_percent: row.querySelector('.component-waste').value
        }));
    }

    function calculateCost() {
        const batch = componentsFromForm().reduce((total, component) => total + Number(component.quantity || 0) * Number(component.unit_cost || 0) * (1 + Number(component.waste_percent || 0) / 100), 0);
        const output = Number($('costOutputQuantity').value || 0) * (Number($('costYield').value || 0) / 100);
        $('costBatchTotal').textContent = money(batch);
        $('costUnitTotal').textContent = output > 0 ? money(batch / output) : 'N/D';
    }

    function closeModal() {
        $('productCostModal').classList.remove('is-open');
        $('productCostModal').setAttribute('aria-hidden', 'true');
        document.body.classList.remove('is-modal-open');
    }

    async function saveDraft(event) {
        event.preventDefault();
        const components = componentsFromForm();
        if (!components.length) { notice('Agrega al menos un componente.', 'error'); return; }
        $('costComponentsJson').value = JSON.stringify(components);
        try {
            const payload = await action($('productCostForm'));
            $('costVersionId').value = payload.data.version_id;
            if (state.data.permissions.approve) $('approveCostVersionBtn').hidden = false;
            await loadWorkspace('Borrador guardado. Costo unitario estimado: ' + money(payload.data.unit_standard_cost) + '.');
        } catch (error) { notice(error.message, 'error'); }
    }

    async function approveVersion() {
        const versionId = Number($('costVersionId').value || 0);
        if (!versionId) { notice('Guarda el borrador antes de aprobarlo.', 'error'); return; }
        if (!window.confirm('¿Aprobar esta versión? El costo quedará vigente desde la fecha indicada y las ventas futuras conservarán su fotografía.')) return;
        try {
            await action({ action: 'approve_version', version_id: versionId });
            closeModal();
            await loadWorkspace('Versión aprobada y costo vigente actualizado.');
        } catch (error) { notice(error.message, 'error'); }
    }

    async function rebuildSnapshots() {
        if (!window.confirm('Se procesarán únicamente líneas de venta locales demostrables en el rango seleccionado. ¿Continuar?')) return;
        try {
            const payload = await action({ action: 'rebuild_snapshots', from: state.from, to: state.to });
            await loadWorkspace('Fotografías actualizadas: ' + number(payload.data.documents) + ' documentos, ' + number(payload.data.costed) + ' líneas con costo y ' + number(payload.data.missing) + ' pendientes.');
        } catch (error) { notice(error.message, 'error'); }
    }

    on(document, 'click', (event) => {
        const tab = event.target.closest('[data-product-cost-tab]');
        if (tab) {
            document.querySelectorAll('[data-product-cost-tab]').forEach((el) => el.classList.toggle('is-active', el === tab));
            document.querySelectorAll('[data-product-cost-panel]').forEach((panel) => panel.classList.toggle('is-active', panel.getAttribute('data-product-cost-panel') === tab.getAttribute('data-product-cost-tab')));
            return;
        }
        const open = event.target.closest('[data-open-cost-product]');
        if (open) { openProduct(open.getAttribute('data-open-cost-product')); return; }
        if (event.target.closest('[data-close-product-cost]')) { closeModal(); return; }
        const remove = event.target.closest('.component-remove');
        if (remove) { remove.closest('.component-row').remove(); calculateCost(); }
    });
    on(document, 'input', (event) => { if (event.target.matches('.cost-calc-input')) calculateCost(); });
    on($('productCostSearch'), 'input', renderProducts);
    on($('refreshCostingBtn'), 'click', () => loadWorkspace());
    on($('addCostComponentBtn'), 'click', () => addComponent());
    on($('productCostForm'), 'submit', saveDraft);
    on($('approveCostVersionBtn'), 'click', approveVersion);
    on($('rebuildSnapshotsBtn'), 'click', rebuildSnapshots);
    on($('productCostModal'), 'click', (event) => { if (event.target === $('productCostModal')) closeModal(); });
    on(document, 'keydown', (event) => { if (event.key === 'Escape' && $('productCostModal').classList.contains('is-open')) closeModal(); });

    loadWorkspace();
})();
