/* Sync .is-checked on image-select / image-radio options.
   Checkboxes: each label is independent — `change` fires per input.
   Radios: when one radio is checked, its siblings lose `checked` silently
   (no `change` event on them), so we resync every sibling in the same
   name group whenever any radio in the group fires `change`. */
(function () {
    'use strict';

    document.addEventListener('DOMContentLoaded', function () {
        initImageOptionSync();
        initWalletCap();
        initWalletLiveValidation();
    });

    // ---------- Image-select / image-radio is-checked sync ----------
    function initImageOptionSync() {
        var items = document.querySelectorAll('.cn-image-option');

        items.forEach(function (item) {
            var input = item.querySelector('input[type="checkbox"], input[type="radio"]');
            if (!input) return;

            var sync = function () { item.classList.toggle('is-checked', input.checked); };
            sync();

            if (input.type === 'radio') {
                input.addEventListener('change', function () { syncRadioGroup(input.name); });
                item.addEventListener('click', function () {
                    setTimeout(function () { syncRadioGroup(input.name); }, 0);
                });
            } else {
                input.addEventListener('change', sync);
                item.addEventListener('click', function () { setTimeout(sync, 0); });
            }
        });
    }

    function syncRadioGroup(name) {
        var sel = 'input[type="radio"][name="' + escapeAttr(name) + '"]';
        document.querySelectorAll(sel).forEach(function (radio) {
            var label = radio.closest('.cn-image-option');
            if (label) label.classList.toggle('is-checked', radio.checked);
        });
    }

    function escapeAttr(value) {
        return String(value).replace(/(["\\])/g, '\\$1');
    }

    // ---------- Wallet-address total cap (Lite: 10, PRO: 50) ----------
    function initWalletCap() {
        if (typeof cryptoniqAdmin === 'undefined') return;
        var limit = parseInt(cryptoniqAdmin.walletLimit, 10);
        var keys  = cryptoniqAdmin.walletKeys || [];
        if (!limit || !keys.length) return;

        function activeWalletFields() {
            return keys
                .map(function (k) { return document.querySelector('[data-field-id="' + cssEscape(k) + '"]'); })
                .filter(Boolean);
        }

        function countFilled() {
            var n = 0;
            activeWalletFields().forEach(function (field) {
                field.querySelectorAll('.cn-multitext-input').forEach(function (input) {
                    if (input.value.trim() !== '') n++;
                });
            });
            return n;
        }

        var counterEl = document.querySelector('.cn-wallet-counter');

        function updateUI() {
            var filled   = countFilled();
            var atOrOver = filled >= limit;

            if (counterEl) {
                counterEl.textContent = formatCounter(filled, limit);
                counterEl.classList.toggle('is-full', atOrOver);
            }

            activeWalletFields().forEach(function (field) {
                field.querySelectorAll('.cn-multitext-add').forEach(function (btn) {
                    btn.disabled = atOrOver;
                    btn.classList.toggle('is-disabled', atOrOver);
                    if (atOrOver) {
                        btn.setAttribute('title', cryptoniqAdmin.walletLabels.limit_reached);
                    } else {
                        btn.removeAttribute('title');
                    }
                });
            });
        }

        document.addEventListener('input', function (e) {
            if (e.target && e.target.classList && e.target.classList.contains('cn-multitext-input')) {
                updateUI();
            }
        });
        document.addEventListener('click', function (e) {
            var t = e.target;
            if (!t) return;
            if (t.closest('.cn-multitext-add, .cn-multitext-remove')) {
                setTimeout(updateUI, 0);
            }
        });

        updateUI();

        function formatCounter(filled, max) {
            var tpl = cryptoniqAdmin.walletLabels.counter || '%1$d / %2$d';
            return tpl.replace('%1$d', filled).replace('%2$d', max);
        }

        function cssEscape(s) {
            return String(s).replace(/(["\\])/g, '\\$1');
        }
    }

    // ---------- Live wallet-address format validation ----------
    /**
     * Per-coin address format check. Mirrors the PHP regexes in
     * admin/validators.php so client- and server-side stay in sync.
     * Returns true only for syntactically-valid addresses for that chain.
     */
    var Format = {
        EVM:  function (a) { return /^0x[a-fA-F0-9]{40}$/.test(a); },
        BTC:  function (a) {
            // Legacy P2PKH / P2SH (Base58, 26-35 chars)
            if (/^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(a)) return true;
            // SegWit Bech32 (bc1q P2WPKH = 42 / bc1q P2WSH = 62 / bc1p Taproot = 62)
            if (/^bc1[ac-hj-np-z02-9]{39,59}$/.test(a))      return true;
            return false;
        },
        LTC:  function (a) {
            if (/^[LM3][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(a)) return true;
            if (/^ltc1[ac-hj-np-z02-9]{39,59}$/.test(a))      return true;
            return false;
        },
        DOGE: function (a) { return /^D[5-9A-HJ-NP-U][1-9A-HJ-NP-Za-km-z]{32}$/.test(a); },
        SOL:  function (a) { return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(a); },
        TRX:  function (a) { return /^T[1-9A-HJ-NP-Za-km-z]{33}$/.test(a); }
    };

    /**
     * Map a wallets_* field id to the address-format family.
     * Most coins/stablecoins are EVM-compatible (0x40hex), so EVM is the
     * default; we explicitly route the non-EVM chains.
     */
    function chainOf(fieldId) {
        var slug = (fieldId || '').replace(/^wallets_/, '').toLowerCase();
        if (slug === 'btc')                          return 'BTC';
        if (slug === 'doge')                         return 'DOGE';
        if (slug === 'ltc')                          return 'LTC';
        if (slug === 'sol' || /(^|_)sol$/.test(slug)) return 'SOL';
        if (slug === 'trx' || /(^|_)trx$/.test(slug)) return 'TRX';
        return 'EVM'; // ETH, ARB, OP, BNB, all *USDT*/*USDC* on EVM chains
    }

    function initWalletLiveValidation() {
        var walletFields = document.querySelectorAll('[data-field-id^="wallets_"]');
        if (!walletFields.length) return;

        function checkOne(input) {
            var row    = input.closest('.cn-multitext-row');
            if (!row) return false;

            var val   = input.value.trim();
            var field = input.closest('[data-field-id^="wallets_"]');
            if (val === '') {
                row.classList.remove('is-invalid');
                return false; // empty rows don't count as invalid (server drops them)
            }

            var fn  = Format[chainOf(field.getAttribute('data-field-id'))] || function () { return true; };
            var bad = !fn(val);
            row.classList.toggle('is-invalid', bad);
            return bad;
        }

        function recheckAll() {
            var anyInvalid = false;
            document.querySelectorAll(
                '[data-field-id^="wallets_"] .cn-multitext-input'
            ).forEach(function (input) {
                if (checkOne(input)) anyInvalid = true;
            });
            updateSaveButton(anyInvalid);
            updateTabErrorIndicators();
        }

        function updateSaveButton(disabled) {
            var save = document.querySelector('.cn-save');
            if (!save) return;
            save.disabled = disabled;
            save.classList.toggle('is-disabled', disabled);
            save.setAttribute(
                'title',
                disabled ? 'Fix invalid wallet addresses to save' : ''
            );
        }

        /**
         * Mirror per-row invalid state up to the tab nav, so a user who
         * navigates AWAY from the Wallets tab while a row is broken still
         * sees an error dot on the tab. Without this the save button looks
         * mysteriously disabled with no clue why.
         *
         * For each panel that contains at least one .is-invalid row, find
         * its matching tab (.cn-tab + .cn-panel share data-tab="id") and
         * toggle .has-error on the tab. CSS draws the dot.
         */
        function updateTabErrorIndicators() {
            var panels = document.querySelectorAll('.cryptoniq-options-wrap .cn-panel');
            panels.forEach(function (panel) {
                var tabId = panel.getAttribute('data-tab');
                if (!tabId) return;
                var hasError = !!panel.querySelector('.cn-multitext-row.is-invalid');
                var tab = document.querySelector(
                    '.cryptoniq-options-wrap .cn-tab[data-tab="' + cssEscape(tabId) + '"]'
                );
                if (tab) {
                    tab.classList.toggle('has-error', hasError);
                    if (hasError) {
                        tab.setAttribute('title', 'Fix invalid wallet addresses on this tab to save');
                    } else {
                        tab.removeAttribute('title');
                    }
                }
            });
        }

        function cssEscape(s) {
            return String(s).replace(/(["\\])/g, '\\$1');
        }

        // Re-check on each keystroke in any wallet input.
        document.addEventListener('input', function (e) {
            var t = e.target;
            if (!t || !t.classList || !t.classList.contains('cn-multitext-input')) return;
            if (!t.closest('[data-field-id^="wallets_"]')) return;
            recheckAll();
        });

        // Re-check after add/remove rows (multi-text DOM mutations).
        document.addEventListener('click', function (e) {
            if (e.target && e.target.closest('.cn-multitext-add, .cn-multitext-remove')) {
                setTimeout(recheckAll, 0);
            }
        });

        // Initial pass for pre-existing rows.
        recheckAll();
    }
})();
