/* modules/free/calculator/assets/js/admin.js */
(function (window, $) {
    'use strict';

    var modules = window.noesiaSwaAdminModules || (window.noesiaSwaAdminModules = {});
    var state = {
        booted: false,
        calculatorBound: false,
        bmiBound: false
    };

    function formatCalcNumber(value) {
        var rounded;
        var text;

        if (!isFinite(value)) {
            return 'Error';
        }

        rounded = Math.round(value * 1000000000) / 1000000000;
        text = String(rounded);

        if (text.indexOf('.') !== -1) {
            text = text.replace(/0+$/, '').replace(/\.$/, '');
        }

        return text;
    }

    function sanitizeExpression(expr) {
        return String(expr || '').replace(/[^0-9+\-*/.()]/g, '');
    }

    function getCalcFields() {
        return {
            $expr: $('input[name="noesia_swa_calc_expr"]'),
            $display: $('#noesia-swa-calculator-display')
        };
    }

    function setCalcState(expr, display) {
        var fields = getCalcFields();

        if (fields.$expr.length) {
            fields.$expr.val(String(expr || ''));
        }

        if (fields.$display.length) {
            fields.$display.val(String(display || '0'));
        }
    }

    function getCalcExpression() {
        var fields = getCalcFields();
        var expr = fields.$expr.length ? String(fields.$expr.val() || '') : '';

        return sanitizeExpression(expr);
    }

    function getCalcDisplayValue() {
        var fields = getCalcFields();
        var display = fields.$display.length ? String(fields.$display.val() || '') : '';

        display = String(display || '').trim();

        if (!display || display === 'Error') {
            return '0';
        }

        return display;
    }

    function evaluateExpression(expr) {
        var clean = sanitizeExpression(expr);
        var result;

        if (!clean) {
            return '';
        }

        if (!/^[0-9+\-*/.()\s]+$/.test(clean)) {
            return 'Error';
        }

        try {
            result = Function('return (' + clean + ');')();

            if (!isFinite(result)) {
                return 'Error';
            }

            return formatCalcNumber(result);
        } catch (err) {
            return 'Error';
        }
    }

    function lastNumberRange(expr) {
        var clean = String(expr || '');
        var match = clean.match(/(-?\d*\.?\d+)$/);

        if (!match) {
            return null;
        }

        return {
            start: clean.length - match[1].length,
            value: match[1]
        };
    }

    function toggleExpressionSign(expr) {
        var clean = String(expr || '');
        var range = lastNumberRange(clean);

        if (!range) {
            return clean ? clean : '-';
        }

        if (range.value.charAt(0) === '-') {
            return clean.slice(0, range.start) + range.value.slice(1);
        }

        return clean.slice(0, range.start) + '-' + range.value;
    }

    function handleCalcKey(key) {
        var expr = getCalcExpression();
        var operators = '+-*/';
        var display;
        var range;

        key = String(key || '');

        if (!key) {
            return;
        }

        if (key === 'C') {
            setCalcState('', '0');
            return;
        }

        if (key === 'BS') {
            expr = expr.slice(0, -1);
            setCalcState(expr, expr || '0');
            return;
        }

        if (key === 'SIGN') {
            expr = toggleExpressionSign(expr);
            setCalcState(expr, expr || '0');
            return;
        }

        if (key === '=') {
            display = evaluateExpression(expr);

            if (display === 'Error') {
                setCalcState('', 'Error');
                return;
            }

            setCalcState(display, display || '0');
            return;
        }

        if (operators.indexOf(key) !== -1) {
            if (!expr) {
                if (key === '-') {
                    expr = '-';
                }
            } else if (operators.indexOf(expr.slice(-1)) !== -1) {
                expr = expr.slice(0, -1) + key;
            } else {
                expr += key;
            }

            setCalcState(expr, expr || '0');
            return;
        }

        if (key === '.') {
            range = lastNumberRange(expr);

            if (range && range.value.indexOf('.') !== -1) {
                return;
            }

            if (!expr || operators.indexOf(expr.slice(-1)) !== -1 || expr.slice(-1) === '(') {
                expr += '0';
            }

            expr += '.';
            setCalcState(expr, expr);
            return;
        }

        if (/^[0-9]$/.test(key)) {
            if (getCalcDisplayValue() === '0' && !expr) {
                expr = key;
            } else {
                expr += key;
            }

            setCalcState(expr, expr);
        }
    }

    function bindCalculator() {
        if (state.calculatorBound) {
            return true;
        }

        $(document)
            .off('click.noesiaSwaCalculator', 'button[name="noesia_swa_calc_key"]')
            .on('click.noesiaSwaCalculator', 'button[name="noesia_swa_calc_key"]', function (e) {
                e.preventDefault();
                e.stopPropagation();
                handleCalcKey($(this).val());
            });

        state.calculatorBound = true;
        return true;
    }

    function getBmiCard() {
        var $btn = $('#noesia-swa-bmi-calc');

        if (!$btn.length) {
            return $();
        }

        return $btn.closest('.noesia-swa-card');
    }

    function bmiResultTarget() {
        var $card = getBmiCard();
        var $live;
        var $header;

        if (!$card.length) {
            return $();
        }

        $live = $card.find('#noesia-swa-bmi-live-result');

        if ($live.length) {
            return $live;
        }

        $live = $('<div id="noesia-swa-bmi-live-result" class="noesia-swa-status-box" aria-live="polite"></div>');
        $header = $card.find('.noesia-swa-card-header').first();

        if ($header.length) {
            $header.after($live);
        } else {
            $card.prepend($live);
        }

        return $live;
    }

    function renderBmiResult(payload) {
        var $target = bmiResultTarget();
        var html = '';

        if (!$target.length) {
            return;
        }

        if (!payload || payload.error) {
            $target
                .removeClass('noesia-swa-mini-stats')
                .addClass('noesia-swa-status-box')
                .html('<strong>Notice</strong><span>' + String((payload && payload.error) || 'Please enter valid height and weight values.') + '</span>');
            return;
        }

        html += '<div><strong>Your BMI</strong><span>' + payload.bmi + '</span><p class="noesia-swa-muted">' + payload.category + '</p></div>';
        html += '<div><strong>Healthy weight range for this height</strong><span>' + payload.rangeMin + ' to ' + payload.rangeMax + ' kg</span><p class="noesia-swa-muted">Reference BMI range: 18.5–24.9 (adults).</p></div>';

        if (payload.bmr) {
            html += '<div><strong>Optional estimates (age/sex-based)</strong><span>BMR: ~' + payload.bmr + ' kcal/day';

            if (payload.bodyFat) {
                html += '<br>Body fat estimate: ~' + payload.bodyFat + '%';
            }

            html += '</span><p class="noesia-swa-muted">These are approximations; use clinical judgment.</p></div>';
        }

        $target
            .removeClass('noesia-swa-status-box')
            .addClass('noesia-swa-mini-stats')
            .html(html);
    }

    function calculateBmiPayload() {
        var height = parseFloat(String($('#noesia-swa-bmi-height').val() || '').replace(',', '.'));
        var weight = parseFloat(String($('#noesia-swa-bmi-weight').val() || '').replace(',', '.'));
        var ageRaw = String($('#noesia-swa-bmi-age').val() || '').trim();
        var age = ageRaw === '' ? null : parseInt(ageRaw, 10);
        var sex = String($('#noesia-swa-bmi-sex').val() || 'female').toLowerCase();
        var meters;
        var bmi;
        var category = 'Obesity';
        var rangeMin;
        var rangeMax;
        var payload;
        var bmr;
        var bodyFat;

        if (!isFinite(height) || !isFinite(weight) || height <= 0 || weight <= 0) {
            return { error: 'Please enter valid height and weight values.' };
        }

        meters = height / 100;

        if (!isFinite(meters) || meters <= 0) {
            return { error: 'Please enter valid height and weight values.' };
        }

        bmi = weight / (meters * meters);

        if (bmi < 18.5) {
            category = 'Underweight';
        } else if (bmi < 25) {
            category = 'Healthy weight';
        } else if (bmi < 30) {
            category = 'Overweight';
        }

        rangeMin = 18.5 * meters * meters;
        rangeMax = 24.9 * meters * meters;
        payload = {
            bmi: (Math.round(bmi * 10) / 10).toFixed(1),
            category: category,
            rangeMin: (Math.round(rangeMin * 10) / 10).toFixed(1),
            rangeMax: (Math.round(rangeMax * 10) / 10).toFixed(1)
        };

        if (isFinite(age) && age > 0) {
            if (sex === 'male') {
                bmr = (10 * weight) + (6.25 * height) - (5 * age) + 5;
            } else {
                bmr = (10 * weight) + (6.25 * height) - (5 * age) - 161;
            }

            payload.bmr = String(Math.round(bmr));
            bodyFat = (1.20 * bmi) + (0.23 * age) - (sex === 'male' ? 16.2 : 5.4);

            if (isFinite(bodyFat)) {
                payload.bodyFat = (Math.round(bodyFat * 10) / 10).toFixed(1);
            }
        }

        return payload;
    }

    function bindBmiCalculator() {
        if (state.bmiBound) {
            return true;
        }

        $(document)
            .off('click.noesiaSwaBmiCalc', '#noesia-swa-bmi-calc')
            .on('click.noesiaSwaBmiCalc', '#noesia-swa-bmi-calc', function (e) {
                e.preventDefault();
                e.stopPropagation();
                renderBmiResult(calculateBmiPayload());
            })
            .off('input.noesiaSwaBmiCalc change.noesiaSwaBmiCalc', '#noesia-swa-bmi-height, #noesia-swa-bmi-weight, #noesia-swa-bmi-age, #noesia-swa-bmi-sex')
            .on('input.noesiaSwaBmiCalc change.noesiaSwaBmiCalc', '#noesia-swa-bmi-height, #noesia-swa-bmi-weight, #noesia-swa-bmi-age, #noesia-swa-bmi-sex', function () {
                var height = String($('#noesia-swa-bmi-height').val() || '').trim();
                var weight = String($('#noesia-swa-bmi-weight').val() || '').trim();

                if (height && weight) {
                    renderBmiResult(calculateBmiPayload());
                }
            });

        state.bmiBound = true;
        return true;
    }

    function initCalculator() {
        bindCalculator();
        return true;
    }

    function initBmiCalculator() {
        bindBmiCalculator();
        return true;
    }

    function boot() {
        if (state.booted) {
            return true;
        }

        initCalculator();
        initBmiCalculator();
        state.booted = true;

        return true;
    }

    function init() {
        return boot();
    }

    function onSectionOpen() {
        boot();
        return true;
    }

    function onShow() {
        return onSectionOpen();
    }

    function show() {
        return onSectionOpen();
    }

    modules.calculator = {
        boot: boot,
        init: init,
        onSectionOpen: onSectionOpen,
        onShow: onShow,
        show: show,
        initCalculator: initCalculator,
        initBmiCalculator: initBmiCalculator,
        calculateBmiPayload: calculateBmiPayload,
        renderBmiResult: renderBmiResult
    };

    boot();
})(window, jQuery);