/**
 * VocabularyModule - Groups of 5 vocabulary exercise implementation
 * Implements DRSExerciseInterface for strict contract enforcement
 */

import DRSExerciseInterface from '../interfaces/DRSExerciseInterface.js';

class VocabularyModule extends DRSExerciseInterface {
    constructor(orchestrator, llmValidator, prerequisiteEngine, contextMemory) {
        super('VocabularyModule');

        // Validate dependencies (llmValidator can be null since we use local validation)
        if (!orchestrator || !prerequisiteEngine || !contextMemory) {
            throw new Error('VocabularyModule requires orchestrator, prerequisiteEngine, and contextMemory');
        }

        this.orchestrator = orchestrator;
        this.llmValidator = llmValidator;
        this.prerequisiteEngine = prerequisiteEngine;
        this.contextMemory = contextMemory;

        // Module state
        this.initialized = false;
        this.container = null;
        this.currentExerciseData = null;
        this.currentVocabularyGroup = [];
        this.currentWordIndex = 0;
        this.groupResults = [];
        this.isRevealed = false;

        // Configuration
        this.config = {
            groupSize: 5,
            masteryThreshold: 80, // 80% correct to consider mastered
            maxAttempts: 3,
            showPronunciation: true,
            randomizeOrder: true
        };

        // Bind methods
        this._handleNextWord = this._handleNextWord.bind(this);
        this._handleRevealAnswer = this._handleRevealAnswer.bind(this);
        this._handleUserInput = this._handleUserInput.bind(this);
        this._handleDifficultySelection = this._handleDifficultySelection.bind(this);
    }

    /**
     * Initialize the exercise module
     * @param {Object} config - Exercise configuration
     * @param {Object} content - Exercise content data
     * @returns {Promise<void>}
     */
    async init(config = {}, content = {}) {
        if (this.initialized) return;

        console.log('📚 Initializing VocabularyModule...');

        // Merge provided config with defaults
        this.config = {
            ...this.config,
            ...config
        };

        // Store content for later use
        this.currentExerciseData = content;
        this.startTime = Date.now();

        this.initialized = true;
        console.log('✅ VocabularyModule initialized');
    }

    /**
     * Render the exercise UI
     * @param {HTMLElement} container - Container element to render into
     * @returns {Promise<void>}
     */
    async render(container) {
        if (!this.initialized) {
            throw new Error('VocabularyModule must be initialized before rendering');
        }

        // Use existing present() logic
        await this.present(container, this.currentExerciseData);
    }

    /**
     * Clean up and destroy the exercise
     * @returns {Promise<void>}
     */
    async destroy() {
        console.log('🧹 Destroying VocabularyModule...');

        // Remove event listeners
        if (this.container) {
            const input = this.container.querySelector('.vocabulary-input');
            const submitBtn = this.container.querySelector('.btn-submit');
            const revealBtn = this.container.querySelector('.btn-reveal');
            const nextBtn = this.container.querySelector('.btn-next');
            const difficultyButtons = this.container.querySelectorAll('.difficulty-btn');

            if (input) input.removeEventListener('input', this._handleUserInput);
            if (submitBtn) submitBtn.removeEventListener('click', this._handleUserInput);
            if (revealBtn) revealBtn.removeEventListener('click', this._handleRevealAnswer);
            if (nextBtn) nextBtn.removeEventListener('click', this._handleNextWord);
            difficultyButtons.forEach(btn => {
                btn.removeEventListener('click', this._handleDifficultySelection);
            });

            // Clear container
            this.container.innerHTML = '';
            this.container = null;
        }

        // Reset state
        this.currentVocabularyGroup = [];
        this.currentWordIndex = 0;
        this.groupResults = [];
        this.isRevealed = false;
        this.currentExerciseData = null;
        this.initialized = false;

        console.log('✅ VocabularyModule destroyed');
    }

    /**
     * Check if module can run with current prerequisites
     * @param {Array} prerequisites - List of learned vocabulary/concepts
     * @param {Object} chapterContent - Full chapter content
     * @returns {boolean} - True if module can run
     */
    canRun(prerequisites, chapterContent) {
        // Vocabulary module can always run if there's vocabulary in the chapter
        const hasVocabulary = chapterContent && chapterContent.vocabulary &&
                             Object.keys(chapterContent.vocabulary).length > 0;

        return hasVocabulary;
    }

    /**
     * Present exercise UI and content
     * @param {HTMLElement} container - DOM container to render into
     * @param {Object} exerciseData - Specific exercise data to present
     * @returns {Promise<void>}
     */
    async present(container, exerciseData) {
        if (!this.initialized) {
            throw new Error('VocabularyModule must be initialized before use');
        }

        this.container = container;
        this.currentExerciseData = exerciseData;

        // Extract and process all vocabulary
        const allVocabulary = exerciseData.vocabulary || [];

        // Pre-process all vocabulary items to extract clean translations
        allVocabulary.forEach(word => {
            let translation = word.translation;
            if (typeof translation === 'object' && translation !== null) {
                // Try different field names that might contain the translation
                translation = translation.user_language ||
                             translation.target_language ||
                             translation.translation ||
                             translation.meaning ||
                             translation.fr ||
                             translation.definition ||
                             Object.values(translation).find(val => typeof val === 'string' && val !== word.word) ||
                             JSON.stringify(translation);
            }
            word.cleanTranslation = translation;
        });

        // Filter out already mastered words using PrerequisiteEngine
        const unmastedVocabulary = allVocabulary.filter(word => {
            if (!this.prerequisiteEngine || !this.prerequisiteEngine.isInitialized) {
                return true; // Include all words if PrerequisiteEngine not available
            }
            const isMastered = this.prerequisiteEngine.isMastered(word.word);
            if (isMastered) {
                console.log(`🎯 Skipping already mastered word: ${word.word}`);
            }
            return !isMastered; // Only include non-mastered words
        });

        console.log(`📚 Filtered vocabulary: ${allVocabulary.length} total → ${unmastedVocabulary.length} unmastered words`);

        // Check if all words are already mastered
        if (unmastedVocabulary.length === 0) {
            this.container.innerHTML = `
                <div class="vocabulary-exercise-complete">
                    <div class="completion-icon">🎉</div>
                    <h2>Vocabulary Mastered!</h2>
                    <p>All vocabulary words in this chapter have been mastered.</p>
                    <div class="completion-stats">
                        <div class="stat">
                            <span class="stat-number">${allVocabulary.length}</span>
                            <span class="stat-label">Words Mastered</span>
                        </div>
                    </div>
                    <button class="btn btn-primary" onclick="window.drsDebug?.instance?.completeExercise?.()">
                        <span class="btn-icon">✅</span>
                        <span class="btn-text">Continue</span>
                    </button>
                </div>
            `;
            return;
        }

        // DYNAMIC MODE: Pick 5 random words from discovered words (no pre-calculation)
        const discoveredWords = unmastedVocabulary.filter(word => {
            return this.prerequisiteEngine.isDiscovered(word.word);
        });

        console.log(`📚 Found ${discoveredWords.length} discovered words (out of ${unmastedVocabulary.length} unmastered)`);

        // Take up to 5 random discovered words
        const selectedWords = this._selectRandomWords(discoveredWords, this.config.groupSize);

        this.currentVocabularyGroup = selectedWords;
        this.currentWordIndex = 0;
        this.groupResults = [];
        this.isRevealed = false;

        console.log(`📚 Selected ${selectedWords.length} random words for this session:`, selectedWords.map(w => w.word));

        if (this.config.randomizeOrder) {
            this._shuffleArray(this.currentVocabularyGroup);
        }

        console.log(`📚 Presenting vocabulary group (${this.currentVocabularyGroup.length} words)`);

        // Render initial UI
        await this._renderVocabularyExercise();

        // Start with first word
        this._presentCurrentWord();
    }

    /**
     * Validate user input with simple string matching (NO AI)
     * @param {string} userInput - User's response
     * @param {Object} context - Exercise context and expected answer
     * @returns {Promise<ValidationResult>} - Validation result with score and feedback
     */
    async validate(userInput, context) {
        if (!userInput || !userInput.trim()) {
            return {
                score: 0,
                correct: false,
                feedback: "Please provide an answer.",
                timestamp: new Date().toISOString(),
                provider: 'local'
            };
        }

        const currentWord = this.currentVocabularyGroup[this.currentWordIndex];
        const expectedTranslation = currentWord.cleanTranslation || currentWord.translation;
        const userAnswer = userInput.trim();

        // Simple string matching validation (NO AI)
        const isCorrect = this._checkTranslation(userAnswer, expectedTranslation);

        const result = {
            score: isCorrect ? 100 : 0,
            correct: isCorrect,
            feedback: isCorrect
                ? "Correct! Well done."
                : `Incorrect. The correct answer is: ${expectedTranslation}`,
            timestamp: new Date().toISOString(),
            provider: 'local',
            expectedAnswer: expectedTranslation,
            userAnswer: userAnswer
        };

        // Record interaction in context memory
        this.contextMemory.recordInteraction({
            type: 'vocabulary',
            subtype: 'translation',
            content: {
                vocabulary: [currentWord],
                word: currentWord.word,
                expectedTranslation
            },
            userResponse: userAnswer,
            validation: result,
            context: { validationType: 'simple_string_match' }
        });

        return result;
    }

    /**
     * Get current progress data
     * @returns {ProgressData} - Progress information for this module
     */
    getProgress() {
        const totalWords = this.currentVocabularyGroup.length;
        const completedWords = this.groupResults.length;
        const correctWords = this.groupResults.filter(result => result.correct).length;

        return {
            type: 'vocabulary',
            totalWords,
            completedWords,
            correctWords,
            currentWordIndex: this.currentWordIndex,
            groupResults: this.groupResults,
            progressPercentage: totalWords > 0 ? Math.round((completedWords / totalWords) * 100) : 0,
            accuracyPercentage: completedWords > 0 ? Math.round((correctWords / completedWords) * 100) : 0
        };
    }

    /**
     * Clean up and prepare for unloading
     */
    cleanup() {
        console.log('🧹 Cleaning up VocabularyModule...');

        // Remove event listeners
        if (this.container) {
            this.container.innerHTML = '';
        }

        // Reset state
        this.container = null;
        this.currentExerciseData = null;
        this.currentVocabularyGroup = [];
        this.currentWordIndex = 0;
        this.groupResults = [];
        this.isRevealed = false;

        console.log('✅ VocabularyModule cleaned up');
    }

    /**
     * Get module metadata
     * @returns {Object} - Module information
     */
    getMetadata() {
        return {
            name: 'VocabularyModule',
            type: 'vocabulary',
            version: '1.0.0',
            description: 'Groups of 5 vocabulary exercises with LLM validation',
            capabilities: ['translation', 'pronunciation', 'spaced_repetition'],
            config: this.config
        };
    }

    // Private Methods

    /**
     * Check translation with simple string matching and fuzzy logic
     * @param {string} userAnswer - User's answer
     * @param {string} expectedTranslation - Expected correct answer
     * @returns {boolean} - True if answer is acceptable
     * @private
     */
    _checkTranslation(userAnswer, expectedTranslation) {
        if (!userAnswer || !expectedTranslation) return false;

        // Normalize both strings
        const normalizeString = (str) => {
            return str.toLowerCase()
                .trim()
                .replace(/[.,!?;:"'()]/g, '') // Remove punctuation
                .replace(/\s+/g, ' '); // Normalize whitespace
        };

        const normalizedUser = normalizeString(userAnswer);
        const normalizedExpected = normalizeString(expectedTranslation);

        // Exact match after normalization
        if (normalizedUser === normalizedExpected) {
            return true;
        }

        // Split expected answer into alternatives (e.g., "shirt, t-shirt" or "shirt / t-shirt")
        const alternatives = normalizedExpected.split(/[,/|;]/).map(alt => alt.trim());

        // Check if user answer matches any alternative
        for (const alternative of alternatives) {
            if (normalizedUser === alternative) {
                return true;
            }

            // Allow partial matches for single words if they're very close
            if (alternative.split(' ').length === 1 && normalizedUser.split(' ').length === 1) {
                const similarity = this._calculateSimilarity(normalizedUser, alternative);
                if (similarity > 0.85) { // 85% similarity threshold
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Calculate string similarity using simple character comparison
     * @param {string} str1 - First string
     * @param {string} str2 - Second string
     * @returns {number} - Similarity score between 0 and 1
     * @private
     */
    _calculateSimilarity(str1, str2) {
        if (str1 === str2) return 1.0;
        if (str1.length === 0 || str2.length === 0) return 0.0;

        // Simple character-based similarity
        const longer = str1.length > str2.length ? str1 : str2;
        const shorter = str1.length > str2.length ? str2 : str1;

        if (longer.length === 0) return 1.0;

        const editDistance = this._levenshteinDistance(str1, str2);
        return (longer.length - editDistance) / longer.length;
    }

    /**
     * Calculate Levenshtein distance between two strings
     * @param {string} str1 - First string
     * @param {string} str2 - Second string
     * @returns {number} - Edit distance
     * @private
     */
    _levenshteinDistance(str1, str2) {
        const matrix = [];

        for (let i = 0; i <= str2.length; i++) {
            matrix[i] = [i];
        }

        for (let j = 0; j <= str1.length; j++) {
            matrix[0][j] = j;
        }

        for (let i = 1; i <= str2.length; i++) {
            for (let j = 1; j <= str1.length; j++) {
                if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
                    matrix[i][j] = matrix[i - 1][j - 1];
                } else {
                    matrix[i][j] = Math.min(
                        matrix[i - 1][j - 1] + 1,
                        matrix[i][j - 1] + 1,
                        matrix[i - 1][j] + 1
                    );
                }
            }
        }

        return matrix[str2.length][str1.length];
    }

    async _renderVocabularyExercise() {
        if (!this.container) return;

        const totalWords = this.currentVocabularyGroup.length;
        const progressPercentage = totalWords > 0 ?
            Math.round((this.currentWordIndex / totalWords) * 100) : 0;

        this.container.innerHTML = `
            <div class="vocabulary-exercise">
                <div class="exercise-header">
                    <h2>📚 Vocabulary Practice</h2>
                    <div class="progress-info">
                        <span class="progress-text" id="progress-text">
                            Word ${this.currentWordIndex + 1} of ${totalWords}
                        </span>
                        <div class="progress-bar">
                            <div class="progress-fill" id="progress-fill" style="width: ${progressPercentage}%"></div>
                        </div>
                    </div>
                </div>

                <div class="vocabulary-card" id="vocabulary-card">
                    <!-- Card content will be populated by _presentCurrentWord -->
                </div>

                <div class="exercise-controls" id="exercise-controls">
                    <!-- Controls will be populated dynamically -->
                </div>

                <div class="group-results" id="group-results" style="display: none;">
                    <!-- Results will be shown when group is complete -->
                </div>
            </div>
        `;

        // Add CSS styles
        this._addStyles();
    }

    _updateProgressDisplay() {
        const progressText = document.getElementById('progress-text');
        const progressFill = document.getElementById('progress-fill');

        if (progressText && progressFill) {
            const totalWords = this.currentVocabularyGroup.length;
            const progressPercentage = totalWords > 0 ?
                Math.round((this.currentWordIndex / totalWords) * 100) : 0;

            // Update text (no group numbers in dynamic mode)
            progressText.textContent = `Word ${this.currentWordIndex + 1} of ${totalWords}`;

            // Update progress bar
            progressFill.style.width = `${progressPercentage}%`;
        }
    }

    _presentCurrentWord() {
        if (this.currentWordIndex >= this.currentVocabularyGroup.length) {
            this._showGroupResults();
            return;
        }

        // Update progress display
        this._updateProgressDisplay();

        const currentWord = this.currentVocabularyGroup[this.currentWordIndex];
        const card = document.getElementById('vocabulary-card');
        const controls = document.getElementById('exercise-controls');

        if (!card || !controls) return;

        this.isRevealed = false;

        card.innerHTML = `
            <div class="word-card">
                <div class="word-display">
                    <h3 class="target-word clickable" id="target-word-tts" title="Click to hear pronunciation">
                        ${currentWord.word}
                    </h3>
                    ${this.config.showPronunciation && currentWord.pronunciation ?
                        `<div class="pronunciation" id="pronunciation-display">[${currentWord.pronunciation}]</div>` : ''}
                    <div class="word-type">${currentWord.type || 'word'}</div>
                </div>

                <div class="answer-section" id="answer-section">
                    <div class="translation-input">
                        <label for="translation-input">Translation:</label>
                        <input type="text"
                               id="translation-input"
                               placeholder="Enter the translation..."
                               autocomplete="off">
                    </div>
                </div>

                <div class="revealed-answer" id="revealed-answer" style="display: none;">
                    <div class="correct-translation clickable" id="answer-tts" title="Click to hear pronunciation">
                        <strong>Correct Answer:</strong> ${currentWord.cleanTranslation}
                    </div>
                    ${this.config.showPronunciation && currentWord.pronunciation ?
                        `<div class="pronunciation-text" id="pronunciation-reveal">[${currentWord.pronunciation}]</div>` : ''}
                </div>
            </div>
        `;

        controls.innerHTML = `
            <div class="control-buttons">
                <button id="tts-btn" class="btn btn-secondary">🔊 Listen</button>
                <button id="reveal-btn" class="btn btn-secondary">Reveal Answer</button>
                <button id="submit-btn" class="btn btn-primary">Submit</button>
            </div>
        `;

        // Add event listeners
        document.getElementById('tts-btn').onclick = () => this._handleTTS();
        document.getElementById('reveal-btn').onclick = this._handleRevealAnswer;
        document.getElementById('submit-btn').onclick = this._handleUserInput;

        // Add click listener on the word itself for TTS
        const targetWord = document.getElementById('target-word-tts');
        if (targetWord) {
            targetWord.onclick = () => {
                this._handleTTS();
                this._highlightPronunciation();
            };
        }

        // Allow Enter key to submit
        const input = document.getElementById('translation-input');
        input.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                this._handleUserInput();
            }
        });

        // Focus on input
        input.focus();
    }

    async _handleUserInput() {
        const input = document.getElementById('translation-input');
        const userInput = input ? input.value.trim() : '';

        if (!userInput) {
            this._showFeedback('Please enter a translation.', 'warning');
            return;
        }

        // Disable input during validation
        this._setInputEnabled(false);
        this._showFeedback('Checking answer...', 'info');

        try {
            const validationResult = await this.validate(userInput, {});

            // Store result
            this.groupResults[this.currentWordIndex] = {
                word: this.currentVocabularyGroup[this.currentWordIndex].word,
                userAnswer: userInput,
                correct: validationResult.correct,
                score: validationResult.score,
                feedback: validationResult.feedback,
                timestamp: new Date().toISOString()
            };

            // Show result and difficulty selection
            this._showValidationResult(validationResult);

        } catch (error) {
            console.error('Validation error:', error);
            this._showFeedback('Error validating answer. Please try again.', 'error');
            this._setInputEnabled(true);
        }
    }

    _handleRevealAnswer() {
        const revealedSection = document.getElementById('revealed-answer');
        const answerSection = document.getElementById('answer-section');

        if (revealedSection && answerSection) {
            revealedSection.style.display = 'block';
            answerSection.style.display = 'none';
            this.isRevealed = true;

            // Add click listener on revealed answer for TTS
            const answerTTS = document.getElementById('answer-tts');
            if (answerTTS) {
                answerTTS.onclick = () => {
                    this._handleTTS();
                    this._highlightPronunciation();
                };
            }

            // Auto-play TTS when answer is revealed
            setTimeout(() => {
                this._handleTTS();
                this._highlightPronunciation();
            }, 100); // Quick delay to let the answer appear

            // Don't mark as incorrect yet - wait for user self-assessment
            // The difficulty selection will determine the actual result

            this._showDifficultySelection();
        }
    }

    _showValidationResult(validationResult) {
        const feedbackClass = validationResult.correct ? 'success' : 'error';
        this._showFeedback(validationResult.feedback, feedbackClass);

        // Show correct answer if incorrect
        if (!validationResult.correct) {
            const revealedSection = document.getElementById('revealed-answer');
            if (revealedSection) {
                revealedSection.style.display = 'block';
            }
        }

        // Show difficulty selection
        setTimeout(() => {
            this._showDifficultySelection();
        }, 2000);
    }

    _showDifficultySelection() {
        const controls = document.getElementById('exercise-controls');
        if (!controls) return;

        controls.innerHTML = `
            <div class="difficulty-selection">
                <div class="difficulty-buttons">
                    <button class="difficulty-btn btn-error" data-difficulty="again">
                        Again (< 1 min)
                    </button>
                    <button class="difficulty-btn btn-warning" data-difficulty="hard">
                        Hard (< 6 min)
                    </button>
                    <button class="difficulty-btn btn-primary" data-difficulty="good">
                        Good (< 10 min)
                    </button>
                    <button class="difficulty-btn btn-success" data-difficulty="easy">
                        Easy (< 4 days)
                    </button>
                </div>
            </div>
        `;

        // Add event listeners for difficulty buttons
        document.querySelectorAll('.difficulty-btn').forEach(btn => {
            btn.onclick = async (e) => await this._handleDifficultySelection(e.target.dataset.difficulty);
        });
    }

    async _handleDifficultySelection(difficulty) {
        const currentWord = this.currentVocabularyGroup[this.currentWordIndex];

        // Create or update result based on user self-assessment
        const userAnswer = this.isRevealed ? '[revealed]' :
                          (this.groupResults[this.currentWordIndex]?.userAnswer || '[self-assessed]');

        // Convert difficulty to success/score based on spaced repetition logic
        const difficultyMapping = {
            'again': { correct: false, score: 0 },    // Failed - need to see again soon
            'hard': { correct: true, score: 60 },     // Passed but difficult
            'good': { correct: true, score: 80 },     // Good understanding
            'easy': { correct: true, score: 100 }     // Perfect understanding
        };

        const assessment = difficultyMapping[difficulty] || { correct: false, score: 0 };

        // Create/update the result entry
        this.groupResults[this.currentWordIndex] = {
            word: currentWord.word,
            userAnswer: userAnswer,
            correct: assessment.correct,
            score: assessment.score,
            difficulty: difficulty,
            feedback: `Self-assessed as: ${difficulty}`,
            timestamp: new Date().toISOString(),
            wasRevealed: this.isRevealed
        };

        // ALWAYS mark word as discovered (seen/introduced) - Enhanced with persistence
        const discoveryMetadata = {
            difficulty: difficulty,
            sessionId: this.orchestrator?.sessionId || 'unknown',
            moduleType: 'vocabulary',
            timestamp: new Date().toISOString(),
            wasRevealed: this.isRevealed,
            responseTime: Date.now() - (this.wordStartTime || Date.now())
        };

        try {
            await this.prerequisiteEngine.markWordDiscovered(currentWord.word, discoveryMetadata);
            console.log('📚 Enhanced persistence: Word discovered:', currentWord.word);
        } catch (error) {
            console.error('❌ Error marking word discovered:', error);
        }

        // Mark word as mastered ONLY if good or easy - Enhanced with persistence
        if (['good', 'easy'].includes(difficulty)) {
            const masteryMetadata = {
                difficulty: difficulty,
                sessionId: this.orchestrator?.sessionId || 'unknown',
                moduleType: 'vocabulary',
                attempts: 1, // Single attempt with self-assessment
                correct: assessment.correct,
                scores: [assessment.score],
                masteryLevel: difficulty === 'easy' ? 2 : 1
            };

            try {
                await this.prerequisiteEngine.markWordMastered(currentWord.word, masteryMetadata);
                console.log('🏆 Enhanced persistence: Word mastered:', currentWord.word);
            } catch (error) {
                console.error('❌ Error marking word mastered:', error);
            }

            // Legacy persistent storage removed - now using enhanced PrerequisiteEngine persistence
        }

        console.log(`Word "${currentWord.word}" marked as ${difficulty}`);

        // Move to next word
        this.currentWordIndex++;
        this._presentCurrentWord();
    }

    _handleNextWord() {
        this.currentWordIndex++;
        this._presentCurrentWord();
    }

    _handleTTS() {
        const currentWord = this.currentVocabularyGroup[this.currentWordIndex];
        if (currentWord && currentWord.word) {
            this._speakWord(currentWord.word);
        }
    }

    async _speakWord(text, options = {}) {
        // Check if browser supports Speech Synthesis
        if ('speechSynthesis' in window) {
            try {
                // Cancel any ongoing speech
                window.speechSynthesis.cancel();

                const utterance = new SpeechSynthesisUtterance(text);

                // Get language from chapter data, fallback to options or en-US
                const chapterLanguage = this.currentExerciseData?.language || 'en-US';
                utterance.lang = options.lang || chapterLanguage;
                utterance.rate = options.rate || 0.8;
                utterance.pitch = options.pitch || 1;
                utterance.volume = options.volume || 1;

                // Wait for voices to be loaded before selecting one
                const voices = await this._getVoices();
                if (voices.length > 0) {
                    // Find voice matching the chapter language
                    const langPrefix = chapterLanguage.split('-')[0]; // e.g., "zh" from "zh-CN"
                    const matchingVoice = voices.find(voice =>
                        voice.lang.startsWith(langPrefix) && voice.default
                    ) || voices.find(voice => voice.lang.startsWith(langPrefix));

                    if (matchingVoice) {
                        utterance.voice = matchingVoice;
                        console.log('🔊 Using voice:', matchingVoice.name, matchingVoice.lang);
                    } else {
                        console.warn(`🔊 No voice found for language: ${chapterLanguage}, available:`, voices.map(v => v.lang));
                    }
                }

                // Add event handlers
                utterance.onstart = () => {
                    console.log('🔊 TTS started for:', text);
                    this._updateTTSButton(true);
                };

                utterance.onend = () => {
                    console.log('🔊 TTS finished for:', text);
                    this._updateTTSButton(false);
                };

                utterance.onerror = (event) => {
                    console.warn('🔊 TTS error:', event.error);
                    this._updateTTSButton(false);
                };

                // Speak the text
                window.speechSynthesis.speak(utterance);

            } catch (error) {
                console.warn('🔊 TTS failed:', error);
                this._fallbackTTS(text);
            }
        } else {
            console.warn('🔊 Speech Synthesis not supported in this browser');
            this._fallbackTTS(text);
        }
    }

    /**
     * Get available speech synthesis voices, waiting for them to load if necessary
     * @returns {Promise<SpeechSynthesisVoice[]>} Array of available voices
     * @private
     */
    _getVoices() {
        return new Promise((resolve) => {
            let voices = window.speechSynthesis.getVoices();

            // If voices are already loaded, return them immediately
            if (voices.length > 0) {
                resolve(voices);
                return;
            }

            // Otherwise, wait for voiceschanged event
            const voicesChangedHandler = () => {
                voices = window.speechSynthesis.getVoices();
                if (voices.length > 0) {
                    window.speechSynthesis.removeEventListener('voiceschanged', voicesChangedHandler);
                    resolve(voices);
                }
            };

            window.speechSynthesis.addEventListener('voiceschanged', voicesChangedHandler);

            // Fallback timeout in case voices never load
            setTimeout(() => {
                window.speechSynthesis.removeEventListener('voiceschanged', voicesChangedHandler);
                resolve(window.speechSynthesis.getVoices());
            }, 1000);
        });
    }

    _updateTTSButton(isPlaying) {
        // Update main TTS button
        const ttsBtn = document.getElementById('tts-btn');
        if (ttsBtn) {
            if (isPlaying) {
                ttsBtn.innerHTML = '🔄 Speaking...';
                ttsBtn.disabled = true;
            } else {
                ttsBtn.innerHTML = '🔊 Listen';
                ttsBtn.disabled = false;
            }
        }
    }

    _fallbackTTS(text) {
        // Fallback when TTS fails - show pronunciation if available
        const currentWord = this.currentVocabularyGroup[this.currentWordIndex];
        if (currentWord && currentWord.pronunciation) {
            alert(`Pronunciation: /${currentWord.pronunciation}/`);
        } else {
            alert(`Word: ${text}\n(Text-to-speech not available)`);
        }
    }

    _highlightPronunciation() {
        // Highlight pronunciation when TTS is played
        const pronunciation = document.getElementById('pronunciation-display') ||
                            document.getElementById('pronunciation-reveal');

        if (pronunciation) {
            // Add highlight class
            pronunciation.classList.add('pronunciation-highlight');

            // Remove highlight after animation
            setTimeout(() => {
                pronunciation.classList.remove('pronunciation-highlight');
            }, 2000);
        }
    }

    _showGroupResults() {
        const resultsContainer = document.getElementById('group-results');
        const card = document.getElementById('vocabulary-card');
        const controls = document.getElementById('exercise-controls');

        if (!resultsContainer) return;

        const correctCount = this.groupResults.filter(result => result.correct).length;
        const totalCount = this.groupResults.length;
        const accuracy = totalCount > 0 ? Math.round((correctCount / totalCount) * 100) : 0;

        let resultClass = 'results-poor';
        if (accuracy >= 80) resultClass = 'results-excellent';
        else if (accuracy >= 60) resultClass = 'results-good';

        // DYNAMIC MODE: Single "Continue" button - orchestrator decides next exercise
        const resultsHTML = `
            <div class="group-results-content ${resultClass}">
                <h3>📊 Session Results</h3>
                <div class="results-summary">
                    <div class="accuracy-display">
                        <span class="accuracy-number">${accuracy}%</span>
                        <span class="accuracy-label">Accuracy</span>
                    </div>
                    <div class="count-display">
                        ${correctCount} / ${totalCount} correct
                    </div>
                </div>

                <div class="results-actions">
                    <button id="continue-btn" class="btn btn-primary">Continue →</button>
                </div>
            </div>
        `;

        resultsContainer.innerHTML = resultsHTML;
        resultsContainer.style.display = 'block';

        // Hide other sections
        if (card) card.style.display = 'none';
        if (controls) controls.style.display = 'none';

        // Add button listener
        const continueBtn = document.getElementById('continue-btn');

        if (continueBtn) {
            continueBtn.onclick = () => {
                // Complete exercise and let orchestrator decide next step
                if (this.orchestrator && this.orchestrator.completeExercise) {
                    this.orchestrator.completeExercise({
                        moduleType: 'vocabulary',
                        results: this.groupResults,
                        progress: this.getProgress()
                    });
                } else {
                    console.log('✅ Vocabulary session completed, orchestrator will decide next exercise');
                    // Fallback: use drsDebug if available
                    if (window.drsDebug?.instance?.completeExercise) {
                        window.drsDebug.instance.completeExercise();
                    }
                }
            };
        }
    }

    _setInputEnabled(enabled) {
        const input = document.getElementById('translation-input');
        const submitBtn = document.getElementById('submit-btn');
        const revealBtn = document.getElementById('reveal-btn');

        if (input) input.disabled = !enabled;
        if (submitBtn) submitBtn.disabled = !enabled;
        if (revealBtn) revealBtn.disabled = !enabled;
    }

    _showFeedback(message, type = 'info') {
        // Create or update feedback element
        let feedback = document.getElementById('feedback-message');
        if (!feedback) {
            feedback = document.createElement('div');
            feedback.id = 'feedback-message';
            feedback.className = 'feedback-message';

            const card = document.getElementById('vocabulary-card');
            if (card) {
                card.appendChild(feedback);
            }
        }

        feedback.className = `feedback-message feedback-${type}`;
        feedback.textContent = message;
        feedback.style.display = 'block';

        // Auto-hide info messages
        if (type === 'info') {
            setTimeout(() => {
                if (feedback) {
                    feedback.style.display = 'none';
                }
            }, 3000);
        }
    }

    /**
     * Select N random words from an array
     * @param {Array} words - Array of word objects
     * @param {number} count - Number of words to select
     * @returns {Array} - Random selection of words
     */
    _selectRandomWords(words, count) {
        if (words.length <= count) {
            return [...words]; // Return all if not enough words
        }

        // Fisher-Yates shuffle and take first N
        const shuffled = [...words];
        for (let i = shuffled.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
        }

        return shuffled.slice(0, count);
    }

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

    _addStyles() {
        if (document.getElementById('vocabulary-module-styles')) return;

        const styles = document.createElement('style');
        styles.id = 'vocabulary-module-styles';
        styles.textContent = `
            .vocabulary-exercise {
                max-width: 600px;
                margin: 0 auto;
                padding: 20px;
            }

            .exercise-header {
                text-align: center;
                margin-bottom: 30px;
            }

            .progress-info {
                margin-top: 10px;
            }

            .progress-bar {
                width: 100%;
                height: 8px;
                background-color: #e0e0e0;
                border-radius: 4px;
                margin-top: 5px;
                overflow: hidden;
            }

            .progress-fill {
                height: 100%;
                background: linear-gradient(90deg, #667eea, #764ba2);
                transition: width 0.3s ease;
            }

            .vocabulary-card {
                background: white;
                border-radius: 12px;
                padding: 30px;
                box-shadow: 0 4px 20px rgba(0,0,0,0.1);
                margin-bottom: 20px;
            }

            .word-display {
                text-align: center;
                margin-bottom: 30px;
            }

            .target-word {
                font-size: 2.5em;
                color: #333;
                margin-bottom: 10px;
                font-weight: bold;
            }

            .target-word.clickable {
                cursor: pointer;
                transition: all 0.2s ease;
            }

            .target-word.clickable:hover {
                color: #667eea;
                transform: scale(1.05);
            }

            .pronunciation {
                font-style: italic;
                color: #666;
                margin-bottom: 5px;
                transition: all 0.3s ease;
            }

            .pronunciation-highlight {
                color: #667eea !important;
                font-weight: bold;
                font-size: 1.2em;
                animation: pulse 0.5s ease-in-out;
            }

            @keyframes pulse {
                0%, 100% { transform: scale(1); }
                50% { transform: scale(1.1); }
            }

            .word-type {
                color: #888;
                font-size: 0.9em;
                text-transform: uppercase;
            }

            .translation-input {
                margin-bottom: 20px;
            }

            .translation-input label {
                display: block;
                margin-bottom: 8px;
                font-weight: bold;
                color: #555;
            }

            .translation-input input {
                width: 100%;
                padding: 12px;
                font-size: 1.1em;
                border: 2px solid #ddd;
                border-radius: 8px;
                box-sizing: border-box;
            }

            .translation-input input:focus {
                border-color: #667eea;
                outline: none;
            }

            .revealed-answer {
                background-color: #f8f9fa;
                padding: 15px;
                border-radius: 8px;
                margin-top: 15px;
            }

            .correct-translation {
                font-size: 1.2em;
                color: #28a745;
                margin-bottom: 5px;
            }

            .correct-translation.clickable {
                cursor: pointer;
                transition: all 0.2s ease;
                padding: 5px;
                border-radius: 4px;
            }

            .correct-translation.clickable:hover {
                background-color: #d4edda;
                transform: scale(1.02);
            }

            .pronunciation-text {
                font-style: italic;
                color: #666;
                transition: all 0.3s ease;
            }

            .exercise-controls {
                text-align: center;
            }

            .control-buttons {
                display: flex;
                gap: 15px;
                justify-content: center;
            }

            .difficulty-selection {
                text-align: center;
            }

            .difficulty-buttons {
                display: flex;
                gap: 8px;
                justify-content: center;
                flex-wrap: nowrap;
                margin-top: 15px;
            }

            .difficulty-btn {
                padding: 8px 12px;
                border: none;
                border-radius: 8px;
                cursor: pointer;
                font-size: 0.85em;
                transition: all 0.3s ease;
            }

            .group-results-content {
                background: white;
                border-radius: 12px;
                padding: 30px;
                box-shadow: 0 4px 20px rgba(0,0,0,0.1);
                text-align: center;
            }

            .results-summary {
                margin-bottom: 30px;
            }

            .accuracy-display {
                margin-bottom: 10px;
            }

            .accuracy-number {
                font-size: 3em;
                font-weight: bold;
                display: block;
            }

            .results-excellent .accuracy-number { color: #28a745; }
            .results-good .accuracy-number { color: #ffc107; }
            .results-poor .accuracy-number { color: #dc3545; }

            .word-results {
                text-align: left;
                margin-bottom: 30px;
            }

            .word-result {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 10px;
                margin-bottom: 5px;
                border-radius: 8px;
                background-color: #f8f9fa;
            }

            .word-result.correct { background-color: #d4edda; }
            .word-result.incorrect { background-color: #f8d7da; }

            .feedback-message {
                padding: 10px;
                border-radius: 8px;
                margin-top: 15px;
                text-align: center;
            }

            .feedback-info { background-color: #d1ecf1; color: #0c5460; }
            .feedback-success { background-color: #d4edda; color: #155724; }
            .feedback-warning { background-color: #fff3cd; color: #856404; }
            .feedback-error { background-color: #f8d7da; color: #721c24; }

            .btn-primary {
                background: linear-gradient(135deg, #667eea, #764ba2);
                color: white;
                border: none;
                padding: 12px 24px;
                border-radius: 8px;
                cursor: pointer;
                font-size: 1em;
                transition: all 0.3s ease;
            }

            .btn-primary:hover {
                transform: translateY(-2px);
                box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
            }

            .btn-secondary {
                background: #6c757d;
                color: white;
                border: none;
                padding: 12px 24px;
                border-radius: 8px;
                cursor: pointer;
                font-size: 1em;
                transition: all 0.3s ease;
            }

            .btn-secondary:hover {
                background: #5a6268;
            }

            .btn-success { background-color: #28a745; color: white; }
            .btn-warning { background-color: #ffc107; color: #212529; }
            .btn-error { background-color: #dc3545; color: white; }

            button:disabled {
                opacity: 0.6;
                cursor: not-allowed;
            }
        `;

        document.head.appendChild(styles);
    }

    // ========================================
    // DRSExerciseInterface REQUIRED METHODS
    // ========================================

    /**
     * Get exercise results and statistics
     * @returns {Object} - Results data
     */
    getResults() {
        const correctWords = this.groupResults.filter(result => result.correct).length;
        const totalWords = this.groupResults.length;
        const score = totalWords > 0 ? Math.round((correctWords / totalWords) * 100) : 0;
        const timeSpent = this.startTime ? Date.now() - this.startTime : 0;

        return {
            score,
            attempts: totalWords,
            timeSpent,
            completed: this.currentWordIndex >= this.currentVocabularyGroup.length,
            details: {
                correctWords,
                totalWords,
                groupResults: this.groupResults,
                masteryPercentage: score
            }
        };
    }

    /**
     * Handle user input during exercise
     * @param {Event} event - User input event
     * @param {*} data - Input data
     * @returns {void}
     */
    handleUserInput(event, data) {
        // This method delegates to existing handlers
        // Already implemented through _handleUserInput, _handleDifficultySelection, etc.
        if (event && event.type) {
            switch (event.type) {
                case 'input':
                case 'change':
                    this._handleUserInput(event);
                    break;
                case 'click':
                    if (event.target.classList.contains('difficulty-btn')) {
                        this._handleDifficultySelection(event);
                    } else if (event.target.classList.contains('btn-next')) {
                        this._handleNextWord(event);
                    } else if (event.target.classList.contains('btn-reveal')) {
                        this._handleRevealAnswer(event);
                    }
                    break;
            }
        }
    }

    /**
     * Mark exercise as completed and save progress
     * @param {Object} results - Exercise results
     * @returns {Promise<void>}
     */
    async markCompleted(results) {
        console.log('💾 Marking VocabularyModule as completed...');

        // Mark all words in current group as mastered if score is high enough
        const { score, details } = results || this.getResults();

        if (score >= this.config.masteryThreshold) {
            // Mark all words in group as mastered
            for (const word of this.currentVocabularyGroup) {
                if (this.prerequisiteEngine && this.prerequisiteEngine.isInitialized) {
                    await this.prerequisiteEngine.markWordMastered(word.word, {
                        score,
                        timestamp: new Date().toISOString(),
                        moduleType: 'vocabulary',
                        attempts: details.totalWords
                    });
                }
            }
            console.log(`✅ Marked ${this.currentVocabularyGroup.length} words as mastered`);
        } else {
            console.log(`⚠️ Score ${score}% below mastery threshold ${this.config.masteryThreshold}%`);
        }

        // Save completion metadata
        if (this.contextMemory) {
            this.contextMemory.recordInteraction({
                type: 'vocabulary',
                subtype: 'completion',
                content: {
                    vocabulary: this.currentVocabularyGroup
                },
                validation: results,
                context: {
                    moduleType: 'vocabulary',
                    dynamicMode: true
                }
            });
        }

        console.log('✅ VocabularyModule completion saved');
    }

    /**
     * Get exercise type identifier
     * @returns {string} - Exercise type
     */
    getExerciseType() {
        return 'vocabulary';
    }

    /**
     * Get exercise configuration
     * @returns {Object} - Configuration object
     */
    getExerciseConfig() {
        const wordCount = this.currentVocabularyGroup ? this.currentVocabularyGroup.length : 0;
        const estimatedTimePerWord = 0.5; // 30 seconds per word

        return {
            type: this.getExerciseType(),
            difficulty: wordCount <= 3 ? 'easy' : (wordCount <= 7 ? 'medium' : 'hard'),
            estimatedTime: Math.ceil(wordCount * estimatedTimePerWord), // in minutes
            prerequisites: [], // Vocabulary has no prerequisites
            metadata: {
                ...this.config,
                groupSize: this.config.groupSize,
                masteryThreshold: this.config.masteryThreshold,
                wordCount,
                dynamicMode: true // Flag to indicate dynamic word selection
            }
        };
    }
}

export default VocabularyModule;