/**
 * SmartPreviewOrchestrator - Main controller for Dynamic Revision System
 * Manages dynamic loading/unloading of exercise modules and coordinates shared services
 */

import Module from '../core/Module.js';

const privateData = new WeakMap();

class SmartPreviewOrchestrator extends Module {
    constructor(name, dependencies, config) {
        super(name, ['eventBus', 'contentLoader']);

        // Validate dependencies
        if (!dependencies.eventBus) {
            throw new Error('SmartPreviewOrchestrator requires EventBus dependency');
        }
        if (!dependencies.contentLoader) {
            throw new Error('SmartPreviewOrchestrator requires ContentLoader dependency');
        }

        // Store dependencies and configuration
        this._eventBus = dependencies.eventBus;
        this._contentLoader = dependencies.contentLoader;
        this._config = config || {};

        // Initialize private data
        privateData.set(this, {
            loadedModules: new Map(),
            availableModules: new Map(),
            currentModule: null,
            sharedServices: {
                llmValidator: null,
                prerequisiteEngine: null,
                contextMemory: null,
                aiReportInterface: null
            },
            sessionState: {
                currentChapter: null,
                chapterContent: null,
                masteredVocabulary: new Set(),
                masteredPhrases: new Set(),
                masteredGrammar: new Set(),
                sessionProgress: {},
                exerciseSequence: [],
                sequenceIndex: 0
            },
            moduleRegistry: {
                'vocabulary': './exercise-modules/VocabularyModule.js',
                'phrase': './exercise-modules/PhraseModule.js',
                'text': './exercise-modules/TextModule.js',
                'text-analysis': './exercise-modules/TextAnalysisModule.js',
                'audio': './exercise-modules/AudioModule.js',
                'image': './exercise-modules/ImageModule.js',
                'grammar': './exercise-modules/GrammarModule.js',
                'grammar-analysis': './exercise-modules/GrammarAnalysisModule.js',
                'translation': './exercise-modules/TranslationModule.js'
            }
        });

        Object.seal(this);
    }

    async init() {
        this._validateNotDestroyed();

        try {
            console.log('🎯 Initializing Smart Preview Orchestrator...');

            // Initialize shared services
            await this._initializeSharedServices();

            // Set up event listeners
            this._setupEventListeners();

            // Register available module types
            this._registerModuleTypes();

            this._setInitialized();
            console.log('✅ Smart Preview Orchestrator initialized successfully');

        } catch (error) {
            console.error('❌ SmartPreviewOrchestrator initialization failed:', error);
            throw error;
        }
    }

    async destroy() {
        this._validateNotDestroyed();

        try {
            console.log('🧹 Cleaning up Smart Preview Orchestrator...');

            // Unload all loaded modules
            await this._unloadAllModules();

            // Cleanup shared services
            await this._cleanupSharedServices();

            // Remove event listeners
            this._eventBus.off('drs:startSession', this._handleStartSession, this.name);
            this._eventBus.off('drs:switchModule', this._handleSwitchModule, this.name);
            this._eventBus.off('drs:updateProgress', this._handleUpdateProgress, this.name);

            this._setDestroyed();
            console.log('✅ Smart Preview Orchestrator destroyed successfully');

        } catch (error) {
            console.error('❌ SmartPreviewOrchestrator cleanup failed:', error);
            throw error;
        }
    }

    // Public API Methods

    /**
     * Start a new revision session for a chapter
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @returns {Promise<boolean>} - Success status
     */
    async startRevisionSession(bookId, chapterId) {
        this._validateInitialized();

        try {
            console.log(`🚀 Starting revision session: ${bookId} - ${chapterId}`);

            // Load chapter content
            const chapterContent = await this._contentLoader.loadContent(chapterId);

            const data = privateData.get(this);
            data.sessionState.currentChapter = { bookId, chapterId };
            data.sessionState.chapterContent = chapterContent;

            // Load existing progress from files
            if (window.getChapterProgress) {
                try {
                    const savedProgress = await window.getChapterProgress(bookId, chapterId);

                    // Populate session state with saved progress (handle both old and new format)
                    if (savedProgress.masteredVocabulary) {
                        const vocabItems = savedProgress.masteredVocabulary.map(entry => {
                            return typeof entry === 'string' ? entry : entry.item;
                        });
                        data.sessionState.masteredVocabulary = new Set(vocabItems);
                    }
                    if (savedProgress.masteredPhrases) {
                        const phraseItems = savedProgress.masteredPhrases.map(entry => {
                            return typeof entry === 'string' ? entry : entry.item;
                        });
                        data.sessionState.masteredPhrases = new Set(phraseItems);
                    }
                    if (savedProgress.masteredGrammar) {
                        const grammarItems = savedProgress.masteredGrammar.map(entry => {
                            return typeof entry === 'string' ? entry : entry.item;
                        });
                        data.sessionState.masteredGrammar = new Set(grammarItems);
                    }

                    console.log(`📁 Loaded existing progress: ${savedProgress.masteredVocabulary.length} vocab, ${savedProgress.masteredPhrases.length} phrases, mastery count: ${savedProgress.masteryCount}`);

                } catch (error) {
                    console.warn('Failed to load existing progress:', error);
                }
            }

            // Initialize prerequisites
            await this._analyzePrerequisites(chapterContent);

            // Generate exercise sequence
            await this._generateExerciseSequence();

            // Start AI reporting session
            if (data.sharedServices.llmValidator && data.sharedServices.aiReportInterface) {
                const sessionId = data.sharedServices.llmValidator.startReportSession({
                    bookId,
                    chapterId,
                    difficulty: this._config.difficulty || 'medium',
                    exerciseTypes: Array.from(data.availableModules.keys()),
                    totalExercises: data.sessionState.exerciseSequence.length
                });

                // Notify the report interface
                data.sharedServices.aiReportInterface.onSessionStart({
                    bookId,
                    chapterId,
                    sessionId
                });

                console.log(`📊 Started AI report session: ${sessionId}`);
            }

            // Start with first available exercise
            await this._startNextExercise();

            // Emit session started event
            this._eventBus.emit('drs:sessionStarted', {
                bookId,
                chapterId,
                totalExercises: data.sessionState.exerciseSequence.length,
                availableModules: Array.from(data.availableModules.keys())
            }, this.name);

            return true;

        } catch (error) {
            console.error('❌ Failed to start revision session:', error);
            this._eventBus.emit('drs:sessionError', { error: error.message }, this.name);
            return false;
        }
    }

    /**
     * Get available exercise modules based on current prerequisites
     * @returns {Array<string>} - Available module names
     */
    getAvailableModules() {
        this._validateInitialized();

        const data = privateData.get(this);
        return Array.from(data.availableModules.keys());
    }

    /**
     * Get shared services for external access
     * @returns {Object} - Shared services
     */
    getSharedServices() {
        this._validateInitialized();
        const data = privateData.get(this);
        return data.sharedServices;
    }

    /**
     * Switch to a different exercise module
     * @param {string} moduleType - Type of module to switch to
     * @returns {Promise<boolean>} - Success status
     */
    async switchToModule(moduleType) {
        this._validateInitialized();

        try {
            const data = privateData.get(this);

            if (!data.availableModules.has(moduleType)) {
                throw new Error(`Module type ${moduleType} is not available`);
            }

            // Unload current module
            if (data.currentModule) {
                await this._unloadModule(data.currentModule);
            }

            // Load new module
            const module = await this._loadModule(moduleType);
            data.currentModule = moduleType;

            // Present exercise
            const exerciseData = await this._getExerciseData(moduleType);
            const container = document.getElementById('drs-exercise-container');
            await module.present(container, exerciseData);

            this._eventBus.emit('drs:moduleActivated', { moduleType, exerciseData }, this.name);
            return true;

        } catch (error) {
            console.error(`❌ Failed to switch to module ${moduleType}:`, error);
            return false;
        }
    }

    /**
     * Get current session progress
     * @returns {Object} - Progress information
     */
    getSessionProgress() {
        this._validateInitialized();

        const data = privateData.get(this);
        const state = data.sessionState;

        return {
            currentChapter: state.currentChapter,
            masteredVocabulary: state.masteredVocabulary.size,
            masteredPhrases: state.masteredPhrases.size,
            masteredGrammar: state.masteredGrammar.size,
            completedExercises: state.sequenceIndex,
            totalExercises: state.exerciseSequence.length,
            progressPercentage: Math.round((state.sequenceIndex / state.exerciseSequence.length) * 100)
        };
    }

    // Private Methods

    async _initializeSharedServices() {
        console.log('🔧 Initializing shared services...');

        const data = privateData.get(this);

        try {
            // Initialize LLMValidator (mock for now)
            const { default: LLMValidator } = await import('./services/LLMValidator.js');
            data.sharedServices.llmValidator = new LLMValidator(this._config.llm || {});

            // Initialize AIReportInterface
            const { default: AIReportInterface } = await import('../components/AIReportInterface.js');
            data.sharedServices.aiReportInterface = new AIReportInterface(
                data.sharedServices.llmValidator,
                this._config.aiReporting || {}
            );

            // Initialize PrerequisiteEngine
            const { default: PrerequisiteEngine } = await import('./services/PrerequisiteEngine.js');
            data.sharedServices.prerequisiteEngine = new PrerequisiteEngine();

            // Initialize ContextMemory
            const { default: ContextMemory } = await import('./services/ContextMemory.js');
            data.sharedServices.contextMemory = new ContextMemory();

            console.log('✅ Shared services initialized');

        } catch (error) {
            console.error('❌ Failed to initialize shared services:', error);
            throw error;
        }
    }

    async _cleanupSharedServices() {
        const data = privateData.get(this);

        // Cleanup services if they have cleanup methods
        Object.values(data.sharedServices).forEach(service => {
            if (service && typeof service.cleanup === 'function') {
                service.cleanup();
            }
        });
    }

    _setupEventListeners() {
        this._eventBus.on('drs:startSession', this._handleStartSession.bind(this), this.name);
        this._eventBus.on('drs:switchModule', this._handleSwitchModule.bind(this), this.name);
        this._eventBus.on('drs:updateProgress', this._handleUpdateProgress.bind(this), this.name);
        this._eventBus.on('drs:exerciseCompleted', this._handleExerciseCompleted.bind(this), this.name);
    }

    _registerModuleTypes() {
        const data = privateData.get(this);

        // Register all available module types
        Object.keys(data.moduleRegistry).forEach(moduleType => {
            data.availableModules.set(moduleType, {
                path: data.moduleRegistry[moduleType],
                loaded: false,
                instance: null
            });
        });
    }

    async _loadModule(moduleType) {
        const data = privateData.get(this);
        const moduleInfo = data.availableModules.get(moduleType);

        if (!moduleInfo) {
            throw new Error(`Unknown module type: ${moduleType}`);
        }

        if (data.loadedModules.has(moduleType)) {
            return data.loadedModules.get(moduleType);
        }

        try {
            console.log(`📦 Loading module: ${moduleType}`);

            // Dynamic import of module
            const modulePath = moduleInfo.path.startsWith('./') ?
                moduleInfo.path : `./${moduleInfo.path}`;

            const { default: ModuleClass } = await import(modulePath);

            // Create instance with shared services
            const moduleInstance = new ModuleClass(
                this, // orchestrator reference
                data.sharedServices.llmValidator,
                data.sharedServices.prerequisiteEngine,
                data.sharedServices.contextMemory
            );

            // Initialize module
            await moduleInstance.init();

            data.loadedModules.set(moduleType, moduleInstance);
            moduleInfo.loaded = true;
            moduleInfo.instance = moduleInstance;

            console.log(`✅ Module loaded: ${moduleType}`);
            return moduleInstance;

        } catch (error) {
            console.error(`❌ Failed to load module ${moduleType}:`, error);
            throw error;
        }
    }

    async _unloadModule(moduleType) {
        const data = privateData.get(this);
        const module = data.loadedModules.get(moduleType);

        if (module) {
            try {
                await module.cleanup();
                data.loadedModules.delete(moduleType);

                const moduleInfo = data.availableModules.get(moduleType);
                if (moduleInfo) {
                    moduleInfo.loaded = false;
                    moduleInfo.instance = null;
                }

                console.log(`📤 Module unloaded: ${moduleType}`);

            } catch (error) {
                console.error(`❌ Error unloading module ${moduleType}:`, error);
            }
        }
    }

    async _unloadAllModules() {
        const data = privateData.get(this);
        const moduleTypes = Array.from(data.loadedModules.keys());

        for (const moduleType of moduleTypes) {
            await this._unloadModule(moduleType);
        }
    }

    async _analyzePrerequisites(chapterContent) {
        const data = privateData.get(this);

        // Use PrerequisiteEngine to analyze chapter content
        const prerequisites = data.sharedServices.prerequisiteEngine.analyzeChapter(chapterContent);

        console.log('📊 Prerequisites analyzed:', prerequisites);
    }

    async _generateExerciseSequence() {
        const data = privateData.get(this);

        // Generate exercise sequence based on content and mastery
        const chapterContent = data.sessionState.chapterContent;
        const masteredVocab = data.sessionState.masteredVocabulary;
        const masteredPhrases = data.sessionState.masteredPhrases;

        // Filter content to focus on non-mastered items
        const allVocab = Object.keys(chapterContent.vocabulary || {});
        const allPhrases = Object.keys(chapterContent.phrases || {});

        const unmasteredVocab = allVocab.filter(word => !masteredVocab.has(word));
        const unmasteredPhrases = allPhrases.filter(phrase => !masteredPhrases.has(phrase));

        console.log(`📊 Content analysis:`);
        console.log(`   📚 Vocabulary: ${unmasteredVocab.length}/${allVocab.length} unmastered`);
        console.log(`   💬 Phrases: ${unmasteredPhrases.length}/${allPhrases.length} unmastered`);

        const sequence = [];

        // Create vocabulary groups (focus on unmastered, but include some mastered for review)
        const vocabGroupSize = 5;
        const vocabGroups = Math.ceil(unmasteredVocab.length / vocabGroupSize);

        for (let i = 0; i < vocabGroups; i++) {
            sequence.push({
                type: 'vocabulary',
                subtype: 'group',
                groupSize: vocabGroupSize,
                groupIndex: i,
                adaptive: true // Mark as adaptive sequence
            });
        }

        // Add unmastered phrases (prioritize new content)
        unmasteredPhrases.forEach((phrase, index) => {
            if (index < 10) { // Limit to 10 phrases per session
                sequence.push({
                    type: 'phrase',
                    subtype: 'individual',
                    index: allPhrases.indexOf(phrase),
                    adaptive: true
                });
            }
        });

        // Add some review items if we have extra capacity
        if (sequence.length < 15) {
            const reviewVocab = [...masteredVocab].slice(0, 3);
            const reviewPhrases = [...masteredPhrases].slice(0, 2);

            reviewVocab.forEach(word => {
                sequence.push({
                    type: 'vocabulary',
                    subtype: 'review',
                    word: word,
                    adaptive: true
                });
            });

            reviewPhrases.forEach(phrase => {
                sequence.push({
                    type: 'phrase',
                    subtype: 'review',
                    index: allPhrases.indexOf(phrase),
                    adaptive: true
                });
            });
        }

        // Shuffle for variety
        for (let i = sequence.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [sequence[i], sequence[j]] = [sequence[j], sequence[i]];
        }

        const adaptiveInfo = unmasteredVocab.length === 0 && unmasteredPhrases.length === 0 ?
            ' (Review mode - all content mastered!)' :
            ' (Adaptive - focusing on unmastered content)';

        console.log(`🧠 Generated adaptive sequence: ${sequence.length} exercises${adaptiveInfo}`);

        data.sessionState.exerciseSequence = sequence;
        data.sessionState.sequenceIndex = 0;
    }

    async _startNextExercise() {
        const data = privateData.get(this);
        const sequence = data.sessionState.exerciseSequence;
        const currentIndex = data.sessionState.sequenceIndex;

        if (currentIndex >= sequence.length) {
            // End AI reporting session
            if (data.sharedServices.llmValidator && data.sharedServices.aiReportInterface) {
                const sessionStats = this.getSessionProgress();

                // End the report session
                data.sharedServices.llmValidator.endReportSession();

                // Notify the report interface
                data.sharedServices.aiReportInterface.onSessionEnd({
                    exerciseCount: sequence.length,
                    averageScore: sessionStats.averageScore || 0,
                    completedAt: new Date()
                });

                console.log('📊 Ended AI report session');
            }

            // Session complete - mark as completed and save
            const currentChapter = data.sessionState.currentChapter;
            if (currentChapter && window.markChapterCompleted) {
                try {
                    await window.markChapterCompleted(currentChapter.bookId, currentChapter.chapterId);
                    console.log(`🏆 Chapter marked as completed: ${currentChapter.bookId}/${currentChapter.chapterId}`);
                } catch (error) {
                    console.warn('Failed to mark chapter as completed:', error);
                }
            }

            this._eventBus.emit('drs:sessionComplete', this.getSessionProgress(), this.name);
            return;
        }

        const exercise = sequence[currentIndex];
        await this.switchToModule(exercise.type);
    }

    async _getExerciseData(moduleType) {
        const data = privateData.get(this);
        const chapterContent = data.sessionState.chapterContent;
        const sequence = data.sessionState.exerciseSequence;
        const currentExercise = sequence[data.sessionState.sequenceIndex];

        // Generate exercise data based on module type and current exercise parameters
        switch (moduleType) {
            case 'vocabulary':
                return this._generateVocabularyExerciseData(chapterContent, currentExercise);
            case 'phrase':
                return this._generatePhraseExerciseData(chapterContent, currentExercise);
            case 'text':
                return this._generateTextExerciseData(chapterContent, currentExercise);
            default:
                return { type: moduleType, content: chapterContent };
        }
    }

    _generateVocabularyExerciseData(chapterContent, exercise) {
        const vocabulary = chapterContent.vocabulary || {};
        const vocabArray = Object.entries(vocabulary);

        const startIndex = exercise.groupIndex * exercise.groupSize;
        const endIndex = Math.min(startIndex + exercise.groupSize, vocabArray.length);
        const vocabGroup = vocabArray.slice(startIndex, endIndex);

        return {
            type: 'vocabulary',
            subtype: exercise.subtype,
            groupIndex: exercise.groupIndex,
            vocabulary: vocabGroup.map(([word, data]) => ({
                word,
                translation: data.user_language,
                pronunciation: data.pronunciation,
                type: data.type
            }))
        };
    }

    _generatePhraseExerciseData(chapterContent, exercise) {
        const phrases = chapterContent.phrases || {};
        const phraseEntries = Object.entries(phrases);
        const phraseIndex = exercise.index || 0;

        // Check if phrase exists at this index
        if (phraseIndex >= phraseEntries.length) {
            console.warn(`⚠️ Phrase at index ${phraseIndex} not found (total: ${phraseEntries.length})`);
            return null;
        }

        const [phraseText, phraseData] = phraseEntries[phraseIndex];

        // Create phrase object for compatibility
        const phrase = {
            id: `phrase_${phraseIndex}`,
            english: phraseText,
            text: phraseText,
            translation: phraseData.user_language,
            user_language: phraseData.user_language,
            pronunciation: phraseData.pronunciation,
            context: phraseData.context || 'general',
            ...phraseData
        };

        // Verify prerequisites for this phrase
        const data = privateData.get(this);
        const unlockStatus = data.sharedServices.prerequisiteEngine.canUnlock('phrase', phrase);

        return {
            type: 'phrase',
            subtype: exercise.subtype,
            phrase: phrase,
            phraseIndex: phraseIndex,
            totalPhrases: phraseEntries.length,
            unlockStatus: unlockStatus,
            chapterContent: chapterContent, // For language detection
            metadata: {
                userLanguage: chapterContent.metadata?.userLanguage || 'English',
                targetLanguage: chapterContent.metadata?.targetLanguage || 'French'
            }
        };
    }

    _generateTextExerciseData(chapterContent, exercise) {
        const texts = chapterContent.texts || [];
        const textIndex = exercise.textIndex || 0;
        const text = texts[textIndex];

        return {
            type: 'text',
            subtype: exercise.subtype,
            text,
            sentenceIndex: exercise.sentenceIndex || 0
        };
    }

    // Event Handlers

    async _handleStartSession(event) {
        const { bookId, chapterId } = event.data;
        await this.startRevisionSession(bookId, chapterId);
    }

    async _handleSwitchModule(event) {
        const { moduleType } = event.data;
        await this.switchToModule(moduleType);
    }

    async _handleUpdateProgress(event) {
        const data = privateData.get(this);
        const { type, item, mastered } = event.data;
        const currentChapter = data.sessionState.currentChapter;

        if (type === 'vocabulary' && mastered) {
            data.sessionState.masteredVocabulary.add(item);
            // Save to persistent storage with metadata
            if (currentChapter && window.addMasteredItem) {
                try {
                    const metadata = {
                        exerciseType: 'vocabulary',
                        sessionId: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
                        moduleType: 'VocabularyModule',
                        sequenceIndex: data.sessionState.sequenceIndex
                    };
                    await window.addMasteredItem(currentChapter.bookId, currentChapter.chapterId, 'vocabulary', item, metadata);
                } catch (error) {
                    console.warn('Failed to save vocabulary progress:', error);
                }
            }
        } else if (type === 'phrase' && mastered) {
            data.sessionState.masteredPhrases.add(item);
            // Save to persistent storage with metadata
            if (currentChapter && window.addMasteredItem) {
                try {
                    const metadata = {
                        exerciseType: 'phrase',
                        sessionId: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
                        moduleType: 'PhraseModule',
                        sequenceIndex: data.sessionState.sequenceIndex,
                        aiValidated: true
                    };
                    await window.addMasteredItem(currentChapter.bookId, currentChapter.chapterId, 'phrases', item, metadata);
                } catch (error) {
                    console.warn('Failed to save phrase progress:', error);
                }
            }
        } else if (type === 'grammar' && mastered) {
            data.sessionState.masteredGrammar.add(item);
            // Save to persistent storage with metadata
            if (currentChapter && window.addMasteredItem) {
                try {
                    const metadata = {
                        exerciseType: 'grammar',
                        sessionId: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
                        moduleType: 'GrammarModule',
                        sequenceIndex: data.sessionState.sequenceIndex
                    };
                    await window.addMasteredItem(currentChapter.bookId, currentChapter.chapterId, 'grammar', item, metadata);
                } catch (error) {
                    console.warn('Failed to save grammar progress:', error);
                }
            }
        }

        this._eventBus.emit('drs:progressUpdated', this.getSessionProgress(), this.name);
    }

    async _handleExerciseCompleted(event) {
        const data = privateData.get(this);
        data.sessionState.sequenceIndex++;

        // Move to next exercise
        await this._startNextExercise();
    }

    /**
     * Get mastery progress from PrerequisiteEngine
     * @returns {Object} - Progress statistics
     */
    getMasteryProgress() {
        this._validateInitialized();
        const data = privateData.get(this);

        if (!data.sharedServices.prerequisiteEngine) {
            return {
                vocabulary: { mastered: 0, total: 0, percentage: 0 },
                phrases: { mastered: 0, total: 0, percentage: 0 },
                grammar: { mastered: 0, total: 0, percentage: 0 }
            };
        }

        return data.sharedServices.prerequisiteEngine.getMasteryProgress();
    }

    /**
     * Get list of mastered words from PrerequisiteEngine
     * @returns {Array} - Array of mastered words
     */
    getMasteredWords() {
        this._validateInitialized();
        const data = privateData.get(this);

        if (!data.sharedServices.prerequisiteEngine) {
            return [];
        }

        return Array.from(data.sharedServices.prerequisiteEngine.masteredWords);
    }
}

export default SmartPreviewOrchestrator;