// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * @module     block_mwa_dashboard/dashboardstore
 * @copyright  2026 Bruno Porto
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
define([], function() {

    'use strict';

    var config = {};
    var strings = {};
    var dashboard = null;
    var actionCaller = null;
    var modules = {};
    var handlers = {};
    var legacy = {};
    var facade = null;

    var configure = function(newConfig, newStrings, caller) {
        config = newConfig || {};
        strings = newStrings || {};
        actionCaller = caller || null;
    };

    var register = function(name, api) {
        modules[name] = api;
        if (name !== 'MWADashboard') {
            window[name] = api;
        }
        return api;
    };

    var getModule = function(name) {
        return modules[name] || null;
    };

    var getStrings = function() {
        return strings;
    };

    var getConfig = function() {
        return config;
    };

    var setDashboard = function(api) {
        dashboard = api;
        modules.MWADashboard = api;
        return api;
    };

    var callAction = function(method, args) {
        if (!actionCaller) {
            return Promise.reject(new Error('Dashboard AJAX bridge is not available.'));
        }
        var actionArgs = args || {};
        var aiReadOnlyActions = ['get_ai_recommendation', 'chat_message'];
        var canRetry = aiReadOnlyActions.indexOf(method) !== -1;
        var isTransientFailure = function(error) {
            var details = [
                error && error.message,
                error && error.errorcode,
                error && error.debuginfo,
                error && error.exception
            ].filter(Boolean).join(' ').toLowerCase();
            return /database|banco de dados|dml|timeout|timed out|tempor|network|fetch|service unavailable/.test(details);
        };
        var run = function(attempt) {
            return actionCaller(method, actionArgs).catch(function(error) {
                if (!canRetry || attempt > 0 || !isTransientFailure(error)) {
                    throw error;
                }
                return new Promise(function(resolve) {
                    window.setTimeout(resolve, 650);
                }).then(function() {
                    return run(attempt + 1);
                });
            });
        };
        return run(0);
    };

    var setHandler = function(name, handler) {
        handlers[name] = handler;
        if (name === 'showPage' || name === 'markSeen' || name === 'toggleSelectPriority' || name === 'openBulkEmail') {
            window[name] = handler;
        }
        return handler;
    };

    var clearElement = function(element) {
        if (element && element.replaceChildren) {
            element.replaceChildren();
        } else if (element) {
            while (element.firstChild) {
                element.removeChild(element.firstChild);
            }
        }
    };

    var notify = function(message, type) {
        var root = document.getElementById('block-mwa-dashboard-app') || document.body;
        var region = root.querySelector('.mwa-feedback-region');
        if (!region) {
            region = document.createElement('div');
            region.className = 'mwa-feedback-region';
            region.setAttribute('aria-live', 'polite');
            region.setAttribute('aria-atomic', 'true');
            root.appendChild(region);
        }
        var item = document.createElement('div');
        var status = type === 'error' ? 'error' : (type === 'warning' ? 'warning' : 'success');
        item.className = 'mwa-feedback ' + status;
        item.setAttribute('role', status === 'error' ? 'alert' : 'status');
        var svgNs = 'http://www.w3.org/2000/svg';
        var icon = document.createElementNS(svgNs, 'svg');
        icon.setAttribute('class', 'mwa-ui-icon');
        icon.setAttribute('aria-hidden', 'true');
        var iconUse = document.createElementNS(svgNs, 'use');
        iconUse.setAttribute('href', '#mwa-icon-' + (status === 'error' ? 'warning' : (status === 'warning' ? 'clock' : 'check')));
        icon.appendChild(iconUse);
        var text = document.createElement('span');
        text.textContent = String(message || '');
        var close = document.createElement('button');
        close.type = 'button';
        close.setAttribute('aria-label', strings.close || 'Close');
        var closeIcon = document.createElementNS(svgNs, 'svg');
        closeIcon.setAttribute('class', 'mwa-ui-icon');
        closeIcon.setAttribute('aria-hidden', 'true');
        var closeUse = document.createElementNS(svgNs, 'use');
        closeUse.setAttribute('href', '#mwa-icon-close');
        closeIcon.appendChild(closeUse);
        close.appendChild(closeIcon);
        item.appendChild(icon);
        item.appendChild(text);
        item.appendChild(close);
        var remove = function() {
            item.classList.add('leaving');
            window.setTimeout(function() { if (item.parentNode) item.parentNode.removeChild(item); }, 180);
        };
        close.addEventListener('click', remove);
        region.appendChild(item);
        window.setTimeout(remove, status === 'error' ? 5200 : 3600);
        return item;
    };

    var renderHtml = function(element, html) {
        if (!element) {
            return;
        }
        clearElement(element);
        var tag = element.tagName ? element.tagName.toLowerCase() : '';
        var wrapped = html;
        
        if (tag === 'tbody' || tag === 'thead') {
            wrapped = '<table><tbody>' + html + '</tbody></table>';
        } else if (tag === 'tr') {
            wrapped = '<table><tbody><tr>' + html + '</tr></tbody></table>';
        }
        var doc = new DOMParser().parseFromString(String(wrapped || ''), 'text/html');
        var src = (tag === 'tbody' || tag === 'thead')
            ? doc.querySelector('tbody')
            : doc.body;
        if (!src) { return; }
        while (src.firstChild) {
            element.appendChild(document.importNode(src.firstChild, true));
            src.removeChild(src.firstChild);
        }
    };

    var callHandler = function(name) {
        var handler = handlers[name];
        if (typeof handler === 'function') {
            return handler.apply(null, Array.prototype.slice.call(arguments, 1));
        }
        return null;
    };

    var bindDomEvents = function(root) {
        if (!root || root.dataset.mwaEventsBound === '1') {
            return;
        }
        root.dataset.mwaEventsBound = '1';
        root.addEventListener('click', function(e) {
            var pageButton = e.target.closest('[data-action-page]');
            if (pageButton && root.contains(pageButton)) {
                e.preventDefault();
                callHandler('showPage', pageButton.getAttribute('data-action-page'));
                if (pageButton.getAttribute('data-act-low') === '1') {
                    setTimeout(function() {
                        var acts = getModule('MWAActivities');
                        if (acts && acts.showLowPerformers) {
                            acts.showLowPerformers();
                        }
                    }, 0);
                }
                return;
            }
            var profileButton = e.target.closest('[data-profile-student]');
            if (profileButton && root.contains(profileButton)) {
                e.preventDefault();
                var studentName = profileButton.getAttribute('data-profile-student') || '';
                if (window.goToStudentProfile) {
                    window.goToStudentProfile(studentName);
                    return;
                }
                callHandler('showPage', 'studentprofile');
                setTimeout(function() {
                    var profile = getModule('MWAProfile');
                    if (profile && typeof profile.render === 'function') {
                        profile.render();
                    }
                    var sel = document.getElementById('spStudentSel');
                    var selected = studentName;
                    if (sel) {
                        var opts = Array.prototype.slice.call(sel.options || []);
                        var opt = opts.find(function(o) {
                            return o.value === studentName || o.text === studentName;
                        });
                        if (opt) {
                            sel.value = opt.value;
                            selected = opt.value;
                        }
                    }
                    if (profile && typeof profile.loadProfile === 'function') {
                        profile.loadProfile(selected);
                    }
                }, 80);
                return;
            }
            var actionButton = e.target.closest('[data-mwa-action]');
            if (!actionButton || !root.contains(actionButton)) {
                return;
            }
            e.preventDefault();
            var action = actionButton.getAttribute('data-mwa-action');
            if (action === 'mark-seen') {
                callHandler('markSeen');
            } else if (action === 'toggle-select-priority') {
                callHandler('toggleSelectPriority');
            } else if (action === 'open-bulk-email') {
                callHandler('openBulkEmail');
            } else if (action === 'classlist-toggle') {
                var classList = getModule('MWAClassList');
                if (classList) {
                    classList.toggle();
                }
            } else if (action === 'activity-filter') {
                var activities = getModule('MWAActivities');
                if (activities) {
                    activities.setFilter(actionButton.getAttribute('data-filter'), actionButton);
                }
            } else if (action === 'send-selected-intervention') {
                var interventions = getModule('MWAInterventions');
                if (interventions) {
                    interventions.sendToSelected();
                }
            } else if (action === 'classlist-clear-filters') {
                var classListClear = getModule('MWAClassList');
                if (classListClear) {
                    var sort = root.querySelector('#clSort');
                    if (sort) sort.value = 'risk';
                    classListClear.setFilter('all', '');
                }
            }
        });
        root.addEventListener('change', function(e) {
            if (e.target && e.target.id === 'clFilterBar') {
                var classListFilter = getModule('MWAClassList');
                if (classListFilter) {
                    classListFilter.setFilter(e.target.value || 'all', (root.querySelector('#clSearch') || {}).value || '');
                }
            } else if (e.target && e.target.id === 'clSort') {
                var classList = getModule('MWAClassList');
                if (classList) {
                    classList.render();
                }
            } else if (e.target && e.target.id === 'spStudentSel') {
                var profile = getModule('MWAProfile');
                if (profile) {
                    profile.loadProfile(e.target.value);
                }
            }
        });
        root.addEventListener('input', function(e) {
            if (e.target && e.target.id === 'clSearch') {
                var classList = getModule('MWAClassList');
                if (classList) {
                    classList.filter(e.target.value);
                }
            }
        });
    };

    var defineFacadeProperty = function(obj, name, getter, setter) {
        Object.defineProperty(obj, name, {
            configurable: true,
            enumerable: false,
            get: getter,
            set: setter || function(value) { legacy[name] = value; }
        });
    };

    var windowFacade = function() {
        if (facade) {
            return facade;
        }
        facade = {};
        defineFacadeProperty(facade, 'MWADashboard', function() { return dashboard; }, setDashboard);
        ['MWAActionCenter', 'MWAAlerts', 'MWAClassList', 'MWAProfile', 'MWAActivities', 'MWAGrades', 'MWAInterventions', 'MWAChat'].forEach(function(name) {
            defineFacadeProperty(facade, name, function() { return modules[name]; }, function(value) { register(name, value); });
        });
        ['MWA_GRADE_CACHE', 'MWA_ACT_NAMES', 'MWA_ACT_CMIDS', 'MWA_ACT_MODULES', 'MWA_NOTES', 'MWA_CONTACTS', 'mwaRetentionChart'].forEach(function(name) {
            defineFacadeProperty(facade, name, function() { return legacy[name]; }, function(value) { legacy[name] = value; });
        });
        defineFacadeProperty(facade, 'Chart', function() { return window.Chart; });
        defineFacadeProperty(facade, 'showPage', function() { return handlers.showPage; }, function(value) { handlers.showPage = value; });
        defineFacadeProperty(facade, 'markSeen', function() { return handlers.markSeen; }, function(value) { handlers.markSeen = value; });
        defineFacadeProperty(facade, 'toggleSelectPriority', function() { return handlers.toggleSelectPriority; }, function(value) { handlers.toggleSelectPriority = value; });
        defineFacadeProperty(facade, 'openBulkEmail', function() { return handlers.openBulkEmail; }, function(value) { handlers.openBulkEmail = value; });
        facade.location = window.location;
        facade.history = window.history;
        facade.URL = window.URL;
        facade.parent = window.parent;
        facade.confirm = window.confirm.bind(window);
        facade.alert = window.alert.bind(window);
        facade.requestAnimationFrame = window.requestAnimationFrame.bind(window);
        facade.matchMedia = window.matchMedia.bind(window);
        return facade;
    };

    return {
        configure: configure,
        register: register,
        getModule: getModule,
        getStrings: getStrings,
        getConfig: getConfig,
        setDashboard: setDashboard,
        callAction: callAction,
        setHandler: setHandler,
        callHandler: callHandler,
        clearElement: clearElement,
        notify: notify,
        renderHtml: renderHtml,
        bindDomEvents: bindDomEvents,
        windowFacade: windowFacade
    };
});
