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

class WordDiscovery extends Module {
    constructor(name, dependencies, config = {}) {
        super(name, ['eventBus']);

        if (!dependencies.eventBus || !dependencies.content) {
            throw new Error('WordDiscovery requires eventBus and content dependencies');
        }

        this._eventBus = dependencies.eventBus;
        this._content = dependencies.content;
        this._config = {
            container: null,
            difficulty: 'medium',
            practiceCount: 10,
            timerDuration: 30,
            ...config
        };

        this._currentPhase = 'discovery';
        this._discoveredWords = [];
        this._practiceWords = [];
        this._currentWordIndex = 0;
        this._currentPracticeLevel = 0;
        this._practiceCorrect = 0;
        this._practiceTotal = 0;
        this._timer = null;
        this._timeLeft = 0;
        this._gameContainer = null;
        this._audioElements = new Map();
        this._imageCache = new Map();

        this._practiceOptions = [];
        this._correctAnswer = null;
        this._currentQuestion = null;

        Object.seal(this);
    }

    static getMetadata() {
        return {
            id: 'word-discovery',
            name: 'Word Discovery',
            description: 'Discover and practice vocabulary with adaptive difficulty',
            version: '2.0.0',
            author: 'Class Generator',
            category: 'vocabulary',
            tags: ['vocabulary', 'learning', 'discovery', 'practice'],
            difficulty: {
                min: 1,
                max: 4,
                default: 2
            },
            estimatedDuration: 15,
            requiredContent: ['vocabulary']
        };
    }

    static getCompatibilityScore(content) {
        if (!content || (!Array.isArray(content.vocabulary) && !content.vocabulary)) {
            return 0;
        }

        // Handle both array and object vocabulary formats
        let vocabCount;
        if (Array.isArray(content.vocabulary)) {
            vocabCount = content.vocabulary.length;
        } else if (content.vocabulary && typeof content.vocabulary === 'object') {
            vocabCount = Object.keys(content.vocabulary).length;
        } else {
            return 0;
        }

        let score = 50;

        if (vocabCount >= 10) score += 20;
        if (vocabCount >= 20) score += 15;
        if (vocabCount >= 50) score += 10;

        // Check for bonus features depending on format
        let hasImages, hasAudio, hasTranslations;

        if (Array.isArray(content.vocabulary)) {
            hasImages = content.vocabulary.some(word => word.image);
            hasAudio = content.vocabulary.some(word => word.audio);
            hasTranslations = content.vocabulary.some(word => word.translation);
        } else {
            // Object format (SBS style)
            const vocabEntries = Object.values(content.vocabulary);
            hasImages = vocabEntries.some(entry => entry.image);
            hasAudio = vocabEntries.some(entry => entry.audio);
            hasTranslations = vocabEntries.some(entry => entry.user_language || entry.translation);
        }

        if (hasImages) score += 5;
        if (hasAudio) score += 5;
        if (hasTranslations) score += 5;

        return Math.min(score, 100);
    }

    async init() {
        this._validateNotDestroyed();

        // Validate container
        if (!this._config.container) {
            throw new Error('Game container is required');
        }

        this._eventBus.on('game:start', this._handleGameStart.bind(this), this.name);
        this._eventBus.on('game:stop', this._handleGameStop.bind(this), this.name);
        this._eventBus.on('navigation:change', this._handleNavigationChange.bind(this), this.name);

        this._injectCSS();

        // Start game immediately
        try {
            this._gameContainer = this._config.container;
            const content = this._content;

            if (!content || !content.vocabulary || Object.keys(content.vocabulary).length === 0) {
                throw new Error('No vocabulary content available');
            }

            this._practiceWords = Object.entries(content.vocabulary).map(([word, data]) => ({
                word: word,
                translation: typeof data === 'string' ? data :
                           data.user_language || data.translation || 'unknown',
                pronunciation: data.pronunciation,
                type: data.type || 'general',
                audio: data.audio,
                image: data.image,
                definition: data.definition,
                example: data.example
            }));

            this._discoveredWords = [];
            this._currentWordIndex = 0;
            this._currentPhase = 'discovery';

            await this._preloadAssets();
            this._renderDiscoveryPhase();

            // Emit game ready event
            this._eventBus.emit('game:ready', {
                gameId: 'word-discovery',
                instanceId: this.name,
                vocabulary: this._practiceWords.length
            }, this.name);

        } catch (error) {
            this._showError(error.message);
            throw error;
        }

        this._setInitialized();
    }

    async destroy() {
        this._validateNotDestroyed();

        this._cleanup();
        this._removeCSS();
        this._eventBus.off('game:start', this.name);
        this._eventBus.off('game:stop', this.name);
        this._eventBus.off('navigation:change', this.name);

        this._setDestroyed();
    }

    _handleGameStart(event) {
        this._validateInitialized();
        if (event.gameId === 'word-discovery') {
            this._startGame();
        }
    }

    _handleGameStop(event) {
        this._validateInitialized();
        if (event.gameId === 'word-discovery') {
            this._stopGame();
        }
    }

    _handleNavigationChange(event) {
        this._validateInitialized();
        if (event.from === '/games/word-discovery') {
            this._cleanup();
        }
    }

    async _startGame() {
        try {
            this._gameContainer = document.getElementById('game-content');
            if (!this._gameContainer) {
                throw new Error('Game container not found');
            }

            const content = window.contentLoader ? window.contentLoader.getContent(window.currentChapterId) : await this._content.getCurrentContent();
            if (!content || !content.vocabulary || content.vocabulary.length === 0) {
                throw new Error('No vocabulary content available');
            }

            this._practiceWords = [...content.vocabulary];
            this._discoveredWords = [];
            this._currentWordIndex = 0;
            this._currentPhase = 'discovery';

            await this._preloadAssets();
            this._renderDiscoveryPhase();

        } catch (error) {
            console.error('Error starting Word Discovery:', error);
            this._eventBus.emit('game:error', {
                gameId: 'word-discovery',
                error: error.message,
                module: this.name
            });
        }
    }

    _stopGame() {
        this._cleanup();
    }

    _cleanup() {
        if (this._timer) {
            clearInterval(this._timer);
            this._timer = null;
        }

        this._audioElements.forEach(audio => {
            audio.pause();
            audio.src = '';
        });
        this._audioElements.clear();

        if (this._gameContainer) {
            this._gameContainer.innerHTML = '';
        }
    }

    async _preloadAssets() {
        for (const word of this._practiceWords) {
            if (word.audio) {
                try {
                    const audio = new Audio();
                    audio.preload = 'auto';
                    audio.src = word.audio;
                    this._audioElements.set(word.word, audio);
                } catch (error) {
                    console.warn(`Failed to preload audio for ${word.word}:`, error);
                }
            }

            if (word.image) {
                try {
                    const img = new Image();
                    img.src = word.image;
                    await new Promise((resolve, reject) => {
                        img.onload = resolve;
                        img.onerror = reject;
                        setTimeout(reject, 5000);
                    });
                    this._imageCache.set(word.word, word.image);
                } catch (error) {
                    console.warn(`Failed to preload image for ${word.word}:`, error);
                }
            }
        }
    }

    _renderDiscoveryPhase() {
        const word = this._practiceWords[this._currentWordIndex];
        if (!word) {
            this._startPracticePhase();
            return;
        }

        this._gameContainer.innerHTML = `
            <div class="word-discovery-container">
                <div class="discovery-header">
                    <h2>Word Discovery</h2>
                    <div class="progress-bar">
                        <div class="progress-fill" style="width: ${(this._currentWordIndex / this._practiceWords.length) * 100}%"></div>
                    </div>
                    <p>Progress: ${this._currentWordIndex + 1} / ${this._practiceWords.length}</p>
                </div>

                <div class="word-card discovery-card">
                    ${word.image ? `<div class="word-image">
                        <img src="${word.image}" alt="${word.word}" onerror="this.style.display='none'">
                    </div>` : ''}

                    <div class="word-content">
                        <h3 class="word-text">${word.word}</h3>
                        ${word.translation ? `<p class="word-translation">${word.translation}</p>` : ''}
                        ${word.definition ? `<p class="word-definition">${word.definition}</p>` : ''}
                        ${word.example ? `<p class="word-example">"${word.example}"</p>` : ''}
                    </div>

                    <div class="word-controls">
                        ${word.audio ? `<button class="audio-btn" onclick="window.wordDiscovery._playAudio('${word.word}')">
                            🔊 Listen
                        </button>` : ''}
                        <button class="next-btn" onclick="window.wordDiscovery._nextWord()">
                            Next Word
                        </button>
                    </div>
                </div>

                <div class="discovery-controls">
                    <button class="practice-btn" onclick="window.wordDiscovery._startPracticePhase()">
                        Start Practice
                    </button>
                </div>
            </div>
        `;

        window.wordDiscovery = this;
    }

    _nextWord() {
        const currentWord = this._practiceWords[this._currentWordIndex];
        if (currentWord && !this._discoveredWords.find(w => w.word === currentWord.word)) {
            this._discoveredWords.push(currentWord);
        }

        this._currentWordIndex++;
        this._renderDiscoveryPhase();
    }

    _playAudio(word) {
        const audio = this._audioElements.get(word);
        if (audio) {
            audio.currentTime = 0;
            audio.play().catch(error => {
                console.warn(`Failed to play audio for ${word}:`, error);
            });
        }
    }

    _startPracticePhase() {
        if (this._discoveredWords.length === 0) {
            this._discoveredWords = [...this._practiceWords];
        }

        this._currentPhase = 'practice';
        this._currentPracticeLevel = 0;
        this._practiceCorrect = 0;
        this._practiceTotal = 0;

        this._renderPracticeLevel();
    }

    _renderPracticeLevel() {
        const levels = ['Easy', 'Medium', 'Hard', 'Expert'];
        const levelConfig = {
            0: { time: 45, options: 2, type: 'translation' },
            1: { time: 30, options: 3, type: 'mixed' },
            2: { time: 20, options: 4, type: 'definition' },
            3: { time: 15, options: 4, type: 'context' }
        };

        const config = levelConfig[this._currentPracticeLevel];
        const levelName = levels[this._currentPracticeLevel];

        this._gameContainer.innerHTML = `
            <div class="word-discovery-container">
                <div class="practice-header">
                    <h2>Practice Phase - ${levelName}</h2>
                    <div class="practice-stats">
                        <span>Correct: ${this._practiceCorrect}</span>
                        <span>Total: ${this._practiceTotal}</span>
                        <span>Accuracy: ${this._practiceTotal > 0 ? Math.round((this._practiceCorrect / this._practiceTotal) * 100) : 0}%</span>
                    </div>
                    <div class="timer">Time: <span id="timer-display">${config.time}</span></div>
                </div>

                <div class="practice-question" id="practice-question">
                    Loading question...
                </div>

                <div class="practice-controls">
                    <button class="back-btn" onclick="window.wordDiscovery._backToDiscovery()">
                        Back to Discovery
                    </button>
                    <button class="next-level-btn" onclick="window.wordDiscovery._nextLevel()"
                            style="display: ${this._currentPracticeLevel < 3 ? 'inline-block' : 'none'}">
                        Next Level
                    </button>
                </div>
            </div>
        `;

        this._timeLeft = config.time;
        this._startTimer();
        this._generateQuestion(config);
    }

    _startTimer() {
        const timerDisplay = document.getElementById('timer-display');
        if (!timerDisplay) return;

        this._timer = setInterval(() => {
            this._timeLeft--;
            timerDisplay.textContent = this._timeLeft;

            if (this._timeLeft <= 0) {
                clearInterval(this._timer);
                this._handleTimeUp();
            }
        }, 1000);
    }

    _handleTimeUp() {
        this._practiceTotal++;
        this._showResult(false, 'Time up!');
        setTimeout(() => {
            this._generateQuestion();
        }, 1500);
    }

    _generateQuestion(config = null) {
        if (!config) {
            const levelConfig = {
                0: { time: 45, options: 2, type: 'translation' },
                1: { time: 30, options: 3, type: 'mixed' },
                2: { time: 20, options: 4, type: 'definition' },
                3: { time: 15, options: 4, type: 'context' }
            };
            config = levelConfig[this._currentPracticeLevel];
        }

        const questionContainer = document.getElementById('practice-question');
        if (!questionContainer) return;

        const availableWords = this._discoveredWords.filter(w => w);
        if (availableWords.length === 0) return;

        const correctWord = availableWords[Math.floor(Math.random() * availableWords.length)];
        this._correctAnswer = correctWord;

        const wrongWords = availableWords
            .filter(w => w.word !== correctWord.word)
            .sort(() => Math.random() - 0.5)
            .slice(0, config.options - 1);

        this._practiceOptions = [correctWord, ...wrongWords]
            .sort(() => Math.random() - 0.5);

        this._renderQuestion(config.type, correctWord);
    }

    _renderQuestion(type, correctWord) {
        const questionContainer = document.getElementById('practice-question');
        let questionHTML = '';

        switch (type) {
            case 'translation':
                questionHTML = this._renderTranslationQuestion(correctWord);
                break;
            case 'definition':
                questionHTML = this._renderDefinitionQuestion(correctWord);
                break;
            case 'context':
                questionHTML = this._renderContextQuestion(correctWord);
                break;
            case 'mixed':
                const types = ['translation', 'definition'];
                const randomType = types[Math.floor(Math.random() * types.length)];
                questionHTML = this._renderQuestion(randomType, correctWord);
                return;
        }

        questionContainer.innerHTML = questionHTML;
    }

    _renderTranslationQuestion(correctWord) {
        return `
            <div class="question-content">
                <h3>What does this word mean?</h3>
                <div class="question-word">
                    ${correctWord.word}
                    ${correctWord.audio ? `<button class="audio-btn-small" onclick="window.wordDiscovery._playAudio('${correctWord.word}')">🔊</button>` : ''}
                </div>
                <div class="options-grid">
                    ${this._practiceOptions.map(option => `
                        <button class="option-btn" onclick="window.wordDiscovery._selectAnswer('${option.word}')">
                            ${option.translation || option.definition || option.word}
                        </button>
                    `).join('')}
                </div>
            </div>
        `;
    }

    _renderDefinitionQuestion(correctWord) {
        return `
            <div class="question-content">
                <h3>Which word matches this definition?</h3>
                <div class="question-definition">
                    ${correctWord.definition || correctWord.translation}
                </div>
                <div class="options-grid">
                    ${this._practiceOptions.map(option => `
                        <button class="option-btn" onclick="window.wordDiscovery._selectAnswer('${option.word}')">
                            ${option.word}
                        </button>
                    `).join('')}
                </div>
            </div>
        `;
    }

    _renderContextQuestion(correctWord) {
        return `
            <div class="question-content">
                <h3>Complete the sentence:</h3>
                <div class="question-context">
                    ${correctWord.example ? correctWord.example.replace(correctWord.word, '_____') : `The _____ is very important.`}
                </div>
                <div class="options-grid">
                    ${this._practiceOptions.map(option => `
                        <button class="option-btn" onclick="window.wordDiscovery._selectAnswer('${option.word}')">
                            ${option.word}
                        </button>
                    `).join('')}
                </div>
            </div>
        `;
    }

    _selectAnswer(selectedWord) {
        this._practiceTotal++;
        const isCorrect = selectedWord === this._correctAnswer.word;

        if (isCorrect) {
            this._practiceCorrect++;
        }

        this._showResult(isCorrect, isCorrect ? 'Correct!' : `Wrong! The answer was: ${this._correctAnswer.word}`);

        setTimeout(() => {
            this._generateQuestion();
        }, 1500);
    }

    _showResult(isCorrect, message) {
        if (this._timer) {
            clearInterval(this._timer);
            this._timer = null;
        }

        const questionContainer = document.getElementById('practice-question');
        if (!questionContainer) return;

        questionContainer.innerHTML = `
            <div class="result-display ${isCorrect ? 'correct' : 'incorrect'}">
                <h3>${message}</h3>
                ${!isCorrect && this._correctAnswer.translation ? `<p>Translation: ${this._correctAnswer.translation}</p>` : ''}
            </div>
        `;

        this._updateStats();
    }

    _updateStats() {
        const statsElements = document.querySelectorAll('.practice-stats span');
        if (statsElements.length >= 3) {
            statsElements[0].textContent = `Correct: ${this._practiceCorrect}`;
            statsElements[1].textContent = `Total: ${this._practiceTotal}`;
            statsElements[2].textContent = `Accuracy: ${this._practiceTotal > 0 ? Math.round((this._practiceCorrect / this._practiceTotal) * 100) : 0}%`;
        }
    }

    _nextLevel() {
        if (this._currentPracticeLevel < 3) {
            this._currentPracticeLevel++;
            this._renderPracticeLevel();
        }
    }

    _backToDiscovery() {
        this._currentPhase = 'discovery';
        this._currentWordIndex = 0;
        this._renderDiscoveryPhase();
    }

    _injectCSS() {
        const cssId = 'word-discovery-styles';
        if (document.getElementById(cssId)) return;

        const style = document.createElement('style');
        style.id = cssId;
        style.textContent = `
            .word-discovery-container {
                max-width: 800px;
                margin: 0 auto;
                padding: 20px;
                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            }

            .discovery-header, .practice-header {
                text-align: center;
                margin-bottom: 30px;
            }

            .discovery-header h2, .practice-header h2 {
                color: #2c3e50;
                margin-bottom: 15px;
            }

            .progress-bar {
                width: 100%;
                height: 8px;
                background-color: #ecf0f1;
                border-radius: 4px;
                overflow: hidden;
                margin: 10px 0;
            }

            .progress-fill {
                height: 100%;
                background: linear-gradient(90deg, #3498db, #2980b9);
                transition: width 0.3s ease;
            }

            .word-card {
                background: white;
                border-radius: 12px;
                box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
                padding: 30px;
                margin: 20px 0;
                text-align: center;
                border: 2px solid #e74c3c;
            }

            .word-image img {
                max-width: 200px;
                max-height: 200px;
                border-radius: 8px;
                margin-bottom: 20px;
            }

            .word-text {
                font-size: 2.5em;
                color: #2c3e50;
                margin: 15px 0;
                font-weight: bold;
            }

            .word-translation {
                font-size: 1.4em;
                color: #e74c3c;
                margin: 10px 0;
                font-weight: 600;
            }

            .word-definition {
                font-size: 1.1em;
                color: #7f8c8d;
                margin: 10px 0;
                font-style: italic;
            }

            .word-example {
                font-size: 1em;
                color: #95a5a6;
                margin: 15px 0;
                padding: 10px;
                background-color: #f8f9fa;
                border-radius: 6px;
            }

            .word-controls, .discovery-controls, .practice-controls {
                display: flex;
                gap: 15px;
                justify-content: center;
                margin-top: 20px;
            }

            .audio-btn, .next-btn, .practice-btn, .back-btn, .next-level-btn {
                padding: 12px 24px;
                border: none;
                border-radius: 8px;
                font-size: 1.1em;
                cursor: pointer;
                transition: all 0.3s ease;
                font-weight: 600;
            }

            .audio-btn {
                background: linear-gradient(135deg, #3498db, #2980b9);
                color: white;
            }

            .audio-btn:hover {
                transform: translateY(-2px);
                box-shadow: 0 4px 12px rgba(52, 152, 219, 0.4);
            }

            .next-btn, .next-level-btn {
                background: linear-gradient(135deg, #27ae60, #229954);
                color: white;
            }

            .next-btn:hover, .next-level-btn:hover {
                transform: translateY(-2px);
                box-shadow: 0 4px 12px rgba(39, 174, 96, 0.4);
            }

            .practice-btn {
                background: linear-gradient(135deg, #e74c3c, #c0392b);
                color: white;
                font-size: 1.3em;
                padding: 15px 30px;
            }

            .practice-btn:hover {
                transform: translateY(-2px);
                box-shadow: 0 4px 12px rgba(231, 76, 60, 0.4);
            }

            .back-btn {
                background: linear-gradient(135deg, #95a5a6, #7f8c8d);
                color: white;
            }

            .back-btn:hover {
                transform: translateY(-2px);
                box-shadow: 0 4px 12px rgba(149, 165, 166, 0.4);
            }

            .practice-stats {
                display: flex;
                gap: 20px;
                justify-content: center;
                margin: 15px 0;
                font-size: 1.1em;
                font-weight: 600;
            }

            .practice-stats span {
                color: #2c3e50;
            }

            .timer {
                font-size: 1.3em;
                font-weight: bold;
                color: #e74c3c;
                margin: 10px 0;
            }

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

            .question-content h3 {
                color: #2c3e50;
                margin-bottom: 20px;
                text-align: center;
            }

            .question-word {
                font-size: 2em;
                font-weight: bold;
                color: #e74c3c;
                text-align: center;
                margin: 20px 0;
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 10px;
            }

            .question-definition, .question-context {
                font-size: 1.3em;
                color: #2c3e50;
                text-align: center;
                margin: 20px 0;
                padding: 15px;
                background-color: #f8f9fa;
                border-radius: 8px;
                border-left: 4px solid #3498db;
            }

            .audio-btn-small {
                padding: 8px 12px;
                background: linear-gradient(135deg, #3498db, #2980b9);
                color: white;
                border: none;
                border-radius: 6px;
                cursor: pointer;
                font-size: 0.9em;
            }

            .options-grid {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                gap: 15px;
                margin-top: 25px;
            }

            .option-btn {
                padding: 15px 20px;
                background: linear-gradient(135deg, #ecf0f1, #bdc3c7);
                border: 2px solid #95a5a6;
                border-radius: 8px;
                cursor: pointer;
                font-size: 1.1em;
                font-weight: 600;
                color: #2c3e50;
                transition: all 0.3s ease;
            }

            .option-btn:hover {
                background: linear-gradient(135deg, #3498db, #2980b9);
                color: white;
                transform: translateY(-2px);
                box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
            }

            .result-display {
                text-align: center;
                padding: 30px;
                border-radius: 12px;
                margin: 20px 0;
            }

            .result-display.correct {
                background: linear-gradient(135deg, #2ecc71, #27ae60);
                color: white;
            }

            .result-display.incorrect {
                background: linear-gradient(135deg, #e74c3c, #c0392b);
                color: white;
            }

            .result-display h3 {
                margin: 0 0 10px 0;
                font-size: 1.5em;
            }

            .result-display p {
                margin: 10px 0 0 0;
                font-size: 1.1em;
                opacity: 0.9;
            }

            @media (max-width: 768px) {
                .word-discovery-container {
                    padding: 10px;
                }

                .word-text {
                    font-size: 2em;
                }

                .word-controls, .discovery-controls, .practice-controls {
                    flex-direction: column;
                    align-items: center;
                }

                .practice-stats {
                    flex-direction: column;
                    gap: 10px;
                }

                .options-grid {
                    grid-template-columns: 1fr;
                }

                .question-word {
                    font-size: 1.5em;
                }
            }
        `;

        document.head.appendChild(style);
    }

    _showError(message) {
        if (this._gameContainer) {
            this._gameContainer.innerHTML = `
                <div class="game-error">
                    <div class="error-icon">❌</div>
                    <h3>Word Discovery Error</h3>
                    <p>${message}</p>
                    <button class="btn btn-primary" onclick="history.back()">Go Back</button>
                </div>
            `;
        }
    }

    _removeCSS() {
        const cssElement = document.getElementById('word-discovery-styles');
        if (cssElement) {
            cssElement.remove();
        }

        if (window.wordDiscovery === this) {
            delete window.wordDiscovery;
        }
    }
}

export default WordDiscovery;