/**
 * Forms Engine — Client-side dynamic form companion
 * Handles: conditional visibility, NID auto-parse, dependent fields,
 * repeatable sections, fee calculation triggers, client-side validation
 */
var FormsEngine = (function() {
    'use strict';

    var repeatCounters = {};

    function init() {
        initConditionalVisibility();
        initNidParsers();
        initRepeatableSections();
        initDependentDropdowns();
        initFeeCalculationTriggers();
        initClientValidation();
    }

    // ─────────────────────────────────────────────
    // CONDITIONAL VISIBILITY
    // ─────────────────────────────────────────────
    function initConditionalVisibility() {
        var elements = document.querySelectorAll('[data-visible-when]');
        elements.forEach(function(el) {
            try {
                var condition = JSON.parse(el.getAttribute('data-visible-when'));
                if (!condition || !condition.field) return;
                bindVisibilityWatcher(el, condition);
            } catch (e) {
                // Bad JSON — skip
            }
        });
    }

    function bindVisibilityWatcher(el, condition) {
        var watchField = findFieldByKey(condition.field);
        if (!watchField) return;

        function evaluate() {
            var visible = evaluateCondition(condition, getFieldValue(watchField));
            el.style.display = visible ? '' : 'none';

            // When hidden, strip required so form can submit
            if (!visible) {
                el.querySelectorAll('[required]').forEach(function(inp) {
                    inp.setAttribute('data-was-required', 'true');
                    inp.removeAttribute('required');
                });
            } else {
                el.querySelectorAll('[data-was-required="true"]').forEach(function(inp) {
                    inp.setAttribute('required', 'required');
                    inp.removeAttribute('data-was-required');
                });
            }
        }

        watchField.addEventListener('change', evaluate);
        watchField.addEventListener('input', evaluate);
        evaluate();
    }

    function evaluateCondition(condition, actualValue) {
        var expected = condition.value;
        var op = condition.operator || 'eq';

        switch (op) {
            case 'eq':        return String(actualValue) === String(expected);
            case 'neq':       return String(actualValue) !== String(expected);
            case 'in':        return Array.isArray(expected) && expected.indexOf(String(actualValue)) !== -1;
            case 'gt':        return parseFloat(actualValue) > parseFloat(expected);
            case 'lt':        return parseFloat(actualValue) < parseFloat(expected);
            case 'gte':       return parseFloat(actualValue) >= parseFloat(expected);
            case 'lte':       return parseFloat(actualValue) <= parseFloat(expected);
            case 'not_empty': return actualValue !== '' && actualValue !== null && actualValue !== undefined;
            case 'empty':     return actualValue === '' || actualValue === null || actualValue === undefined;
            default:          return String(actualValue) === String(expected);
        }
    }

    // ─────────────────────────────────────────────
    // NATIONAL ID PARSER
    // ─────────────────────────────────────────────
    function initNidParsers() {
        var nidInputs = document.querySelectorAll('[data-nid-parser="true"]');
        nidInputs.forEach(function(input) {
            input.addEventListener('input', function() {
                var val = input.value.replace(/\D/g, '');
                input.value = val;
                if (val.length === 14) {
                    parseNid(val, input);
                } else {
                    input.style.borderColor = '';
                }
            });

            input.addEventListener('blur', function() {
                var val = input.value.replace(/\D/g, '');
                if (val.length === 14) {
                    parseNid(val, input);
                } else if (val.length > 0 && val.length < 14) {
                    input.style.borderColor = '#DC2626';
                    showFieldError(input, 'الرقم القومي يجب أن يكون 14 رقم');
                }
            });
        });
    }

    function parseNid(nid, inputEl) {
        if (nid.length !== 14 || !/^\d{14}$/.test(nid)) return;

        var century = parseInt(nid[0]);
        if (century !== 2 && century !== 3) {
            showFieldError(inputEl, 'رمز القرن غير صالح');
            inputEl.style.borderColor = '#DC2626';
            return;
        }

        var yearPrefix = century === 2 ? '19' : '20';
        var year = parseInt(yearPrefix + nid.substring(1, 3));
        var month = parseInt(nid.substring(3, 5));
        var day = parseInt(nid.substring(5, 7));

        if (month < 1 || month > 12 || day < 1 || day > 31) {
            showFieldError(inputEl, 'تاريخ الميلاد في الرقم القومي غير صالح');
            inputEl.style.borderColor = '#DC2626';
            return;
        }

        // Validate actual date
        var testDate = new Date(year, month - 1, day);
        if (testDate.getFullYear() !== year || testDate.getMonth() !== month - 1 || testDate.getDate() !== day) {
            showFieldError(inputEl, 'تاريخ الميلاد في الرقم القومي غير صالح');
            inputEl.style.borderColor = '#DC2626';
            return;
        }

        var dob = year + '-' + pad(month) + '-' + pad(day);

        // Age calculation
        var birthDate = new Date(year, month - 1, day);
        var today = new Date();
        var ageYears = today.getFullYear() - birthDate.getFullYear();
        var ageMonths = today.getMonth() - birthDate.getMonth();
        if (today.getMonth() < birthDate.getMonth() ||
            (today.getMonth() === birthDate.getMonth() && today.getDate() < birthDate.getDate())) {
            ageYears--;
        }
        ageMonths = today.getMonth() - birthDate.getMonth();
        if (ageMonths < 0) ageMonths += 12;
        if (today.getDate() < birthDate.getDate()) {
            ageMonths--;
            if (ageMonths < 0) ageMonths += 12;
        }

        // Gender: position 13 (index 12), odd = male
        var genderDigit = parseInt(nid[12]);
        var gender = (genderDigit % 2 !== 0) ? 'male' : 'female';

        // Governorate code: positions 8-9 (index 7-8)
        var govCode = nid.substring(7, 9);

        // Get populates list from the input
        var populates = getPopulatesList(inputEl);

        // Determine field prefix from input name (handles repeatable: child_national_id -> child_)
        var inputName = inputEl.getAttribute('name') || inputEl.id.replace('field-', '');
        var prefix = '';
        if (inputName.indexOf('national_id') > 0) {
            prefix = inputName.replace('national_id', '');
        }

        // Populate target fields
        var dobTargets = ['date_of_birth', prefix + 'dob', prefix + 'date_of_birth'];
        var ageYearTargets = ['age_years', prefix + 'age', prefix + 'age_years'];
        var ageMonthTargets = ['age_months', prefix + 'age_months'];
        var genderTargets = ['gender', prefix + 'gender'];
        var govTargets = ['governorate_code'];

        dobTargets.forEach(function(k) { setFieldValue(k, dob); });
        ageYearTargets.forEach(function(k) { setFieldValue(k, String(ageYears)); });
        ageMonthTargets.forEach(function(k) { setFieldValue(k, String(ageMonths)); });
        genderTargets.forEach(function(k) { setFieldValue(k, gender); });
        govTargets.forEach(function(k) { setFieldValue(k, govCode); });

        // Classification for spouses
        if (ageYears >= 21) {
            setFieldValue('spouse_classification', 'عضو عامل');
        } else {
            setFieldValue('spouse_classification', 'عضو تابع');
        }

        // Clear errors and show success
        clearFieldError(inputEl);
        inputEl.style.borderColor = '#059669';
        setTimeout(function() { inputEl.style.borderColor = ''; }, 3000);
    }

    // ─────────────────────────────────────────────
    // REPEATABLE SECTIONS
    // ─────────────────────────────────────────────
    function initRepeatableSections() {
        var repeatableSections = document.querySelectorAll('[data-repeatable="true"]');
        repeatableSections.forEach(function(section) {
            var sectionKey = section.getAttribute('data-section-key') || '';
            var maxRepeats = parseInt(section.getAttribute('data-max-repeats') || '10');
            repeatCounters[sectionKey] = 1;

            var btnContainer = document.createElement('div');
            btnContainer.style.cssText = 'padding:0 20px 15px;display:flex;gap:10px;';

            var addBtn = document.createElement('button');
            addBtn.type = 'button';
            addBtn.className = 'btn btn-sm btn-outline';
            addBtn.textContent = '+ إضافة سجل جديد';
            addBtn.style.color = '#059669';

            addBtn.addEventListener('click', function() {
                if (repeatCounters[sectionKey] >= maxRepeats) {
                    if (typeof toast === 'function') {
                        toast('تم الوصول للحد الأقصى (' + maxRepeats + ')', 'warning');
                    } else {
                        alert('تم الوصول للحد الأقصى (' + maxRepeats + ')');
                    }
                    return;
                }
                repeatCounters[sectionKey]++;
                addRepeatableRow(section, sectionKey, repeatCounters[sectionKey]);
            });

            btnContainer.appendChild(addBtn);
            section.appendChild(btnContainer);
        });
    }

    function addRepeatableRow(section, sectionKey, index) {
        var gridContainer = section.querySelector('.repeatable-grid');
        if (!gridContainer) {
            // Find the grid div inside the section
            var grids = section.querySelectorAll('div[style*="display:grid"]');
            if (grids.length > 0) {
                gridContainer = grids[grids.length - 1];
            } else {
                return;
            }
        }

        // Clone all field wrappers from the first row
        var firstRowFields = gridContainer.querySelectorAll('.form-group');
        if (firstRowFields.length === 0) return;

        // Add separator
        var separator = document.createElement('div');
        separator.style.cssText = 'grid-column:1/-1;border-top:2px dashed #E5E7EB;margin:10px 0;padding-top:10px;display:flex;justify-content:space-between;align-items:center;';
        separator.innerHTML = '<span style="color:#0D7377;font-weight:600;">سجل #' + index + '</span>';

        var removeBtn = document.createElement('button');
        removeBtn.type = 'button';
        removeBtn.className = 'btn btn-sm';
        removeBtn.style.cssText = 'color:#DC2626;border:1px solid #DC2626;background:transparent;cursor:pointer;';
        removeBtn.textContent = '✕ حذف';
        removeBtn.setAttribute('data-remove-index', String(index));

        removeBtn.addEventListener('click', function() {
            // Remove all elements for this index
            var toRemove = gridContainer.querySelectorAll('[data-row-index="' + index + '"]');
            toRemove.forEach(function(el) { el.remove(); });
            separator.remove();
            repeatCounters[sectionKey]--;
        });

        separator.appendChild(removeBtn);
        gridContainer.appendChild(separator);
        separator.setAttribute('data-row-index', String(index));

        firstRowFields.forEach(function(fieldWrap) {
            if (fieldWrap.getAttribute('data-row-index') && fieldWrap.getAttribute('data-row-index') !== '1') return;

            var clone = fieldWrap.cloneNode(true);
            clone.setAttribute('data-row-index', String(index));

            // Update field names and IDs to include index
            var inputs = clone.querySelectorAll('input, select, textarea');
            inputs.forEach(function(inp) {
                var origName = inp.getAttribute('name') || '';
                var origId = inp.getAttribute('id') || '';

                if (origName) {
                    inp.setAttribute('name', origName + '_' + index);
                }
                if (origId) {
                    inp.setAttribute('id', origId + '_' + index);
                }

                // Clear values
                if (inp.type === 'checkbox' || inp.type === 'radio') {
                    inp.checked = false;
                } else {
                    inp.value = '';
                }
            });

            // Update label for attributes
            var labels = clone.querySelectorAll('label');
            labels.forEach(function(lbl) {
                var forAttr = lbl.getAttribute('for');
                if (forAttr) {
                    lbl.setAttribute('for', forAttr + '_' + index);
                }
            });

            // Clear error messages
            var errDivs = clone.querySelectorAll('div[style*="color:#DC2626"]');
            errDivs.forEach(function(d) { d.remove(); });

            gridContainer.appendChild(clone);

            // Re-init NID parsers on new fields
            var newNids = clone.querySelectorAll('[data-nid-parser="true"]');
            newNids.forEach(function(nidInput) {
                nidInput.addEventListener('input', function() {
                    var val = nidInput.value.replace(/\D/g, '');
                    nidInput.value = val;
                    if (val.length === 14) parseNid(val, nidInput);
                });
            });

            // Re-init conditional visibility on new fields
            var visEls = clone.querySelectorAll('[data-visible-when]');
            visEls.forEach(function(ve) {
                try {
                    var cond = JSON.parse(ve.getAttribute('data-visible-when'));
                    if (cond && cond.field) {
                        // Adjust field reference for the index
                        var adjustedCond = Object.assign({}, cond);
                        adjustedCond.field = cond.field + '_' + index;
                        bindVisibilityWatcher(ve, adjustedCond);
                    }
                } catch(e) {}
            });
        });
    }

    // ─────────────────────────────────────────────
    // DEPENDENT DROPDOWNS
    // ─────────────────────────────────────────────
    function initDependentDropdowns() {
        var dependents = document.querySelectorAll('[data-depends-on]');
        dependents.forEach(function(childSelect) {
            var parentKey = childSelect.getAttribute('data-depends-on');
            var sourceUrl = childSelect.getAttribute('data-depends-url') || '';
            var parentField = findFieldByKey(parentKey);
            if (!parentField || !sourceUrl) return;

            parentField.addEventListener('change', function() {
                var parentVal = getFieldValue(parentField);
                if (!parentVal) {
                    childSelect.innerHTML = '<option value="">-- اختر --</option>';
                    return;
                }

                var url = sourceUrl.replace('{value}', encodeURIComponent(parentVal));
                fetchJson(url).then(function(options) {
                    childSelect.innerHTML = '<option value="">-- اختر --</option>';
                    if (Array.isArray(options)) {
                        options.forEach(function(opt) {
                            var option = document.createElement('option');
                            option.value = opt.value || '';
                            option.textContent = opt.label || opt.value || '';
                            childSelect.appendChild(option);
                        });
                    }
                }).catch(function() {
                    // Silent fail — keep existing options
                });
            });
        });
    }

    // ─────────────────────────────────────────────
    // FEE CALCULATION TRIGGERS
    // ─────────────────────────────────────────────
    function initFeeCalculationTriggers() {
        var feeFields = document.querySelectorAll('[data-fee-trigger]');
        feeFields.forEach(function(field) {
            var triggerConfig = field.getAttribute('data-fee-trigger');
            try {
                var config = JSON.parse(triggerConfig);
                var watchFields = config.watch || [];
                var targetField = config.target || '';
                var calcUrl = config.url || '';

                watchFields.forEach(function(watchKey) {
                    var watchEl = findFieldByKey(watchKey);
                    if (!watchEl) return;

                    watchEl.addEventListener('change', function() {
                        calculateFee(watchFields, targetField, calcUrl);
                    });
                });
            } catch(e) {}
        });

        // Also listen for age changes to trigger child/spouse fee recalculation
        var ageFields = document.querySelectorAll('[id*="age_years"], [id*="child_age"], [id*="spouse_age"]');
        ageFields.forEach(function(af) {
            af.addEventListener('change', function() {
                triggerNearestFeeCalc(af);
            });
        });
    }

    function calculateFee(watchKeys, targetFieldKey, calcUrl) {
        if (!calcUrl) return;

        var params = {};
        watchKeys.forEach(function(key) {
            var el = findFieldByKey(key);
            if (el) {
                params[key] = getFieldValue(el);
            }
        });

        fetchJson(calcUrl, 'POST', params).then(function(result) {
            if (result && result.fee !== undefined) {
                setFieldValue(targetFieldKey, String(result.fee));
            }
            if (result && result.breakdown) {
                var breakdownEl = findFieldByKey(targetFieldKey + '_breakdown');
                if (breakdownEl) {
                    if (breakdownEl.tagName === 'DIV') {
                        breakdownEl.innerHTML = result.breakdown;
                    } else {
                        breakdownEl.value = result.breakdown;
                    }
                }
            }
        }).catch(function() {
            // Silent — fee calc failed, user can still submit
        });
    }

    function triggerNearestFeeCalc(element) {
        var section = element.closest('.card');
        if (!section) return;
        var feeField = section.querySelector('[id*="fee"]');
        if (feeField && feeField.hasAttribute('data-fee-trigger')) {
            feeField.dispatchEvent(new Event('recalculate'));
        }
    }

    // ─────────────────────────────────────────────
    // CLIENT-SIDE VALIDATION
    // ─────────────────────────────────────────────
    function initClientValidation() {
        var forms = document.querySelectorAll('form[action*="/forms/submit/"]');
        forms.forEach(function(form) {
            form.addEventListener('submit', function(e) {
                var isValid = true;
                var firstError = null;

                // Clear all previous client errors
                form.querySelectorAll('.client-error').forEach(function(err) { err.remove(); });
                form.querySelectorAll('.form-input, .form-select, .form-textarea').forEach(function(inp) {
                    inp.style.borderColor = '';
                });

                // Validate required fields that are visible
                form.querySelectorAll('[required]').forEach(function(field) {
                    var wrapper = field.closest('.form-group');
                    if (wrapper && wrapper.style.display === 'none') return;
                    if (field.disabled) return;

                    var val = getFieldValue(field);
                    if (val === '' || val === null || val === undefined) {
                        isValid = false;
                        field.style.borderColor = '#DC2626';
                        showFieldError(field, 'هذا الحقل مطلوب');
                        if (!firstError) firstError = field;
                    }
                });

                // Validate NID fields
                form.querySelectorAll('[data-nid-parser="true"]').forEach(function(nidField) {
                    if (nidField.disabled) return;
                    var wrapper = nidField.closest('.form-group');
                    if (wrapper && wrapper.style.display === 'none') return;

                    var val = nidField.value;
                    if (val && val.length > 0 && val.length !== 14) {
                        isValid = false;
                        nidField.style.borderColor = '#DC2626';
                        showFieldError(nidField, 'الرقم القومي يجب أن يكون 14 رقم');
                        if (!firstError) firstError = nidField;
                    }
                });

                // Validate Egyptian phone fields
                form.querySelectorAll('input[type="tel"]').forEach(function(phoneField) {
                    if (phoneField.disabled) return;
                    var wrapper = phoneField.closest('.form-group');
                    if (wrapper && wrapper.style.display === 'none') return;

                    var val = phoneField.value;
                    if (val && val.length > 0) {
                        var nameAttr = phoneField.getAttribute('name') || '';
                        if (nameAttr.indexOf('mobile') !== -1 || nameAttr.indexOf('phone_eg') !== -1) {
                            if (!/^01[0-9]{9}$/.test(val)) {
                                isValid = false;
                                phoneField.style.borderColor = '#DC2626';
                                showFieldError(phoneField, 'رقم الهاتف المصري يجب أن يبدأ بـ 01 ويتكون من 11 رقم');
                                if (!firstError) firstError = phoneField;
                            }
                        }
                    }
                });

                // Validate email fields
                form.querySelectorAll('input[type="email"]').forEach(function(emailField) {
                    if (emailField.disabled) return;
                    var val = emailField.value;
                    if (val && val.length > 0 && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)) {
                        isValid = false;
                        emailField.style.borderColor = '#DC2626';
                        showFieldError(emailField, 'بريد إلكتروني غير صالح');
                        if (!firstError) firstError = emailField;
                    }
                });

                if (!isValid) {
                    e.preventDefault();
                    if (firstError) {
                        firstError.scrollIntoView({ behavior: 'smooth', block: 'center' });
                        firstError.focus();
                    }
                }
            });
        });
    }

    // ─────────────────────────────────────────────
    // UTILITY FUNCTIONS
    // ─────────────────────────────────────────────
    function findFieldByKey(key) {
        var el = document.getElementById('field-' + key);
        if (el) return el;
        el = document.querySelector('[name="' + key + '"]');
        return el;
    }

    function getFieldValue(field) {
        if (!field) return '';
        if (field.type === 'checkbox') return field.checked ? '1' : '';
        if (field.type === 'radio') {
            var checked = document.querySelector('input[name="' + field.name + '"]:checked');
            return checked ? checked.value : '';
        }
        return field.value || '';
    }

    function setFieldValue(fieldKey, value) {
        var el = document.getElementById('field-' + fieldKey);
        if (!el) return;

        if (el.tagName === 'SELECT') {
            var found = false;
            for (var i = 0; i < el.options.length; i++) {
                if (el.options[i].value === value) {
                    el.selectedIndex = i;
                    found = true;
                    break;
                }
            }
            if (!found && value) {
                // Value not in options — might be loaded dynamically
                var opt = document.createElement('option');
                opt.value = value;
                opt.textContent = value;
                opt.selected = true;
                el.appendChild(opt);
            }
        } else if (el.tagName === 'DIV') {
            el.textContent = value;
        } else {
            el.value = value;
        }

        el.dispatchEvent(new Event('change', { bubbles: true }));
    }

    function showFieldError(field, message) {
        clearFieldError(field);
        var wrapper = field.closest('.form-group');
        if (!wrapper) wrapper = field.parentElement;
        var errDiv = document.createElement('div');
        errDiv.className = 'client-error';
        errDiv.style.cssText = 'color:#DC2626;font-size:12px;margin-top:4px;';
        errDiv.textContent = message;
        wrapper.appendChild(errDiv);
    }

    function clearFieldError(field) {
        var wrapper = field.closest('.form-group');
        if (!wrapper) wrapper = field.parentElement;
        var existing = wrapper.querySelectorAll('.client-error');
        existing.forEach(function(e) { e.remove(); });
        field.style.borderColor = '';
    }

    function pad(num) {
        return num < 10 ? '0' + num : String(num);
    }

    function fetchJson(url, method, data) {
        method = method || 'GET';
        var opts = {
            method: method,
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest'
            }
        };

        var csrfMeta = document.querySelector('meta[name="csrf-token"]');
        if (csrfMeta) {
            opts.headers['X-CSRF-TOKEN'] = csrfMeta.getAttribute('content');
        }

        if (method === 'POST' && data) {
            opts.body = JSON.stringify(data);
        }

        return fetch(url, opts).then(function(r) {
            if (!r.ok) throw new Error('HTTP ' + r.status);
            return r.json();
        });
    }

    // Public API
    return {
        init: init,
        parseNid: parseNid,
        setFieldValue: setFieldValue,
        findFieldByKey: findFieldByKey,
        getFieldValue: getFieldValue,
        addRepeatableRow: addRepeatableRow,
        evaluateCondition: evaluateCondition
    };
})();