/**
 * Application - Main application bootstrap and lifecycle manager
 * Auto-initializes the entire system without external commands
 */

import { EventBus, ModuleLoader, Router } from './core/index.js';

class Application {
    constructor(config = {}) {
        // Application state
        this._isRunning = false;
        this._isInitialized = false;
        this._startTime = null;

        // Core system instances
        this._eventBus = new EventBus();
        this._moduleLoader = new ModuleLoader(this._eventBus);
        this._router = null;

        // Register core modules immediately for early access
        this._registerCoreModules();

        // Configuration
        this._config = {
            autoStart: config.autoStart !== false, // Default true
            defaultRoute: config.defaultRoute || '/',
            enableDebug: config.enableDebug || false,
            modules: config.modules || [],
            ...config
        };

        // Auto-start if enabled
        if (this._config.autoStart) {
            this._autoStart();
        }

        // Seal to prevent modification
        Object.seal(this);
    }

    /**
     * Initialize and start the application
     */
    async start() {
        if (this._isRunning) {
            console.warn('Application is already running');
            return;
        }

        try {
            this._startTime = Date.now();

            console.log('🚀 Starting Class Generator Application...');

            // Validate all progress item implementations (STRICT MODE)
            console.log('🔍 Validating progress item implementations...');
            const { default: ImplementationValidator } = await import('./DRS/services/ImplementationValidator.js');
            const isValid = await ImplementationValidator.validateAll();

            if (!isValid) {
                throw new Error('❌ Implementation validation failed - check console for details');
            }

            // Initialize core systems
            await this._initializeCore();

            // Load and initialize modules
            await this._loadModules();

            // Start routing
            await this._startRouting();

            // Set up global error handling
            this._setupErrorHandling();

            this._isRunning = true;
            this._isInitialized = true;

            const startupTime = Date.now() - this._startTime;
            console.log(`✅ Application started successfully in ${startupTime}ms`);

            // Emit application ready event
            this._eventBus.emit('app:ready', {
                startupTime,
                modules: this._moduleLoader.getStatus()
            }, 'Application');

        } catch (error) {
            console.error('❌ Failed to start application:', error);
            throw error;
        }
    }

    /**
     * Stop the application and clean up
     */
    async stop() {
        if (!this._isRunning) {
            return;
        }

        try {
            console.log('🛑 Stopping application...');

            // Emit application stopping event
            this._eventBus.emit('app:stopping', {}, 'Application');

            // Destroy all modules
            const status = this._moduleLoader.getStatus();
            for (const moduleName of status.loaded) {
                await this._moduleLoader.destroy(moduleName);
            }

            // Destroy router
            if (this._router) {
                await this._moduleLoader.destroy('router');
            }

            this._isRunning = false;
            this._isInitialized = false;

            console.log('✅ Application stopped successfully');

        } catch (error) {
            console.error('❌ Error stopping application:', error);
        }
    }

    /**
     * Get application status
     */
    getStatus() {
        return {
            isRunning: this._isRunning,
            isInitialized: this._isInitialized,
            startTime: this._startTime,
            uptime: this._startTime ? Date.now() - this._startTime : 0,
            modules: this._moduleLoader.getStatus(),
            config: { ...this._config }
        };
    }

    /**
     * Get core system instances (for advanced usage)
     */
    getCore() {
        return {
            eventBus: this._eventBus,
            moduleLoader: this._moduleLoader,
            router: this._router
        };
    }

    /**
     * Get a loaded module by name
     * @param {string} moduleName - Name of the module to get
     * @returns {Object|null} Module instance or null if not found
     */
    getModule(moduleName) {
        return this._moduleLoader ? this._moduleLoader.getModule(moduleName) : null;
    }

    // Private methods
    async _autoStart() {
        // Wait for DOM to be ready
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', () => this.start());
        } else {
            // DOM is already loaded
            setTimeout(() => this.start(), 0);
        }
    }

    _registerCoreModules() {
        // Register bootstrap module to allow HTML script to use EventBus
        this._eventBus.registerModule({ name: 'Bootstrap' });

        // Register Application itself as a module
        this._eventBus.registerModule({ name: 'Application' });

        // Register ModuleLoader as a module
        this._eventBus.registerModule({ name: 'ModuleLoader' });

        // Register core dependencies by storing them directly in ModuleLoader
        // This allows other modules to depend on 'eventBus'
        this._moduleLoader._loadedModules.set('eventBus', this._eventBus);
        this._moduleLoader._modules.set('eventBus', {
            name: 'eventBus',
            instance: this._eventBus,
            loaded: true,
            initialized: true
        });
    }

    async _initializeCore() {
        // Register router as a module
        this._moduleLoader.register('router', Router, ['eventBus']);

        // Create and initialize router
        this._router = await this._moduleLoader.loadAndInitialize('router', {
            defaultRoute: this._config.defaultRoute,
            maxHistorySize: 100
        });

        if (this._config.enableDebug) {
            console.log('🔧 Core systems initialized');
        }
    }

    async _loadModules() {
        console.log(`🔄 Loading ${this._config.modules.length} modules...`);

        // PHASE 1: Register all modules first
        console.log('📋 PHASE 1: Registering all modules...');
        for (const moduleConfig of this._config.modules) {
            try {
                const { name, path, dependencies = [], config = {} } = moduleConfig;

                console.log(`📝 Registering module: ${name} from ${path}`);

                // Dynamically import module
                const moduleModule = await import(path);
                const ModuleClass = moduleModule.default;

                if (!ModuleClass) {
                    throw new Error(`Module ${name} does not export a default class`);
                }

                // Register only
                this._moduleLoader.register(name, ModuleClass, dependencies);
                console.log(`✅ Registered module: ${name} with dependencies: [${dependencies.join(', ')}]`);

            } catch (error) {
                console.error(`❌ Failed to register module ${moduleConfig.name}:`, error);
                console.error(`❌ Module config was:`, moduleConfig);
                console.error(`❌ Full error stack:`, error.stack);

                // Emit module load error
                this._eventBus.emit('app:module-error', {
                    module: moduleConfig.name,
                    error: error.message
                }, 'Application');
            }
        }

        // Show registration status
        const status = this._moduleLoader.getStatus();
        console.log(`📊 Registration complete. Registered modules: [${status.registered.join(', ')}]`);

        // PHASE 2: Load and initialize all modules
        console.log('🚀 PHASE 2: Loading and initializing modules...');
        for (const moduleConfig of this._config.modules) {
            try {
                const { name, config = {} } = moduleConfig;

                console.log(`🔄 Loading and initializing module: ${name}`);
                await this._moduleLoader.loadAndInitialize(name, config);
                console.log(`✅ Module ${name} loaded and initialized successfully`);

            } catch (error) {
                console.error(`❌ Failed to load/initialize module ${moduleConfig.name}:`, error);
                console.error(`❌ Module config was:`, moduleConfig);
                console.error(`❌ Full error stack:`, error.stack);

                // Emit module load error
                this._eventBus.emit('app:module-error', {
                    module: moduleConfig.name,
                    error: error.message
                }, 'Application');
            }
        }

        // Final status
        const finalStatus = this._moduleLoader.getStatus();
        console.log(`🎯 Module loading complete. Initialized modules: [${finalStatus.initialized.join(', ')}]`);
    }

    async _startRouting() {
        // Register generic routes with dynamic loading
        this._router.register('/', this._handleHomeRoute.bind(this));
        this._router.register('/books', this._handleBooksRoute.bind(this));
        this._router.register('/chapters', this._handleChaptersRoute.bind(this), { exact: false });
        this._router.register('/games', this._handleGamesRoute.bind(this), { exact: false });
        this._router.register('/dynamic-revision', this._handleDynamicRevisionRoute.bind(this));
        this._router.register('/settings', this._handleSettingsRoute.bind(this));

        // Now that routes are registered, handle the current route
        console.log('🛣️ Routes registered, handling initial route...');
        this._router._handleCurrentRoute();

        if (this._config.enableDebug) {
            console.log('🛣️ Routing system started');
        }
    }

    _setupErrorHandling() {
        // Global error handler
        window.addEventListener('error', (event) => {
            console.error('Global error:', event.error);
            this._eventBus.emit('app:error', {
                message: event.error.message,
                filename: event.filename,
                lineno: event.lineno,
                colno: event.colno
            }, 'Application');
        });

        // Unhandled promise rejection handler
        window.addEventListener('unhandledrejection', (event) => {
            console.error('Unhandled promise rejection:', event.reason);
            this._eventBus.emit('app:promise-rejection', {
                reason: event.reason
            }, 'Application');
        });

        if (this._config.enableDebug) {
            console.log('🛡️ Error handling setup complete');
        }
    }

    // Default route handlers
    async _handleHomeRoute(path, state) {
        this._eventBus.emit('navigation:home', { path, state }, 'Application');
    }

    async _handleBooksRoute(path, state) {
        this._eventBus.emit('navigation:books', { path, state }, 'Application');
    }

    async _handleChaptersRoute(path, state) {
        this._eventBus.emit('navigation:chapters', { path, state }, 'Application');
    }

    async _handleGamesRoute(path, state) {
        // Simple approach: Force re-render by emitting the chapter navigation event
        console.log('🔄 Games route - path:', path, 'state:', state);

        // Extract ID from path
        const pathParts = path.split('/');
        const pathId = pathParts[2];

        // IMPORTANT: Use window.currentChapterId if available (set by Smart Guide/Chapter selection)
        // If not available, check if we should use the path ID
        let chapterId = window.currentChapterId;

        if (!chapterId && pathId) {
            // Path has an ID, but we don't know if it's a book or chapter
            // Try to use it, but warn the user
            console.warn(`⚠️ Using ID from path: ${pathId} (may be book ID, should be chapter ID)`);
            chapterId = pathId;
        }

        if (!chapterId) {
            console.warn('⚠️ No chapter selected. Please select a chapter first.');
            // Redirect to home - user needs to select a chapter
            this._router.navigate('/');
            return;
        }

        console.log('🔄 Games route - using chapterId:', chapterId, '(from', window.currentChapterId ? 'window.currentChapterId' : 'path', ')');

        // Keep currentChapterId consistent
        window.currentChapterId = chapterId;

        // Emit navigation event ONCE - don't emit twice
        this._eventBus.emit('navigation:games', {
            path: `/games/${chapterId}`,
            data: { path: `/games/${chapterId}` }
        }, 'Application');
    }

    async _handleDynamicRevisionRoute(path, state) {
        this._eventBus.emit('navigation:dynamic-revision', { path, state }, 'Application');
    }

    async _handleSettingsRoute(path, state) {
        this._eventBus.emit('navigation:settings', { path, state }, 'Application');
    }
}

// Create global application instance
const app = new Application({
    enableDebug: true,
    modules: [
        // Core system modules
        { name: 'contentLoader', path: './core/ContentLoader.js', dependencies: ['eventBus'] },
        { name: 'gameLoader', path: './core/GameLoader.js', dependencies: ['eventBus'] },
        { name: 'intelligentSequencer', path: './core/IntelligentSequencer.js', dependencies: ['eventBus'] },
        // DRS system
        { name: 'unifiedDRS', path: './DRS/UnifiedDRS.js', dependencies: ['eventBus', 'contentLoader'] },
        { name: 'smartPreviewOrchestrator', path: './DRS/SmartPreviewOrchestrator.js', dependencies: ['eventBus', 'contentLoader'] },
        // UI components
        { name: 'settingsDebug', path: './components/SettingsDebug.js', dependencies: ['eventBus', 'router'] }
    ]
});

// Export for manual control if needed
export default app;

// Auto-start is handled by the constructor