# app.py - Versão Final com Respostas V/F em Português

# --- 1. Importações ---
import os
from dotenv import load_dotenv
from functools import wraps
from flask import Flask, request, render_template_string, session, redirect, url_for, jsonify
import json

# Carrega as variáveis do ficheiro .env
load_dotenv()

# --- 2. Configuração da Aplicação ---
SECRET_KEY = os.getenv('SECRET_KEY', 'default_secret_key_change_me')
LTI_CONSUMER_KEY_ESPERADA = os.getenv('LTI_CONSUMER_KEY', 'default_key')
MOODLE_URL = os.getenv('MOODLE_URL', 'https://lms.ed-consulting.ao')

# Inicializar app Flask
app = Flask(__name__)
app.secret_key = SECRET_KEY

# --- 3. Módulos da Aplicação ---
from src.question_generation import QuestionGenerator
from src.grading import Grader

try:
    question_generator = QuestionGenerator()
except Exception as e:
    print(f"Aviso: Falha ao inicializar QuestionGenerator: {e}")
    question_generator = None

grader = Grader()

# --- 4. Segurança para Iframe ---
@app.after_request
def add_security_headers(response):
    response.headers['Content-Security-Policy'] = f"frame-ancestors 'self' {MOODLE_URL};"
    return response

# --- 5. Autenticação LTI (Manual e Simplificada) ---
def login_required(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        if not session.get("lti_user_id"):
            return "Acesso Negado. Esta aplicação deve ser iniciada a partir do Moodle.", 403
        return f(*args, **kwargs)
    return wrapper

@app.route('/launch', methods=['POST'])
def launch():
    """ Rota de entrada do Moodle com validação manual. """
    try:
        consumer_key_recebida = request.form.get('oauth_consumer_key')
        user_id = request.form.get('user_id')
        user_fullname = request.form.get('lis_person_name_full')
        return_url = request.form.get('launch_presentation_return_url')

        if consumer_key_recebida == LTI_CONSUMER_KEY_ESPERADA:
            session["lti_user_id"] = user_id
            session["lti_user_fullname"] = user_fullname
            session['launch_presentation_return_url'] = return_url
            return redirect(url_for("index"))
        else:
            print(f"ERRO: Chave do consumidor inválida. Esperada='{LTI_CONSUMER_KEY_ESPERADA}', Recebida='{consumer_key_recebida}'")
            return "Erro de autenticação LTI: Chave do consumidor inválida.", 401

    except Exception as e:
        print(f"ERRO na rota /launch: {str(e)}")
        return "Ocorreu um erro interno durante o processo de autenticação.", 500

@app.route("/logout")
def logout():
    """ Função chamada pelo temporizador de inatividade para fazer logout do Moodle. """
    session.clear()
    moodle_base_url = MOODLE_URL.rstrip('/')
    moodle_logout_url = f"{moodle_base_url}/login/logout.php"
    return redirect(moodle_logout_url)

# --- 6. Rotas da Aplicação (Páginas e API) ---
@app.route('/')
@login_required
def index():
    user_name = session.get('lti_user_fullname', 'Utilizador')
    return_url = session.get('launch_presentation_return_url', '#')
    
    return render_template_string("""
<!DOCTYPE html>
<html lang="pt">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sistema de Auto-Avaliação</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; background-color: #f5f5f5; }
        .header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #ddd; padding-bottom: 10px; margin-bottom: 20px; }
        .header h1 { margin: 0; font-size: 24px; }
        .container { background-color: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        h1 { color: #333; text-align: center; margin-bottom: 30px; }
        .section { margin-bottom: 30px; padding: 20px; border: 1px solid #ddd; border-radius: 5px; }
        .section h2 { color: #555; margin-top: 0; }
        textarea, input[type="text"], select { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
        button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; margin: 5px; text-decoration: none; display: inline-block; font-size: 14px; }
        button:hover { background-color: #0056b3; }
        .return-button {
            background-color: #6c757d; color: white; padding: 10px 15px;
            text-decoration: none; border-radius: 4px; font-size: 14px;
        }
        .return-button:hover { background-color: #5a6268; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <div>
                <h1>Sistema de Auto-Avaliação</h1>
                <p>Bem-vindo, {{user_name}}!</p>
            </div>
            <div>
                <a href="{{ return_url }}" class="return-button">Voltar à Plataforma</a>
            </div>
        </div>
        <div class="section">
            <h2>1. Gerar Perguntas</h2>
            <textarea id="textContent" placeholder="Inserir o conteúdo do texto para gerar perguntas..." rows="6"></textarea>
            <select id="questionType">
                <option value="multiple_choice">Múltipla Escolha</option>
                <option value="true_false">Verdadeiro/Falso</option>
            </select>
            <select id="difficulty">
                <option value="easy">Fácil</option>
                <option value="medium">Médio</option>
                <option value="hard">Difícil</option>
            </select>
            <button onclick="generateQuestion()">Gerar Pergunta</button>
            <div id="questionResult" class="result" style="display:none;"></div>
        </div>
        <div class="section">
            <h2>2. Responder Pergunta</h2>
            <div id="questionDisplay" class="question-display" style="display:none;"></div>
            <input type="text" id="studentAnswer" placeholder="A sua resposta..." style="display:none;">
            <button id="submitAnswer" onclick="submitAnswer()" style="display:none;">Enviar Resposta</button>
            <div id="gradingResult" class="result" style="display:none;"></div>
        </div>
    </div>
    <script>
        let currentQuestion = null;
        async function generateQuestion() {
            const textContent = document.getElementById('textContent').value;
            const questionType = document.getElementById('questionType').value;
            const difficulty = document.getElementById('difficulty').value;
            if (!textContent.trim()) { alert('Por favor, insira o conteúdo do texto.'); return; }
            try {
                const response = await fetch('/generate_question', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({text_content: textContent, question_type: questionType, difficulty: difficulty})
                });
                const result = await response.json();
                if (result.success) {
                    currentQuestion = result.question;
                    displayQuestion(result.question);
                    document.getElementById('questionResult').style.display = 'block';
                    document.getElementById('questionResult').innerHTML = '<strong>Pergunta gerada com sucesso!</strong>';
                } else {
                    document.getElementById('questionResult').style.display = 'block';
                    document.getElementById('questionResult').innerHTML = '<strong>Erro:</strong> ' + result.error;
                }
            } catch (error) {
                document.getElementById('questionResult').style.display = 'block';
                document.getElementById('questionResult').innerHTML = '<strong>Erro:</strong> ' + error.message;
            }
        }
        function displayQuestion(question) {
            const questionDisplay = document.getElementById('questionDisplay');
            const studentAnswer = document.getElementById('studentAnswer');
            const submitButton = document.getElementById('submitAnswer');
            let html = '<h3>' + question.question + '</h3>';
            if (question.type === 'multiple_choice' && question.options) {
                html += '<div>';
                question.options.forEach((option, index) => {
                    const letter = String.fromCharCode(65 + index);
                    html += '<div><strong>' + letter + ')</strong> ' + option + '</div>';
                });
                html += '</div>';
                studentAnswer.placeholder = 'Insira a letra da opção: A, B, C ou D';
            } else if (question.type === 'true_false') {
                // MODIFICADO: Placeholder atualizado para Português
                studentAnswer.placeholder = 'Insira Verdadeiro ou Falso';
            }
            questionDisplay.innerHTML = html;
            questionDisplay.style.display = 'block';
            studentAnswer.style.display = 'block';
            submitButton.style.display = 'block';
            studentAnswer.value = '';
            document.getElementById('gradingResult').style.display = 'none';
        }
        async function submitAnswer() {
            const studentAnswer = document.getElementById('studentAnswer').value;
            if (!studentAnswer.trim()) { alert('Por favor, insira a sua resposta.'); return; }
            if (!currentQuestion) { alert('Não há pergunta para avaliar.'); return; }
            try {
                const response = await fetch('/grade_question', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({question: currentQuestion, student_answer: studentAnswer})
                });
                const result = await response.json();
                if (result.success) {
                    const gradingResult = document.getElementById('gradingResult');
                    const feedbackClass = result.grading.is_correct ? 'correct' : 'incorrect';
                    gradingResult.innerHTML = '<div class="feedback ' + feedbackClass + '">' + result.grading.feedback + '</div>';
                    document.getElementById('gradingResult').style.display = 'block';
                } else {
                    document.getElementById('gradingResult').innerHTML = '<strong>Erro:</strong> ' + result.error;
                    document.getElementById('gradingResult').style.display = 'block';
                }
            } catch (error) {
                document.getElementById('gradingResult').innerHTML = '<strong>Erro:</strong> ' + error.message;
                document.getElementById('gradingResult').style.display = 'block';
            }
        }
        let inactivityTimer;
        function logoutUser() { window.location.href = '/logout'; }
        function resetInactivityTimer() {
            clearTimeout(inactivityTimer);
            inactivityTimer = setTimeout(logoutUser, 300000); // 5 minutos
        }
        window.onload = resetInactivityTimer;
        document.onmousemove = resetInactivityTimer;
        document.onmousedown = resetInactivityTimer;
        document.ontouchstart = resetInactivityTimer;
        document.onclick = resetInactivityTimer;
        document.onkeydown = resetInactivityTimer;
        document.addEventListener('scroll', resetInactivityTimer, true);
    </script>
</body>
</html>
    """, user_name=user_name, return_url=return_url)

@app.route('/generate_question', methods=['POST'])
@login_required
def generate_question():
    try:
        data = request.json
        if not data.get('text_content'):
            return jsonify({'success': False, 'error': 'O conteúdo do texto é obrigatório'})
        if question_generator is None:
            return jsonify({'success': False, 'error': 'Gerador de perguntas não disponível. Verifique a OPENAI_API_KEY.'})
        question_json = question_generator.generate_question(data.get('text_content'), data.get('question_type', 'multiple_choice'), data.get('difficulty', 'medium'))
        if question_json:
            return jsonify({'success': True, 'question': json.loads(question_json)})
        else:
            return jsonify({'success': False, 'error': 'Falha ao gerar pergunta'})
    except Exception as e:
        return jsonify({'success': False, 'error': str(e)})

# --- MODIFICADO: Rota de Avaliação de Respostas ---
@app.route('/grade_question', methods=['POST'])
@login_required
def grade_question():
    try:
        data = request.json
        if not data.get('question') or not data.get('student_answer'):
            return jsonify({'success': False, 'error': 'A pergunta e a resposta do aluno são obrigatórias'})
        
        question = data.get('question')
        student_answer = data.get('student_answer')
        processed_answer = student_answer

        # --- LÓGICA DE TRADUÇÃO DA RESPOSTA ---
        # Se a pergunta for de verdadeiro/falso, converte a resposta para o formato esperado pelo avaliador.
        if question.get('type') == 'true_false':
            answer_lower = student_answer.strip().lower()
            if answer_lower in ['verdadeiro', 'v', 'true']:
                processed_answer = 'True'
            elif answer_lower in ['falso', 'f', 'false']:
                processed_answer = 'False'
        
        # Envia a resposta processada para o avaliador
        grading_result = grader.grade_question(question, processed_answer)
        return jsonify({'success': True, 'grading': grading_result})
    except Exception as e:
        return jsonify({'success': False, 'error': str(e)})

# --- 7. Execução da Aplicação ---
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

# app.py - Versão Final com Respostas V/F em Português

# --- 1. Importações ---
import os
from dotenv import load_dotenv
from functools import wraps
from flask import Flask, request, render_template_string, session, redirect, url_for, jsonify
import json

# Carrega as variáveis do ficheiro .env
load_dotenv()

# --- 2. Configuração da Aplicação ---
SECRET_KEY = os.getenv('SECRET_KEY', 'default_secret_key_change_me')
LTI_CONSUMER_KEY_ESPERADA = os.getenv('LTI_CONSUMER_KEY', 'default_key')
MOODLE_URL = os.getenv('MOODLE_URL', 'https://lms.ed-consulting.ao')

# Inicializar app Flask
app = Flask(__name__)
app.secret_key = SECRET_KEY

# --- 3. Módulos da Aplicação ---
from src.question_generation import QuestionGenerator
from src.grading import Grader

try:
    question_generator = QuestionGenerator()
except Exception as e:
    print(f"Aviso: Falha ao inicializar QuestionGenerator: {e}")
    question_generator = None

grader = Grader()

# --- 4. Segurança para Iframe ---
@app.after_request
def add_security_headers(response):
    response.headers['Content-Security-Policy'] = f"frame-ancestors 'self' {MOODLE_URL};"
    return response

# --- 5. Autenticação LTI (Manual e Simplificada) ---
def login_required(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        if not session.get("lti_user_id"):
            return "Acesso Negado. Esta aplicação deve ser iniciada a partir do Moodle.", 403
        return f(*args, **kwargs)
    return wrapper

@app.route('/launch', methods=['POST'])
def launch():
    """ Rota de entrada do Moodle com validação manual. """
    try:
        consumer_key_recebida = request.form.get('oauth_consumer_key')
        user_id = request.form.get('user_id')
        user_fullname = request.form.get('lis_person_name_full')
        return_url = request.form.get('launch_presentation_return_url')

        if consumer_key_recebida == LTI_CONSUMER_KEY_ESPERADA:
            session["lti_user_id"] = user_id
            session["lti_user_fullname"] = user_fullname
            session['launch_presentation_return_url'] = return_url
            return redirect(url_for("index"))
        else:
            print(f"ERRO: Chave do consumidor inválida. Esperada='{LTI_CONSUMER_KEY_ESPERADA}', Recebida='{consumer_key_recebida}'")
            return "Erro de autenticação LTI: Chave do consumidor inválida.", 401

    except Exception as e:
        print(f"ERRO na rota /launch: {str(e)}")
        return "Ocorreu um erro interno durante o processo de autenticação.", 500

@app.route("/logout")
def logout():
    """ Função chamada pelo temporizador de inatividade para fazer logout do Moodle. """
    session.clear()
    moodle_base_url = MOODLE_URL.rstrip('/')
    moodle_logout_url = f"{moodle_base_url}/login/logout.php"
    return redirect(moodle_logout_url)

# --- 6. Rotas da Aplicação (Páginas e API) ---
@app.route('/')
@login_required
def index():
    user_name = session.get('lti_user_fullname', 'Utilizador')
    return_url = session.get('launch_presentation_return_url', '#')
    
    return render_template_string("""
<!DOCTYPE html>
<html lang="pt">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sistema de Auto-Avaliação</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; background-color: #f5f5f5; }
        .header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #ddd; padding-bottom: 10px; margin-bottom: 20px; }
        .header h1 { margin: 0; font-size: 24px; }
        .container { background-color: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        h1 { color: #333; text-align: center; margin-bottom: 30px; }
        .section { margin-bottom: 30px; padding: 20px; border: 1px solid #ddd; border-radius: 5px; }
        .section h2 { color: #555; margin-top: 0; }
        textarea, input[type="text"], select { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
        button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; margin: 5px; text-decoration: none; display: inline-block; font-size: 14px; }
        button:hover { background-color: #0056b3; }
        .return-button {
            background-color: #6c757d; color: white; padding: 10px 15px;
            text-decoration: none; border-radius: 4px; font-size: 14px;
        }
        .return-button:hover { background-color: #5a6268; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <div>
                <h1>Sistema de Auto-Avaliação</h1>
                <p>Bem-vindo, {{user_name}}!</p>
            </div>
            <div>
                <a href="{{ return_url }}" class="return-button">Voltar à Plataforma</a>
            </div>
        </div>
        <div class="section">
            <h2>1. Gerar Perguntas</h2>
            <textarea id="textContent" placeholder="Inserir o conteúdo do texto para gerar perguntas..." rows="6"></textarea>
            <select id="questionType">
                <option value="multiple_choice">Múltipla Escolha</option>
                <option value="true_false">Verdadeiro/Falso</option>
            </select>
            <select id="difficulty">
                <option value="easy">Fácil</option>
                <option value="medium">Médio</option>
                <option value="hard">Difícil</option>
            </select>
            <button onclick="generateQuestion()">Gerar Pergunta</button>
            <div id="questionResult" class="result" style="display:none;"></div>
        </div>
        <div class="section">
            <h2>2. Responder Pergunta</h2>
            <div id="questionDisplay" class="question-display" style="display:none;"></div>
            <input type="text" id="studentAnswer" placeholder="A sua resposta..." style="display:none;">
            <button id="submitAnswer" onclick="submitAnswer()" style="display:none;">Enviar Resposta</button>
            <div id="gradingResult" class="result" style="display:none;"></div>
        </div>
    </div>
    <script>
        let currentQuestion = null;
        async function generateQuestion() {
            const textContent = document.getElementById('textContent').value;
            const questionType = document.getElementById('questionType').value;
            const difficulty = document.getElementById('difficulty').value;
            if (!textContent.trim()) { alert('Por favor, insira o conteúdo do texto.'); return; }
            try {
                const response = await fetch('/generate_question', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({text_content: textContent, question_type: questionType, difficulty: difficulty})
                });
                const result = await response.json();
                if (result.success) {
                    currentQuestion = result.question;
                    displayQuestion(result.question);
                    document.getElementById('questionResult').style.display = 'block';
                    document.getElementById('questionResult').innerHTML = '<strong>Pergunta gerada com sucesso!</strong>';
                } else {
                    document.getElementById('questionResult').style.display = 'block';
                    document.getElementById('questionResult').innerHTML = '<strong>Erro:</strong> ' + result.error;
                }
            } catch (error) {
                document.getElementById('questionResult').style.display = 'block';
                document.getElementById('questionResult').innerHTML = '<strong>Erro:</strong> ' + error.message;
            }
        }
        function displayQuestion(question) {
            const questionDisplay = document.getElementById('questionDisplay');
            const studentAnswer = document.getElementById('studentAnswer');
            const submitButton = document.getElementById('submitAnswer');
            let html = '<h3>' + question.question + '</h3>';
            if (question.type === 'multiple_choice' && question.options) {
                html += '<div>';
                question.options.forEach((option, index) => {
                    const letter = String.fromCharCode(65 + index);
                    html += '<div><strong>' + letter + ')</strong> ' + option + '</div>';
                });
                html += '</div>';
                studentAnswer.placeholder = 'Insira a letra da opção: A, B, C ou D';
            } else if (question.type === 'true_false') {
                // MODIFICADO: Placeholder atualizado para Português
                studentAnswer.placeholder = 'Insira Verdadeiro ou Falso';
            }
            questionDisplay.innerHTML = html;
            questionDisplay.style.display = 'block';
            studentAnswer.style.display = 'block';
            submitButton.style.display = 'block';
            studentAnswer.value = '';
            document.getElementById('gradingResult').style.display = 'none';
        }
        async function submitAnswer() {
            const studentAnswer = document.getElementById('studentAnswer').value;
            if (!studentAnswer.trim()) { alert('Por favor, insira a sua resposta.'); return; }
            if (!currentQuestion) { alert('Não há pergunta para avaliar.'); return; }
            try {
                const response = await fetch('/grade_question', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({question: currentQuestion, student_answer: studentAnswer})
                });
                const result = await response.json();
                if (result.success) {
                    const gradingResult = document.getElementById('gradingResult');
                    const feedbackClass = result.grading.is_correct ? 'correct' : 'incorrect';
                    gradingResult.innerHTML = '<div class="feedback ' + feedbackClass + '">' + result.grading.feedback + '</div>';
                    document.getElementById('gradingResult').style.display = 'block';
                } else {
                    document.getElementById('gradingResult').innerHTML = '<strong>Erro:</strong> ' + result.error;
                    document.getElementById('gradingResult').style.display = 'block';
                }
            } catch (error) {
                document.getElementById('gradingResult').innerHTML = '<strong>Erro:</strong> ' + error.message;
                document.getElementById('gradingResult').style.display = 'block';
            }
        }
        let inactivityTimer;
        function logoutUser() { window.location.href = '/logout'; }
        function resetInactivityTimer() {
            clearTimeout(inactivityTimer);
            inactivityTimer = setTimeout(logoutUser, 300000); // 5 minutos
        }
        window.onload = resetInactivityTimer;
        document.onmousemove = resetInactivityTimer;
        document.onmousedown = resetInactivityTimer;
        document.ontouchstart = resetInactivityTimer;
        document.onclick = resetInactivityTimer;
        document.onkeydown = resetInactivityTimer;
        document.addEventListener('scroll', resetInactivityTimer, true);
    </script>
</body>
</html>
    """, user_name=user_name, return_url=return_url)

@app.route('/generate_question', methods=['POST'])
@login_required
def generate_question():
    try:
        data = request.json
        if not data.get('text_content'):
            return jsonify({'success': False, 'error': 'O conteúdo do texto é obrigatório'})
        if question_generator is None:
            return jsonify({'success': False, 'error': 'Gerador de perguntas não disponível. Verifique a OPENAI_API_KEY.'})
        question_json = question_generator.generate_question(data.get('text_content'), data.get('question_type', 'multiple_choice'), data.get('difficulty', 'medium'))
        if question_json:
            return jsonify({'success': True, 'question': json.loads(question_json)})
        else:
            return jsonify({'success': False, 'error': 'Falha ao gerar pergunta'})
    except Exception as e:
        return jsonify({'success': False, 'error': str(e)})

# --- MODIFICADO: Rota de Avaliação de Respostas ---
@app.route('/grade_question', methods=['POST'])
@login_required
def grade_question():
    try:
        data = request.json
        if not data.get('question') or not data.get('student_answer'):
            return jsonify({'success': False, 'error': 'A pergunta e a resposta do aluno são obrigatórias'})
        
        question = data.get('question')
        student_answer = data.get('student_answer')
        processed_answer = student_answer

        # --- LÓGICA DE TRADUÇÃO DA RESPOSTA ---
        # Se a pergunta for de verdadeiro/falso, converte a resposta para o formato esperado pelo avaliador.
        if question.get('type') == 'true_false':
            answer_lower = student_answer.strip().lower()
            if answer_lower in ['verdadeiro', 'v', 'true']:
                processed_answer = 'True'
            elif answer_lower in ['falso', 'f', 'false']:
                processed_answer = 'False'
        
        # Envia a resposta processada para o avaliador
        grading_result = grader.grade_question(question, processed_answer)
        return jsonify({'success': True, 'grading': grading_result})
    except Exception as e:
        return jsonify({'success': False, 'error': str(e)})

# --- 7. Execução da Aplicação ---
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)


