# servidor_app.py
from flask import Flask, render_template, request, redirect, url_for, session, flash, jsonify
import mysql.connector
import random
import os
from datetime import datetime
from collections import defaultdict

app = Flask(__name__)
app.secret_key = os.urandom(24)

ADMIN_PASSWORD = "Admin_Teste_2@25"
SENHA_DO_EXAME = "Inicio_Teste_2@25"

db_config = {
    'host': '127.0.0.1',
    'user': 'teste_app',
    'password': 'N71j1ngl1c6n',
    'database': 'insutec_acesso'
}

def get_db_connection():
    try:
        conn = mysql.connector.connect(**db_config)
        return conn
    except mysql.connector.Error as err:
        print(f"Erro de Base de Dados: {err}")
        return None

# ... (O resto das suas rotas como login, logout, iniciar_teste, etc., permanecem iguais) ...
@app.route("/acesso-exame", methods=["GET", "POST"])
def acesso_exame():
    if request.method == "POST":
        senha_inserida = request.form.get('senha')
        if senha_inserida == SENHA_DO_EXAME:
            session['acesso_permitido'] = True
            return redirect(url_for('pagina_inscricao'))
        else:
            flash('Senha de acesso incorreta. Tente novamente.', 'error')
    return render_template("acesso_exame.html")

@app.route("/", methods=["GET"])
def pagina_inscricao():
    if session.get('acesso_permitido'):
        return render_template("inscricao.html")
    else:
        return redirect(url_for('acesso_exame'))

@app.route("/login", methods=["GET", "POST"])
def login():
    error = None
    if request.method == "POST":
        if request.form['password'] == ADMIN_PASSWORD:
            session['logged_in'] = True
            return redirect(url_for('painel_admin'))
        else:
            error = "Palavra-passe incorreta. Tente novamente."
    return render_template("login.html", error=error)

@app.route("/logout")
def logout():
    session.pop('logged_in', None)
    return redirect(url_for('login'))

@app.route("/iniciar-teste", methods=["POST"])
def iniciar_teste():
    numero_candidato = request.form['numero_candidato']
    nome_completo = request.form['nome_completo']
    curso_desejado = request.form['curso_desejado']

    conn = get_db_connection()
    if conn is None: return "<h1>Erro: Não foi possível ligar à base de dados.</h1>"
    cursor = conn.cursor(dictionary=True)

    sql_find_candidato_id = "SELECT id FROM candidatos WHERE numero_candidato = %s"
    cursor.execute(sql_find_candidato_id, (numero_candidato,))
    candidato_existente = cursor.fetchone()
    cursor.fetchall() 

    if candidato_existente:
        candidato_id_existente = candidato_existente['id']
        sql_check_resultado = "SELECT id FROM resultados WHERE candidato_id = %s"
        cursor.execute(sql_check_resultado, (candidato_id_existente,))
        resultado_existente = cursor.fetchone()
        cursor.fetchall() 
        if resultado_existente:
            cursor.close()
            conn.close()
            return render_template("acesso_negado.html")

    sql_insert_candidato = "INSERT IGNORE INTO candidatos (numero_candidato, nome_completo, curso_desejado) VALUES (%s, %s, %s)"
    cursor.execute(sql_insert_candidato, (numero_candidato, nome_completo, curso_desejado))
    conn.commit()
    candidato_id = cursor.lastrowid
    if candidato_id == 0:
        cursor.execute(sql_find_candidato_id, (numero_candidato,))
        candidato_existente = cursor.fetchone()
        candidato_id = candidato_existente['id']
        cursor.fetchall() 

    sql_select_teste = "SELECT id FROM testes WHERE curso_associado = %s LIMIT 1"
    cursor.execute(sql_select_teste, (curso_desejado,))
    resultado_teste = cursor.fetchone()
    cursor.fetchall() 

    if not resultado_teste:
        return f"<h1>Erro: Não existem testes disponíveis para o curso de {curso_desejado}.</h1>"
    teste_id = resultado_teste['id']
    
    cursor.close()
    conn.close()

    return render_template("regras.html",
                           candidato_id=candidato_id,
                           teste_id=teste_id,
                           nome_candidato=nome_completo,
                           numero_candidato=numero_candidato,
                           curso_desejado=curso_desejado)


@app.route("/comecar-exame", methods=["POST"])
def comecar_exame():
    candidato_id = request.form['candidato_id']
    teste_id = request.form['teste_id']
    nome_completo = request.form['nome_completo']
    numero_candidato = request.form['numero_candidato']
    curso_desejado = request.form['curso_desejado']

    conn = get_db_connection()
    if conn is None: return "<h1>Erro: Não foi possível ligar à base de dados.</h1>"
    cursor = conn.cursor(dictionary=True)

    perguntas_finais = []
    
    # Estrutura de perguntas para cada curso
    if curso_desejado == 'Ciências Criminais':
        categorias = {'Especialidade': 6, 'Língua Portuguesa': 4}
    elif curso_desejado == 'Hotelaria e Turismo':
        categorias = {'Língua Portuguesa': 4, 'Lógica': 2, 'Especialidade': 4}
    elif curso_desejado in ['Logística e Gestão Comercial', 'Contabilidade e Finanças']:
        categorias = {'Matemática': 6, 'Especialidade': 4}
    elif curso_desejado in ['Direito', 'Gestão de Recursos Humanos']:
        categorias = {'Língua Portuguesa': 6, 'Especialidade': 4}
    else: # Engenharias
        categorias = {'Matemática': 4, 'Lógica': 4, 'Especialidade': 2}

    categorias_necessarias = list(categorias.keys())
    placeholders = ','.join(['%s'] * len(categorias_necessarias))
    sql_todas_as_perguntas = f"""
        SELECT id, enunciado, opcao_a, opcao_b, opcao_c, opcao_d, categoria 
        FROM perguntas 
        WHERE teste_id = %s AND categoria IN ({placeholders})
    """
    params = [teste_id] + categorias_necessarias
    cursor.execute(sql_todas_as_perguntas, tuple(params))
    perguntas_disponiveis = cursor.fetchall()

    pool_por_categoria = {cat: [] for cat in categorias_necessarias}
    for p in perguntas_disponiveis:
        pool_por_categoria[p['categoria']].append(p)

    for categoria, limite in categorias.items():
        pool_da_categoria = pool_por_categoria.get(categoria, [])
        
        if len(pool_da_categoria) < limite:
            cursor.close()
            conn.close()
            return f"<h1>Erro: O banco de perguntas para '{curso_desejado}' não tem perguntas suficientes na categoria '{categoria}'. Precisa de {limite}, mas só existem {len(pool_da_categoria)}.</h1>"
        
        perguntas_selecionadas = random.sample(pool_da_categoria, limite)
        perguntas_finais.extend(perguntas_selecionadas)

    random.shuffle(perguntas_finais)
    
    cursor.close()
    conn.close()

    return render_template("teste.html", 
                           candidato_id=candidato_id,
                           teste_id=teste_id,
                           nome_candidato=nome_completo,
                           numero_candidato=numero_candidato,
                           curso=curso_desejado,
                           perguntas=perguntas_finais)

@app.route("/submeter-teste", methods=["POST"])
def submeter_teste():
    candidato_id = request.form['candidato_id']
    teste_id = request.form['teste_id']
    ordem_perguntas_str = request.form.get('ordem_perguntas', '')
    ordem_perguntas = ordem_perguntas_str.split(',')
    tentativa_fraude = request.form.get('tentativa_fraude', '0') == '1'
    conn = get_db_connection()
    if conn is None: return "<h1>Erro: Não foi possível ligar à base de dados.</h1>"
    cursor = conn.cursor(dictionary=True)

    sql_check_resultado = "SELECT id FROM resultados WHERE candidato_id = %s AND teste_id = %s"
    cursor.execute(sql_check_resultado, (candidato_id, teste_id))
    resultado_existente = cursor.fetchone()
    cursor.fetchall()
    if resultado_existente:
        return redirect(url_for('pagina_resultado', resultado_id=resultado_existente['id']))

    ids_perguntas = [key.split('_')[1] for key in request.form if key.startswith('pergunta_')]
    if not ids_perguntas and ordem_perguntas: ids_perguntas = ordem_perguntas
    if not ids_perguntas or ids_perguntas == ['']: return "<h1>Erro: Nenhuma pergunta foi submetida.</h1>"

    sql_perguntas = f"SELECT id, resposta_correta FROM perguntas WHERE id IN ({','.join(['%s'] * len(ids_perguntas))})"
    cursor.execute(sql_perguntas, ids_perguntas)
    perguntas_db_dict = {p['id']: p['resposta_correta'] for p in cursor.fetchall()}

    respostas_corretas = 0
    respostas_para_inserir = []

    for i, pergunta_id_str in enumerate(ordem_perguntas):
        pergunta_id = int(pergunta_id_str)
        resposta_correta = perguntas_db_dict.get(pergunta_id)
        resposta_dada = request.form.get(f'pergunta_{pergunta_id}')
        ordem = i + 1
        foi_correta = (resposta_dada == resposta_correta)
        if foi_correta:
            respostas_corretas += 1
        respostas_para_inserir.append((pergunta_id, resposta_dada if resposta_dada else 'N/A', foi_correta, ordem))

    nota_final = 0.0 if tentativa_fraude else (respostas_corretas / len(ordem_perguntas)) * 20
    status = "Aprovado" if nota_final >= 10 else "Reprovado"
    
    sql_insert_resultado = "INSERT INTO resultados (candidato_id, teste_id, nota_final, status, tentativa_fraude) VALUES (%s, %s, %s, %s, %s)"
    cursor.execute(sql_insert_resultado, (candidato_id, teste_id, nota_final, status, tentativa_fraude))
    conn.commit()
    resultado_id = cursor.lastrowid
    
    sql_insert_respostas = "INSERT INTO respostas_candidato (resultado_id, pergunta_id, resposta_dada, foi_correta, ordem) VALUES (%s, %s, %s, %s, %s)"
    dados_respostas = [(resultado_id,) + resp for resp in respostas_para_inserir]
    cursor.executemany(sql_insert_respostas, dados_respostas)
    conn.commit()
    
    cursor.close()
    conn.close()
    
    return redirect(url_for('pagina_resultado', resultado_id=resultado_id))

@app.route("/resultado/<int:resultado_id>")
def pagina_resultado(resultado_id):
    conn = get_db_connection()
    if conn is None: return "<h1>Erro: Não foi possível ligar à base de dados.</h1>"
    cursor = conn.cursor(dictionary=True)
    
    sql_resultado = "SELECT r.nota_final, r.status, r.tentativa_fraude, c.nome_completo FROM resultados r JOIN candidatos c ON r.candidato_id = c.id WHERE r.id = %s"
    cursor.execute(sql_resultado, (resultado_id,))
    resultado = cursor.fetchone()
    resultado['nome_candidato'] = resultado.pop('nome_completo')
    
    sql_correcao = """
        SELECT p.enunciado, p.opcao_a, p.opcao_b, p.opcao_c, p.opcao_d, 
               rc.resposta_dada, p.resposta_correta, rc.foi_correta
        FROM respostas_candidato rc 
        JOIN perguntas p ON rc.pergunta_id = p.id
        WHERE rc.resultado_id = %s
        ORDER BY rc.ordem ASC; 
    """
    
    cursor.execute(sql_correcao, (resultado_id,))
    correcao = cursor.fetchall()
    
    cursor.close()
    conn.close()
    
    return render_template("resultado.html", resultado=resultado, correcao=correcao)

@app.route("/admin")
def painel_admin():
    if not session.get('logged_in'):
        return redirect(url_for('login'))
    curso_filtro = request.args.get('curso_filtro', 'todos') 
    data_inicio = request.args.get('data_inicio', '')
    data_fim = request.args.get('data_fim', '')
    conn = get_db_connection()
    if conn is None: return "<h1>Erro: Não foi possível ligar à base de dados.</h1>"
    cursor = conn.cursor(dictionary=True)
    
    sql_base = "SELECT c.id AS candidato_id, r.id AS resultado_id, c.numero_candidato, c.nome_completo, c.curso_desejado, r.nota_final, r.status, r.data_submissao, r.tentativa_fraude FROM resultados r JOIN candidatos c ON r.candidato_id = c.id"
    conditions = []
    params = []
    if curso_filtro != 'todos':
        conditions.append("c.curso_desejado = %s")
        params.append(curso_filtro)
    if data_inicio:
        conditions.append("r.data_submissao >= %s")
        params.append(data_inicio)
    if data_fim:
        conditions.append("r.data_submissao <= %s")
        params.append(data_fim + ' 23:59:59')
    if conditions:
        sql_base += " WHERE " + " AND ".join(conditions)
    sql_base += " ORDER BY r.data_submissao DESC;"
    cursor.execute(sql_base, tuple(params))
    resultados = cursor.fetchall()
    cursor.close()
    conn.close()
    
    return render_template("admin.html", 
                           resultados=resultados, 
                           curso_selecionado=curso_filtro, 
                           data_inicio=data_inicio, 
                           data_fim=data_fim,
                           now=datetime.now())

@app.route("/apagar_candidato/<int:candidato_id>", methods=["POST"])
def apagar_candidato(candidato_id):
    if not session.get('logged_in'):
        return redirect(url_for('login'))
    conn = get_db_connection()
    if conn is None: return "<h1>Erro: Não foi possível ligar à base de dados.</h1>"
    cursor = conn.cursor()
    sql_delete = "DELETE FROM candidatos WHERE id = %s"
    try:
        cursor.execute(sql_delete, (candidato_id,))
        conn.commit()
    except mysql.connector.Error as err:
        print(f"Erro ao apagar o candidato: {err}")
    finally:
        cursor.close()
        conn.close()
    return redirect(url_for('painel_admin'))

@app.route("/admin/ver_prova/<int:resultado_id>")
def ver_prova(resultado_id):
    if not session.get('logged_in'):
        return redirect(url_for('login'))
    conn = get_db_connection()
    if conn is None: return "<h1>Erro: Não foi possível ligar à base de dados.</h1>"
    cursor = conn.cursor(dictionary=True)

    sql_resultado = "SELECT r.*, c.nome_completo, c.numero_candidato, c.curso_desejado FROM resultados r JOIN candidatos c ON r.candidato_id = c.id WHERE r.id = %s"
    cursor.execute(sql_resultado, (resultado_id,))
    resultado = cursor.fetchone()
    if not resultado:
        return "<h1>Erro: Resultado não encontrado.</h1>"

    sql_prova = """
        SELECT p.enunciado, p.opcao_a, p.opcao_b, p.opcao_c, p.opcao_d, 
               rc.resposta_dada, p.resposta_correta, rc.foi_correta
        FROM respostas_candidato rc 
        JOIN perguntas p ON rc.pergunta_id = p.id
        WHERE rc.resultado_id = %s
        ORDER BY rc.ordem ASC; 
    """
    cursor.execute(sql_prova, (resultado_id,))
    prova = cursor.fetchall()
    
    cursor.close()
    conn.close()
    
    return render_template("ver_prova.html", resultado=resultado, candidato=resultado, prova=prova)

# --- ROTAS DE ESTATÍSTICAS ATUALIZADAS ---

@app.route("/admin/estatisticas")
def estatisticas_page():
    """Renderiza a página HTML que irá mostrar os gráficos."""
    if not session.get('logged_in'):
        return redirect(url_for('login'))
    # Passamos o URL para o template para que o JavaScript o possa usar
    data_url = url_for('estatisticas_data')
    return render_template("estatisticas.html", data_url=data_url)

@app.route("/admin/estatisticas_data")
def estatisticas_data():
    """Fornece os dados para todos os gráficos em formato JSON."""
    if not session.get('logged_in'):
        return jsonify({"error": "Não autorizado"}), 401

    conn = get_db_connection()
    if conn is None:
        return jsonify({"error": "Erro de base de dados"}), 500
    cursor = conn.cursor(dictionary=True)

    # --- 1. Desempenho por Categoria ---
    query_categoria = """
        SELECT 
            c.curso_desejado,
            p.categoria,
            SUM(rc.foi_correta) AS acertos,
            COUNT(rc.id) AS total_respostas
        FROM respostas_candidato rc
        JOIN perguntas p ON rc.pergunta_id = p.id
        JOIN resultados r ON rc.resultado_id = r.id
        JOIN candidatos c ON r.candidato_id = c.id
        JOIN testes t ON r.teste_id = t.id
        GROUP BY t.curso_associado, p.categoria
        ORDER BY t.curso_associado, p.categoria;
    """
    cursor.execute(query_categoria)
    desempenho_db = cursor.fetchall()
    
    desempenho_por_curso = defaultdict(lambda: {'labels': [], 'data': []})
    for row in desempenho_db:
        curso = row['curso_associado']
        taxa_acerto = (row['acertos'] / row['total_respostas']) * 100 if row['total_respostas'] > 0 else 0
        desempenho_por_curso[curso]['labels'].append(row['categoria'])
        desempenho_por_curso[curso]['data'].append(round(taxa_acerto, 2))

    # --- 2. Perguntas Mais Difíceis e Fáceis ---
    query_perguntas = """
        SELECT 
            p.enunciado,
            SUM(rc.foi_correta) AS acertos,
            COUNT(rc.id) AS total,
            (SUM(rc.foi_correta) / COUNT(rc.id)) * 100 AS taxa_acerto
        FROM respostas_candidato rc
        JOIN perguntas p ON rc.pergunta_id = p.id
        GROUP BY p.id, p.enunciado
        HAVING COUNT(rc.id) > 4 -- Apenas perguntas respondidas 5+ vezes
    """
    cursor.execute(f"{query_perguntas} ORDER BY taxa_acerto ASC LIMIT 5;")
    perguntas_dificeis = cursor.fetchall()
    
    cursor.execute(f"{query_perguntas} ORDER BY taxa_acerto DESC LIMIT 5;")
    perguntas_faceis = cursor.fetchall()

    # --- 3. Distribuição de Notas (Histograma) ---
    query_histograma = """
        SELECT 
            SUM(CASE WHEN nota_final >= 0 AND nota_final < 5 THEN 1 ELSE 0 END) AS '0-4',
            SUM(CASE WHEN nota_final >= 5 AND nota_final < 10 THEN 1 ELSE 0 END) AS '5-9',
            SUM(CASE WHEN nota_final >= 10 AND nota_final < 15 THEN 1 ELSE 0 END) AS '10-14',
            SUM(CASE WHEN nota_final >= 15 AND nota_final <= 20 THEN 1 ELSE 0 END) AS '15-20'
        FROM resultados;
    """
    cursor.execute(query_histograma)
    dist_notas_db = cursor.fetchone()
    distribuicao_notas = {
        "labels": list(dist_notas_db.keys()),
        "data": [int(v) if v is not None else 0 for v in dist_notas_db.values()]
    }

    # --- 4. Evolução ao Longo do Tempo ---
    query_evolucao = """
        SELECT 
            DATE(data_submissao) as dia,
            COUNT(id) as total_testes,
            SUM(CASE WHEN status = 'Aprovado' THEN 1 ELSE 0 END) as total_aprovados
        FROM resultados
        GROUP BY DATE(data_submissao)
        ORDER BY dia;
    """
    cursor.execute(query_evolucao)
    evolucao_db = cursor.fetchall()
    evolucao_tempo = {
        "labels": [row['dia'].strftime('%d/%m') for row in evolucao_db],
        "testesData": [row['total_testes'] for row in evolucao_db],
        "aprovadosData": [row['total_aprovados'] for row in evolucao_db]
    }

    cursor.close()
    conn.close()

    # --- Compilar todos os dados para a resposta JSON ---
    data_para_graficos = {
        "desempenhoPorCurso": desempenho_por_curso,
        "perguntasDificeis": perguntas_dificeis,
        "perguntasFaceis": perguntas_faceis,
        "distribuicaoNotas": distribuicao_notas,
        "evolucaoTempo": evolucao_tempo
    }

    return jsonify(data_para_graficos)


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000, debug=True)
