// Dynamic Module Loader System
window.ModuleLoader = (function () {
    const loadedScripts = new Set();
    const loadedStyles = new Set();
    const moduleInstances = new Map();

    // Cache de recursos carregados
    const resourceCache = new Map();

    function log(message, ...args) {
        console.log(`🔧 ModuleLoader: ${message}`, ...args);
    }

    function error(message, ...args) {
        console.error(`❌ ModuleLoader: ${message}`, ...args);
    }

    async function loadScript(url, moduleBaseUrl) {
        const fullUrl = resolveUrl(url, moduleBaseUrl);

        if (loadedScripts.has(fullUrl)) {
            log(`Script já carregado: ${fullUrl}`);
            return true;
        }

        try {
            log(`Carregando script: ${fullUrl}`);

            const response = await fetch(fullUrl);
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }

            const scriptContent = await response.text();

            // Criar script element e executar
            const script = document.createElement('script');
            script.textContent = scriptContent;
            script.setAttribute('data-module-script', fullUrl);
            document.head.appendChild(script);

            loadedScripts.add(fullUrl);
            log(`✅ Script carregado com sucesso: ${fullUrl}`);
            return true;
        } catch (err) {
            error(`Falha ao carregar script ${fullUrl}:`, err);
            return false;
        }
    }

    async function loadStyle(url, moduleBaseUrl) {
        const fullUrl = resolveUrl(url, moduleBaseUrl);

        if (loadedStyles.has(fullUrl)) {
            log(`CSS já carregado: ${fullUrl}`);
            return true;
        }

        try {
            log(`Carregando CSS: ${fullUrl}`);

            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = fullUrl;
            link.setAttribute('data-module-style', fullUrl);

            return new Promise((resolve, reject) => {
                link.onload = () => {
                    loadedStyles.add(fullUrl);
                    log(`✅ CSS carregado com sucesso: ${fullUrl}`);
                    resolve(true);
                };
                link.onerror = () => {
                    error(`Falha ao carregar CSS: ${fullUrl}`);
                    reject(false);
                };
                document.head.appendChild(link);
            });
        } catch (err) {
            error(`Erro ao carregar CSS ${fullUrl}:`, err);
            return false;
        }
    }

    function resolveUrl(url, baseUrl) {
        if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//')) {
            return url;
        }

        if (url.startsWith('/')) {
            const base = new URL(baseUrl);
            return `${base.protocol}//${base.host}${url}`;
        }

        return new URL(url, baseUrl).href;
    }

    function extractModuleMetadata(container) {
        const metadataScript = container.querySelector('#module-metadata');
        if (!metadataScript) {
            log('Nenhum metadata encontrado no módulo');
            return null;
        }

        try {
            const metadata = JSON.parse(metadataScript.textContent);
            log('Metadata extraído:', metadata);
            return metadata;
        } catch (err) {
            error('Erro ao parsear metadata:', err);
            return null;
        }
    }

    function getModuleBaseUrl(moduleUrl) {
        try {
            const url = new URL(moduleUrl, window.location.href);
            const pathParts = url.pathname.split('/');
            pathParts.pop(); // Remove o último segmento (nome do endpoint)
            url.pathname = pathParts.join('/');
            return url.href;
        } catch (err) {
            error('Erro ao extrair base URL:', err);
            return window.location.origin;
        }
    }

    async function initializeModule(containerId, moduleUrl, metadata) {
        const moduleBaseUrl = getModuleBaseUrl(moduleUrl);
        log(`Inicializando módulo em ${containerId} com base URL: ${moduleBaseUrl}`);

        try {
            // Carregar CSS se especificado
            if (metadata.cssUrl) {
                await loadStyle(metadata.cssUrl, moduleBaseUrl);
            }

            // Carregar JavaScript
            if (metadata.jsUrl) {
                const scriptLoaded = await loadScript(metadata.jsUrl, moduleBaseUrl);
                if (!scriptLoaded) {
                    throw new Error('Falha ao carregar script principal');
                }
            }

            // Aguardar um momento para o script ser executado
            await new Promise(resolve => setTimeout(resolve, 100));

            // Chamar função de inicialização
            if (metadata.jsFunction) {
                const functionPath = metadata.jsFunction.split('.');
                let func = window;

                for (const part of functionPath) {
                    func = func[part];
                    if (!func) {
                        throw new Error(`Função ${metadata.jsFunction} não encontrada`);
                    }
                }

                if (typeof func === 'function') {
                    log(`Chamando função de inicialização: ${metadata.jsFunction}`);
                    const result = func(containerId);

                    if (result) {
                        moduleInstances.set(containerId, {
                            metadata,
                            moduleUrl,
                            moduleBaseUrl,
                            initialized: true
                        });
                        log(`✅ Módulo ${metadata.moduleId} inicializado com sucesso`);
                        return true;
                    }
                }
            }

            return false;
        } catch (err) {
            error(`Erro ao inicializar módulo:`, err);
            return false;
        }
    }

    async function loadModule(moduleId, containerId, moduleUrl) {
        log(`Carregando módulo ${moduleId} em ${containerId} de ${moduleUrl}`);

        try {
            // Carregar HTML do módulo
            const response = await fetch(moduleUrl);
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }

            const html = await response.text();
            const container = document.getElementById(containerId);

            if (!container) {
                throw new Error(`Container ${containerId} não encontrado`);
            }

            // Inserir HTML
            container.innerHTML = html;

            // Extrair metadata
            const metadata = extractModuleMetadata(container);
            if (!metadata) {
                log('⚠️ Módulo sem metadata, tentando funcionar sem JavaScript');
                return true;
            }

            // Inicializar módulo
            const success = await initializeModule(containerId, moduleUrl, metadata);

            if (success) {
                // Disparar evento
                const event = new CustomEvent('moduleLoaded', {
                    detail: {
                        moduleId: metadata.moduleId,
                        containerId,
                        moduleUrl,
                        metadata
                    }
                });
                document.dispatchEvent(event);

                return true;
            }

            return false;

        } catch (err) {
            error(`Erro ao carregar módulo ${moduleId}:`, err);
            return false;
        }
    }

    function getModuleInfo(containerId) {
        return moduleInstances.get(containerId);
    }

    function unloadModule(containerId) {
        const info = moduleInstances.get(containerId);
        if (info) {
            // Limpar container
            const container = document.getElementById(containerId);
            if (container) {
                container.innerHTML = '';
            }

            moduleInstances.delete(containerId);
            log(`Módulo removido: ${containerId}`);
        }
    }

    // API pública
    return {
        loadModule,
        getModuleInfo,
        unloadModule,
        version: '2.0.0'
    };
})();

// Compatibilidade com sistema antigo
window.ModuleSystem = {
    loadModule: window.ModuleLoader.loadModule,
    version: '2.0.0-compat'
};