<?php
namespace DiviBooster\DiviBooster\Modules\NumberCounter\CounterDuration;

const DIVI4_MODULE_SLUG = 'et_pb_number_counter';
const DIVI5_MODULE_SLUG = 'divi/number-counter';
const DIVI4_SETTING_SLUG = 'divibooster_counter_duration';
const DIVI5_SETTING_SLUG = 'diviboosterCounterDuration';
const FRONTEND_JS_HANDLE = 'divibooster_number_counter_duration';

// === Divi 4: Field Registration ===
add_filter('et_pb_all_fields_unprocessed_' . DIVI4_MODULE_SLUG, __NAMESPACE__ . '\\add_divi4_field');
function add_divi4_field($fields) {
    if (!is_array($fields)) return $fields;
  $fields[DIVI4_SETTING_SLUG] = [
    'label'           => 'Counter Duration',
    'type'            => 'range',
    'option_category' => 'configuration',
    'description'     => 'Set how long the number animation takes (in milliseconds).',
    'default'         => 1800,
    'range_settings'  => array(
        'min'             => 0,
        'max'             => 10000,
        'step'            => 100,
    ),
    'toggle_slug'     => 'main_content',
    'tab_slug'        => 'general',
    'default_on_front'=> '',
    'vb_support'      => true,
  ];
    return $fields;
}

// === Divi 5: Attribute Registration (PHP Fallback) ===
add_filter('divi_module_library_register_module_attrs', function($module_attrs, $filter_args) {
    if (($filter_args['name'] ?? '') !== DIVI5_MODULE_SLUG) {
        return $module_attrs;
    }
    $module_attrs[DIVI5_SETTING_SLUG] = get_divi5_attribute_definition();
    return $module_attrs;
}, 10, 2);

function get_divi5_attribute_definition() {
  return [
    'type'     => 'object',
    'settings' => [
      'innerContent' => [
        'groupType' => 'group-items',
        'items'     => [
          'diviboosterCounterDurationField' => [
            'groupSlug'   => 'contentText',
            'attrName'    => DIVI5_SETTING_SLUG,
            'label'       => 'Counter Duration',
            'description' => 'Set how long the number animation takes (in milliseconds).',
            'features'    => [
              'hover'      => false,
              'sticky'     => false,
              'responsive' => false,
              'preset'     => 'advanced',
            ],
            'render'      => true,
            'priority'    => 110,
            'component'   => [
              'type' => 'field',
              'name' => 'divi/range',
              'props' => [
                'min' => 0,
                'max' => 10000,
                'step' => 100,
                "allowedUnits" => [],
                "defaultUnit" => ""
              ],
            ],
            'defaultAttr' => [ 'desktop' => [ 'value' => 1800 ] ],
          ],
        ],
      ],
    ],
  ];
}

// === Divi 5: Attribute Mapping & D4→D5 Conversion (Inline JS) ===
add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\enqueue_divi5_mapping_js');
function enqueue_divi5_mapping_js() {
    if ((!function_exists('et_builder_d5_enabled') || !\et_builder_d5_enabled()) ||
        (!function_exists('et_core_is_fb_enabled') || !\et_core_is_fb_enabled())) {
        return;
    }
    $handle = sanitize_title('divi-booster-' . DIVI5_MODULE_SLUG . '-' . DIVI5_SETTING_SLUG . '-mapping');
    wp_register_script($handle, '', ['lodash', 'divi-vendor-wp-hooks'], null, true);
    wp_enqueue_script($handle);
    wp_add_inline_script($handle, get_divi5_mapping_inline_js());
}

function get_divi5_mapping_inline_js() {
    $attribute_json = wp_json_encode(get_divi5_attribute_definition());
    $divi4_slug = wp_json_encode(DIVI4_MODULE_SLUG);
    $divi5_setting_slug = wp_json_encode(DIVI5_SETTING_SLUG);
    $divi4_setting_slug = wp_json_encode(DIVI4_SETTING_SLUG);
    return <<<END
// Adds the custom attribute to the Number Counter module.
window.vendor.wp.hooks.addFilter('divi.moduleLibrary.moduleAttributes.divi.number-counter', 'divi', (attributes, metadata) => {
console.log(attributes);
    attributes[{$divi5_setting_slug}] = {$attribute_json};
    return attributes;
});

// Map Divi 4 field to Divi 5 attribute for conversion
window.vendor.wp.hooks.addFilter('divi.moduleLibrary.conversion.moduleConversionOutline', 'divi', (conversionOutline, name) => {
    if (name !== {$divi4_slug}) return conversionOutline;
    if (!conversionOutline.module) conversionOutline.module = {};
    conversionOutline.module[{$divi4_setting_slug}] = {$divi5_setting_slug} + '.*';
    return conversionOutline;
});
END;
}

// === Frontend JS Registration (once) ===
add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\register_frontend_js');
function register_frontend_js() {
    $js = <<<'END'
(function(){
  function parseMs(val){
    if (val === undefined || val === null) return null;
    if (typeof val === 'number') return val < 0 ? 0 : Math.floor(val);
    var s = String(val).trim();
    if (s === '') return null;
    s = s.replace(/[^0-9\-]/g, '');
    if (s === '' || s === '-' ) return null;
    var n = parseInt(s, 10);
    if (isNaN(n)) return null;
    return n < 0 ? 0 : n;
  }
  function parseNum(str){
    if (typeof str !== 'string') str = String(str || '');
    str = str.replace(/[^0-9+\-\.]/g, '');
    var n = parseFloat(str);
    return isNaN(n) ? 0 : n;
  }

  function applyDuration(wrapper){
    var attempts = 0;
    var maxAttempts = 120; // ~6s window similar to other features
    var msAttr = wrapper.getAttribute('data-divibooster-duration');
    var ms = parseMs(msAttr);
    if (ms === null) return; // use default, nothing to do

    var valueEl = wrapper.querySelector('.percent .percent-value');
    var startAttr = valueEl ? valueEl.getAttribute('data-divibooster-initial-value') : null;
    var start = (startAttr !== null) ? parseNum(startAttr) : 0;
    if (isNaN(start)) start = 0;
    // Get target from wrapper or our attribute, fallback to current text
    var targetAttr = valueEl ? valueEl.getAttribute('data-divibooster-target-value') : null;
    var targetSrc = wrapper.getAttribute('data-number-value') || targetAttr || (valueEl ? valueEl.textContent : '0');
    var target = parseNum(targetSrc);
    // If percent-value is NaN, set it to a safe value (start or 0)
    if (valueEl) {
      var currentVal = parseFloat(valueEl.textContent);
      if (isNaN(currentVal)) {
        valueEl.textContent = String(start || 0);
      }
    }

    function tryApply(){
      attempts++;
      var $ = window.jQuery;
      if ($){
          // Divi initializes easyPieChart on the inner .percent element
          var $percent = $(wrapper).find('.percent');
          var chart = $percent.data('easyPieChart') || $(wrapper).data('easyPieChart');
        if (chart){
          var equal = (start !== null) ? (Number(start) === Number(target)) : false;
          // Respect easyPieChart version: number for v1 (Divi 4), object for v2 (Divi 5)
          chart.options = chart.options || {};
          var wantsObject = chart.options && typeof chart.options.animate === 'object';
          var animateVal = (ms <= 0 || equal)
            ? false
            : (wantsObject ? { duration: ms, enabled: true } : ms);
          chart.options.animate = animateVal;
          // Only override onStep if invalid values detected (avoids interfering with Divi 4 normal behavior)
          var currentText = valueEl ? valueEl.textContent : '';
          var invalidWrapperTarget = !isFinite(parseFloat(wrapper.getAttribute('data-number-value')));
          var invalidText = (currentText === 'NaN' || isNaN(parseFloat(currentText)));
          var hasValidLabel = !invalidText && currentText !== '';
          if (!hasValidLabel && (invalidWrapperTarget || invalidText)) {
            chart.options.onStep = function(from, to, current){
              var t = parseFloat(wrapper.getAttribute('data-number-value'));
              if (!isFinite(t)) {
                t = valueEl ? parseNum(valueEl.getAttribute('data-divibooster-target-value') || '0') : 0;
              }
              var s = valueEl ? parseNum(valueEl.getAttribute('data-divibooster-initial-value') || '0') : 0;
              if (!isFinite(t)) t = 0;
              if (!isFinite(s)) s = 0;
              var label;
              if (t > 100 || current > 100) {
                label = Math.round(current);
              } else {
                var progress = current / 100;
                label = Math.round(s + (t - s) * progress);
              }
              if (valueEl) { valueEl.textContent = String(label); }
            };
          }
          if (animateVal === false && typeof chart.disableAnimation === 'function') {
            chart.disableAnimation();
          } else if (animateVal !== false && typeof chart.enableAnimation === 'function') {
            chart.enableAnimation();
          }
          return true;
        }
      }
      if (attempts < maxAttempts){ setTimeout(tryApply, 50); }
      return false;
    }

    tryApply();
  }

    function initInstance(wrapper){
    if (!wrapper || wrapper.__dbiv_ncdur_init) return;
    applyDuration(wrapper);
      // Safety: fix any NaN left by other scripts shortly after init
      setTimeout(function(){
        var el = wrapper.querySelector('.percent .percent-value');
        if (el && (el.textContent === 'NaN' || isNaN(parseFloat(el.textContent)))){
          var t = wrapper.getAttribute('data-number-value');
          var n = parseFloat(t);
          el.textContent = String(isFinite(n) ? n : 0);
        }
      }, 150);
    wrapper.__dbiv_ncdur_init = true;
  }

  function initAll(root){
    root = root || document;
    var nodes = root.querySelectorAll('.dbiv-ncdur');
    nodes.forEach(initInstance);
  }

  if (document.readyState === 'loading'){
    document.addEventListener('DOMContentLoaded', function(){ initAll(document); });
  } else {
    initAll(document);
  }

  if (window.MutationObserver){
    var mo = new MutationObserver(function(muts){
      muts.forEach(function(m){
        if (m.type === 'childList'){
          m.addedNodes && m.addedNodes.forEach(function(node){
            if (node.nodeType === 1){
              if (node.classList && node.classList.contains('dbiv-ncdur')){
                initAll(node);
              }
              var inner = node.querySelectorAll ? node.querySelectorAll('.dbiv-ncdur') : [];
              inner.forEach(initInstance);
            }
          });
        }
      });
    });
    mo.observe(document.documentElement, {childList: true, subtree: true});
  }
})();
END;
    // Load early (in head) so we can affect easyPieChart before Divi triggers animations.
    wp_register_script(FRONTEND_JS_HANDLE, '', [], null, false);
    wp_add_inline_script(FRONTEND_JS_HANDLE, $js);
}

// === Shared: Process Output ===
function process_number_counter_duration_output($content, $duration_raw) {
    if (!is_string($content)) return $content;
    $duration = sanitize_duration($duration_raw);
    if ($duration === null) return $content; // empty -> default behavior

    // Inject data-divibooster-duration into the first wrapper with et_pb_number_counter
    $content = preg_replace_callback(
        '#(<[^>]*class="[^"]*\bet_pb_number_counter\b[^"]*"[^>]*)(>)#',
        function($m) use ($duration) {
            $attr = ' data-divibooster-duration="' . esc_attr((string)$duration) . '"';
            if (strpos($m[0], 'data-divibooster-duration') !== false) {
                return $m[0];
            }
            return $m[1] . $attr . $m[2];
        },
        $content,
        1
    );

    // Add feature class to wrapper to allow JS to target instances
    $content = add_wrapper_class($content, 'dbiv-ncdur');

    // Ensure feature JS is enqueued only if the feature is present in the output
    if (strpos($content, 'dbiv-ncdur') !== false && !wp_script_is(FRONTEND_JS_HANDLE, 'enqueued')) {
        wp_enqueue_script(FRONTEND_JS_HANDLE);
    }

    return $content;
}

function sanitize_duration($value) {
    if ($value === null) return null;
    if (is_string($value)) {
        $trim = trim($value);
        if ($trim === '') return null; // empty -> use default
        $value = preg_replace('/[^0-9\-]/', '', $trim);
        if ($value === '' || $value === '-') return null;
        $value = (int) $value;
    }
    if (is_float($value)) $value = (int) floor($value);
    if (!is_int($value)) {
        return null;
    }
    if ($value < 0) $value = 0;
    return $value;
}

function add_wrapper_class($html, $class_to_add) {
    return preg_replace(
        '#(<[^>]+class=")([^\"]*\bet_pb_number_counter\b[^\"]*)(")#',
        '$1$2 ' . $class_to_add . '$3',
        $html,
        1
    );
}

// === Divi 4: Output Filter ===
add_filter('et_module_shortcode_output', function($output, $render_slug, $module) {
    if (!is_string($output) || $render_slug !== DIVI4_MODULE_SLUG || !isset($module->props) || !is_array($module->props)) {
        return $output;
    }
    $duration = isset($module->props[DIVI4_SETTING_SLUG]) ? $module->props[DIVI4_SETTING_SLUG] : '';
    return process_number_counter_duration_output($output, $duration);
}, 10, 3);

// === Divi 5: Output Filter ===
add_filter('render_block_' . DIVI5_MODULE_SLUG, function($block_content, $parsed_block, $block) {
    $attrs = isset($parsed_block['attrs']) && is_array($parsed_block['attrs']) ? $parsed_block['attrs'] : [];
    $duration = null;
    if (isset($attrs[DIVI5_SETTING_SLUG])) {
        if (isset($attrs[DIVI5_SETTING_SLUG]['desktop']['value'])) {
            $duration = $attrs[DIVI5_SETTING_SLUG]['desktop']['value'];
        } elseif (isset($attrs[DIVI5_SETTING_SLUG]['value'])) {
            $duration = $attrs[DIVI5_SETTING_SLUG]['value'];
        }
    }
    return process_number_counter_duration_output($block_content, $duration);
}, 10, 3);

// Created at 1756532570.
