<?php
namespace DiviBooster\DiviBooster\Features\SocialMediaFollowNetworks\ExtraNetworks;

// === Constants ===
const D4_CHILD_SLUG  = 'et_pb_social_media_follow_network';
const D5_PARENT_SLUG = 'divi/social-media-follow';
const D5_CHILD_SLUG  = 'divi/social-media-follow-network';

// === Hooks ===
if (function_exists('add_filter')) {
    // Register filters for adding extra networks and styling (Divi 4 + Divi 5).
    add_filter('dbdbsmsn_networks', __NAMESPACE__ . '\dbdbsmsn_remove_built_in_networks');
    add_filter('dbdbsmsn_add_social_media_follow_fields', __NAMESPACE__ . '\dbdbsmsn_sort_network_options');

    add_filter('et_pb_all_fields_unprocessed_' . D4_CHILD_SLUG, __NAMESPACE__ . '\dbdbsmsn_add_social_media_follow_fields');
    add_filter('et_module_shortcode_output', __NAMESPACE__ . '\dbdbsmsn_replace_network_names_in_shortcode_output', 10, 3);
    add_filter('et_module_shortcode_output', __NAMESPACE__ . '\dbdbsmsn_set_frontend_styles', 10, 3);

    // Provide conversion mapping for Divi 5.
    add_filter('divi.moduleLibrary.conversion.moduleConversionOutline', __NAMESPACE__ . '\d5_register_conversion_outline', 10, 2);

    // Adjust front-end output for Divi 5 child block.
    add_filter('render_block_' . D5_CHILD_SLUG, __NAMESPACE__ . '\d5_child_render_block', 10, 3);
}

if (function_exists('add_action')) {
    // Output global CSS for custom icon fonts.
    add_action('wp_head', __NAMESPACE__ . '\output_global_icon_css');

    // Output builder-only CSS for icon previews.
    add_action('wp_head', __NAMESPACE__ . '\dbdbsmsn_set_builder_styles');

    // Enqueue builder-only logic for injecting extra networks.
    add_action('divi_visual_builder_assets_before_enqueue_scripts', __NAMESPACE__ . '\enqueue_divi5_builder_script');
}

// === Networks (data + filtering) ===
if (!function_exists(__NAMESPACE__ . '\dbdbsmsn_networks')) {
    // Build the list of available networks from registered icon data (cached per request).
    function dbdbsmsn_networks() {
        static $cached = null;
        if ($cached !== null) {
            return $cached;
        }

        // Fail silent if WordPress filters aren't available.
        if (!function_exists('apply_filters')) {
            $cached = array();
            return $cached;
        }

        $icons    = apply_filters('dbdb_font_icon_data', array());
        $networks = array();

        if (is_array($icons)) {
            foreach ($icons as $id => $network) {
                $networks['dbdb-' . $id] = $network;
            }
        }

        $cached = apply_filters('dbdbsmsn_networks', $networks);
        return $cached;
    }
}

if (!function_exists(__NAMESPACE__ . '\dbdbsmsn_remove_built_in_networks')) {
    // Remove networks that would otherwise duplicate Divi's built-in set.
    function dbdbsmsn_remove_built_in_networks($networks) {
        if (!is_array($networks)) {
            return $networks;
        }
        unset($networks['dbdb-facebook']);
        unset($networks['dbdb-twitter']);
        unset($networks['dbdb-googleplus']);
        unset($networks['dbdb-pinterest']);
        unset($networks['dbdb-linkedin']);
        unset($networks['dbdb-tumblr']);
        unset($networks['dbdb-instagram']);
        unset($networks['dbdb-skype']);
        unset($networks['dbdb-flickr']);
        unset($networks['dbdb-myspace']);
        unset($networks['dbdb-dribbble']);
        unset($networks['dbdb-youtube']);
        unset($networks['dbdb-vimeo']);
        unset($networks['dbdb-rss']);
        return $networks;
    }
}

// === Sorting ===
if (!function_exists(__NAMESPACE__ . '\dbdbsmsn_sort_network_options')) {
    // Sort the network select field options alphabetically.
    function dbdbsmsn_sort_network_options($fields) {
        if (isset($fields['social_network']['options']) && is_array($fields['social_network']['options'])) {
            uasort($fields['social_network']['options'], __NAMESPACE__ . '\dbdbsmsm_sort_networks_alphabetically');
        }
        return $fields;
    }
}

if (!function_exists(__NAMESPACE__ . '\dbdbsmsm_sort_networks_alphabetically')) {
    // uasort callback for alphabetically ordering select options.
    function dbdbsmsm_sort_networks_alphabetically($a, $b) {
        // Sort placeholder options (no 'value') first.
        if (!isset($a['value'])) {
            return -1;
        }
        if (!isset($b['value'])) {
            return 1;
        }

        // Sort alphabetically.
        return strcasecmp((string) $a['value'], (string) $b['value']);
    }
}

// === Divi 4: Front-end output ===
if (!function_exists(__NAMESPACE__ . '\dbdbsmsn_set_frontend_styles')) {
    // Inject per-instance CSS for custom icon fonts.
    function dbdbsmsn_set_frontend_styles($html, $render_slug, $module) {
        if (!is_string($html) || $render_slug !== D4_CHILD_SLUG || !isset($module->props) || !is_array($module->props)) {
            return $html;
        }

        $social_network = isset($module->props['social_network']) ? $module->props['social_network'] : '';
        if ($social_network === '') {
            return $html;
        }

        if (!function_exists('apply_filters')) {
            return $html;
        }

        $isIconFont = apply_filters('dbdbsmsn_network_is_icon_font', true, $social_network);
        if (!$isIconFont) {
            return $html;
        }

        $networks = dbdbsmsn_networks();
        if (!isset($networks[$social_network]['code']) || $networks[$social_network]['code'] === '') {
            return $html;
        }

        // Ensure the icon font files are available.
        if (function_exists('do_action')) {
            do_action('dbdb_font_icons_enqueue_fonts');
        }

        $fontFamily = dbdbsmsn_font_family($social_network);
        $code       = $networks[$social_network]['code'];

    if (class_exists('ET_Builder_Element') && method_exists('ET_Builder_Element', 'set_style')) {
            \ET_Builder_Element::set_style($render_slug, array(
                'selector'    => '%%order_class%% a.icon:before',
                'declaration' => 'content: "' . esc_attr($code) . '";font-family: "' . esc_attr($fontFamily) . '" !important;',
            ));
        }

        return $html;
    }
}

// === Divi 4: Tooltips ===
if (!function_exists(__NAMESPACE__ . '\dbdbsmsn_replace_network_names_in_shortcode_output')) {
    // Replace network slugs with friendly names inside rendered title attributes.
    function dbdbsmsn_replace_network_names_in_shortcode_output($html, $render_slug, $module) {
        if ($render_slug !== D4_CHILD_SLUG) {
            return $html;
        }

    // Skip builder mode.
        if (!empty($_GET['et_fb'])) {
            return $html;
        }

    // If HTML isn't a string, it isn't markup we can safely edit.
    if (!is_string($html)) {
            return $html;
        }


    $props    = isset($module->props) && is_array($module->props) ? $module->props : array();
    $networks = dbdbsmsn_networks();
    return replace_network_slugs_in_title_attributes($html, $networks, $props);
    }
}

// === Builder-only output ===
if (!function_exists(__NAMESPACE__ . '\dbdbsmsn_set_builder_styles')) {
    // Output CSS for icon previews while editing.
    function dbdbsmsn_set_builder_styles() {
        if (empty($_GET['et_fb'])) {
            return;
        }

    // Ensure the icon font files are available.
        if (function_exists('do_action')) {
            do_action('dbdb_font_icons_enqueue_fonts');
        }

        $networks = dbdbsmsn_networks();
        if (empty($networks) || !is_array($networks)) {
            return;
        }
        ?>
        <style>
        <?php foreach ($networks as $id => $network) {
            if (!isset($network['code']) || $network['code'] === '') {
                continue;
            }
            $fontFamily = dbdbsmsn_font_family($id);
            ?>
            .et-social-<?php echo esc_attr($id); ?> a.icon:before,
            .et-db #et-boc .et-l .et_pb_social_icon.et-social-<?php echo esc_attr($id); ?> a.icon:before,
            .et_pb_social_icon.et-social-<?php echo esc_attr($id); ?> a.icon:before {
                content: "<?php echo esc_attr($network['code']); ?>";
                font-family: '<?php echo esc_attr($fontFamily); ?>' !important;
            }
        <?php } ?>
        </style>
        <?php
    }
}

// === Font helpers ===
if (!function_exists(__NAMESPACE__ . '\dbdbsmsn_font_family')) {
    // Return the font-family name for a given network ID.
    function dbdbsmsn_font_family($id) {
        // Strip dbdb- prefix before passing to the icon-set filter.
        $slug = str_replace('dbdb-', '', $id);
        if (!function_exists('apply_filters')) {
            return 'Socicon';
        }
        return apply_filters('dbdb_font_icon_set', 'Socicon', $slug);
    }
}

// === Divi 4: Module fields ===
if (!function_exists(__NAMESPACE__ . '\dbdbsmsn_add_social_media_follow_fields')) {
    // Add extra networks to the social_network select field.
    function dbdbsmsn_add_social_media_follow_fields($fields) {
        if (!isset($fields['social_network'])) {
            return $fields;
        }

        $select = new dbdbsmsn_SocialNetworksField($fields['social_network']);

        foreach (dbdbsmsn_networks() as $id => $network) {
            $name  = isset($network['name']) ? $network['name'] : $id;
            $color = isset($network['color']) ? $network['color'] : '';
            if (!$select->has_option($id)) {
                $select->add_option($id, $name, array('color' => $color));
            }
        }

        $fields['social_network'] = $select->get_field();

    // Allow other features to extend the same fields array.
        return apply_filters('dbdbsmsn_add_social_media_follow_fields', $fields);
    }
}

// === Divi 4: Field builder ===
if (!class_exists(__NAMESPACE__ . '\dbdbsmsn_SocialNetworksField')) {
    class dbdbsmsn_SocialNetworksField {
        private $_field;

        public function __construct($field) {
            $this->_field = is_array($field) ? $field : array();
            if (!isset($this->_field['options']) || !is_array($this->_field['options'])) {
                $this->_field['options'] = array();
            }
            if (!isset($this->_field['value_overwrite']) || !is_array($this->_field['value_overwrite'])) {
                $this->_field['value_overwrite'] = array();
            }
        }

        public function has_option($network_id) {
            return isset($this->_field['options'][$network_id]);
        }

        public function add_option($network_id, $name, $data) {
            $this->_field['options'][$network_id] = array(
                'value' => $name,
                'data'  => $data,
            );
            if (isset($data['color'])) {
                $this->_field['value_overwrite'][$network_id] = $data['color'];
            }
        }

        public function get_field() {
            return $this->_field;
        }
    }
}

// === Shared: Global icon CSS ===
if (!function_exists(__NAMESPACE__ . '\output_global_icon_css')) {
    // Output CSS rules for all custom icon networks.
    function output_global_icon_css() {
        static $css = null;
        if (is_string($css)) {
            echo $css;
            return;
        }

        // Fail silent if common WordPress escaping helpers are missing.
        if (!function_exists('esc_attr')) {
            $css = '';
            return;
        }

        $networks = dbdbsmsn_networks();
        if (empty($networks) || !is_array($networks)) {
            $css = '';
            return;
        }

        $rules = array();
        foreach ($networks as $id => $network) {
            if (!isset($network['code']) || $network['code'] === '') {
                continue;
            }
            $fontFamily = dbdbsmsn_font_family($id);
            $content    = 'content:"' . esc_attr($network['code']) . '";font-family:"' . esc_attr($fontFamily) . '" !important;';

            $rules[] = '.et-social-' . esc_attr($id) . ' a.icon:before{' . $content . '}';
            $rules[] = '.et-db #et-boc .et-l .et_pb_social_icon.et-social-' . esc_attr($id) . ' a.icon:before{' . $content . '}';
            // Additional selector for alternate output context.
            $rules[] = '.et_pb_social_icon.et-social-' . esc_attr($id) . ' a.icon:before{' . $content . '}';
        }


        $css = $rules ? '<style>' . implode('', $rules) . '</style>' : '';
        echo $css;
    }
}

// === Utilities ===
if (!function_exists(__NAMESPACE__ . '\extract_order_class_from_html')) {
    // Find the first class that matches a prefix.
    function extract_order_class_from_html($html, $prefix) {
        if (!is_string($html) || $html === '') {
            return '';
        }
        if (!preg_match('/class="([^"]+)"/i', $html, $m)) {
            return '';
        }
        $classes = preg_split('/\s+/', $m[1], -1, PREG_SPLIT_NO_EMPTY);
        foreach ($classes as $cls) {
            if (strpos($cls, $prefix) === 0) {
                return $cls;
            }
        }
        return '';
    }
}

// Replace network slugs with friendly names inside title="..." attributes.
if (!function_exists(__NAMESPACE__ . '\replace_network_slugs_in_title_attributes')) {
    function replace_network_slugs_in_title_attributes($html, $networks, $props = array()) {
        if (!is_string($html) || $html === '' || empty($networks) || !is_array($networks)) {
            return $html;
        }

        if (!function_exists('esc_attr')) {
            return $html;
        }

        // Fast path: nothing to do if there are no title attributes in the markup.
        if (stripos($html, 'title=') === false) {
            return $html;
        }

        foreach ($networks as $id => $network) {
            $name = isset($network['name']) ? $network['name'] : '';
            if ($name === '') {
                continue;
            }

            // Special handling for Image Icon network (from separate feature)
            if (function_exists('__') && $name === __('Image Icon', 'divi-booster')) {
                if (is_array($props) && isset($props['dbdb_icon_title']) && $props['dbdb_icon_title'] !== '') {
                    $name = $props['dbdb_icon_title'];
                }
                $slug = preg_quote($id, '/');
                $html = preg_replace('/title="([^"]*)' . $slug . '([^"]*)"/i', 'title="' . esc_attr($name) . '"', $html);
                $html = preg_replace("/title='([^']*)" . $slug . "([^']*)'/i", "title='" . esc_attr($name) . "'", $html);
                continue;
            }

            $slug = preg_quote($id, '/');
            // Escape for HTML attribute context.
            $html = preg_replace('/title="([^"]*)' . $slug . '([^"]*)"/i', 'title="$1' . esc_attr($name) . '$2"', $html);
            $html = preg_replace("/title='([^']*)" . $slug . "([^']*)'/i", "title='$1" . esc_attr($name) . "$2'", $html);
        }

        return $html;
    }
}

// === Divi 5: Conversion mapping ===
if (!function_exists(__NAMESPACE__ . '\d5_register_conversion_outline')) {
    // Map settings from the Divi 4 module to the Divi 5 block.
    function d5_register_conversion_outline($conversion_outline, $module_name) {
        if ($module_name !== D5_CHILD_SLUG) {
            return $conversion_outline;
        }

        if (!isset($conversion_outline['module']) || !is_array($conversion_outline['module'])) {
            $conversion_outline['module'] = array();
        }

    // Map the Divi 4 network setting into the Divi 5 title field.
        if (!isset($conversion_outline['module']['social_network'])) {
            $conversion_outline['module']['social_network'] = 'socialNetwork.innerContent.*.title';
        }

        return $conversion_outline;
    }
}

// === Divi 5: Front-end output ===
if (!function_exists(__NAMESPACE__ . '\d5_child_render_block')) {
    // Apply custom icon styling and tooltip name replacement to the rendered block.
    function d5_child_render_block($block_content, $parsed_block, $block) {
        if (!is_string($block_content)) {
            return $block_content;
        }

    $attrs = isset($parsed_block['attrs']) && is_array($parsed_block['attrs']) ? $parsed_block['attrs'] : array();

    // Extract the configured network slug.
        $social_title = '';
        if (isset($attrs['socialNetwork']) && is_array($attrs['socialNetwork']) &&
            isset($attrs['socialNetwork']['innerContent']) && is_array($attrs['socialNetwork']['innerContent'])) {
            if (isset($attrs['socialNetwork']['innerContent']['desktop']['value']['title'])) {
                $social_title = $attrs['socialNetwork']['innerContent']['desktop']['value']['title'];
            } elseif (isset($attrs['socialNetwork']['innerContent']['value']['title'])) {
                $social_title = $attrs['socialNetwork']['innerContent']['value']['title'];
            }
        }

        if (!is_string($social_title) || $social_title === '') {
            return $block_content;
        }

        $networks = dbdbsmsn_networks();

        // Add per-instance font-icon CSS when this network uses a custom icon font.
        if (isset($networks[$social_title])) {
            $network    = $networks[$social_title];
            if (!function_exists('apply_filters')) {
                return $block_content;
            }
            $isIconFont = apply_filters('dbdbsmsn_network_is_icon_font', true, $social_title);
            if ($isIconFont && isset($network['code']) && $network['code'] !== '') {
                if (function_exists('do_action')) {
                    do_action('dbdb_font_icons_enqueue_fonts');
                }

                $order_class = extract_order_class_from_html($block_content, 'et_pb_social_media_follow_network_');
                if ($order_class !== '') {
                    $fontFamily   = dbdbsmsn_font_family($social_title);
                    $inline_style = '<style>.' . esc_attr($order_class) . ' a.icon:before{content:"' . esc_attr($network['code']) . '";font-family:"' . esc_attr($fontFamily) . '" !important;}</style>';
                    $block_content = $inline_style . $block_content;
                }
            }
        }

        // Replace slugs with friendly names in any title attributes.
        return replace_network_slugs_in_title_attributes($block_content, $networks);
    }
}

// === Divi 5: Builder integration ===
if (!function_exists(__NAMESPACE__ . '\enqueue_divi5_builder_script')) {
    // Inject extra networks into the builder UI.
    function enqueue_divi5_builder_script() {
        if ((!function_exists('et_builder_d5_enabled') || !\et_builder_d5_enabled()) ||
            (!function_exists('et_core_is_fb_enabled') || !\et_core_is_fb_enabled())) {
            return;
        }

        // Fail silent if required WordPress script helpers are missing.
        if (!function_exists('sanitize_title') ||
            !function_exists('wp_register_script') ||
            !function_exists('wp_enqueue_script') ||
            !function_exists('wp_add_inline_script') ||
            !function_exists('wp_json_encode')) {
            return;
        }

        $handle = sanitize_title('divibooster-d5-sfnetworks-extra');

    // Pass the network list to JS.
        $networks    = dbdbsmsn_networks();
        $js_networks = array();
        foreach ($networks as $id => $network) {
            $label       = isset($network['name']) ? $network['name'] : $id;
            $background  = isset($network['color']) && $network['color'] !== '' ? $network['color'] : '#58a9de';
            $js_networks[$id] = array(
                'label'      => $label,
                'background' => $background,
            );
        }

        $networks_json = wp_json_encode($js_networks);
        $d5_child_slug = wp_json_encode(D5_CHILD_SLUG);

        $inline = <<<JS
(function(){
  var customNetworks = {$networks_json} || {};

  function getHooks(){
    if (window.vendor && window.vendor.wp && window.vendor.wp.hooks) return window.vendor.wp.hooks;
    if (window.wp && window.wp.hooks) return window.wp.hooks;
    return null;
  }

  function injectOptionsIntoGroups(groups){
    try {
      var path = ["contentNetwork", "component", "props", "fields", "socialNetworkTitle", "component", "props", "options"];
      var current = groups;
      for (var i = 0; i < path.length; i++) {
        if (current && typeof current === 'object' && path[i] in current) {
          current = current[path[i]];
        } else {
          return; // path not found
        }
      }
      if (!current || typeof current !== 'object') return;

      // Merge custom networks
      Object.keys(customNetworks).forEach(function(key){
        if (!current[key]) {
          current[key] = customNetworks[key];
        }
      });

      // Sort options alphabetically, keeping empty key on top
      var sorted = {};
      var keys = Object.keys(current).sort(function(a, b){
        if (a === '') return -1;
        if (b === '') return 1;
        var la = (current[a] && current[a].label) ? String(current[a].label) : String(a);
        var lb = (current[b] && current[b].label) ? String(current[b].label) : String(b);
        return la.localeCompare(lb);
      });
      keys.forEach(function(k){ sorted[k] = current[k]; });
      Object.keys(current).forEach(function(k){ delete current[k]; });
      Object.assign(current, sorted);
    } catch(e){}
  }

  function patchModule(module){
    if (!module || module._diviBoosterExtraNetworksPatched) return;
    module._diviBoosterExtraNetworksPatched = true;

    // 1. Patch settings.content to re-inject options
    try {
      if (module.settings && typeof module.settings.content === 'function') {
        var originalContent = module.settings.content;
        module.settings.content = function(args){
          var result = originalContent(args);
          if (args && args.groupConfiguration) {
            injectOptionsIntoGroups(args.groupConfiguration);
          }
          return result;
        };
      }
    } catch(e){}

    // 2. Patch onChange handler using prototype injection
    try {
      var callbacks = module.callbacks;
      if (callbacks && callbacks.content && callbacks.content.contentNetwork &&
          callbacks.content.contentNetwork.fields &&
          callbacks.content.contentNetwork.fields.socialNetworkTitle) {
        var field = callbacks.content.contentNetwork.fields.socialNetworkTitle;
        var originalOnChange = field.onChange;
        var isExecuting = false;

                field.onChange = function(e){
          if (isExecuting) return;
          isExecuting = true;
          var inputValue = e && e.inputValue ? e.inputValue : null;
          var network = inputValue && customNetworks[inputValue] ? customNetworks[inputValue] : null;
                    var tempKey = network ? ('__dbdb_extra_network__' + String(inputValue)) : null;
                    // Some internal lookups may check for the selected key on the options object.
                    // Injecting onto Object.prototype is unsafe; inject a temporary key on the options map instead.
                    var optionsMap = (this && this.props && this.props.options) ? this.props.options : null;
                    if (network && optionsMap && typeof optionsMap === 'object') {
                        try { optionsMap[tempKey] = network; } catch(_e) {}
                        try { e = Object.assign({}, e, { inputValue: tempKey }); } catch(_e) {}
                    }
          var result;
          try {
            if (typeof originalOnChange === 'function') {
              result = originalOnChange.call(this, e);
            }
          } catch(err) {
          } finally {
                        if (tempKey && optionsMap && typeof optionsMap === 'object') {
                            try { delete optionsMap[tempKey]; } catch(_e) {}
                        }
            isExecuting = false;
          }
          return result;
        };
      }
    } catch(e){}
  }

  function init(){
    var hooks = getHooks();
    if (!hooks) return;

    var moduleName = {$d5_child_slug};

    // Early injection: modify groups when requested
    hooks.addFilter('divi.moduleLibrary.moduleSettings.groups', 'divibooster.extraNetworks', function(groups, metadata){
      try {
        if (metadata && metadata.name === moduleName) {
          injectOptionsIntoGroups(groups);
        }
      } catch(e){}
      return groups;
    });

    // Late patch: find module in moduleLibrary
    var attempts = 0;
    var maxAttempts = 100;
    var interval = setInterval(function(){
      attempts++;
      if (attempts > maxAttempts) {
        clearInterval(interval);
        return;
      }

      if (window.divi && window.divi.moduleLibrary) {
        // Strategy A: moduleMapping
        if (window.divi.moduleLibrary.moduleMapping && window.divi.moduleLibrary.moduleMapping[moduleName]) {
          clearInterval(interval);
          patchModule(window.divi.moduleLibrary.moduleMapping[moduleName]);
          return;
        }
        // Strategy B: wp.data store
        if (window.wp && window.wp.data) {
          try {
            var libStore = window.wp.data.select('divi/module-library');
            if (libStore && typeof libStore.getModule === 'function') {
              var module = libStore.getModule(moduleName);
              if (module) {
                clearInterval(interval);
                patchModule(module);
                return;
              }
            }
          } catch(e){}
        }
      }
    }, 100);
  }

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

        \dbdb_enqueue_inline_script_if_dependencies_available($handle, $inline, array('lodash', array('divi-vendor-wp-hooks', 'wp-hooks')));
    }
}
