/**
 * OpenResponseModule - Free-form open response exercises with AI validation
 * Allows students to write free-text responses that are evaluated by AI
 * Implements DRSExerciseInterface for strict contract enforcement
 */

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

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

        // Validate dependencies
        if (!orchestrator || !llmValidator || !prerequisiteEngine || !contextMemory) {
            throw new Error('OpenResponseModule requires all service dependencies');
        }

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

        // Module state
        this.initialized = false;
        this.container = null;
        this.currentExerciseData = null;
        this.currentQuestion = null;
        this.userResponse = '';
        this.validationInProgress = false;
        this.lastValidationResult = null;

        // Configuration
        this.config = {
            requiredProvider: 'openai', // Open response needs good comprehension
            model: 'gpt-4o-mini',
            temperature: 0.2, // Low for consistent evaluation
            maxTokens: 1000,
            timeout: 45000,
            minResponseLength: 10, // Minimum characters for response
            maxResponseLength: 2000, // Maximum characters for response
            allowMultipleAttempts: true,
            feedbackDepth: 'detailed' // detailed, brief, or minimal
        };

        // Progress tracking
        this.progress = {
            questionsAnswered: 0,
            questionsCorrect: 0,
            averageScore: 0,
            totalAttempts: 0,
            timeSpent: 0,
            startTime: null
        };
    }

    /**
     * Check if module can run with given content
     */
    canRun(prerequisites, chapterContent) {
        // Can run with any content - will generate open questions
        return chapterContent && (
            chapterContent.vocabulary ||
            chapterContent.texts ||
            chapterContent.phrases ||
            chapterContent.grammar
        );
    }

    /**
     * Present the open response exercise
     */
    async present(container, exerciseData) {
        this.container = container;
        this.currentExerciseData = exerciseData;
        this.progress.startTime = Date.now();

        console.log('📝 Starting Open Response exercise...');

        // Generate or select question
        await this._generateQuestion();

        // Create UI
        this._createExerciseInterface();

        this.initialized = true;
    }

    /**
     * Validate user response using AI
     */
    async validate(userInput, context) {
        if (this.validationInProgress) {
            return { score: 0, feedback: 'Validation already in progress', isCorrect: false };
        }

        this.validationInProgress = true;
        this.userResponse = userInput.trim();

        try {
            // Basic validation
            if (this.userResponse.length < this.config.minResponseLength) {
                return {
                    score: 0,
                    feedback: `Response too short. Please provide at least ${this.config.minResponseLength} characters.`,
                    isCorrect: false,
                    suggestions: ['Try to elaborate more on your answer', 'Provide more details and examples']
                };
            }

            if (this.userResponse.length > this.config.maxResponseLength) {
                return {
                    score: 0,
                    feedback: `Response too long. Please keep it under ${this.config.maxResponseLength} characters.`,
                    isCorrect: false,
                    suggestions: ['Try to be more concise', 'Focus on the main points']
                };
            }

            // AI validation
            const aiResult = await this._validateWithAI();

            // Update progress
            this._updateProgress(aiResult);

            this.lastValidationResult = aiResult;
            return aiResult;

        } catch (error) {
            console.error('Open response validation error:', error);
            return {
                score: 0.5,
                feedback: 'Unable to validate response. Please try again.',
                isCorrect: false,
                error: error.message
            };
        } finally {
            this.validationInProgress = false;
        }
    }

    /**
     * Get current progress
     */
    getProgress() {
        const timeSpent = this.progress.startTime ? Date.now() - this.progress.startTime : 0;

        return {
            type: 'open-response',
            questionsAnswered: this.progress.questionsAnswered,
            questionsCorrect: this.progress.questionsCorrect,
            accuracy: this.progress.questionsAnswered > 0 ?
                this.progress.questionsCorrect / this.progress.questionsAnswered : 0,
            averageScore: this.progress.averageScore,
            timeSpent: timeSpent,
            currentQuestion: this.currentQuestion?.question,
            responseLength: this.userResponse.length
        };
    }

    /**
     * Get module metadata
     */
    getMetadata() {
        return {
            name: 'Open Response',
            type: 'open-response',
            difficulty: 'advanced',
            estimatedTime: 300, // 5 minutes per question
            capabilities: ['creative_writing', 'comprehension', 'analysis'],
            prerequisites: ['basic_vocabulary']
        };
    }

    /**
     * Cleanup module
     */
    cleanup() {
        if (this.container) {
            this.container.innerHTML = '';
        }
        this.initialized = false;
        this.validationInProgress = false;
    }

    // Private methods

    /**
     * Generate open response question
     */
    async _generateQuestion() {
        const chapterContent = this.currentExerciseData.chapterContent || {};

        // Question types based on available content
        const questionTypes = [];

        if (chapterContent.vocabulary) {
            questionTypes.push('vocabulary_usage', 'vocabulary_explanation');
        }

        if (chapterContent.texts) {
            questionTypes.push('text_comprehension', 'text_analysis');
        }

        if (chapterContent.phrases) {
            questionTypes.push('phrase_creation', 'situation_usage');
        }

        if (chapterContent.grammar) {
            questionTypes.push('grammar_explanation', 'grammar_examples');
        }

        // Fallback questions
        if (questionTypes.length === 0) {
            questionTypes.push('general_discussion', 'opinion_question');
        }

        const selectedType = questionTypes[Math.floor(Math.random() * questionTypes.length)];
        this.currentQuestion = await this._createQuestionByType(selectedType, chapterContent);
    }

    /**
     * Create question based on type
     */
    async _createQuestionByType(type, content) {
        const questions = {
            vocabulary_usage: {
                question: this._createVocabularyUsageQuestion(content.vocabulary),
                type: 'vocabulary',
                expectedLength: 100,
                criteria: ['correct_word_usage', 'context_appropriateness', 'grammar']
            },
            vocabulary_explanation: {
                question: this._createVocabularyExplanationQuestion(content.vocabulary),
                type: 'vocabulary',
                expectedLength: 150,
                criteria: ['accuracy', 'clarity', 'examples']
            },
            text_comprehension: {
                question: this._createTextComprehensionQuestion(content.texts),
                type: 'comprehension',
                expectedLength: 200,
                criteria: ['understanding', 'details', 'inference']
            },
            phrase_creation: {
                question: this._createPhraseCreationQuestion(content.phrases),
                type: 'creative',
                expectedLength: 150,
                criteria: ['creativity', 'relevance', 'grammar']
            },
            grammar_explanation: {
                question: this._createGrammarExplanationQuestion(content.grammar),
                type: 'grammar',
                expectedLength: 180,
                criteria: ['accuracy', 'examples', 'clarity']
            },
            general_discussion: {
                question: this._createGeneralDiscussionQuestion(),
                type: 'discussion',
                expectedLength: 200,
                criteria: ['coherence', 'development', 'language_use']
            }
        };

        return questions[type] || questions.general_discussion;
    }

    _createVocabularyUsageQuestion(vocabulary) {
        if (!vocabulary || Object.keys(vocabulary).length === 0) {
            return "Describe your daily routine using as much detail as possible.";
        }

        const words = Object.keys(vocabulary);
        const selectedWords = words.slice(0, 3).join(', ');

        return `Write a short paragraph using these words: ${selectedWords}. Make sure to use each word correctly in context.`;
    }

    _createVocabularyExplanationQuestion(vocabulary) {
        if (!vocabulary || Object.keys(vocabulary).length === 0) {
            return "Explain the difference between 'house' and 'home' and give examples.";
        }

        const words = Object.keys(vocabulary);
        const selectedWord = words[Math.floor(Math.random() * words.length)];

        return `Explain the meaning of "${selectedWord}" and provide at least two example sentences showing how to use it.`;
    }

    _createTextComprehensionQuestion(texts) {
        if (!texts || texts.length === 0) {
            return "Describe a memorable experience you had and explain why it was important to you.";
        }

        return "Based on the chapter content, what are the main themes discussed and how do they relate to everyday life?";
    }

    _createPhraseCreationQuestion(phrases) {
        if (!phrases || Object.keys(phrases).length === 0) {
            return "Create a dialogue between two people meeting for the first time.";
        }

        return "Using the phrases from this chapter, write a short conversation that might happen in a real-life situation.";
    }

    _createGrammarExplanationQuestion(grammar) {
        if (!grammar || Object.keys(grammar).length === 0) {
            return "Explain when to use 'a' vs 'an' and give three examples of each.";
        }

        const concepts = Object.keys(grammar);
        const selectedConcept = concepts[Math.floor(Math.random() * concepts.length)];

        return `Explain the grammar rule for "${selectedConcept}" and provide examples showing correct and incorrect usage.`;
    }

    _createGeneralDiscussionQuestion() {
        const questions = [
            "What advice would you give to someone learning English for the first time?",
            "Describe your ideal weekend and explain why these activities appeal to you.",
            "What are the advantages and disadvantages of living in a big city?",
            "How has technology changed the way people communicate?",
            "What qualities make a good friend? Explain with examples."
        ];

        return questions[Math.floor(Math.random() * questions.length)];
    }

    /**
     * Validate response with AI
     */
    async _validateWithAI() {
        const prompt = this._buildValidationPrompt();

        try {
            const result = await this.llmValidator.validateAnswer(
                this.currentQuestion.question,
                this.userResponse,
                {
                    provider: this.config.requiredProvider,
                    model: this.config.model,
                    temperature: this.config.temperature,
                    maxTokens: this.config.maxTokens,
                    timeout: this.config.timeout,
                    context: prompt
                }
            );

            return this._parseAIResponse(result);

        } catch (error) {
            console.error('AI validation failed:', error);
            throw error;
        }
    }

    _buildValidationPrompt() {
        return `
You are evaluating an open response answer from an English language learner.

Question: "${this.currentQuestion.question}"
Student Response: "${this.userResponse}"

Evaluation Criteria:
- ${this.currentQuestion.criteria.join('\n- ')}

Expected Response Length: ~${this.currentQuestion.expectedLength} characters
Actual Response Length: ${this.userResponse.length} characters

Please evaluate the response and provide:
1. A score from 0.0 to 1.0
2. Detailed feedback on strengths and areas for improvement
3. Specific suggestions for enhancement
4. Whether the response adequately addresses the question

Format your response as:
[score]0.85
[feedback]Your response shows good understanding... [detailed feedback]
[suggestions]Consider adding more examples... [specific suggestions]
[correct]yes/no
        `.trim();
    }

    _parseAIResponse(aiResult) {
        try {
            const response = aiResult.response || '';

            // Extract score
            const scoreMatch = response.match(/\[score\]([\d.]+)/);
            const score = scoreMatch ? parseFloat(scoreMatch[1]) : 0.5;

            // Extract feedback
            const feedbackMatch = response.match(/\[feedback\](.*?)\[suggestions\]/s);
            const feedback = feedbackMatch ? feedbackMatch[1].trim() : 'Response evaluated';

            // Extract suggestions
            const suggestionsMatch = response.match(/\[suggestions\](.*?)\[correct\]/s);
            const suggestions = suggestionsMatch ? suggestionsMatch[1].trim().split('\n') : [];

            // Extract correctness
            const correctMatch = response.match(/\[correct\](yes|no)/i);
            const isCorrect = correctMatch ? correctMatch[1].toLowerCase() === 'yes' : score >= 0.7;

            return {
                score,
                feedback,
                suggestions: suggestions.filter(s => s.trim().length > 0),
                isCorrect,
                criteria: this.currentQuestion.criteria,
                questionType: this.currentQuestion.type,
                aiProvider: this.config.requiredProvider
            };

        } catch (error) {
            console.error('Error parsing AI response:', error);
            return {
                score: 0.5,
                feedback: 'Unable to parse evaluation. Please try again.',
                suggestions: [],
                isCorrect: false,
                error: 'parsing_error'
            };
        }
    }

    /**
     * Create exercise interface
     */
    _createExerciseInterface() {
        this.container.innerHTML = `
            <div class="open-response-exercise">
                <div class="exercise-header">
                    <h2>📝 Open Response</h2>
                    <div class="exercise-meta">
                        <span class="question-type">${this.currentQuestion.type}</span>
                        <span class="expected-length">Target: ~${this.currentQuestion.expectedLength} chars</span>
                    </div>
                </div>

                <div class="question-section">
                    <div class="question-text">
                        ${this.currentQuestion.question}
                    </div>

                    <div class="criteria-info">
                        <strong>Evaluation criteria:</strong>
                        <ul>
                            ${this.currentQuestion.criteria.map(c => `<li>${c.replace(/_/g, ' ')}</li>`).join('')}
                        </ul>
                    </div>
                </div>

                <div class="response-section">
                    <textarea
                        id="open-response-input"
                        placeholder="Write your response here..."
                        maxlength="${this.config.maxResponseLength}"
                    ></textarea>

                    <div class="response-meta">
                        <span id="character-count">0 / ${this.config.maxResponseLength}</span>
                        <span class="min-length">Minimum: ${this.config.minResponseLength} characters</span>
                    </div>
                </div>

                <div class="action-section">
                    <button id="validate-response" class="btn btn-primary" disabled>
                        Submit Response
                    </button>
                    <button id="clear-response" class="btn btn-secondary">
                        Clear
                    </button>
                </div>

                <div id="validation-result" class="validation-result" style="display: none;">
                    <!-- Validation results will appear here -->
                </div>
            </div>
        `;

        this._attachEventListeners();
    }

    _attachEventListeners() {
        const textarea = document.getElementById('open-response-input');
        const validateBtn = document.getElementById('validate-response');
        const clearBtn = document.getElementById('clear-response');
        const charCount = document.getElementById('character-count');

        if (textarea) {
            textarea.addEventListener('input', (e) => {
                const length = e.target.value.length;
                charCount.textContent = `${length} / ${this.config.maxResponseLength}`;

                // Enable/disable submit button
                validateBtn.disabled = length < this.config.minResponseLength;

                // Update character count color
                if (length < this.config.minResponseLength) {
                    charCount.style.color = '#dc3545';
                } else if (length > this.config.maxResponseLength * 0.9) {
                    charCount.style.color = '#ffc107';
                } else {
                    charCount.style.color = '#28a745';
                }
            });
        }

        if (validateBtn) {
            validateBtn.addEventListener('click', async () => {
                await this._handleValidation();
            });
        }

        if (clearBtn) {
            clearBtn.addEventListener('click', () => {
                textarea.value = '';
                textarea.dispatchEvent(new Event('input'));
                document.getElementById('validation-result').style.display = 'none';
            });
        }
    }

    async _handleValidation() {
        const textarea = document.getElementById('open-response-input');
        const validateBtn = document.getElementById('validate-response');
        const resultDiv = document.getElementById('validation-result');

        validateBtn.disabled = true;
        validateBtn.textContent = 'Validating...';

        try {
            const result = await this.validate(textarea.value, {});
            this._displayValidationResult(result);
        } catch (error) {
            console.error('Validation error:', error);
            this._displayValidationResult({
                score: 0,
                feedback: 'Error validating response. Please try again.',
                isCorrect: false,
                suggestions: []
            });
        } finally {
            validateBtn.disabled = false;
            validateBtn.textContent = 'Submit Response';
        }
    }

    _displayValidationResult(result) {
        const resultDiv = document.getElementById('validation-result');

        const scorePercentage = Math.round(result.score * 100);
        const scoreClass = result.isCorrect ? 'success' : (result.score >= 0.5 ? 'warning' : 'error');

        resultDiv.innerHTML = `
            <div class="result-header ${scoreClass}">
                <div class="score-display">
                    <span class="score-value">${scorePercentage}%</span>
                    <span class="score-label">${result.isCorrect ? 'Good Response!' : 'Needs Improvement'}</span>
                </div>
            </div>

            <div class="feedback-section">
                <h4>Feedback:</h4>
                <p>${result.feedback}</p>
            </div>

            ${result.suggestions && result.suggestions.length > 0 ? `
                <div class="suggestions-section">
                    <h4>Suggestions for improvement:</h4>
                    <ul>
                        ${result.suggestions.map(s => `<li>${s}</li>`).join('')}
                    </ul>
                </div>
            ` : ''}

            <div class="result-actions">
                <button id="try-again" class="btn btn-secondary">Try Again</button>
                <button id="next-question" class="btn btn-primary">Next Question</button>
            </div>
        `;

        resultDiv.style.display = 'block';

        // Attach action handlers
        document.getElementById('try-again')?.addEventListener('click', () => {
            resultDiv.style.display = 'none';
        });

        document.getElementById('next-question')?.addEventListener('click', () => {
            this._nextQuestion();
        });
    }

    async _nextQuestion() {
        await this._generateQuestion();
        this._createExerciseInterface();
    }

    _updateProgress(result) {
        this.progress.questionsAnswered++;
        this.progress.totalAttempts++;

        if (result.isCorrect) {
            this.progress.questionsCorrect++;
        }

        // Update average score
        const previousTotal = this.progress.averageScore * (this.progress.questionsAnswered - 1);
        this.progress.averageScore = (previousTotal + result.score) / this.progress.questionsAnswered;
    }

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

    async init(config = {}, content = {}) {
        this.config = { ...this.config, ...config };
        this.currentExerciseData = content;
        this.startTime = Date.now();
        this.initialized = true;
    }

    async render(container) {
        if (!this.initialized) throw new Error('OpenResponseModule must be initialized before rendering');
        await this.present(container, this.currentExerciseData);
    }

    async destroy() {
        this.cleanup?.();
        this.container = null;
        this.initialized = false;
    }

    getResults() {
        const totalQuestions = this.questions ? this.questions.length : 0;
        const answeredQuestions = this.userResponses ? this.userResponses.length : 0;
        const score = this.progress ? Math.round(this.progress.averageScore * 100) : 0;

        return {
            score,
            attempts: answeredQuestions,
            timeSpent: this.startTime ? Date.now() - this.startTime : 0,
            completed: answeredQuestions >= totalQuestions,
            details: {
                totalQuestions,
                answeredQuestions,
                averageScore: this.progress?.averageScore || 0,
                responses: this.userResponses || []
            }
        };
    }

    handleUserInput(event, data) {
        if (event && event.type === 'input') this._handleInputChange?.(event);
        if (event && event.type === 'click' && event.target.id === 'submitButton') this._handleSubmit?.(event);
    }

    async markCompleted(results) {
        const { score, details } = results || this.getResults();
        if (this.contextMemory) {
            this.contextMemory.recordInteraction({
                type: 'open-response',
                subtype: 'completion',
                content: { questions: this.questions },
                userResponse: this.userResponses,
                validation: { score, averageScore: details.averageScore },
                context: { moduleType: 'open-response', totalQuestions: details.totalQuestions }
            });
        }
    }

    getExerciseType() {
        return 'open-response';
    }

    getExerciseConfig() {
        const questionCount = this.questions ? this.questions.length : this.config?.questionsPerExercise || 2;
        return {
            type: this.getExerciseType(),
            difficulty: this.currentExerciseData?.difficulty || 'medium',
            estimatedTime: questionCount * 3, // 3 min per question
            prerequisites: [],
            metadata: { ...this.config, questionCount, requiresAI: true }
        };
    }
}

export default OpenResponseModule;