/**
 * VocabularyProgressManager - Comprehensive vocabulary progress persistence
 * Manages discovered/mastered words with full persistence and caching
 */

class VocabularyProgressManager {
    constructor() {
        // In-memory cache for performance
        this._cache = new Map();
        this._isDirty = new Set(); // Track which chapters need saving

        // Auto-save after changes
        this._autoSaveTimeout = null;
        this._autoSaveDelay = 2000; // 2 seconds
    }

    /**
     * Load progress for a specific chapter
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @returns {Object} - Progress data
     */
    async loadProgress(bookId, chapterId) {
        const key = `${bookId}/${chapterId}`;

        // Return cached data if available
        if (this._cache.has(key)) {
            console.log('📖 Loading vocabulary progress from cache:', key);
            return this._cache.get(key);
        }

        try {
            console.log('📥 Loading vocabulary progress from server:', key);
            const response = await fetch(`/api/progress/load/drs/${bookId}/${chapterId}`);

            let progressData;
            if (response.ok) {
                const rawData = await response.json();

                // Convert old format to new format if needed
                if (rawData.masteredVocabulary || rawData.discoveredVocabulary) {
                    console.log('🔄 Converting legacy data format to new format');
                    progressData = this._convertLegacyData(rawData);
                } else if (rawData.discovered || rawData.mastered) {
                    // Already in new format
                    progressData = rawData;
                } else {
                    // Empty or unknown format
                    progressData = this._createEmptyProgress();
                }

                console.log('✅ Vocabulary progress loaded:', progressData);
            } else {
                // Initialize empty progress if not found
                progressData = this._createEmptyProgress();
                console.log('🆕 Creating new vocabulary progress for:', key);
            }

            // Cache the loaded data
            this._cache.set(key, progressData);
            return progressData;

        } catch (error) {
            console.error('❌ Error loading vocabulary progress:', error);
            const emptyProgress = this._createEmptyProgress();
            this._cache.set(key, emptyProgress);
            return emptyProgress;
        }
    }

    /**
     * Save progress for a specific chapter
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @param {Object} progressData - Progress data to save
     */
    async saveProgress(bookId, chapterId, progressData = null) {
        const key = `${bookId}/${chapterId}`;

        // Use cached data if no specific data provided
        const dataToSave = progressData || this._cache.get(key);
        if (!dataToSave) {
            console.warn('⚠️ No progress data to save for:', key);
            return;
        }

        try {
            // Update metadata
            dataToSave.metadata.lastUpdate = new Date().toISOString();

            console.log('💾 Saving vocabulary progress:', key, dataToSave);
            const response = await fetch('/api/progress/save', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    system: 'drs',
                    bookId,
                    chapterId,
                    progressData: dataToSave
                })
            });

            if (response.ok) {
                const result = await response.json();
                console.log('✅ Vocabulary progress saved:', result.filename);

                // Update cache and mark as clean
                this._cache.set(key, dataToSave);
                this._isDirty.delete(key);
            } else {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }

        } catch (error) {
            console.error('❌ Error saving vocabulary progress:', error);
            throw error;
        }
    }

    /**
     * Mark a word as discovered
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @param {string} word - Word to mark as discovered
     * @param {Object} metadata - Additional metadata (difficulty, timestamp, etc.)
     */
    async markWordDiscovered(bookId, chapterId, word, metadata = {}) {
        const key = `${bookId}/${chapterId}`;
        const progressData = await this.loadProgress(bookId, chapterId);

        if (!progressData.discovered[word]) {
            progressData.discovered[word] = {
                timestamp: new Date().toISOString(),
                difficulty: metadata.difficulty || 'unknown',
                responseTime: metadata.responseTime,
                sessionId: metadata.sessionId
            };

            console.log('📚 Word discovered:', word, progressData.discovered[word]);
            this._markDirty(key);
            this._scheduleAutoSave(bookId, chapterId);
        }
    }

    /**
     * Mark a word as mastered (implies discovered)
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @param {string} word - Word to mark as mastered
     * @param {Object} metadata - Additional metadata (scores, timestamp, etc.)
     */
    async markWordMastered(bookId, chapterId, word, metadata = {}) {
        const key = `${bookId}/${chapterId}`;
        const progressData = await this.loadProgress(bookId, chapterId);

        // Ensure word is discovered first
        await this.markWordDiscovered(bookId, chapterId, word, metadata);

        // Add to mastered
        if (!progressData.mastered[word]) {
            progressData.mastered[word] = {
                timestamp: new Date().toISOString(),
                scores: metadata.scores || [],
                difficulty: metadata.difficulty || 'unknown',
                masteryLevel: metadata.masteryLevel || 1
            };
        } else {
            // Update existing mastery data
            if (metadata.scores) {
                progressData.mastered[word].scores.push(...metadata.scores);
            }
            progressData.mastered[word].masteryLevel = (progressData.mastered[word].masteryLevel || 1) + 1;
        }

        console.log('🏆 Word mastered:', word, progressData.mastered[word]);
        this._markDirty(key);
        this._scheduleAutoSave(bookId, chapterId);
    }

    /**
     * Check if a word is discovered
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @param {string} word - Word to check
     * @returns {boolean} - True if word is discovered
     */
    async isWordDiscovered(bookId, chapterId, word) {
        const progressData = await this.loadProgress(bookId, chapterId);
        return !!progressData.discovered[word];
    }

    /**
     * Check if a word is mastered
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @param {string} word - Word to check
     * @returns {boolean} - True if word is mastered
     */
    async isWordMastered(bookId, chapterId, word) {
        const progressData = await this.loadProgress(bookId, chapterId);
        return !!progressData.mastered[word];
    }

    /**
     * Get all discovered words for a chapter
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @returns {Array} - Array of discovered words
     */
    async getDiscoveredWords(bookId, chapterId) {
        const progressData = await this.loadProgress(bookId, chapterId);
        return Object.keys(progressData.discovered);
    }

    /**
     * Get all mastered words for a chapter
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @returns {Array} - Array of mastered words
     */
    async getMasteredWords(bookId, chapterId) {
        const progressData = await this.loadProgress(bookId, chapterId);
        return Object.keys(progressData.mastered);
    }

    /**
     * Get progress statistics
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     * @returns {Object} - Progress statistics
     */
    async getProgressStats(bookId, chapterId) {
        const progressData = await this.loadProgress(bookId, chapterId);

        const discoveredCount = Object.keys(progressData.discovered).length;
        const masteredCount = Object.keys(progressData.mastered).length;
        const totalWords = progressData.metadata.totalWords || 0;

        return {
            discovered: {
                count: discoveredCount,
                percentage: totalWords > 0 ? Math.round((discoveredCount / totalWords) * 100) : 0
            },
            mastered: {
                count: masteredCount,
                percentage: totalWords > 0 ? Math.round((masteredCount / totalWords) * 100) : 0
            },
            total: totalWords,
            lastUpdate: progressData.metadata.lastUpdate
        };
    }

    /**
     * Force save all dirty chapters
     */
    async forceSaveAll() {
        const savePromises = [];

        for (const key of this._isDirty) {
            const [bookId, chapterId] = key.split('/');
            savePromises.push(this.saveProgress(bookId, chapterId));
        }

        if (savePromises.length > 0) {
            console.log('💾 Force saving all dirty chapters:', savePromises.length);
            await Promise.all(savePromises);
        }
    }

    /**
     * Create empty progress structure
     * @returns {Object} - Empty progress data
     */
    _createEmptyProgress() {
        return {
            discovered: {},
            mastered: {},
            metadata: {
                totalWords: 0,
                sessionCount: 0,
                lastUpdate: new Date().toISOString(),
                version: '1.0'
            }
        };
    }

    /**
     * Convert legacy data format to new format
     * @param {Object} legacyData - Old format data
     * @returns {Object} - New format data
     */
    _convertLegacyData(legacyData) {
        console.log('🔄 Converting legacy vocabulary data format');

        const newData = this._createEmptyProgress();

        // Convert old masteredVocabulary array to new mastered object
        if (legacyData.masteredVocabulary && Array.isArray(legacyData.masteredVocabulary)) {
            legacyData.masteredVocabulary.forEach(word => {
                if (typeof word === 'string') {
                    newData.mastered[word] = {
                        timestamp: new Date().toISOString(),
                        difficulty: 'unknown',
                        scores: [100],
                        masteryLevel: 1,
                        source: 'legacy-migration'
                    };
                    // Also mark as discovered
                    newData.discovered[word] = {
                        timestamp: new Date().toISOString(),
                        difficulty: 'unknown',
                        source: 'legacy-migration'
                    };
                }
            });
        }

        // Convert discoveredVocabulary if it exists
        if (legacyData.discoveredVocabulary && Array.isArray(legacyData.discoveredVocabulary)) {
            legacyData.discoveredVocabulary.forEach(word => {
                if (typeof word === 'string' && !newData.discovered[word]) {
                    newData.discovered[word] = {
                        timestamp: new Date().toISOString(),
                        difficulty: 'unknown',
                        source: 'legacy-migration'
                    };
                }
            });
        }

        // Preserve metadata if available
        if (legacyData.masteryCount) {
            newData.metadata.totalWords = legacyData.masteryCount;
        }

        console.log('✅ Legacy data converted:', {
            discovered: Object.keys(newData.discovered).length,
            mastered: Object.keys(newData.mastered).length
        });

        return newData;
    }

    /**
     * Mark a chapter as dirty (needs saving)
     * @param {string} key - Chapter key (bookId/chapterId)
     */
    _markDirty(key) {
        this._isDirty.add(key);
    }

    /**
     * Schedule auto-save with debouncing
     * @param {string} bookId - Book identifier
     * @param {string} chapterId - Chapter identifier
     */
    _scheduleAutoSave(bookId, chapterId) {
        // Clear existing timeout
        if (this._autoSaveTimeout) {
            clearTimeout(this._autoSaveTimeout);
        }

        // Schedule new save
        this._autoSaveTimeout = setTimeout(async () => {
            try {
                await this.saveProgress(bookId, chapterId);
                console.log('🔄 Auto-saved vocabulary progress for:', `${bookId}/${chapterId}`);
            } catch (error) {
                console.error('❌ Auto-save failed:', error);
            }
        }, this._autoSaveDelay);
    }
}

export default VocabularyProgressManager;