/**
 * Elementor frontend handler for the Advanced Progress Bar widget.
 *
 * Animates each bar once it scrolls into view: a single requestAnimationFrame
 * count-up drives the percentage number, the linear fill width and the circular
 * conic value together, with an easing curve and a configurable duration. Honors
 * prefers-reduced-motion ( jumps to final ) and falls back to an instant set
 * when IntersectionObserver is unavailable. Editor-safe teardown.
 *
 * @package captain-widgets-kit
 * @since   1.6.0
 */

(function ($) {
    'use strict';

    /**
     * Per-instance handler — called by Elementor for every widget instance.
     *
     * @param {jQuery} $scope - The widget wrapper element.
     */
    var CaptwikiProgressHandler = function ($scope) {

        var root = $scope[0].querySelector('.captwiki-progress');
        if (!root) {
            return;
        }

        // Re-run safe: tear down a previous controller on editor re-render.
        if (root._cwkProgressTeardown) {
            root._cwkProgressTeardown();
        }

        var items = Array.prototype.slice.call(root.querySelectorAll('.captwiki-progress__item'));
        if (!items.length) {
            return;
        }

        var doAnimate = root.getAttribute('data-animate') === 'yes';
        var duration = parseInt(root.getAttribute('data-duration'), 10) || 1500;
        var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

        var observer = null;
        var frames = [];

        /**
         * Apply a 0-100 value to one item's sub-elements.
         *
         * @param {Element} item  - The bar item.
         * @param {number}  value - Current value.
         */
        var paint = function (item, value) {
            var fill = item.querySelector('.captwiki-progress__fill');
            if (fill) {
                fill.style.width = value + '%';
            }
            var circle = item.querySelector('.captwiki-progress__circle');
            if (circle) {
                circle.style.setProperty('--captwiki-pb-p', value);
            }
            var percent = item.querySelector('.captwiki-progress__percent');
            if (percent) {
                var suffix = percent.getAttribute('data-suffix') || '';
                percent.textContent = Math.round(value) + suffix;
            }
        };

        /**
         * Count-up from 0 to the item's target value.
         *
         * @param {Element} item - The bar item.
         */
        var animateItem = function (item) {
            if (item._cwkDone) {
                return;
            }
            item._cwkDone = true;

            var target = parseFloat(item.getAttribute('data-value')) || 0;

            if (!doAnimate || reduceMotion) {
                paint(item, target);
                return;
            }

            var start = null;
            var step = function (ts) {
                if (start === null) {
                    start = ts;
                }
                var progress = Math.min((ts - start) / duration, 1);
                // easeOutCubic for a natural settle.
                var eased = 1 - Math.pow(1 - progress, 3);
                paint(item, target * eased);
                if (progress < 1) {
                    var id = window.requestAnimationFrame(step);
                    frames.push(id);
                }
            };
            var first = window.requestAnimationFrame(step);
            frames.push(first);
        };

        /* ── Trigger ───────────────────────────────────────── */
        if (doAnimate && typeof window.IntersectionObserver !== 'undefined') {
            observer = new IntersectionObserver(function (entries) {
                entries.forEach(function (entry) {
                    if (entry.isIntersecting) {
                        animateItem(entry.target);
                        observer.unobserve(entry.target);
                    }
                });
            }, {
                threshold: 0.3
            });
            items.forEach(function (item) {
                observer.observe(item);
            });
        } else {
            // No observer or animation disabled — set final values now.
            items.forEach(function (item) {
                animateItem(item);
            });
        }

        /* ── Teardown ──────────────────────────────────────── */
        root._cwkProgressTeardown = function () {
            if (observer) {
                observer.disconnect();
                observer = null;
            }
            frames.forEach(function (id) {
                window.cancelAnimationFrame(id);
            });
            frames = [];
            items.forEach(function (item) {
                item._cwkDone = false;
            });
            root._cwkProgressTeardown = null;
        };
    };

    /* ── Register with Elementor frontend ───────────────────── */
    $(window).on('elementor/frontend/init', function () {
        elementorFrontend.hooks.addAction(
            'frontend/element_ready/captwiki-progress-bar.default',
            CaptwikiProgressHandler
        );
    });

})(jQuery);
