from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
from mysql.connector import Error as MySQLError

from ds.db import db
from schema.face_schema import FaceCreateRequest, FaceUpdateRequest, FaceResponse
from schema.response_schema import APIResponse
from middle.auth_middleware import get_current_user
from schema.user_schema import UserResponse

from util.face_util import add_binary_data,get_average_feature
#初始化实例

router = APIRouter(
    prefix="/faces",
    tags=["人脸管理"]
)



# ------------------------------
# 1. 创建人脸记录（核心修正：ID 数据库自增，前端无需传）
# ------------------------------
@router.post("", response_model=APIResponse, summary="创建人脸记录（传名称+文件，ID自增）")
async def create_face(
        # 前端仅需传：name（可选，Form格式）、file（必传，文件）
        name: str = Form(None, max_length=255, description="名称（可选）"),
        file: UploadFile = File(..., description="人脸文件（必传，暂不处理内容）")
):
    """
    创建人脸记录：
    - 需登录认证
    - 前端传参：multipart/form-data 表单（name 可选，file 必传）
    - ID 由数据库自动生成，无需前端传入
    - 暂不处理文件内容，eigenvalue 设为 None
    """

    # 调用你的方法
    conn = None
    cursor = None
    try:
        # 1. 用模型校验 name（仅校验长度，无需ID）
        face_create = FaceCreateRequest(name=name)

        conn = db.get_connection()
        cursor = conn.cursor(dictionary=True)

        # 把文件转为二进制数组
        file_content = await file.read()

        # 计算特征值
        flag, eigenvalue = add_binary_data(file_content)

        if flag == False:
            raise HTTPException(
                status_code=500,
                detail="未检测到人脸"
            )

        # 打印数组长度
        print(f"文件大小：{len(file_content)} 字节")

        # 2. 插入数据库：无需传 ID（自增），只传 name 和 eigenvalue（None）
        insert_query = """
            INSERT INTO face (name, eigenvalue)
            VALUES (%s, %s)
        """
        cursor.execute(insert_query, (face_create.name, str(eigenvalue)))
        conn.commit()

        # 3. 获取数据库自动生成的 ID（关键：用 LAST_INSERT_ID() 查刚插入的记录）
        select_new_query = "SELECT * FROM face WHERE id = LAST_INSERT_ID()"
        cursor.execute(select_new_query)
        created_face = cursor.fetchone()

        if not created_face:
            raise HTTPException(
                status_code=500,
                detail="创建人脸记录成功，但无法获取新创建的记录"
            )

        return APIResponse(
            code=201,
            message=f"人脸记录创建成功（ID：{created_face['id']}，文件名：{file.filename}）",
            data=FaceResponse(** created_face)
        )
    except MySQLError as e:
        if conn:
            conn.rollback()
        # 改为使用HTTPException
        raise HTTPException(
            status_code=500,
            detail=f"创建人脸记录失败：{str(e)}"
        ) from e
    except Exception as e:
        # 捕获其他可能的异常
        raise HTTPException(
            status_code=500,
            detail=f"服务器错误：{str(e)}"
        ) from e
    finally:
        await file.close()  # 关闭文件流
        db.close_connection(conn, cursor)

        # 调用人脸识别得到特征值（这里可以添加你的人脸识别逻辑）
        flag, eigenvalue = add_binary_data(file_content)
        if flag == False:
            raise HTTPException(
                status_code=500,
                detail="未检测到人脸"
            )

        # 将 eigenvalue 转为 str
        eigenvalue = str(eigenvalue)

# ------------------------------
# 2. 获取单个人脸记录（不变，用自增ID查询）
# ------------------------------
@router.get("/{face_id}", response_model=APIResponse, summary="获取单个人脸记录")
async def get_face(
        face_id: int,  # 这里的 ID 是数据库自增的，前端从创建响应中获取
        current_user: UserResponse = Depends(get_current_user)
):
    conn = None
    cursor = None
    try:
        conn = db.get_connection()
        cursor = conn.cursor(dictionary=True)

        query = "SELECT * FROM face WHERE id = %s"
        cursor.execute(query, (face_id,))
        face = cursor.fetchone()

        if not face:
            raise HTTPException(
                status_code=404,
                detail=f"ID为 {face_id} 的人脸记录不存在"
            )

        return APIResponse(
            code=200,
            message="人脸记录查询成功",
            data=FaceResponse(**face)
        )
    except MySQLError as e:
        # 改为使用HTTPException
        raise HTTPException(
            status_code=500,
            detail=f"查询人脸记录失败：{str(e)}"
        ) from e
    finally:
        db.close_connection(conn, cursor)


# 后续 3.获取所有、4.更新、5.删除 接口（修复异常处理）
# ------------------------------
# 3. 获取所有人脸记录（不变）
# ------------------------------
@router.get("", response_model=APIResponse, summary="获取所有人脸记录")
async def get_all_faces(
):
    conn = None
    cursor = None
    try:
        conn = db.get_connection()
        cursor = conn.cursor(dictionary=True)

        query = "SELECT * FROM face ORDER BY id"  # 按自增ID排序
        cursor.execute(query)
        faces = cursor.fetchall()

        return APIResponse(
            code=200,
            message="所有人脸记录查询成功",
            data=[FaceResponse(** face) for face in faces]
        )
    except MySQLError as e:
        raise HTTPException(
            status_code=500,
            detail=f"查询所有人脸记录失败：{str(e)}"
        ) from e
    finally:
        db.close_connection(conn, cursor)


# ------------------------------
# 4. 更新人脸记录（不变，用自增ID更新）
# ------------------------------
@router.put("/{face_id}", response_model=APIResponse, summary="更新人脸记录")
async def update_face(
        face_id: int,
        face_update: FaceUpdateRequest,
        current_user: UserResponse = Depends(get_current_user)
):
    conn = None
    cursor = None
    try:
        conn = db.get_connection()
        cursor = conn.cursor(dictionary=True)

        # 检查记录是否存在
        check_query = "SELECT id FROM face WHERE id = %s"
        cursor.execute(check_query, (face_id,))
        existing_face = cursor.fetchone()
        if not existing_face:
            raise HTTPException(
                status_code=404,
                detail=f"ID为 {face_id} 的人脸记录不存在"
            )

        # 构建更新语句
        update_fields = []
        params = []
        if face_update.name is not None:
            update_fields.append("name = %s")
            params.append(face_update.name)
        if face_update.eigenvalue is not None:
            update_fields.append("eigenvalue = %s")
            params.append(face_update.eigenvalue)

        if not update_fields:
            raise HTTPException(status_code=400, detail="至少需提供一个更新字段")

        params.append(face_id)
        update_query = f"UPDATE face SET {', '.join(update_fields)}, updated_at = CURRENT_TIMESTAMP WHERE id = %s"
        cursor.execute(update_query, params)
        conn.commit()

        # 查询更新后记录
        select_query = "SELECT * FROM face WHERE id = %s"
        cursor.execute(select_query, (face_id,))
        updated_face = cursor.fetchone()

        return APIResponse(
            code=200,
            message="人脸记录更新成功",
            data=FaceResponse(**updated_face)
        )
    except MySQLError as e:
        if conn:
            conn.rollback()
        raise HTTPException(
            status_code=500,
            detail=f"更新人脸记录失败：{str(e)}"
        ) from e
    finally:
        db.close_connection(conn, cursor)


# ------------------------------
# 5. 删除人脸记录（不变，用自增ID删除）
# ------------------------------
@router.delete("/{face_id}", response_model=APIResponse, summary="删除人脸记录")
async def delete_face(
        face_id: int,
        current_user: UserResponse = Depends(get_current_user)
):
    conn = None
    cursor = None
    try:
        conn = db.get_connection()
        cursor = conn.cursor(dictionary=True)

        check_query = "SELECT id FROM face WHERE id = %s"
        cursor.execute(check_query, (face_id,))
        existing_face = cursor.fetchone()
        if not existing_face:
            raise HTTPException(
                status_code=404,
                detail=f"ID为 {face_id} 的人脸记录不存在"
            )

        delete_query = "DELETE FROM face WHERE id = %s"
        cursor.execute(delete_query, (face_id,))
        conn.commit()

        return APIResponse(
            code=200,
            message=f"ID为 {face_id} 的人脸记录删除成功",
            data=None
        )
    except MySQLError as e:
        if conn:
            conn.rollback()
        raise HTTPException(
            status_code=500,
            detail=f"删除人脸记录失败：{str(e)}"
        ) from e
    finally:
        db.close_connection(conn, cursor)


def get_all_face_name_with_eigenvalue() -> dict:
    """
    获取所有人脸的名称及其对应的特征值，组成字典返回
    key: 人脸名称（name）
    value: 人脸特征值（eigenvalue），若名称重复则返回平均特征值
    注：过滤掉name为None的记录，避免字典key为None的情况
    """
    conn = None
    cursor = None
    try:
        # 1. 建立数据库连接并获取游标（dictionary=True使结果以字典形式返回）
        conn = db.get_connection()
        cursor = conn.cursor(dictionary=True)

        # 2. 执行SQL查询：只获取name非空的记录，减少数据传输
        query = "SELECT name, eigenvalue FROM face WHERE name IS NOT NULL"
        cursor.execute(query)
        faces = cursor.fetchall()  # 返回结果：列表套字典，如 [{"name":"张三","eigenvalue":...}, ...]

        # 3. 收集同一名称对应的所有特征值（处理名称重复场景）
        name_to_eigenvalues = {}
        for face in faces:
            name = face["name"]
            eigenvalue = face["eigenvalue"]
            # 若名称已存在，追加特征值；否则新建列表存储
            if name in name_to_eigenvalues:
                name_to_eigenvalues[name].append(eigenvalue)
            else:
                name_to_eigenvalues[name] = [eigenvalue]

        # 4. 构建最终字典：重复名称取平均，唯一名称直接取特征值
        face_dict = {}
        for name, eigenvalues in name_to_eigenvalues.items():

            # 处理特征值：多个则求平均，单个则直接使用
            if len(eigenvalues) > 1:
                # 调用外部方法计算平均特征值（需确保binary_face_feature_handler已正确导入）
                face_dict[name] = get_average_feature(eigenvalues)
            else:
                # 取列表中唯一的特征值（避免value为列表类型）
                face_dict[name] = eigenvalues[0]

        return face_dict

    except MySQLError as e:
        # 捕获数据库异常，添加上下文信息后重新抛出（便于定位问题）
        raise Exception(f"获取人脸名称与特征值失败：{str(e)}") from e
    finally:
        # 5. 无论是否异常，均释放数据库连接和游标（避免资源泄漏）
        db.close_connection(conn, cursor)