/**
 * Thor Tracker — JavaScript
 * Event delegation, no inline JS in HTML
 *
 * @package Thor
 * @since 8.1.0
 */

document.addEventListener('DOMContentLoaded', function() {

    // ================================================================
    // CLICK HANDLER (consolidated)
    // ================================================================
    document.addEventListener('click', function(e) {

        // 1. Toggle details (table rows and detail panels)
        // HTML: <div data-mtcam-toggle="detail-123" data-mtcam-toggle-icon="icon-123">
        var row = e.target.closest('[data-mtcam-toggle]');
        var rowBlocker = e.target.closest('a, button, input, select, textarea, form, .mtcam-no-toggle');
        if (row && (!rowBlocker || rowBlocker === row)) {
            var target = document.getElementById(row.getAttribute('data-mtcam-toggle'));
            if (target) {
                var isHidden = target.style.display === 'none' || target.style.display === '';
                target.style.display = isHidden ? (target.tagName === 'TR' ? 'table-row' : 'block') : 'none';
                row.setAttribute('aria-expanded', isHidden ? 'true' : 'false');
                var iconId = row.getAttribute('data-mtcam-toggle-icon');
                if (iconId) {
                    var icon = document.getElementById(iconId);
                    if (icon) icon.textContent = isHidden ? '➖' : '➕';
                }
            }
            return;
        }

        // 2. Tab switching
        // HTML: <button data-mtcam-tab="cameras">
        var tab = e.target.closest('[data-mtcam-tab]');
        if (tab) {
            var tabName = tab.getAttribute('data-mtcam-tab');
            document.querySelectorAll('.mtcam-tab').forEach(function(el) {
                el.classList.remove('active');
                el.setAttribute('aria-selected', 'false');
            });
            document.querySelectorAll('.mtcam-tab-content').forEach(function(el) {
                el.classList.remove('active');
            });
            var targetContent = document.getElementById('tab-' + tabName);
            if (targetContent) targetContent.classList.add('active');
            tab.classList.add('active');
            tab.setAttribute('aria-selected', 'true');
            return;
        }

        // 3. Copy to clipboard
        // HTML: <button data-mtcam-copy="text to copy">
        var copyBtn = e.target.closest('[data-mtcam-copy]');
        if (copyBtn) {
            var text = copyBtn.getAttribute('data-mtcam-copy');
            navigator.clipboard.writeText(text).then(function() {
                var orig = copyBtn.textContent;
                copyBtn.textContent = '✅ ' + (typeof mtcamData !== 'undefined' && mtcamData.i18n ? mtcamData.i18n.copied : 'Copied!');
                setTimeout(function() { copyBtn.textContent = orig; }, 1500);
            });
            return;
        }

        // 4. End Monitoring modal — open
        var endBtn = e.target.closest('[data-mtcam-end-monitoring]');
        if (endBtn) {
            var modal = document.getElementById('mtcam-end-monitoring-' + endBtn.getAttribute('data-mtcam-end-monitoring'));
            if (modal) modal.style.display = 'flex';
            return;
        }

        // 5. Modal — close
        if (e.target.classList.contains('mtcam-modal-close') || e.target.classList.contains('mtcam-modal')) {
            var closeModal = e.target.closest('.mtcam-modal') || e.target;
            if (closeModal.classList.contains('mtcam-modal')) closeModal.style.display = 'none';
            return;
        }

        // 6. Delete custom profile
        var delBtn = e.target.closest('[data-mtcam-delete-profile]');
        if (delBtn) {
            var msg = delBtn.getAttribute('data-mtcam-confirm') || (typeof mtcamData !== 'undefined' && mtcamData.i18n ? mtcamData.i18n.confirmDelete : 'Are you sure you want to delete?');
            if (!confirm(msg)) return;
            var profileId = delBtn.getAttribute('data-mtcam-delete-profile');
            var nonce = document.querySelector('input[name="_wpnonce"]');
            var form = document.createElement('form');
            form.method = 'POST';
            form.action = '';
            var nonceInput = document.createElement('input');
            nonceInput.type = 'hidden';
            nonceInput.name = '_wpnonce';
            nonceInput.value = nonce ? nonce.value : '';
            form.appendChild(nonceInput);
            var profileInput = document.createElement('input');
            profileInput.type = 'hidden';
            profileInput.name = 'mtcam_delete_profile';
            profileInput.value = profileId;
            form.appendChild(profileInput);
            document.body.appendChild(form);
            form.submit();
            return;
        }

        // 7. Switch owner type (add camera page)
        // HTML: <button data-mtcam-switch-owner="me">
        var switchOwner = e.target.closest('[data-mtcam-switch-owner]');
        if (switchOwner) {
            thorSwitchOwner(switchOwner.getAttribute('data-mtcam-switch-owner'));
            return;
        }

        // 8. Confirm link (before navigation)
        // HTML: <a data-mtcam-confirm="Are you sure?" href="...">
        var confirmLink = e.target.closest('a[data-mtcam-confirm]');
        if (confirmLink) {
            if (!confirm(confirmLink.getAttribute('data-mtcam-confirm'))) {
                e.preventDefault();
            }
            return;
        }

        // 9. Print page
        // HTML: <button data-mtcam-print>
        var printBtn = e.target.closest('[data-mtcam-print]');
        if (printBtn) {
            window.print();
            return;
        }

        // 10. Navigate (clickable div/element)
        // HTML: <div data-mtcam-navigate="url">
        var navigate = e.target.closest('[data-mtcam-navigate]');
        if (navigate) {
            window.location = navigate.getAttribute('data-mtcam-navigate');
            return;
        }

        // 11. Call global function by name
        // HTML: <button data-mtcam-action="thorExportBackup">
        var actionBtn = e.target.closest('[data-mtcam-action]');
        if (actionBtn) {
            var fn = window[actionBtn.getAttribute('data-mtcam-action')];
            if (typeof fn === 'function') fn();
            return;
        }

        // 12. Detail toggle (stolen cameras widget)
        // HTML: <button data-mtcam-detail-toggle data-mtcam-hide="Hide" data-mtcam-show="Detail">
        var detailToggle = e.target.closest('[data-mtcam-detail-toggle]');
        if (detailToggle) {
            detailToggle.classList.toggle('active');
            var details = detailToggle.closest('.mtcam-stolen-camera');
            if (details) {
                var panel = details.querySelector('.mtcam-stolen-details');
                if (panel) panel.classList.toggle('active');
            }
            var hideText = detailToggle.getAttribute('data-mtcam-hide') || 'Hide';
            var showText = detailToggle.getAttribute('data-mtcam-show') || 'Detail';
            var isActive = detailToggle.classList.contains('active');
            detailToggle.textContent = isActive ? '▲ ' + hideText : '▼ ' + showText;
            detailToggle.setAttribute('aria-expanded', isActive ? 'true' : 'false');
            return;
        }

        // 13. Import preview cancel
        // HTML: <button data-mtcam-hide-element="element-id">
        var hideEl = e.target.closest('[data-mtcam-hide-element]');
        if (hideEl) {
            var target = document.getElementById(hideEl.getAttribute('data-mtcam-hide-element'));
            if (target) target.style.display = 'none';
            return;
        }
    });

    // ================================================================
    // CHANGE HANDLER (consolidated)
    // ================================================================
    document.addEventListener('change', function(e) {

        // 1. Stolen status toggle (radio buttons)
        // HTML: <input type="radio" data-mtcam-stolen-toggle="safe_id" value="active">
        var radio = e.target.closest('[data-mtcam-stolen-toggle]');
        if (radio) {
            var safeId = radio.getAttribute('data-mtcam-stolen-toggle');
            var stolenField = document.getElementById('stolen_date_field_' + safeId);
            var dateInput = document.getElementById('edit_cam_stolen_date_input_' + safeId);
            if (stolenField) {
                var isStolen = (radio.value === 'stolen');
                stolenField.style.display = isStolen ? 'block' : 'none';
                var policeField = document.getElementById('police_field_' + safeId);
                if (policeField) policeField.style.display = isStolen ? 'block' : 'none';
                if (dateInput) {
                    if (isStolen && !dateInput.value) {
                        dateInput.value = new Date().toISOString().split('T')[0];
                    }
                    if (!isStolen) dateInput.value = '';
                }
            }
            return;
        }

        // 2. Auto-submit form on select change
        // HTML: <select data-mtcam-autosubmit>
        var autoSubmit = e.target.closest('[data-mtcam-autosubmit]');
        if (autoSubmit) {
            var parentForm = autoSubmit.closest('form');
            if (parentForm) parentForm.submit();
            return;
        }

        // 4. File import handler
        // HTML: <input type="file" data-mtcam-import-backup>
        var importInput = e.target.closest('[data-mtcam-import-backup]');
        if (importInput) {
            if (typeof thorImportBackup === 'function') thorImportBackup(importInput);
            return;
        }
    });

    // ================================================================
    // SUBMIT HANDLER — confirm before delete
    // ================================================================
    // HTML: <form data-mtcam-confirm="Are you sure?">
    document.addEventListener('submit', function(e) {
        var form = e.target.closest('[data-mtcam-confirm]');
        if (form && !confirm(form.getAttribute('data-mtcam-confirm'))) {
            e.preventDefault();
        }
    });

    // ================================================================
    // INIT: URL parameters (tab, edit)
    // ================================================================
    var urlParams = new URLSearchParams(window.location.search);
    var activeTab = urlParams.get('tab');
    var editCamId = urlParams.get('edit');

    if (activeTab) {
        document.querySelectorAll('.mtcam-tab').forEach(function(el) {
            el.classList.remove('active');
            el.setAttribute('aria-selected', 'false');
        });
        document.querySelectorAll('.mtcam-tab-content').forEach(function(el) {
            el.classList.remove('active');
        });
        var targetTab = document.getElementById('tab-' + activeTab);
        var targetButton = document.querySelector('[data-mtcam-tab="' + activeTab + '"]');
        if (targetTab) targetTab.classList.add('active');
        if (targetButton) {
            targetButton.classList.add('active');
            targetButton.setAttribute('aria-selected', 'true');
        }
    }

    if (editCamId) {
        document.querySelectorAll('.mtcam-tab, .mtcam-tab-content').forEach(function(el) {
            el.classList.remove('active');
        });
        var camerasTab = document.getElementById('tab-cameras');
        var camerasButton = document.querySelector('[data-mtcam-tab="cameras"]');
        if (camerasTab) camerasTab.classList.add('active');
        if (camerasButton) camerasButton.classList.add('active');

        setTimeout(function() {
            var editSection = document.getElementById('edit-section-' + editCamId);
            if (!editSection) return;
            editSection.style.display = 'table-row';
            editSection.scrollIntoView({behavior: 'smooth', block: 'center'});
            editSection.style.backgroundColor = '#fffacd';
            setTimeout(function() { editSection.style.backgroundColor = '#f0f8ff'; }, 2000);
            var url = new URL(window.location);
            url.searchParams.delete('edit');
            window.history.replaceState({}, '', url);
        }, 150);
    }

    // ================================================================
    // INIT: Camera profile autocomplete
    // ================================================================
    function thorProfileAutocomplete(inputEl) {
        if (!inputEl || typeof mtcamData === 'undefined' || !mtcamData.profiles) return;

        var wrap = inputEl.closest('.mtcam-profile-autocomplete-wrap');
        if (!wrap) return;
        var hiddenEl = wrap.querySelector('.mtcam-profile-select') || wrap.querySelector('input[type="hidden"]');
        var dropdown = wrap.querySelector('.mtcam-profile-dropdown');
        var tipEl = wrap.querySelector('.mtcam-profile-tip') || document.getElementById('mtcam-profile-tip');
        if (!dropdown || !hiddenEl) return;

        // Build flat list with categories
        var items = [];
        var catLabels = {'user':'\ud83d\udc64 Custom','basic':'\ud83d\udcf7 Basic','4g':'\ud83d\udcf6 4G/LTE','solar':'\u2600\ufe0f Solar','premium':'\u2b50 Premium'};
        for (var pid in mtcamData.profiles) {
            var p = mtcamData.profiles[pid];
            items.push({id: pid, label: p.label || pid, manufacturer: p.manufacturer || '', category: p.category || 'basic', profile: p});
        }
        // Sort: by manufacturer then label
        items.sort(function(a, b) { return (a.manufacturer + a.label).localeCompare(b.manufacturer + b.label); });

        function renderDropdown(query) {
            var q = (query || '').toLowerCase().trim();
            var html = '';
            var count = 0;

            // Always show "Custom" option first
            if (!q || 'custom'.indexOf(q) !== -1) {
                html += '<div class="mtcam-profile-dropdown-item" data-profile-id="custom">' +
                    '<span>\u2014 ' + (mtcamData.i18n.customCamera || 'Custom camera') + ' \u2014</span></div>';
            }

            // Filter matching items
            var filtered = [];
            items.forEach(function(item) {
                if (item.id === 'custom') return;
                var matchLabel = item.label.toLowerCase().indexOf(q) !== -1;
                var matchMfr = item.manufacturer.toLowerCase().indexOf(q) !== -1;
                if (q && !matchLabel && !matchMfr) return;
                filtered.push(item);
            });

            // Group by manufacturer (alphabetical)
            var lastMfr = '';
            filtered.sort(function(a, b) {
                var cmp = a.manufacturer.localeCompare(b.manufacturer);
                return cmp !== 0 ? cmp : a.label.localeCompare(b.label);
            });

            // Count models per manufacturer for group headers
            var mfrCounts = {};
            filtered.forEach(function(item) {
                var m = item.manufacturer || '?';
                mfrCounts[m] = (mfrCounts[m] || 0) + 1;
            });

            var catBadges = {'basic':'\ud83d\udcf7','4g':'\ud83d\udcf6','solar':'\u2600\ufe0f','premium':'\u2b50','user':'\ud83d\udc64'};
            filtered.forEach(function(item) {
                if (item.manufacturer !== lastMfr) {
                    lastMfr = item.manufacturer;
                    var mfrCount = mfrCounts[lastMfr] || 0;
                    html += '<div class="mtcam-profile-dropdown-group">' + lastMfr + ' (' + mfrCount + ')</div>';
                }
                var badge = catBadges[item.category] || '';
                html += '<div class="mtcam-profile-dropdown-item" data-profile-id="' + item.id + '">' +
                    '<span>' + badge + ' ' + item.label + '</span>' +
                    '<small>' + (catLabels[item.category] || item.category) + '</small></div>';
                count++;
            });

            if (count === 0 && q) {
                html += '<div class="mtcam-profile-dropdown-empty">' + (mtcamData.i18n.noResults || 'No models found') + '</div>';
            }

            dropdown.innerHTML = html;
            dropdown.style.display = html ? '' : 'none';
        }

        function selectProfile(profileId) {
            hiddenEl.value = profileId;
            var profile = mtcamData.profiles[profileId];
            if (profileId === 'custom') {
                inputEl.value = '';
            } else if (profile) {
                inputEl.value = profile.label || profileId;
            }
            dropdown.style.display = 'none';

            // Trigger profile apply
            thorApplyProfile(profileId, wrap);
        }

        inputEl.addEventListener('focus', function() {
            renderDropdown(this.value);
        });

        inputEl.addEventListener('input', function() {
            renderDropdown(this.value);
            // If text doesn't match any profile, set to custom
            hiddenEl.value = 'custom';
        });

        dropdown.addEventListener('mousedown', function(e) {
            var item = e.target.closest('.mtcam-profile-dropdown-item');
            if (item && item.dataset.profileId) {
                e.preventDefault();
                selectProfile(item.dataset.profileId);
            }
        });

        inputEl.addEventListener('blur', function() {
            setTimeout(function() { dropdown.style.display = 'none'; }, 150);
        });

        inputEl.addEventListener('keydown', function(e) {
            if (e.key === 'Escape') {
                dropdown.style.display = 'none';
                return;
            }
            var active = dropdown.querySelector('.mtcam-profile-dropdown-item.active');
            var allItems = dropdown.querySelectorAll('.mtcam-profile-dropdown-item');
            if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
                e.preventDefault();
                var idx = -1;
                allItems.forEach(function(el, i) { if (el.classList.contains('active')) idx = i; });
                if (active) active.classList.remove('active');
                if (e.key === 'ArrowDown') idx = (idx + 1) % allItems.length;
                else idx = (idx - 1 + allItems.length) % allItems.length;
                if (allItems[idx]) {
                    allItems[idx].classList.add('active');
                    allItems[idx].scrollIntoView({block: 'nearest'});
                }
            }
            if (e.key === 'Enter') {
                e.preventDefault();
                if (active && active.dataset.profileId) {
                    selectProfile(active.dataset.profileId);
                }
            }
        });
    }

    /**
     * Apply profile settings to the form (shared by add + edit)
     */
    function thorApplyProfile(profileId, wrap) {
        if (typeof mtcamData === 'undefined' || !mtcamData.profiles) return;
        var profile = mtcamData.profiles[profileId];
        if (!profile && profileId !== 'custom') return;
        if (!profile) profile = {};

        var form = wrap.closest('form');
        var tipEl = wrap.querySelector('.mtcam-profile-tip') || document.getElementById('mtcam-profile-tip');

        if (tipEl) {
            tipEl.textContent = profile.tip ? '\ud83d\udca1 ' + profile.tip : '';
            tipEl.style.display = profile.tip ? 'block' : 'none';
        }

        // Detect add vs edit form by checking hidden input name
        var hiddenInput = wrap.querySelector('input[type="hidden"]');
        var fieldName = hiddenInput ? hiddenInput.getAttribute('name') : '';
        var isEdit = fieldName && fieldName.indexOf('edit_cam_') === 0;
        var camId = isEdit ? fieldName.replace('edit_cam_profile_', '') : '';
        var prefix = isEdit ? 'edit_cam_' + camId : 'new_cam_';

        // Manufacturer
        var mfSel = isEdit ? 'input[name="edit_cam_manufacturer_' + camId + '"]' : 'input[name="new_cam_manufacturer"]';
        var mfField = form ? form.querySelector(mfSel) : document.querySelector(mfSel);
        if (mfField) mfField.value = profile.manufacturer || '';

        // Power type — rebuild option list and value from profile.power_types (works for both add and edit forms).
        // Always dispatch a change event at the end so dependent UI (solar field visibility) reacts.
        var ptSel = isEdit ? 'select[name="edit_cam_power_type_' + camId + '"]' : 'select[name="new_cam_power_type"]';
        var ptField = form ? form.querySelector(ptSel) : document.querySelector(ptSel);
        if (ptField) {
            var allowed = (profile.power_types && profile.power_types.length) ? profile.power_types : null;
            if (mtcamData.powerTypes) {
                var keys = allowed || Object.keys(mtcamData.powerTypes);
                var currentVal = ptField.value;
                ptField.innerHTML = '';
                for (var i = 0; i < keys.length; i++) {
                    var key = keys[i];
                    if (!mtcamData.powerTypes[key]) continue;
                    var opt = document.createElement('option');
                    opt.value = key;
                    opt.textContent = mtcamData.powerTypes[key];
                    ptField.appendChild(opt);
                }
                ptField.value = keys.indexOf(currentVal) !== -1 ? currentVal : (keys[0] || '');
            } else if (allowed) {
                // Fallback: powerTypes catalog not localised — at least pick first allowed value.
                ptField.value = allowed[0];
            }
            ptField.dispatchEvent(new Event('change', { bubbles: true }));
        }

        // Accessories
        var accFields = ['acc_battery', 'acc_sdcard', 'acc_lock', 'acc_gpstrack', 'acc_sim'];
        var defaults = profile.default_accessories || [];
        var accPrefix = isEdit ? 'edit_cam_' : 'new_cam_';
        accFields.forEach(function(acc) {
            var sel = 'input[name="' + accPrefix + acc + (isEdit ? '_' + camId : '') + '"]';
            var cb = form ? form.querySelector(sel) : document.querySelector(sel);
            if (cb) cb.checked = defaults.indexOf(acc) !== -1;
        });

        // Resolution select (edit form)
        if (isEdit) {
            var resSelect = form ? form.querySelector('select[name="edit_cam_rec_resolution_' + camId + '"]') : null;
            if (resSelect && profile.video_resolutions && profile.video_resolutions.length > 0) {
                var resLabels = {'4K':'4K Ultra HD','2K':'2K (2560\u00d71440)','1296p':'1296p','1080p':'1080p Full HD','720p':'720p','480p':'480p'};
                var curRes = resSelect.value;
                resSelect.innerHTML = '';
                profile.video_resolutions.forEach(function(res) {
                    var opt = document.createElement('option');
                    opt.value = res;
                    opt.textContent = resLabels[res] || res;
                    resSelect.appendChild(opt);
                });
                resSelect.value = profile.video_resolutions.indexOf(curRes) !== -1 ? curRes : profile.video_resolutions[0];
            }
        }

        // SIM + IMEI visibility
        var hasSim = !!profile.has_sim;
        var searchRoot = form || document;
        var simRow = searchRoot.querySelector('[data-mtcam-acc="sim"]');
        if (simRow) {
            simRow.style.display = hasSim ? '' : 'none';
            if (!hasSim) {
                var simCb = simRow.querySelector('input[type="checkbox"]');
                if (simCb) simCb.checked = false;
            }
        }
        var imeiField = searchRoot.querySelector('[data-mtcam-field="imei"]');
        if (imeiField) {
            imeiField.style.display = hasSim ? '' : 'none';
        }
    }

    // Init autocomplete on all profile inputs
    document.querySelectorAll('.mtcam-profile-input').forEach(thorProfileAutocomplete);

    // ================================================================
    // INIT: Disable hidden "other camera" form inputs
    // ================================================================
    var otherForm = document.getElementById('form-other-camera');
    if (otherForm) {
        thorToggleFormInputs(otherForm, true);
    }

    // --- Duplicate camera ID check ---
    var camIdInput = document.querySelector('input[name="new_cam_id"]');
    if (camIdInput && typeof mtcamData !== 'undefined' && mtcamData.ajaxUrl) {
        var camIdTimer = null;
        var camIdWarn = null;
        camIdInput.addEventListener('input', function() {
            if (camIdTimer) clearTimeout(camIdTimer);
            if (camIdWarn) { camIdWarn.remove(); camIdWarn = null; }
            var val = camIdInput.value.trim();
            if (!val) return;
            camIdTimer = setTimeout(function() {
                var fd = new FormData();
                fd.append('action', 'mtcam_check_cam_id');
                fd.append('_ajax_nonce', mtcamData.camIdNonce);
                fd.append('cam_id', val);
                fetch(mtcamData.ajaxUrl, { method: 'POST', body: fd })
                    .then(function(r) { return r.json(); })
                    .then(function(data) {
                        if (data.success && data.data.exists) {
                            camIdWarn = document.createElement('small');
                            camIdWarn.style.cssText = 'color:#d63638;font-weight:600;display:block;margin-top:4px;';
                            camIdWarn.textContent = (mtcamData.i18n && mtcamData.i18n.duplicateId) || 'Camera with this ID already exists!';
                            camIdInput.parentNode.appendChild(camIdWarn);
                        }
                    });
            }, 500);
        });
    }

});

/**
 * Toggle form inputs — used on add camera page for owner type switching
 */
function thorToggleFormInputs(container, disabled) {
    var inputs = container.querySelectorAll('input, select, textarea, button');
    for (var i = 0; i < inputs.length; i++) {
        inputs[i].disabled = disabled;
    }
}

/**
 * Switch between My Camera / Other's Camera form
 */
function thorSwitchOwner(type) {
    var myForm = document.getElementById('form-my-camera');
    var otherForm = document.getElementById('form-other-camera');
    var ownerInput = document.getElementById('owner_type_input');
    var btnMy = document.getElementById('mtcam-toggle-my');
    var btnOther = document.getElementById('mtcam-toggle-other');
    if (!myForm || !otherForm) return;

    if (type === 'other') {
        myForm.style.display = 'none';
        otherForm.style.display = 'block';
        ownerInput.value = 'other';
        thorToggleFormInputs(myForm, true);
        thorToggleFormInputs(otherForm, false);
        btnMy.className = 'button';
        btnOther.className = 'button button-primary';
    } else {
        myForm.style.display = 'block';
        otherForm.style.display = 'none';
        ownerInput.value = 'me';
        thorToggleFormInputs(myForm, false);
        thorToggleFormInputs(otherForm, true);
        btnMy.className = 'button button-primary';
        btnOther.className = 'button';
    }
}

// ─── Battery capacity preview (preset × cell_count) ───
(function () {
    function updatePreview(scope) {
        if (!scope) return;
        var sel     = scope.querySelector('.mtcam-battery-preset-select');
        var count   = scope.querySelector('.mtcam-cell-count-input');
        var preview = scope.querySelector('.mtcam-capacity-preview');
        if (!preview || !sel || !count) return;
        var data = (window.mtcamData && mtcamData.batteryPresets) || {};
        var preset = data[sel.value];
        var n      = parseInt(count.value, 10) || 0;
        if (!preset || n <= 0) {
            preview.textContent = '';
            return;
        }
        var total = preset.mah * n;
        var tpl   = (mtcamData.i18n && mtcamData.i18n.capacityPreview) || '%1$d × %2$d mAh = %3$d mAh @ %4$s V';
        preview.textContent = tpl
            .replace('%1$d', n)
            .replace('%2$d', preset.mah)
            .replace('%3$d', total)
            .replace('%4$s', preset.voltage);
    }
    function scopeOf(el) {
        // Same form/section is the nearest per-camera grid (edit form) or the whole add form.
        return el.closest('.mtcam-edit-grid-3col, form, fieldset') || document;
    }
    function handler(ev) {
        var el = ev.target;
        if (!el.classList) return;
        if (el.classList.contains('mtcam-battery-preset-select') || el.classList.contains('mtcam-cell-count-input')) {
            updatePreview(scopeOf(el));
        }
    }
    document.addEventListener('change', handler);
    document.addEventListener('input', handler);
    document.addEventListener('DOMContentLoaded', function () {
        document.querySelectorAll('.mtcam-battery-preset-select').forEach(function (el) {
            updatePreview(scopeOf(el));
        });
    });
})();

// ─── Solar panel field visibility (toggled by power_type select) ───
(function () {
    var SOLAR_TYPES = ['solar', 'solar_lithium', 'solar_lead'];
    function fieldFor(sel) {
        var scope = sel.closest('.mtcam-edit-grid-3col, form, fieldset, .mtcam-edit-grid') || document;
        var input = scope.querySelector('input[name^="new_cam_solar_panel_w"], input[name^="edit_cam_solar_panel_w"]');
        return input ? input.closest('.mtcam-edit-field') : null;
    }
    function sync(sel) {
        var field = fieldFor(sel);
        if (!field) return;
        field.style.display = SOLAR_TYPES.indexOf(sel.value) !== -1 ? '' : 'none';
    }
    document.addEventListener('change', function (ev) {
        if (ev.target && ev.target.classList && ev.target.classList.contains('mtcam-power-type-select')) {
            sync(ev.target);
        }
    });
    document.addEventListener('DOMContentLoaded', function () {
        document.querySelectorAll('.mtcam-power-type-select').forEach(sync);
    });
})();
