import os
import face_recognition
import mysql.connector
from flask import Flask, request, jsonify
from PIL import Image
import numpy as np

# --- CONFIGURAÇÃO ---
DB_CONFIG = {
    'host': 'localhost',
    'user': 'root',
    'password': 'SUA_NOVA_SENHA_SEGURA', # <-- Lembre-se de usar sua senha segura
    'database': 'facial'
}
UPLOAD_FOLDER = '/var/www/html/facial/uploads/faces/'

app = Flask(__name__)

# --- CACHE SIMPLES PARA OS VETORES CONHECIDOS ---
# Para evitar ler o DB a cada requisição, guardamos os vetores na memória.
known_face_encodings = []
known_face_metadata = [] # Guarda informações como ID da pessoa, nome, etc.

def carregar_vetores_conhecidos():
    """
    Carrega todos os vetores faciais e metadados do banco de dados para a memória.
    """
    global known_face_encodings, known_face_metadata
    
    # Limpa as listas antes de carregar
    known_face_encodings = []
    known_face_metadata = []

    conn = mysql.connector.connect(**DB_CONFIG)
    cursor = conn.cursor(dictionary=True)

    # SQL para buscar vetores junto com o nome da pessoa
    sql = """
        SELECT 
            f.id as face_id, 
            f.pessoa_id, 
            f.vetor_facial,
            p.nome_completo,
            p.tipo
        FROM faces_cadastradas f
        JOIN pessoas_interesse p ON f.pessoa_id = p.id
        WHERE f.vetor_facial IS NOT NULL
    """
    cursor.execute(sql)
    
    for row in cursor.fetchall():
        # Converte o BLOB do DB de volta para um array numpy
        encoding = np.frombuffer(row['vetor_facial'], dtype=np.float64)
        known_face_encodings.append(encoding)
        known_face_metadata.append({
            "pessoa_id": row['pessoa_id'],
            "nome_completo": row['nome_completo'],
            "tipo": row['tipo']
        })

    cursor.close()
    conn.close()
    print(f"Carregados {len(known_face_encodings)} vetores faciais conhecidos na memória.")


# --- FUNÇÕES AUXILIARES (processar_novas_faces continua igual) ---
def get_db_connection():
    return mysql.connector.connect(**DB_CONFIG)

def processar_novas_faces():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("SELECT id, caminho_imagem FROM faces_cadastradas WHERE vetor_facial IS NULL")
    faces_para_processar = cursor.fetchall()
    count = 0
    for face in faces_para_processar:
        caminho_completo = os.path.join(UPLOAD_FOLDER, face['caminho_imagem'])
        if not os.path.exists(caminho_completo): continue
        try:
            image = face_recognition.load_image_file(caminho_completo)
            face_encodings = face_recognition.face_encodings(image)
            if face_encodings:
                encoding_bytes = face_encodings[0].tobytes()
                update_cursor = conn.cursor()
                update_cursor.execute("UPDATE faces_cadastradas SET vetor_facial = %s WHERE id = %s", (encoding_bytes, face['id']))
                conn.commit()
                update_cursor.close()
                count += 1
        except Exception as e:
            print(f"Erro ao processar {face['caminho_imagem']}: {e}")
    cursor.close()
    conn.close()
    # Após processar, recarrega os vetores em memória
    carregar_vetores_conhecidos()
    return count


# --- ROTAS DA API ---

@app.route('/processar-faces', methods=['POST'])
def api_processar_faces():
    print("Recebida requisição para processar faces...")
    try:
        processed_count = processar_novas_faces()
        return jsonify({"status": "success", "message": f"{processed_count} novas faces foram processadas.", "processed_count": processed_count}), 200
    except Exception as e:
        return jsonify({"status": "error", "message": "Ocorreu um erro interno no servidor de IA."}), 500


# --- NOVA ROTA DE IDENTIFICAÇÃO ---
@app.route('/identificar-face', methods=['POST'])
def api_identificar_face():
    if 'file' not in request.files:
        return jsonify({"status": "error", "message": "Nenhum arquivo enviado."}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({"status": "error", "message": "Nome de arquivo vazio."}), 400

    try:
        # Carrega a imagem enviada
        img = face_recognition.load_image_file(file)
        
        # Encontra rosto e vetor na imagem desconhecida
        unknown_face_encodings = face_recognition.face_encodings(img)

        if not unknown_face_encodings:
            return jsonify({"status": "success", "match_found": False, "message": "Nenhum rosto encontrado na imagem."})

        unknown_encoding = unknown_face_encodings[0]

        # Compara o rosto desconhecido com todos os rostos conhecidos
        matches = face_recognition.compare_faces(known_face_encodings, unknown_encoding, tolerance=0.6)
        
        match_found = False
        result = {"status": "success", "match_found": False}

        if True in matches:
            match_found = True
            first_match_index = matches.index(True)
            
            # Calcula a "distância" para ter uma noção de confiança
            face_distances = face_recognition.face_distance(known_face_encodings, unknown_encoding)
            best_match_distance = face_distances[first_match_index]
            
            # Converte a distância em uma porcentagem de "certeza"
            confidence = (1 - best_match_distance) * 100

            metadata = known_face_metadata[first_match_index]
            result.update({
                "match_found": True,
                "pessoa_id": metadata['pessoa_id'],
                "nome_completo": metadata['nome_completo'],
                "tipo": metadata['tipo'],
                "confianca": round(confidence, 2)
            })

        return jsonify(result)

    except Exception as e:
        print(f"Erro na identificação: {e}")
        return jsonify({"status": "error", "message": "Não foi possível processar a imagem."}), 500


if __name__ == '__main__':
    # Carrega os vetores conhecidos uma vez quando o servidor inicia
    carregar_vetores_conhecidos()
    app.run(host='0.0.0.0', port=5000, debug=True)