import { moduleConfig } from './config.js';
import { Logger } from '../core/logger.js';
import { moduleErrorBoundary } from '../core/ModuleErrorBoundary.js';
import { stateManager } from '../core/StateManager.js';
import { dependencyManager } from '../core/DependencyManager.js';

export const activeModules = new Map(); // key: modulename → { mod, config, state }

export async function registerModules() {
    // Use EAGER loading for single bundle - all modules in one chunk
    let modules;
    if (typeof global !== 'undefined' && global.importMeta?.glob) {
        modules = global.importMeta.glob('./*/index.js', { eager: true });
    } else {
        modules = import.meta.glob('./*/index.js', { eager: true });
    }
    
    Logger.info('[Modules] Found modules:', Object.keys(modules));

    const domModules = new Set(
        Array.from(document.querySelectorAll('[data-module]')).map(el => el.dataset.module).filter(Boolean)
    );

    // Always load these core modules
    const coreModules = new Set(['spa-router', 'form-handling', 'api-manager', 'image-manager', 'livecomponent']);
    
    const usedModules = new Set([...domModules, ...coreModules]);
    const fallbackMode = usedModules.size === coreModules.size && domModules.size === 0;
    
    Logger.info('[Modules] DOM modules found:', [...domModules]);
    Logger.info('[Modules] Core modules:', [...coreModules]);
    Logger.info('[Modules] Used modules:', [...usedModules]);
    Logger.info('[Modules] Fallback mode:', fallbackMode);

    // Phase 1: Register only USED modules with dependency manager
    console.log('🔍 [Modules] Starting Phase 1 - Module Registration');
    console.log('🔍 [Modules] All discovered modules:', Object.keys(modules));
    console.log('🔍 [Modules] Used modules:', [...usedModules]);
    console.log('🔍 [Modules] Fallback mode:', fallbackMode);

    Object.entries(modules).forEach(([path, mod]) => {
        const name = path.split('/').slice(-2, -1)[0];
        console.log(`🔍 [Module] Processing: ${name} from ${path}`);
        console.log(`🔍 [Module] Used modules has ${name}:`, usedModules.has(name));

        if(!fallbackMode && !usedModules.has(name)) {
            console.log(`⏭️ [Module] Skipping unused module: ${name}`);
            return;
        }

        console.log(`✅ [Module] Registering ${name} with dependency manager`);

        // Register module definition if provided
        if (typeof mod.definition === 'object') {
            Logger.info(`📋 [Module] Using definition for ${name}:`, mod.definition);
            dependencyManager.register(mod.definition);
        } else {
            // Create default definition for modules without explicit dependencies
            const defaultDef = {
                name,
                version: '1.0.0',
                dependencies: [],
                provides: [],
                priority: 0
            };
            Logger.info(`📋 [Module] Using default definition for ${name}:`, defaultDef);
            dependencyManager.register(defaultDef);
        }
    });

    // Phase 2: Calculate initialization order
    const initOrder = dependencyManager.calculateInitializationOrder();
    console.log('🔍 [Modules] Phase 2 - Initialization Order:', initOrder);

    // Phase 3: Initialize modules in dependency order
    for (const name of initOrder) {
        console.log(`🔍 [Module] Phase 3 - Processing ${name} for initialization`);
        console.log(`🔍 [Module] Used modules has ${name}:`, usedModules.has(name));
        console.log(`🔍 [Module] Fallback mode:`, fallbackMode);

        if(!fallbackMode && !usedModules.has(name)) {
            console.log(`⏭️ [Module] Skipped (not used in DOM): ${name}`);
            continue;
        }

        const modulePath = Object.keys(modules).find(path =>
            path.split('/').slice(-2, -1)[0] === name
        );

        console.log(`🔍 [Module] Looking for module path for ${name}, found:`, modulePath);

        if (!modulePath) {
            console.log(`⛔ [Module] No implementation found for: ${name}`);
            continue;
        }

        const mod = modules[modulePath];
        const config = moduleConfig[name] || {};

        console.log(`🔍 [Module] Module ${name} object:`, mod);
        console.log(`🔍 [Module] Config for ${name}:`, config);

        // Check dependencies before initialization
        const depCheck = dependencyManager.checkDependencies(name);
        console.log(`🔍 [Module] Dependency check for ${name}:`, depCheck);

        if (!depCheck.satisfied) {
            console.log(`❌ [Module] Cannot initialize ${name}: ${depCheck.reason}`);
            activeModules.set(name, { mod: null, config, error: new Error(depCheck.reason), original: mod });
            continue;
        }

        console.log(`🔍 [Module] Checking init function for ${name}:`, typeof mod.init, mod.init);
        console.log(`🔍 [Module] Module object keys for ${name}:`, Object.keys(mod));
        console.log(`🔍 [Module] Full module object for ${name}:`, mod);

        if (typeof mod.init === 'function') {
            try {
                Logger.info(`🚀 [Module] Starting initialization for ${name}`);
                dependencyManager.markInitializing(name);

                // Create scoped state manager for module
                const scopedState = stateManager.createScope(name);

                // Wrap module with error boundary
                const protectedMod = moduleErrorBoundary.wrapModule(mod, name);

                // Initialize module with config and state
                await protectedMod.init(config, scopedState);

                dependencyManager.markInitialized(name);
                activeModules.set(name, {
                    mod: protectedMod,
                    config,
                    state: scopedState,
                    original: mod
                });
                Logger.info(`✅ [Module] Initialized: ${name}`);
            } catch (error) {
                Logger.error(`❌ [Module] Failed to initialize ${name}:`, error);
                activeModules.set(name, { mod: null, config, error, original: mod });
            }
        } else {
            Logger.warn(`⛔ [Module] No init() in ${name} - typeof:`, typeof mod.init);
            Logger.warn(`⛔ [Module] Available properties:`, Object.getOwnPropertyNames(mod));
        }
    }

    if (fallbackMode) {
        Logger.info('⚠️ [Module] No data-module usage detected, fallback to full init mode');
    }
}

export function destroyModules() {
    for (const [name, { mod, state }] of activeModules.entries()) {
        if (mod && typeof mod.destroy === 'function') {
            try {
                mod.destroy();
                Logger.info(`🧹 [Module] Destroyed: ${name}`);
            } catch (error) {
                Logger.error(`❌ [Module] Failed to destroy ${name}:`, error);
            }
        }
        
        // Clean up state subscriptions
        if (state && typeof state.cleanup === 'function') {
            state.cleanup();
        }
    }
    activeModules.clear();
    moduleErrorBoundary.reset();
    stateManager.reset();
    dependencyManager.reset();
}

/**
 * Gets health status of all active modules
 * @returns {Object} Module health report
 */
export function getModuleHealth() {
    const health = {
        total: activeModules.size,
        active: 0,
        failed: 0,
        modules: {},
        errorBoundary: moduleErrorBoundary.getHealthStatus()
    };

    for (const [name, { mod, error }] of activeModules.entries()) {
        if (error) {
            health.failed++;
            health.modules[name] = { status: 'failed', error: error.message };
        } else if (mod) {
            health.active++;
            health.modules[name] = { status: 'active' };
        } else {
            health.modules[name] = { status: 'unknown' };
        }
    }

    return health;
}

// Debug function - access via console
if (typeof window !== 'undefined') {
    window.moduleHealth = getModuleHealth;
    window.activeModules = activeModules;
}
