import os
import numpy as np
import cv2
from PIL import Image  # 确保正确导入Image类
from insightface.app import FaceAnalysis
# 导入获取人脸信息的服务
from service.face_service import get_all_face_name_with_eigenvalue

# 全局变量
_face_app = None
_known_faces_embeddings = {}  # 存储姓名到特征值的映射
_known_faces_names = []  # 存储所有已知姓名


def load_model():
    """加载人脸识别模型及已知人脸特征库"""
    global _face_app, _known_faces_embeddings, _known_faces_names

    # 初始化InsightFace模型
    try:
        _face_app = FaceAnalysis(name='buffalo_l', root=os.path.expanduser('~/.insightface'))
        _face_app.prepare(ctx_id=0, det_size=(640, 640))
    except Exception as e:
        print(f"Face model load failed: {e}")
        return False

    # 从服务获取所有人脸姓名和特征值
    try:
        face_data = get_all_face_name_with_eigenvalue()

        # 处理获取到的人脸数据
        for person_name, eigenvalue_data in face_data.items():
            # 处理特征值数据 - 兼容数组和字符串两种格式
            if isinstance(eigenvalue_data, np.ndarray):
                # 如果已经是numpy数组，直接使用
                eigenvalue = eigenvalue_data.astype(np.float32)
            elif isinstance(eigenvalue_data, str):
                # 清理字符串：移除方括号、换行符和多余空格
                cleaned = eigenvalue_data.replace('[', '').replace(']', '').replace('\n', '').strip()
                # 按空格或逗号分割（处理可能的不同分隔符）
                values = [v for v in cleaned.split() if v]
                # 转换为数组
                eigenvalue = np.array(list(map(float, values)), dtype=np.float32)
            else:
                # 不支持的类型
                print(f"Unsupported eigenvalue type for {person_name}")
                continue

            # 归一化处理
            norm = np.linalg.norm(eigenvalue)
            if norm != 0:
                eigenvalue = eigenvalue / norm

            _known_faces_embeddings[person_name] = eigenvalue
            _known_faces_names.append(person_name)

    except Exception as e:
        print(f"Error loading face data from service: {e}")

    return True if _face_app else False


def detect(frame, threshold=0.4):
    """检测并识别人脸，返回结果元组(是否匹配到已知人脸, 结果字符串)"""
    global _face_app, _known_faces_embeddings, _known_faces_names

    if not _face_app or not _known_faces_names or frame is None:
        return (False, "未初始化或无效帧")

    try:
        faces = _face_app.get(frame)
    except Exception as e:
        print(f"Face detect error: {e}")
        return (False, f"检测错误: {str(e)}")

    result_parts = []
    has_matched = False  # 新增标记：是否有匹配到的已知人脸

    for face in faces:
        # 特征归一化
        embedding = face.embedding.astype(np.float32)
        norm = np.linalg.norm(embedding)
        if norm == 0:
            continue
        embedding = embedding / norm

        # 对比已知人脸
        max_sim, best_name = -1.0, "Unknown"
        for name in _known_faces_names:
            known_emb = _known_faces_embeddings[name]
            sim = np.dot(embedding, known_emb)
            if sim > max_sim:
                max_sim = sim
                best_name = name

        # 判断匹配结果
        is_match = max_sim >= threshold
        if is_match:
            has_matched = True  # 只要有一个匹配成功，就标记为True

        bbox = face.bbox
        result_parts.append(
            f"{'匹配' if is_match else '不匹配'}: {best_name} (相似度: {max_sim:.2f}, 边界框: {bbox})"
        )

    # 构建结果字符串
    if not result_parts:
        result_str = "未检测到人脸"
    else:
        result_str = "; ".join(result_parts)

    # 第一个返回值改为：是否匹配到已知人脸
    return (has_matched, result_str)
