/**
 * Entity Selector - Category Tree Module
 * Hierarchical tree view for category selection inside the dropdown
 * @partial _tree.js
 *
 * Features:
 * - Expand/collapse individual nodes
 * - Expand all / Collapse all
 * - Select parent with all children button
 * - Visual tree with indentation
 * - Product count display
 * - Search/filter within tree
 */

(function($) {
    'use strict';

    // Create mixin namespace
    window._EntitySelectorMixins = window._EntitySelectorMixins || {};

    // Tree mixin
    window._EntitySelectorMixins.tree = {

        // Tree state
        treeData: null,
        treeFlatData: null,

        /**
         * Load and display category tree in the dropdown
         * Called when view mode is changed to "tree"
         */
        loadCategoryTree: function() {
            var self = this;
            var $results = this.$dropdown.find('.dropdown-results');
            var trans = this.config.trans || {};
            var searchEntity = this.activeGroup ? this.activeGroup.searchEntity : 'categories';

            // Show loading
            $results.html('<div class="tree-loading">' + this.esIcon('progress_activity', 'es-spin') + ' ' +
                this.escapeHtml(trans.loading || 'Loading...') + '</div>');

            // Fetch tree data
            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'getCategoryTree',
                    trait: 'EntitySelector',
                    entity_type: searchEntity
                },
                success: function(response) {
                    if (response.success && response.categories && response.categories.length > 0) {
                        self.treeFlatData = response.categories;
                        self.treeData = self.buildTreeStructure(response.categories);
                        self.renderCategoryTree($results, searchEntity);
                    } else {
                        $results.html('<div class="dropdown-empty">' +
                            self.escapeHtml(trans.no_categories || 'No categories found') + '</div>');
                    }
                },
                error: function() {
                    $results.html('<div class="dropdown-error">' +
                        self.escapeHtml(trans.error_loading || 'Failed to load categories') + '</div>');
                }
            });
        },

        /**
         * Build nested tree structure from flat array
         * @param {Array} flatData - Flat array with parent_id references
         * @returns {Array} Nested tree structure
         */
        buildTreeStructure: function(flatData) {
            var lookup = {};
            var tree = [];

            // Create lookup and initialize children arrays
            flatData.forEach(function(item) {
                lookup[item.id] = $.extend({}, item, { children: [] });
            });

            // Build tree by assigning children to parents
            flatData.forEach(function(item) {
                var node = lookup[item.id];
                var parentId = parseInt(item.parent_id, 10);

                if (parentId && lookup[parentId]) {
                    lookup[parentId].children.push(node);
                } else {
                    tree.push(node);
                }
            });

            return tree;
        },

        /**
         * Render the category tree inside dropdown results
         * @param {jQuery} $container - The dropdown-results container
         * @param {string} entityType - 'categories' or 'cms_categories'
         */
        renderCategoryTree: function($container, entityType) {
            var self = this;
            var trans = this.config.trans || {};

            // Get currently selected IDs from chips
            var selectedIds = this.getSelectedIdsFromChips();

            // Build tree HTML
            var html = '<div class="category-tree" data-entity-type="' + this.escapeAttr(entityType) + '">';

            // Tree toolbar
            html += '<div class="tree-toolbar">';
            html += '<button type="button" class="btn-expand-all" title="' +
                this.escapeAttr(trans.expand_all || 'Expand all') + '">';
            html += this.esIcon('add_box') + ' ' + this.escapeHtml(trans.expand_all || 'Expand all');
            html += '</button>';
            html += '<button type="button" class="btn-collapse-all" title="' +
                this.escapeAttr(trans.collapse_all || 'Collapse all') + '">';
            html += this.esIcon('indeterminate_check_box') + ' ' + this.escapeHtml(trans.collapse_all || 'Collapse all');
            html += '</button>';
            html += '</div>';

            // Tree items
            html += '<div class="tree-items">';
            html += this.renderTreeItems(this.treeData, 0, selectedIds);
            html += '</div>';

            html += '</div>';

            $container.html(html);

            // Update count
            var totalCount = this.treeFlatData ? this.treeFlatData.length : 0;
            var selectedCount = selectedIds.length;
            var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';
            var countText = totalCount + ' ' + categoryLabel;
            if (selectedCount > 0) {
                countText += ' (' + selectedCount + ' selected)';
            }
            this.$dropdown.find('.results-count').text(countText);

            // Update select children button states
            this.updateSelectChildrenButtons(this.$dropdown.find('.tree-item'));
        },

        /**
         * Render tree items recursively
         * @param {Array} nodes - Tree nodes
         * @param {number} level - Current depth level
         * @param {Array} selectedIds - Currently selected IDs
         * @returns {string} HTML string
         */
        renderTreeItems: function(nodes, level, selectedIds) {
            var self = this;
            var html = '';
            var trans = this.config.trans || {};

            nodes.forEach(function(node) {
                var hasChildren = node.children && node.children.length > 0;
                var isSelected = selectedIds.indexOf(parseInt(node.id, 10)) !== -1;
                var indent = level * 20;

                var itemClass = 'tree-item';
                if (hasChildren) itemClass += ' has-children';
                if (isSelected) itemClass += ' selected';
                if (!node.active) itemClass += ' inactive';

                html += '<div class="' + itemClass + '" data-id="' + node.id + '" ';
                html += 'data-name="' + self.escapeAttr(node.name) + '" ';
                html += 'data-level="' + level + '" ';
                html += 'data-parent-id="' + (node.parent_id || 0) + '">';

                // Indentation
                html += '<span class="tree-indent" style="width: ' + indent + 'px;"></span>';

                // Toggle button (expand/collapse)
                if (hasChildren) {
                    html += '<span class="tree-toggle">' + self.esIcon('arrow_drop_down') + '</span>';
                    // Select with children button (next to toggle on the left)
                    html += '<button type="button" class="btn-select-children" title="' +
                        self.escapeAttr(trans.select_with_children || 'Select with all children') + '">';
                    html += self.esIcon('check_box');
                    html += '</button>';
                } else {
                    html += '<span class="tree-toggle tree-leaf"></span>';
                }

                // Checkbox indicator
                html += '<span class="tree-checkbox">' + this.esIcon('check') + '</span>';

                // Category icon
                html += '<span class="tree-icon">' + this.esIcon('folder') + '</span>';

                // Name
                html += '<span class="tree-name">' + self.escapeHtml(node.name) + '</span>';

                // Product/page count with clickable preview
                var itemCount = node.product_count || node.page_count || 0;
                if (itemCount > 0) {
                    var countLabel = node.page_count ? (trans.pages || 'pages') : (trans.products || 'products');
                    html += '<span class="tree-count clickable" data-category-id="' + node.id + '" ';
                    html += 'title="' + self.escapeAttr(itemCount + ' ' + countLabel) + '">';
                    html += self.esIcon('visibility') + ' ' + itemCount;
                    html += '</span>';
                }

                // Inactive badge
                if (!node.active) {
                    html += '<span class="tree-badge inactive">' +
                        self.escapeHtml(trans.inactive || 'Inactive') + '</span>';
                }

                html += '</div>';

                // Render children
                if (hasChildren) {
                    html += '<div class="tree-children">';
                    html += self.renderTreeItems(node.children, level + 1, selectedIds);
                    html += '</div>';
                }
            });

            return html;
        },

        /**
         * Get selected IDs from the current picker's chips
         * @returns {Array} Array of selected IDs
         */
        getSelectedIdsFromChips: function() {
            var selectedIds = [];

            if (!this.activeGroup) return selectedIds;

            var $block = this.$wrapper.find('.target-block[data-block-type="' + this.activeGroup.blockType + '"]');
            var $group = $block.find('.selection-group[data-group-index="' + this.activeGroup.groupIndex + '"]');
            var $picker;

            if (this.activeGroup.section === 'include') {
                $picker = $group.find('.include-picker');
            } else {
                var $excludeRow = $group.find('.exclude-row[data-exclude-index="' + this.activeGroup.excludeIndex + '"]');
                $picker = $excludeRow.find('.exclude-picker');
            }

            $picker.find('.entity-chip').each(function() {
                selectedIds.push(parseInt($(this).data('id'), 10));
            });

            return selectedIds;
        },

        /**
         * Filter category tree by search query
         * @param {string} query - Search query
         */
        filterCategoryTree: function(query) {
            var $tree = this.$dropdown.find('.category-tree');
            if (!$tree.length) return;

            var $items = $tree.find('.tree-item');
            var $children = $tree.find('.tree-children');
            query = (query || '').toLowerCase().trim();

            // Remove any inline display styles set by jQuery .toggle()
            $items.css('display', '');

            if (!query) {
                $items.removeClass('filtered-out filter-match');
                $children.removeClass('filter-expanded');
                return;
            }

            // Mark all as filtered out first
            $items.addClass('filtered-out').removeClass('filter-match');

            // Find matching items and show them with their parents
            $items.each(function() {
                var $item = $(this);
                var name = ($item.data('name') || '').toLowerCase();

                if (name.indexOf(query) !== -1) {
                    $item.removeClass('filtered-out');

                    // Show parent containers
                    $item.parents('.tree-children').addClass('filter-expanded');
                    $item.parents('.tree-item').removeClass('filtered-out');

                    // Show children of matching item
                    $item.next('.tree-children').find('.tree-item').removeClass('filtered-out');
                    $item.next('.tree-children').addClass('filter-expanded');
                }
            });
        },

        /**
         * Find all descendant tree items of a given item
         * @param {jQuery} $item - Parent tree item
         * @param {jQuery} $allItems - All tree items (for performance)
         * @returns {Array} Array of descendant jQuery elements
         */
        findTreeDescendants: function($item, $allItems) {
            var descendants = [];
            var parentId = parseInt($item.data('id'), 10);
            var level = parseInt($item.data('level'), 10);

            // Find immediate children first
            var $next = $item.next('.tree-children');
            if ($next.length) {
                $next.find('.tree-item').each(function() {
                    descendants.push(this);
                });
            }

            return descendants;
        },

        /**
         * Update the state of select-children buttons based on selection
         * @param {jQuery} $allItems - All tree items
         */
        updateSelectChildrenButtons: function($allItems) {
            var self = this;
            var trans = this.config.trans || {};

            $allItems.filter('.has-children').each(function() {
                var $item = $(this);
                var $btn = $item.find('.btn-select-children');
                if (!$btn.length) return;

                var $children = $item.next('.tree-children');
                if (!$children.length) return;

                var $childItems = $children.find('.tree-item');
                var isParentSelected = $item.hasClass('selected');
                var allChildrenSelected = true;

                $childItems.each(function() {
                    if (!$(this).hasClass('selected')) {
                        allChildrenSelected = false;
                        return false;
                    }
                });

                if (isParentSelected && allChildrenSelected) {
                    $btn.find('i').replaceWith(self.esIcon('indeterminate_check_box'));
                    $btn.attr('title', trans.deselect_with_children || 'Deselect with all children');
                } else {
                    $btn.find('i').replaceWith(self.esIcon('add_box'));
                    $btn.attr('title', trans.select_with_children || 'Select with all children');
                }
            });
        }
    };

})(jQuery);
