/**
 * ContextMemory - Progressive context building service
 * Stores user responses and builds context for sequential exercises
 */

class ContextMemory {
    constructor() {
        this.sessions = new Map(); // sessionId -> session data
        this.currentSessionId = null;
        this.maxHistoryLength = 50; // Maximum number of interactions to remember
        this.contextTypes = ['vocabulary', 'phrase', 'text', 'audio', 'image', 'grammar'];
    }

    /**
     * Start a new session
     * @param {string} sessionId - Unique session identifier
     * @param {Object} sessionData - Initial session data
     */
    startSession(sessionId, sessionData = {}) {
        this.currentSessionId = sessionId;

        this.sessions.set(sessionId, {
            id: sessionId,
            startTime: new Date().toISOString(),
            chapterData: sessionData,
            interactions: [],
            contextBuilders: {
                vocabulary: new Map(), // word -> interaction history
                phrase: new Map(),     // phrase -> interaction history
                text: new Map(),       // text -> progressive context
                audio: new Map(),      // audio -> comprehension context
                image: new Map(),      // image -> description context
                grammar: new Map()     // grammar concept -> usage context
            },
            progressiveContext: {
                currentText: null,
                accumulatedSentences: [],
                currentDialog: null,
                accumulatedDialogLines: [],
                learningPath: []
            }
        });

        console.log(`🧠 Context memory session started: ${sessionId}`);
    }

    /**
     * End current session and cleanup
     * @param {string} sessionId - Session to end (optional, defaults to current)
     */
    endSession(sessionId = null) {
        const targetSessionId = sessionId || this.currentSessionId;

        if (this.sessions.has(targetSessionId)) {
            const session = this.sessions.get(targetSessionId);
            session.endTime = new Date().toISOString();
            session.duration = new Date(session.endTime) - new Date(session.startTime);

            console.log(`🧠 Context memory session ended: ${targetSessionId} (${session.interactions.length} interactions)`);
        }

        if (targetSessionId === this.currentSessionId) {
            this.currentSessionId = null;
        }
    }

    /**
     * Record an interaction and build context
     * @param {Object} interaction - Interaction data
     * @returns {Object} - Updated context for this interaction type
     */
    recordInteraction(interaction) {
        if (!this.currentSessionId) {
            throw new Error('No active session. Call startSession() first.');
        }

        const session = this.sessions.get(this.currentSessionId);

        // Add timestamp and normalize interaction
        const normalizedInteraction = {
            timestamp: new Date().toISOString(),
            type: interaction.type || 'unknown',
            subtype: interaction.subtype || 'general',
            content: interaction.content || {},
            userResponse: interaction.userResponse || '',
            validation: interaction.validation || {},
            context: interaction.context || {},
            ...interaction
        };

        // Store interaction
        session.interactions.push(normalizedInteraction);

        // Build type-specific context
        this._buildContextForType(session, normalizedInteraction);

        // Build progressive context if applicable
        this._buildProgressiveContext(session, normalizedInteraction);

        // Maintain history limits
        this._maintainHistoryLimits(session);

        console.log(`🧠 Recorded ${normalizedInteraction.type} interaction`);

        return this.getContextForType(normalizedInteraction.type, normalizedInteraction.content);
    }

    /**
     * Get context for a specific exercise type
     * @param {string} exerciseType - Type of exercise
     * @param {Object} content - Exercise content for context matching
     * @returns {Object} - Context information
     */
    getContextForType(exerciseType, content = {}) {
        if (!this.currentSessionId) {
            return { history: [], progressiveContext: {} };
        }

        const session = this.sessions.get(this.currentSessionId);
        const contextBuilder = session.contextBuilders[exerciseType];

        if (!contextBuilder) {
            return { history: [], progressiveContext: session.progressiveContext };
        }

        // Get relevant history based on content
        const relevantHistory = this._getRelevantHistory(session, exerciseType, content);

        return {
            history: relevantHistory,
            progressiveContext: session.progressiveContext,
            typeSpecificContext: this._getTypeSpecificContext(session, exerciseType, content)
        };
    }

    /**
     * Get full session history
     * @param {string} sessionId - Session ID (optional, defaults to current)
     * @returns {Array} - Session interaction history
     */
    getSessionHistory(sessionId = null) {
        const targetSessionId = sessionId || this.currentSessionId;

        if (!targetSessionId || !this.sessions.has(targetSessionId)) {
            return [];
        }

        return this.sessions.get(targetSessionId).interactions;
    }

    /**
     * Get context summary for LLM prompts
     * @param {string} exerciseType - Type of current exercise
     * @param {Object} content - Current exercise content
     * @returns {string} - Formatted context summary
     */
    getContextSummary(exerciseType, content = {}) {
        const context = this.getContextForType(exerciseType, content);

        if (!context.history.length) {
            return 'No previous context.';
        }

        // Format recent relevant interactions for LLM
        const recentInteractions = context.history.slice(-5); // Last 5 relevant interactions
        const summary = recentInteractions.map(interaction => {
            const score = interaction.validation.score || 'N/A';
            const correct = interaction.validation.correct ? '✅' : '❌';
            return `${interaction.type}: "${interaction.userResponse}" ${correct} (${score})`;
        }).join('\n');

        // Add progressive context if applicable
        let progressiveInfo = '';
        if (context.progressiveContext.accumulatedSentences.length > 0) {
            progressiveInfo = `\nProgressive text context: ${context.progressiveContext.accumulatedSentences.length} previous sentences`;
        }

        return `Recent context:\n${summary}${progressiveInfo}`;
    }

    /**
     * Clear session data
     * @param {string} sessionId - Session to clear (optional, defaults to current)
     */
    clearSession(sessionId = null) {
        const targetSessionId = sessionId || this.currentSessionId;

        if (this.sessions.has(targetSessionId)) {
            this.sessions.delete(targetSessionId);
            console.log(`🧹 Context memory cleared for session: ${targetSessionId}`);
        }

        if (targetSessionId === this.currentSessionId) {
            this.currentSessionId = null;
        }
    }

    /**
     * Get memory statistics
     * @returns {Object} - Memory usage statistics
     */
    getStats() {
        return {
            activeSessions: this.sessions.size,
            currentSessionId: this.currentSessionId,
            currentSessionInteractions: this.currentSessionId ?
                this.sessions.get(this.currentSessionId)?.interactions.length || 0 : 0,
            totalInteractions: Array.from(this.sessions.values())
                .reduce((total, session) => total + session.interactions.length, 0)
        };
    }

    // Private Methods

    _buildContextForType(session, interaction) {
        const { type, content } = interaction;
        const contextBuilder = session.contextBuilders[type];

        if (!contextBuilder) return;

        // Create or update type-specific context
        switch (type) {
            case 'vocabulary':
                this._buildVocabularyContext(contextBuilder, interaction);
                break;
            case 'phrase':
                this._buildPhraseContext(contextBuilder, interaction);
                break;
            case 'text':
                this._buildTextContext(contextBuilder, interaction);
                break;
            case 'audio':
                this._buildAudioContext(contextBuilder, interaction);
                break;
            case 'image':
                this._buildImageContext(contextBuilder, interaction);
                break;
            case 'grammar':
                this._buildGrammarContext(contextBuilder, interaction);
                break;
        }
    }

    _buildVocabularyContext(contextBuilder, interaction) {
        const words = interaction.content.vocabulary || [];

        words.forEach(wordData => {
            const word = wordData.word;
            if (!contextBuilder.has(word)) {
                contextBuilder.set(word, []);
            }
            contextBuilder.get(word).push({
                timestamp: interaction.timestamp,
                userResponse: interaction.userResponse,
                validation: interaction.validation,
                attempts: contextBuilder.get(word).length + 1
            });
        });
    }

    _buildPhraseContext(contextBuilder, interaction) {
        const phraseKey = interaction.content.phrase?.id ||
                         interaction.content.phrase?.english ||
                         `phrase_${interaction.timestamp}`;

        if (!contextBuilder.has(phraseKey)) {
            contextBuilder.set(phraseKey, []);
        }

        contextBuilder.get(phraseKey).push({
            timestamp: interaction.timestamp,
            userResponse: interaction.userResponse,
            validation: interaction.validation,
            attempts: contextBuilder.get(phraseKey).length + 1
        });
    }

    _buildTextContext(contextBuilder, interaction) {
        const textKey = interaction.content.text?.id ||
                       `text_${interaction.content.textIndex || 0}`;

        if (!contextBuilder.has(textKey)) {
            contextBuilder.set(textKey, {
                sentences: [],
                responses: []
            });
        }

        const textContext = contextBuilder.get(textKey);
        textContext.responses.push({
            timestamp: interaction.timestamp,
            sentenceIndex: interaction.content.sentenceIndex || 0,
            userResponse: interaction.userResponse,
            validation: interaction.validation
        });
    }

    _buildAudioContext(contextBuilder, interaction) {
        const audioKey = interaction.content.audio?.id ||
                        `audio_${interaction.timestamp}`;

        if (!contextBuilder.has(audioKey)) {
            contextBuilder.set(audioKey, []);
        }

        contextBuilder.get(audioKey).push({
            timestamp: interaction.timestamp,
            userResponse: interaction.userResponse,
            validation: interaction.validation,
            comprehensionLevel: interaction.validation.score || 0
        });
    }

    _buildImageContext(contextBuilder, interaction) {
        const imageKey = interaction.content.image?.id ||
                        `image_${interaction.timestamp}`;

        if (!contextBuilder.has(imageKey)) {
            contextBuilder.set(imageKey, []);
        }

        contextBuilder.get(imageKey).push({
            timestamp: interaction.timestamp,
            userResponse: interaction.userResponse,
            validation: interaction.validation,
            vocabularyUsed: interaction.validation.vocabularyUsed || []
        });
    }

    _buildGrammarContext(contextBuilder, interaction) {
        const grammarConcepts = interaction.content.grammarConcepts || ['general'];

        grammarConcepts.forEach(concept => {
            if (!contextBuilder.has(concept)) {
                contextBuilder.set(concept, []);
            }
            contextBuilder.get(concept).push({
                timestamp: interaction.timestamp,
                userResponse: interaction.userResponse,
                validation: interaction.validation,
                errors: interaction.validation.grammarErrors || [],
                strengths: interaction.validation.grammarStrengths || []
            });
        });
    }

    _buildProgressiveContext(session, interaction) {
        const { type, content } = interaction;
        const progressive = session.progressiveContext;

        // Handle text progression (sentence by sentence)
        if (type === 'text') {
            const textId = content.text?.id || `text_${content.textIndex || 0}`;

            if (progressive.currentText !== textId) {
                // New text - reset accumulated sentences
                progressive.currentText = textId;
                progressive.accumulatedSentences = [];
            }

            // Add current sentence to accumulation
            if (content.sentence) {
                progressive.accumulatedSentences.push({
                    index: content.sentenceIndex || progressive.accumulatedSentences.length,
                    sentence: content.sentence,
                    userResponse: interaction.userResponse,
                    validation: interaction.validation,
                    timestamp: interaction.timestamp
                });
            }
        }

        // Handle dialog progression
        if (type === 'dialog') {
            const dialogId = content.dialog?.id || `dialog_${content.dialogIndex || 0}`;

            if (progressive.currentDialog !== dialogId) {
                progressive.currentDialog = dialogId;
                progressive.accumulatedDialogLines = [];
            }

            if (content.line) {
                progressive.accumulatedDialogLines.push({
                    index: content.lineIndex || progressive.accumulatedDialogLines.length,
                    line: content.line,
                    userResponse: interaction.userResponse,
                    validation: interaction.validation,
                    timestamp: interaction.timestamp
                });
            }
        }

        // Track learning path
        progressive.learningPath.push({
            type,
            timestamp: interaction.timestamp,
            success: interaction.validation.correct || false,
            score: interaction.validation.score || 0
        });
    }

    _getRelevantHistory(session, exerciseType, content) {
        // Get recent interactions of the same type
        return session.interactions
            .filter(interaction => interaction.type === exerciseType)
            .slice(-10) // Last 10 interactions of this type
            .map(interaction => ({
                timestamp: interaction.timestamp,
                userResponse: interaction.userResponse,
                validation: interaction.validation,
                content: interaction.content
            }));
    }

    _getTypeSpecificContext(session, exerciseType, content) {
        const contextBuilder = session.contextBuilders[exerciseType];
        if (!contextBuilder) return {};

        // Return type-specific context based on current content
        const context = {};

        // Add relevant context based on exercise type and content
        if (exerciseType === 'text' && session.progressiveContext.currentText) {
            context.previousSentences = session.progressiveContext.accumulatedSentences;
        }

        if (exerciseType === 'dialog' && session.progressiveContext.currentDialog) {
            context.previousLines = session.progressiveContext.accumulatedDialogLines;
        }

        return context;
    }

    _maintainHistoryLimits(session) {
        // Limit interaction history to prevent memory bloat
        if (session.interactions.length > this.maxHistoryLength) {
            session.interactions = session.interactions.slice(-this.maxHistoryLength);
        }

        // Clean up old context builders
        Object.values(session.contextBuilders).forEach(builder => {
            if (builder instanceof Map) {
                builder.forEach((value, key) => {
                    if (Array.isArray(value) && value.length > 20) {
                        // Keep only recent 20 entries per item
                        builder.set(key, value.slice(-20));
                    }
                });
            }
        });

        // Limit progressive context
        if (session.progressiveContext.accumulatedSentences.length > 10) {
            session.progressiveContext.accumulatedSentences =
                session.progressiveContext.accumulatedSentences.slice(-10);
        }

        if (session.progressiveContext.learningPath.length > 50) {
            session.progressiveContext.learningPath =
                session.progressiveContext.learningPath.slice(-50);
        }
    }

    /**
     * Cleanup all sessions
     */
    cleanup() {
        this.sessions.clear();
        this.currentSessionId = null;
        console.log('🧹 Context memory completely cleared');
    }
}

export default ContextMemory;