/**
 * ContentLoader - Système de chargement et analyse de contenu JSON
 * Génère des rapports de contenu et des statistiques
 */

import apiService from '../services/APIService.js';

class ContentLoader {
    constructor() {
        this._cache = new Map();
        this._contentReports = new Map();
        this._booksCache = new Map();
        this._booksLoaded = false;
        this._apiService = apiService;
    }

    /**
     * Charge et analyse un fichier JSON de contenu
     * @param {string} bookId - ID du livre
     * @returns {Promise<Object>} - Contenu chargé avec rapport
     */
    async loadContent(bookId) {
        // Vérifier le cache
        if (this._cache.has(bookId)) {
            return this._cache.get(bookId);
        }

        try {
            // Try loading from books first (metadata), then chapters (content)
            let contentData;
            try {
                contentData = await this._apiService.loadBook(bookId);
            } catch (error) {
                // Fallback to chapters directory
                contentData = await this._apiService.loadChapter(bookId);
            }

            // Générer le rapport de contenu
            const contentReport = this._generateContentReport(contentData);

            const processedContent = {
                ...contentData,
                _meta: {
                    loadedAt: new Date().toISOString(),
                    report: contentReport
                }
            };

            // Mettre en cache
            this._cache.set(bookId, processedContent);
            this._contentReports.set(bookId, contentReport);

            console.log(`📊 Content loaded for ${bookId}:`, contentReport);
            return processedContent;

        } catch (error) {
            console.error(`❌ Error loading content for ${bookId}:`, error);
            throw error;
        }
    }

    /**
     * Génère un rapport détaillé du contenu
     * @param {Object} contentData - Données JSON du contenu
     * @returns {Object} - Rapport de contenu
     */
    _generateContentReport(contentData) {
        const report = {
            totalWords: 0,
            wordTypes: {},
            languages: new Set(),
            difficulty: contentData.difficulty || 'unknown',
            categories: {},
            statistics: {},
            metadata: contentData.metadata || {},
            contentStructure: contentData.content_structure || {},
            learningPaths: contentData.learning_paths || {},
            assessment: contentData.assessment || {}
        };

        // Analyser le vocabulaire
        if (contentData.vocabulary) {
            const vocabulary = contentData.vocabulary;
            report.totalWords = Object.keys(vocabulary).length;

            // Analyser par type de mot
            Object.entries(vocabulary).forEach(([word, data]) => {
                const type = data.type || 'unknown';
                report.wordTypes[type] = (report.wordTypes[type] || 0) + 1;

                // Détecter les langues
                if (data.user_language) {
                    // Détecter si c'est du chinois, français, etc.
                    if (/[\u4e00-\u9fff]/.test(data.user_language)) {
                        report.languages.add('Chinese');
                    } else if (/[àâäçéèêëïîôùûüÿ]/.test(data.user_language)) {
                        report.languages.add('French');
                    } else {
                        report.languages.add('English');
                    }
                }

                // Utiliser les sections structurées si disponibles
                if (contentData.content_structure && contentData.content_structure.vocabulary_sections) {
                    const section = this._findWordSection(word, contentData.content_structure.vocabulary_sections);
                    if (section) {
                        report.categories[section.title] = (report.categories[section.title] || 0) + 1;
                    }
                } else {
                    // Fallback sur l'ancien système de catégorisation
                    const category = this._categorizeWord(word, data);
                    report.categories[category] = (report.categories[category] || 0) + 1;
                }
            });
        }

        // Convertir Set en Array pour JSON
        report.languages = Array.from(report.languages);

        // Statistiques finales avec les nouvelles métadonnées
        report.statistics = {
            mostCommonType: this._getMostCommon(report.wordTypes),
            mostCommonCategory: this._getMostCommon(report.categories),
            averageWordLength: this._calculateAverageWordLength(contentData.vocabulary),
            complexityScore: this._calculateComplexityScore(report),
            estimatedHours: contentData.metadata?.estimated_hours || 0,
            totalSections: contentData.content_structure?.vocabulary_sections?.length || 0,
            totalSentences: contentData.sentences?.length || 0,
            learningPathsCount: Object.keys(contentData.learning_paths || {}).length
        };

        return report;
    }

    /**
     * Trouve la section d'un mot dans la structure de contenu
     * @param {string} word - Le mot à chercher
     * @param {Array} sections - Les sections de vocabulaire
     * @returns {Object|null} - Section trouvée ou null
     */
    _findWordSection(word, sections) {
        for (const section of sections) {
            if (section.words && section.words.includes(word)) {
                return section;
            }
        }
        return null;
    }

    /**
     * Catégorise un mot selon son contexte
     * @param {string} word - Le mot à catégoriser
     * @param {Object} data - Données du mot
     * @returns {string} - Catégorie
     */
    _categorizeWord(word, data) {
        const lowerWord = word.toLowerCase();
        const translation = (data.user_language || '').toLowerCase();

        // Catégories basées sur des mots-clés
        if (lowerWord.includes('house') || lowerWord.includes('room') || lowerWord.includes('building') ||
            translation.includes('房') || translation.includes('室') || lowerWord.includes('home')) {
            return 'Housing & Home';
        }

        if (lowerWord.includes('food') || lowerWord.includes('eat') || lowerWord.includes('cook') ||
            translation.includes('食') || translation.includes('饭') || lowerWord.includes('restaurant')) {
            return 'Food & Dining';
        }

        if (lowerWord.includes('work') || lowerWord.includes('job') || lowerWord.includes('office') ||
            translation.includes('工作') || translation.includes('职')) {
            return 'Work & Career';
        }

        if (lowerWord.includes('family') || lowerWord.includes('mother') || lowerWord.includes('father') ||
            translation.includes('家') || translation.includes('妈') || translation.includes('爸')) {
            return 'Family & Relationships';
        }

        if (lowerWord.includes('time') || lowerWord.includes('day') || lowerWord.includes('year') ||
            translation.includes('时间') || translation.includes('天') || translation.includes('年')) {
            return 'Time & Calendar';
        }

        if (data.type === 'adjective') return 'Descriptive Words';
        if (data.type === 'verb') return 'Actions & Verbs';
        if (data.type === 'noun') return 'Objects & Things';

        return 'General Vocabulary';
    }

    /**
     * Trouve l'élément le plus commun dans un objet
     * @param {Object} obj - Objet avec des compteurs
     * @returns {string} - Clé la plus fréquente
     */
    _getMostCommon(obj) {
        return Object.entries(obj).reduce((a, b) => obj[a] > obj[b] ? a : b, Object.keys(obj)[0]);
    }

    /**
     * Calcule la longueur moyenne des mots
     * @param {Object} vocabulary - Vocabulaire
     * @returns {number} - Longueur moyenne
     */
    _calculateAverageWordLength(vocabulary) {
        if (!vocabulary) return 0;
        const words = Object.keys(vocabulary);
        const totalLength = words.reduce((sum, word) => sum + word.length, 0);
        return Math.round((totalLength / words.length) * 100) / 100;
    }

    /**
     * Calcule un score de complexité
     * @param {Object} report - Rapport de contenu
     * @returns {number} - Score de 1 à 10
     */
    _calculateComplexityScore(report) {
        let score = 5; // Base

        // Plus de mots = plus complexe
        if (report.totalWords > 100) score += 1;
        if (report.totalWords > 200) score += 1;

        // Diversité des types de mots
        const typeCount = Object.keys(report.wordTypes).length;
        if (typeCount > 5) score += 1;

        // Longueur moyenne des mots
        if (report.statistics?.averageWordLength > 7) score += 1;

        // Difficulté déclarée
        if (report.difficulty === 'advanced') score += 2;
        if (report.difficulty === 'intermediate') score += 1;

        return Math.min(10, Math.max(1, score));
    }

    /**
     * Génère un tooltip HTML pour un chapitre
     * @param {string} bookId - ID du livre
     * @returns {string} - HTML du tooltip
     */
    generateTooltipHTML(bookId) {
        const report = this._contentReports.get(bookId);
        if (!report) return '<div class="tooltip-content">Loading content info...</div>';

        const topCategories = Object.entries(report.categories)
            .sort(([,a], [,b]) => b - a)
            .slice(0, 3)
            .map(([cat, count]) => `${cat}: ${count} words`)
            .join('<br>');

        // Informations sur les métadonnées si disponibles
        const metadata = report.metadata || {};
        const statistics = report.statistics || {};

        const metadataSection = metadata.estimated_hours ? `
            <div class="tooltip-section">
                <div class="section-header">📋 Learning Info:</div>
                <div class="section-content">
                    ⏱️ Est. Time: ${metadata.estimated_hours}h<br>
                    📖 Sections: ${statistics.totalSections || 0}<br>
                    💬 Sentences: ${statistics.totalSentences || 0}<br>
                    🎯 Paths: ${statistics.learningPathsCount || 0}
                </div>
            </div>
        ` : '';

        const learningObjectives = metadata.learning_objectives ? `
            <div class="tooltip-section">
                <div class="section-header">🎯 Objectives:</div>
                <div class="section-content">
                    ${metadata.learning_objectives.slice(0, 2).map(obj => `• ${obj}`).join('<br>')}
                    ${metadata.learning_objectives.length > 2 ? `<br>+${metadata.learning_objectives.length - 2} more...` : ''}
                </div>
            </div>
        ` : '';

        return `
            <div class="tooltip-content">
                <div class="tooltip-header">
                    <strong>📚 ${metadata.source || 'Content Overview'}</strong>
                    ${metadata.version ? `<span class="version">v${metadata.version}</span>` : ''}
                </div>
                <div class="tooltip-stats">
                    <div class="stat-item">
                        <span class="stat-label">📊 Total Words:</span>
                        <span class="stat-value">${report.totalWords}</span>
                    </div>
                    <div class="stat-item">
                        <span class="stat-label">🏷️ Word Types:</span>
                        <span class="stat-value">${Object.keys(report.wordTypes).length}</span>
                    </div>
                    <div class="stat-item">
                        <span class="stat-label">🌐 Languages:</span>
                        <span class="stat-value">${report.languages.join(', ')}</span>
                    </div>
                    <div class="stat-item">
                        <span class="stat-label">⭐ Complexity:</span>
                        <span class="stat-value">${statistics.complexityScore}/10</span>
                    </div>
                    <div class="stat-item">
                        <span class="stat-label">📝 Level:</span>
                        <span class="stat-value">${metadata.target_level || report.difficulty}</span>
                    </div>
                </div>
                ${metadataSection}
                <div class="tooltip-categories">
                    <div class="categories-header">Top Categories:</div>
                    <div class="categories-list">${topCategories}</div>
                </div>
                ${learningObjectives}
                ${metadata.content_tags ? `
                    <div class="tooltip-tags">
                        ${metadata.content_tags.map(tag => `<span class="tag">#${tag}</span>`).join(' ')}
                    </div>
                ` : ''}
            </div>
        `;
    }

    /**
     * Récupère le rapport d'un contenu
     * @param {string} bookId - ID du livre
     * @returns {Object|null} - Rapport ou null
     */
    getContentReport(bookId) {
        return this._contentReports.get(bookId) || null;
    }

    /**
     * Obtient le contenu chargé pour un livre (depuis le cache)
     * @param {string} bookId - ID du livre
     * @returns {Object|null} - Contenu chargé ou null si pas en cache
     */
    getContent(bookId) {
        return this._cache.get(bookId) || null;
    }

    /**
     * Charge tous les livres disponibles
     * @returns {Promise<Array>} - Liste des livres
     */
    async loadBooks() {
        if (this._booksLoaded) {
            return Array.from(this._booksCache.values());
        }

        try {
            // Use APIService to dynamically discover all books
            const books = await this._apiService.getBooks();

            // Cache all books
            for (const book of books) {
                this._booksCache.set(book.id, book);
            }

            this._booksLoaded = true;
            console.log(`📚 Loaded ${this._booksCache.size} books into cache`);
            return Array.from(this._booksCache.values());

        } catch (error) {
            console.error('Error loading books:', error);
            return [];
        }
    }

    /**
     * Obtient tous les livres (depuis le cache)
     * @returns {Array} - Liste des livres ou tableau vide
     */
    getBooks() {
        return Array.from(this._booksCache.values());
    }

    /**
     * Obtient un livre spécifique
     * @param {string} bookId - ID du livre
     * @returns {Object|null} - Données du livre ou null
     */
    getBook(bookId) {
        return this._booksCache.get(bookId) || null;
    }

    /**
     * Obtient les chapitres d'un livre
     * @param {string} bookId - ID du livre
     * @returns {Array} - Liste des chapitres
     */
    getBookChapters(bookId) {
        const book = this._booksCache.get(bookId);
        return book ? book.chapters || [] : [];
    }

    /**
     * Vide le cache
     */
    clearCache() {
        this._cache.clear();
        this._contentReports.clear();
        this._booksCache.clear();
        this._booksLoaded = false;
    }
}

export default ContentLoader;