/**
 * Refactored User List Module JavaScript
 * Modular architecture with improved maintainability and reduced redundancy
 */
(function($) {
    'use strict';

    // Constants
    const CONSTANTS = {
        DEBOUNCE_DELAY: 500,
        TOGGLE_DELAY: 300,
        AJAX_TIMEOUT: 30000,
        DEFAULT_PER_PAGE: 12,
        DISPLAY_FIELDS: ['age', 'birth_date', 'country', 'gender', 'description', 'phone_number', 'city', 'state'],
        FIELD_LABELS: {
            'age': 'Age',
            'birth_date': 'Birth Date',
            'country': 'Country',
            'gender': 'Gender',
            'description': 'Description',
            'phone_number': 'Phone',
            'city': 'City',
            'state': 'State'
        },
        FILTER_SELECTORS: [
            '.um-filter-control',
            '.um-filter-select',
            '.um-filter-checkbox',
            '.um-filter-radio',
            '.um-filter-text'
        ]
    };

    /**
     * State Manager - Centralized state management
     */
    class StateManager {
        constructor() {
            this.state = {
                currentPage: 1,
                filters: {},
                sort: {},
                search: '',
                loading: false,
                toggling: false
            };
            this.listeners = [];
        }

        updateState(newState) {
            const oldState = { ...this.state };
            this.state = { ...this.state, ...newState };
            this.notifyListeners(oldState, this.state);
        }

        getState() {
            return { ...this.state };
        }

        addListener(listener) {
            this.listeners.push(listener);
        }

        notifyListeners(oldState, newState) {
            this.listeners.forEach(listener => listener(oldState, newState));
        }
    }

    /**
     * Configuration Manager - Handles all configuration data
     */
    class ConfigManager {
        constructor(widgetId, container) {
            this.widgetId = widgetId;
            this.container = container;
            this.config = this.loadConfiguration();
        }

        loadConfiguration() {
            return {
                widgetId: this.widgetId,
                container: this.container,
                ajaxData: this.getAjaxData(),
                perPage: this.getPerPage(),
                displayFields: CONSTANTS.DISPLAY_FIELDS,
                fieldLabels: CONSTANTS.FIELD_LABELS
            };
        }

        getAjaxData() {
            const scriptData = window['um_elementor_ajax_' + this.widgetId];
            const genericData = window['um_elementor_ajax'];
            return scriptData || genericData;
        }

        getPerPage() {
            // Check multiple sources with fallback
            const sources = [
                () => this.config?.ajaxData?.widget_settings?.users_per_page,
                () => this.container.data('widget-settings')?.users_per_page,
                () => parseInt(this.container.attr('data-users-per-page')),
                () => CONSTANTS.DEFAULT_PER_PAGE
            ];

            for (const source of sources) {
                const value = source();
                if (value && !isNaN(value)) return parseInt(value);
            }

            return CONSTANTS.DEFAULT_PER_PAGE;
        }

        getConfig() {
            return { ...this.config };
        }
    }

    /**
     * DOM Utilities - Centralized DOM operations
     */
    class DOMUtils {
        static clearFormElements(container, selectors = CONSTANTS.FILTER_SELECTORS) {
            selectors.forEach(selector => {
                container.find(selector).each((index, element) => {
                    this.clearElement($(element));
                });
            });

            // Clear search input
            container.find('.um-global-search').val('');
            container.find('.um-search-input').val('');
            
            // Reset radio buttons to "All" option
            container.find('.um-filter-radio[value=""]').prop('checked', true);
        }

        static clearElement($element) {
            const type = $element.attr('type');
            
            if (['checkbox', 'radio'].includes(type)) {
                $element.prop('checked', false);
            } else {
                $element.val('');
            }
        }

        static showLoading(container) {
            container.addClass('um-loading');
            container.find('.um-infinite-scroll-spinner, .um-loading-spinner').show();
        }

        static hideLoading(container) {
            container.removeClass('um-loading');
            container.find('.um-infinite-scroll-spinner, .um-loading-spinner').hide();
        }

        static showError(container, message) {
            const resultsContainer = container.find('.um-filter-results');
            resultsContainer.html(`<div class="um-error-message">${message}</div>`);
            container.find('.um-results-announcer').text(message);
        }

        static announce(container, message) {
            container.find('.um-results-announcer').text(message);
        }

        static debounce(func, wait) {
            let timeout;
            return function executedFunction(...args) {
                const later = () => {
                    clearTimeout(timeout);
                    func.apply(this, args);
                };
                clearTimeout(timeout);
                timeout = setTimeout(later, wait);
            };
        }
    }

    /**
     * Filter Manager - Handles all filter operations
     */
    class FilterManager {
        constructor(container) {
            this.container = container;
        }

        collectAllFilters() {
            const filters = {};
            
            CONSTANTS.FILTER_SELECTORS.forEach(selector => {
                this.container.find(selector).each((index, element) => {
                    this.processFilterElement($(element), filters);
                });
            });

            return filters;
        }

        processFilterElement($element, filters) {
            const metaKey = this.getMetaKey($element);
            const type = $element.attr('type');
            const value = $element.val();

            if (!metaKey) return;

            switch (type) {
                case 'checkbox':
                    if ($element.is(':checked')) {
                        if (!filters[metaKey]) filters[metaKey] = [];
                        filters[metaKey].push(value);
                    }
                    break;
                case 'radio':
                    if ($element.is(':checked') && value) {
                        filters[metaKey] = value;
                    }
                    break;
                default:
                    if (value && value.toString().trim()) {
                        filters[metaKey] = value;
                    }
            }
        }

        getMetaKey($element) {
            // Try multiple ways to get the meta key
            return $element.closest('.um-filter-item').data('meta-key') ||
                   $element.data('filter-field') ||
                   $element.attr('name');
        }

        clearAllFilters() {
            DOMUtils.clearFormElements(this.container);
        }

        toggleFilterPanel() {
            const filterPanel = this.container.find('.um-filter-panel');
            const toggleBtn = this.container.find('.um-filter-toggle-btn');
            const arrow = toggleBtn.find('.um-filter-arrow');
            
            const isHidden = filterPanel.hasClass('um-filter-panel-hidden');
            
            if (isHidden) {
                filterPanel.removeClass('um-filter-panel-hidden');
                arrow.removeClass('fa-chevron-down').addClass('fa-chevron-up');
                toggleBtn.attr('aria-expanded', 'true');
            } else {
                filterPanel.addClass('um-filter-panel-hidden');
                arrow.removeClass('fa-chevron-up').addClass('fa-chevron-down');
                toggleBtn.attr('aria-expanded', 'false');
            }
        }
    }

    /**
     * AJAX Manager - Handles all AJAX operations
     */
    class AjaxManager {
        constructor(config) {
            this.config = config;
        }

        async makeRequest(params = {}) {
            if (!this.config.ajaxData) {
                throw new Error('AJAX configuration not available');
            }

            const postIdFromContainer = parseInt(String(this.config.container?.attr('data-post-id') ?? 0), 10) || 0;
            const postId = parseInt(String(this.config.ajaxData?.post_id ?? postIdFromContainer ?? 0), 10) || 0;

            const data = {
                action: 'um_filter_users',
                nonce: this.config.ajaxData.nonce,
                widget_id: this.config.widgetId,
                post_id: postId,
                per_page: this.config.perPage,
                widget_settings: JSON.stringify(this.config.ajaxData.widget_settings || {}),
                ...params
            };

            return $.ajax({
                url: this.config.ajaxData.ajax_url,
                type: 'POST',
                data,
                timeout: CONSTANTS.AJAX_TIMEOUT
            });
        }

        async loadUsers(params = {}) {
            try {
                const response = await this.makeRequest(params);
                
                if (response.success && response.data) {
                    return response.data;
                } else {
                    throw new Error('Failed to load users');
                }
            } catch (error) {
                throw this.handleAjaxError(error);
            }
        }

        async loadMoreUsers(nextPage) {
            return this.makeRequest({
                page: nextPage,
                load_more: true
            });
        }

        handleAjaxError(error) {
            let errorMessage = 'Network error. Please check your connection and try again.';
            
            if (error.statusText === 'timeout') {
                errorMessage = 'Request timed out. Please try again.';
            } else if (error.status >= 500) {
                errorMessage = 'Server error. Please try again later.';
            }
            
            return new Error(errorMessage);
        }
    }

    /**
     * User Renderer - Handles all user display operations
     */
    class UserRenderer {
        constructor(displayFields, fieldLabels) {
            this.displayFields = displayFields;
            this.fieldLabels = fieldLabels;
        }

        renderUsers(container, users, append = false) {
            const resultsContainer = container.find('.um-filter-results');
            
            if (!users || users.length === 0) {
                resultsContainer.html('<div class="um-no-users">No users found</div>');
                DOMUtils.announce(container, 'No users found');
                return;
            }

            const gridContainer = this.getOrCreateGridContainer(resultsContainer, append);
            
            users.forEach(user => {
                const userCard = this.renderUserCard(user);
                gridContainer.append(userCard);
            });

            DOMUtils.announce(container, `${users.length} user${users.length === 1 ? '' : 's'} found`);
        }

        getOrCreateGridContainer(resultsContainer, append) {
            let gridContainer = resultsContainer.find('.um-team-carousel-wrapper');
            
            if (gridContainer.length === 0 || !append) {
                if (gridContainer.length === 0) {
                    gridContainer = $('<div class="um-team-carousel-wrapper grid grid-cols-1 md:grid-cols-3" role="list"></div>');
                    resultsContainer.html(gridContainer);
                } else if (!append) {
                    gridContainer.empty();
                }
            }
            
            return gridContainer;
        }

        renderUserCard(user) {
            const avatarTitle = this.getTitleAttribute(user.display_name || '');
            const nameTitle = this.getTitleAttribute(user.display_name || '');

            return `
                <div class="um-item-user elementor-animation-" role="listitem">
                    <div class="um-widget-member-holder">
                        <div class="um-elementor-member-image text-center">
                            <a ${avatarTitle}
                               href="${user.profile_url || '#'}">
                                <img src="${user.user_avatar || ''}" 
                                     alt="${this.escapeHtml(user.display_name || 'User Avatar')}" />
                            </a>
                        </div>
                        <div class="um-elementor-member-content">
                            <div class="um-elementor-member-name text-center">
                                <p>
                                    <a ${nameTitle}
                                       href="${user.profile_url || '#'}">
                                        ${this.escapeHtml(user.display_name || 'User')}
                                    </a>
                                </p>
                            </div>
                            <div class="um-custom-field-container text-center">
                                ${this.renderUserMeta(user)}
                            </div>
                        </div>
                    </div>
                </div>
            `;
        }

        renderUserMeta(user) {
            if (!user.user_meta || Object.keys(user.user_meta).length === 0) {
                return '';
            }

            const metaFields = user.user_meta;
            
            return this.displayFields
                .filter(field => metaFields[field] && metaFields[field].toString().trim() !== '')
                .map(field => {
                    const fieldLabel = this.getFieldLabel(field);
                    const fieldValue = this.escapeHtml(metaFields[field]);
                    return `<span class="um-meta-field">
                        <span class="um-custom-label">${fieldLabel}:</span>
                        <span class="um-custom-field">${fieldValue}</span>
                    </span>`;
                })
                .join('');
        }

        getFieldLabel(field) {
            return this.fieldLabels[field] || field.charAt(0).toUpperCase() + field.slice(1);
        }

        escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        getTitleAttribute(value) {
            const safeValue = this.escapeHtml(value || '').trim();
            return safeValue ? `title="${safeValue}"` : '';
        }
    }

    /**
     * Pagination Manager - Handles pagination display and logic
     */
    class PaginationManager {
        constructor(container) {
            this.container = container;
        }

        updatePagination(data) {
            const pagination = this.container.find('.um-pagination-container');
            
            if (data.total_pages && data.total_pages > 1) {
                const paginationHtml = this.renderPagination(data);
                pagination.html(paginationHtml).show();
            } else {
                pagination.hide();
            }
        }

        renderPagination(data) {
            const { current_page, total_pages, total_users, per_page } = data;
            const startItem = ((current_page - 1) * per_page) + 1;
            const endItem = Math.min(current_page * per_page, total_users);
            
            return `
                <div class="um-pagination-info">
                    Showing ${startItem}-${endItem} of ${total_users} users
                </div>
                <div class="um-pagination-links">
                    ${this.renderPaginationLinks(current_page, total_pages)}
                </div>
            `;
        }

        renderPaginationLinks(currentPage, totalPages) {
            if (totalPages <= 1) {
                return '<span class="um-pagination-info">No pagination needed</span>';
            }

            let html = '';
            
            // Previous button
            if (currentPage > 1) {
                html += `<a href="#" class="um-pagination-link um-pagination-prev" data-page="${currentPage - 1}">Previous</a>`;
            }
            
            // Page numbers
            const startPage = Math.max(1, currentPage - 2);
            const endPage = Math.min(totalPages, currentPage + 2);
            
            for (let i = startPage; i <= endPage; i++) {
                const currentClass = (i === currentPage) ? 'current' : '';
                html += `<a href="#" class="um-pagination-link ${currentClass}" data-page="${i}">${i}</a>`;
            }
            
            // Next button
            if (currentPage < totalPages) {
                html += `<a href="#" class="um-pagination-link um-pagination-next" data-page="${currentPage + 1}">Next</a>`;
            }
            
            return html;
        }

        updateLoadMoreButton(data, nextPage) {
            const button = this.container.find('.um-load-more-button');
            
            if (nextPage <= data.total_pages) {
                button.data('page', nextPage).text('Load More Users').prop('disabled', false);
            } else {
                button.text('No More Users').prop('disabled', true);
            }
        }
    }

    /**
     * Event Handler Factory - Creates event handlers
     */
    class EventHandlerFactory {
        static createFilterHandler(userList) {
            return function(e) {
                const filters = userList.filterManager.collectAllFilters();
                userList.updateUsers({ filters });
            };
        }

        static createSearchHandler(userList) {
            return function(e) {
                e.preventDefault();
                const searchTerm = userList.getActiveSearchTerm();
                userList.updateUsers({ search: searchTerm });
            };
        }

        static createSortHandler(userList) {
            return function(e) {
                const sortValue = $(e.currentTarget).val();
                userList.updateUsers({ sort_by: sortValue });
            };
        }

        static createPaginationHandler(userList) {
            return function(e) {
                e.preventDefault();
                const page = parseInt($(e.currentTarget).data('page'));
                
                if (page && page > 0) {
                    userList.stateManager.updateState({ currentPage: page });
                    userList.updateUsers({ page });
                }
            };
        }

        static createLoadMoreHandler(userList) {
            return function(e) {
                e.preventDefault();
                const state = userList.stateManager.getState();
                if (state.loading) return;
                
                const nextPage = parseInt($(e.currentTarget).data('page')) + 1;
                userList.loadMoreUsers(nextPage);
            };
        }

        static createToggleHandler(userList) {
            return function(e) {
                e.preventDefault();
                e.stopPropagation();
                
                const state = userList.stateManager.getState();
                if (state.toggling) return;
                
                userList.stateManager.updateState({ toggling: true });
                userList.filterManager.toggleFilterPanel();
                
                setTimeout(() => {
                    userList.stateManager.updateState({ toggling: false });
                }, CONSTANTS.TOGGLE_DELAY);
            };
        }
    }

    /**
     * Main User List Class - Orchestrates all components
     */
    class UMUserList {
        constructor(widgetId, container) {
            this.widgetId = widgetId;
            this.container = container;
            
            // Initialize managers
            this.stateManager = new StateManager();
            this.configManager = new ConfigManager(widgetId, container);
            this.ajaxManager = new AjaxManager(this.configManager.getConfig());
            this.filterManager = new FilterManager(container);
            this.renderer = new UserRenderer(CONSTANTS.DISPLAY_FIELDS, CONSTANTS.FIELD_LABELS);
            this.paginationManager = new PaginationManager(container);
            
            this.init();
        }

        init() {
            this.bindEvents();
            this.initInfiniteScroll();
        }

        bindEvents() {
            const debouncedFilterHandler = DOMUtils.debounce(
                EventHandlerFactory.createFilterHandler(this), 
                CONSTANTS.DEBOUNCE_DELAY
            );
            
            const debouncedSearchHandler = DOMUtils.debounce(
                EventHandlerFactory.createSearchHandler(this), 
                CONSTANTS.DEBOUNCE_DELAY
            );

            // Filter events
            this.container.on('click', '.um-filter-toggle-btn', EventHandlerFactory.createToggleHandler(this));
            this.container.on('change', CONSTANTS.FILTER_SELECTORS.join(','), debouncedFilterHandler);
            this.container.on('input', '.um-filter-text', debouncedFilterHandler);
            this.container.on('click', '.um-filter-apply', EventHandlerFactory.createFilterHandler(this));
            this.container.on('click', '.um-filter-clear', this.handleFilterClear.bind(this));
            this.container.on('submit', '.um-search-filter-form', this.handleFormSubmit.bind(this));
            this.container.on('reset', '.um-search-filter-form', this.handleFormReset.bind(this));

            // Search events
            this.container.on('input', '.um-global-search', debouncedSearchHandler);
            this.container.on('input', '.um-search-input', debouncedSearchHandler);
            this.container.on('click', '.um-search-icon', EventHandlerFactory.createSearchHandler(this));

            // Sort events
            this.container.on('change', '.um-sort-select', EventHandlerFactory.createSortHandler(this));

            // Pagination events
            this.container.on('click', '.um-pagination-link', EventHandlerFactory.createPaginationHandler(this));
            this.container.on('click', '.um-load-more-button', EventHandlerFactory.createLoadMoreHandler(this));
        }

        async updateUsers(params = {}) {
            const state = this.stateManager.getState();
            if (state.loading) return;

            try {
                this.stateManager.updateState({ loading: true });
                DOMUtils.showLoading(this.container);

                const data = await this.ajaxManager.loadUsers(params);
                
                this.renderer.renderUsers(this.container, data.users || data);
                this.paginationManager.updatePagination(data);
                if (data.total_users !== undefined) {
                    DOMUtils.announce(this.container, `${data.total_users} user${data.total_users === 1 ? '' : 's'} found`);
                }
                
            } catch (error) {
                DOMUtils.showError(this.container, error.message);
            } finally {
                DOMUtils.hideLoading(this.container);
                this.stateManager.updateState({ loading: false });
            }
        }

        async loadMoreUsers(nextPage) {
            const state = this.stateManager.getState();
            if (state.loading) return;

            try {
                this.stateManager.updateState({ loading: true });
                const button = this.container.find('.um-load-more-button');
                button.text('Loading...').prop('disabled', true);

                const response = await this.ajaxManager.loadMoreUsers(nextPage);
                
                if (response.success) {
                    this.renderer.renderUsers(this.container, response.data.users, true);
                    this.paginationManager.updateLoadMoreButton(response.data, nextPage);
                }
                
            } catch (error) {
                DOMUtils.showError(this.container, error.message);
            } finally {
                this.stateManager.updateState({ loading: false });
            }
        }

        handleFilterClear(e) {
            e.preventDefault();
            this.filterManager.clearAllFilters();
            this.updateUsers({ filters: {}, search: '' });
        }

        handleFormSubmit(e) {
            e.preventDefault();
            const filters = this.filterManager.collectAllFilters();
            const searchTerm = this.getActiveSearchTerm();
            this.updateUsers({ filters, search: searchTerm });
        }

        handleFormReset(e) {
            e.preventDefault();
            this.filterManager.clearAllFilters();
            this.updateUsers({ filters: {}, search: '' });
        }

        getActiveSearchTerm() {
            const globalSearch = this.container.find('.um-global-search').val();
            const searchInput = this.container.find('.um-search-input').val();
            const searchTerm = (globalSearch || searchInput || '').toString().trim();
            return searchTerm;
        }

        initInfiniteScroll() {
            const trigger = this.container.find('.um-infinite-scroll-trigger');
            
            if (trigger.length && 'IntersectionObserver' in window) {
                const observer = new IntersectionObserver((entries) => {
                    entries.forEach(entry => {
                        if (entry.isIntersecting && !this.stateManager.getState().loading) {
                            const nextPage = parseInt(trigger.data('page')) + 1;
                            this.loadMoreUsers(nextPage);
                            trigger.data('page', nextPage);
                        }
                    });
                });
                
                observer.observe(trigger[0]);
            }
        }
    }

    /**
     * Initialization Functions
     */
    const initializeUserLists = () => {
        $('.um-user-list-container').each((index, container) => {
            const $container = $(container);
            const widgetId = $container.data('widget-id');
            
            if (widgetId && !$container.data('um-user-list-initialized')) {
                $container.data('um-user-list-initialized', true);
                try {
                    new UMUserList(widgetId, $container);
                } catch (error) {
                    console.error('Failed to initialize User List:', error);
                }
            }
        });
    };

    // Document ready initialization
    $(document).ready(initializeUserLists);

    // Elementor frontend initialization
    $(window).on('elementor/frontend/init', () => {
        elementorFrontend.hooks.addAction('frontend/element_ready/ele-um-user-list.default', ($element) => {
            const widgetId = $element.data('widget-id');
            
            if (widgetId && !$element.data('um-user-list-initialized')) {
                $element.data('um-user-list-initialized', true);
                try {
                    new UMUserList(widgetId, $element);
                } catch (error) {
                    console.error('Failed to initialize Elementor User List:', error);
                }
            }
        });
    });

})(jQuery);