import os
# 强制使用CPU，禁用CUDA（必须在导入dlib之前设置）
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'

import threading
import sys
import time
from datetime import datetime
import platform
import urllib
from PIL import Image, ImageDraw, ImageFont
import json, simplejson
import traceback
import base64
from io import BytesIO
import sqlite3
import shutil
from skimage import io
import uuid
import csv
import tempfile

# FastAPI相关导入
from fastapi import FastAPI, File, UploadFile, Form, HTTPException, Request
from fastapi.responses import JSONResponse, FileResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from typing import Optional, List

import dlib          # 人脸处理的库 Dlib
# 设置dlib使用CPU模式（部分版本无效，但不影响CPU强制）
try:
    dlib.DLIB_USE_CUDA = False
except Exception:
    pass
import numpy as np   # 数据处理的库 numpy
import cv2           # 图像处理的库 OpenCv
import pandas as pd  # 数据处理的库 Pandas

# 创建FastAPI应用
app = FastAPI(title="人脸识别API服务", version="1.0.0")

# 启用CORS支持
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 全局变量
# 获取当前脚本所在目录的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 设置人脸图像存储的绝对路径
path_images_from_camera = os.path.join(current_dir, "data/data_faces_from_camera/")

# Dlib 模型全局初始化（只初始化一次）
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("data/data_dlib/shape_predictor_68_face_landmarks.dat")
facerec = dlib.face_recognition_model_v1("data/data_dlib/dlib_face_recognition_resnet_model_v1.dat")

# 全局特征数据数组
features_known_arr = []
last_reload_time = 0
user_info_map = {}  # 用户信息映射字典

######################################################################################
# 工具函数

def readb64(base64_string):
    """从base64字符串读取图像"""
    origStr = base64_string.replace('data:image/bmp;base64,', '')
    origStr = origStr.replace('data:image/jpeg;base64,', '')
    origStr = origStr.replace('data:image/png;base64,', '')
    origStr = origStr.replace('data:image/gif;base64,', '')
    
    sbuf = BytesIO()
    sbuf.write(base64.b64decode(origStr))
    pimg = Image.open(sbuf)
    return cv2.cvtColor(np.array(pimg), cv2.COLOR_RGB2BGR)

def cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20):
    """在图像上添加中文文本"""
    if isinstance(img, np.ndarray):
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    
    draw = ImageDraw.Draw(img)
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
    draw.text((left, top), text, textColor, font=fontStyle)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), size=30):
    """在图像上添加中文文本"""
    if isinstance(img, np.ndarray):
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    
    draw = ImageDraw.Draw(img)
    fontStyle = ImageFont.truetype("simsun.ttc", size, encoding="utf-8")
    draw.text(position, text, textColor, font=fontStyle)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

def return_euclidean_distance(feature_1, feature_2):
    """计算两个128D向量间的欧式距离"""
    feature_1 = np.array(feature_1)
    feature_2 = np.array(feature_2)
    dist = np.sqrt(np.sum(np.square(feature_1 - feature_2)))
    return dist

def file_filter(f):
    """过滤文件类型"""
    return f[-4:] in ['.jpg', '.png', '.bmp']

def return_128d_features(path_img):
    """返回单张图像的128D特征"""
    global detector, predictor, facerec
    
    img_rd = io.imread(path_img)
    img_gray = cv2.cvtColor(img_rd, cv2.COLOR_BGR2GRAY)
    faces = detector(img_gray, 1)

    if len(faces) != 0:
        img_rgb = cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB)
        shape = predictor(img_rgb, faces[0])
        face_descriptor = facerec.compute_face_descriptor(img_rgb, shape)
    else:
        face_descriptor = 0
        print("no face")

    return face_descriptor

def return_features_mean_personX(path_faces_personX):
    """返回一个文件夹中所有图像的128D特征均值"""
    features_list_personX = []
    photos_list = os.listdir(path_faces_personX)
    
    if photos_list:
        for photo in photos_list:
            if photo.endswith('.json'):
                continue
            
            path_photo = os.path.join(path_faces_personX, photo)
            features_128d = return_128d_features(path_photo)
            
            if features_128d == 0:
                print(f"读取 {photo} 时出错")
                continue
            
            features_list_personX.append(features_128d)
    
    if features_list_personX:
        features_mean_personX = np.array(features_list_personX).mean(axis=0)
    else:
        features_mean_personX = np.zeros(128)
    
    return features_mean_personX

def InitDb():
    """初始化数据库"""
    try:
        # 确保数据库目录存在
        db_dir = os.path.join(current_dir, 'data/db')
        os.makedirs(db_dir, exist_ok=True)
        print(f"数据库目录 {db_dir} 已创建或已存在")
        
        # 检查数据库文件是否存在，不存在则创建
        db_path = os.path.join(db_dir, 'recdb.db')
        db_exists = os.path.exists(db_path)
        if not db_exists:
            print(f"数据库文件 {db_path} 不存在，将创建新数据库")
            # 创建一个空的数据库文件
            open(db_path, 'w').close()
        else:
            print(f"数据库文件 {db_path} 已存在")
        
        print(f"尝试连接数据库: {db_path}")
        db_conn = sqlite3.connect(db_path)
        cursor = db_conn.cursor()
        
        # 检查rcinfo表是否存在
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='rcinfo'")
        table_exists = cursor.fetchone() is not None
        
        if not table_exists:
            print("rcinfo表不存在，开始创建...")
            
            # 构建表结构SQL，包含128个特征字段
            create_table_sql = '''
                CREATE TABLE rcinfo (
                    Uid TEXT PRIMARY KEY,
                    Name TEXT,
                    IdNum TEXT'''
            
            # 添加128个特征字段
            for i in range(128):
                create_table_sql += f",\n                    facFeatData{i} REAL"
            
            create_table_sql += "\n                )"
            
            cursor.execute(create_table_sql)
            print("rcinfo表创建完成")
        else:
            print("rcinfo表已存在")
        
        # 验证表是否成功创建
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='rcinfo'")
        table_exists = cursor.fetchone() is not None
        print(f"rcinfo表创建状态: {'成功' if table_exists else '失败'}")
        
        # 检查表结构是否正确
        cursor.execute("PRAGMA table_info(rcinfo)")
        columns = cursor.fetchall()
        print(f"rcinfo表字段数量: {len(columns)}")
        
        db_conn.commit()
        db_conn.close()
        print("数据库初始化完成")
    except Exception as e:
        print(f"数据库初始化失败: {e}")
        # 输出详细的错误信息
        import traceback
        traceback.print_exc()

def LoadFeaturesFromDb():
    """从数据库加载人脸特征数据"""
    # 注意：这里不需要重新初始化dlib模型，使用全局变量即可
    
    features_known_arr = []
    user_info_dict = {}  # 存储用户信息映射
    
    try:
        # 确保数据库目录存在
        db_dir = os.path.join(current_dir, 'data/db')
        os.makedirs(db_dir, exist_ok=True)
        
        db_path = os.path.join(db_dir, 'recdb.db')
        db_conn = sqlite3.connect(db_path)
        cursor = db_conn.cursor()
        
        # 构造查询语句，查询128个特征字段
        field_names = [f"facFeatData{i}" for i in range(128)]
        sql = f"SELECT Uid, Name, IdNum, {', '.join(field_names)} FROM rcinfo"
        cursor.execute(sql)
        users = cursor.fetchall()
        
        for user in users:
            uid, name, id_num = user[0], user[1], user[2]
            
            # 提取128个特征值
            feature_values = user[3:131]  # 从第3个字段开始到第130个字段
            
            if any(feature_values):  # 检查是否有特征数据
                try:
                    feature_array = np.array(feature_values)
                    
                    # 创建特征行: 128维特征 + 标记位 + 索引
                    feature_row = np.zeros(129)
                    feature_row[0:128] = feature_array
                    feature_row[128] = len(features_known_arr)  # 存储索引位置
                    
                    features_known_arr.append(feature_row)
                    
                    # 存储用户信息映射
                    user_info_dict[len(features_known_arr) - 1] = {
                        'uid': uid,
                        'name': name,
                        'id_num': id_num
                    }
                except Exception as e:
                    print(f"解析用户 {name} 特征数据失败: {e}")
        
        db_conn.close()
        print(f"从数据库成功加载 {len(features_known_arr)} 条特征数据")
        
        # 将用户信息映射存储为全局变量
        global user_info_map
        user_info_map = user_info_dict
        
    except Exception as e:
        print(f"加载特征数据失败: {e}")
    
    return features_known_arr

def RecFromImg(imgMat):
    """人脸识别函数"""
    global features_known_arr, detector, predictor, facerec, user_info_map
    
    # 检查特征数据是否已加载
    if not features_known_arr or len(features_known_arr) == 0:
        print("特征数据未加载，跳过识别")
        return []
    
    # 使用全局dlib模型
    img_gray = cv2.cvtColor(imgMat, cv2.COLOR_BGR2GRAY)
    faces = detector(img_gray, 1)
    img_rgb = cv2.cvtColor(imgMat, cv2.COLOR_BGR2RGB)
    
    now = datetime.now()
    nowStr = now.strftime("%Y-%m-%d %H:%M:%S")
    rst = []
    
    if len(faces) == 0:
        rst.append({"Code": "1001", "Name": "未检测到人脸", "Score": "0", "Time": nowStr})
        return rst
    else:
        for k, d in enumerate(faces):
            # 关键点检测
            shape = predictor(img_rgb, d)
            # 描述子提取，128D向量
            face_descriptor = facerec.compute_face_descriptor(img_rgb, shape)
            
            # 与所有数据库中的脸进行比较，找出欧式距离最小的脸
            e_distance_list = []
            for i in range(len(features_known_arr)):
                if features_known_arr[i][128] >= 0:  # 检查索引是否有效
                    e_distance = return_euclidean_distance(face_descriptor, features_known_arr[i][0:128])
                    e_distance_list.append(e_distance)
                else:
                    e_distance_list.append(999999999)
            
            # 找出最小欧式距离对应的人脸
            similar_person_num = e_distance_list.index(min(e_distance_list))
            if min(e_distance_list) < 0.4:
                # 通过索引获取用户信息
                user_index = int(features_known_arr[similar_person_num][128])
                if user_index in user_info_map:
                    user_name = user_info_map[user_index]['name']
                else:
                    user_name = "未知用户"
                
                rst.append({"Code": "1001", "Name": user_name, "Score": str(1 - min(e_distance_list)), "Time": nowStr})
            else:
                rst.append({"Code": "1001", "Name": "未知人脸", "Score": str(1 - min(e_distance_list)), "Time": nowStr})
        return rst

# 数据模型定义
class FaceRecognitionResponse(BaseModel):
    code: int
    data: dict
    message: str

class UserInfo(BaseModel):
    userCode: str
    userName: str
    idNum: str

# API路由
@app.get("/")
async def root():
    """根路径"""
    return {"message": "人脸识别API服务运行中", "version": "1.0.0"}

@app.post("/api/identifyFace", response_model=FaceRecognitionResponse)
async def identify_face(image: UploadFile = File(...)):
    """人脸识别API"""
    temp_dir = None
    temp_path = None
    
    try:
        global features_known_arr
        
        # 检查特征数据是否已加载
        if not features_known_arr or len(features_known_arr) == 0:
            features_known_arr = LoadFeaturesFromDb()
            if not features_known_arr or len(features_known_arr) == 0:
                return JSONResponse(
                    status_code=200,
                    content={
                        "code": 200,
                        "data": {
                            "msg": "未检测到人脸或未注册任何用户",
                            "errno": 0,
                            "data": {
                                "result": [],
                                "log_id": str(int(time.time() * 1000)),
                                "face_token": "",
                                "result_num": 0
                            }
                        },
                        "message": "未检测到人脸或未注册任何用户"
                    }
                )
        
        # 保存临时文件
        temp_dir = tempfile.mkdtemp()
        temp_path = os.path.join(temp_dir, image.filename)
        
        with open(temp_path, "wb") as buffer:
            content = await image.read()
            buffer.write(content)
        
        # 读取图像
        img = cv2.imread(temp_path)
        if img is None:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": f"Failed to load image: {temp_path}", "message": "FAILED"}
            )
        
        # 进行人脸识别
        result_list = RecFromImg(img)
        
        # 处理识别结果
        if result_list and len(result_list) > 0:
            result = result_list[0]
            name = result.get("Name", "未知")
            score = float(result.get("Score", "0"))
            
            # 从数据库中获取用户详细信息
            user_code = ""
            user_name = ""
            id_num = ""
            
            if name != "未知人脸":
                db_conn = None
                try:
                    # 确保数据库目录存在
                    db_dir = os.path.join(current_dir, 'data/db')
                    os.makedirs(db_dir, exist_ok=True)
                    
                    db_path = os.path.join(db_dir, 'recdb.db')
                    db_conn = sqlite3.connect(db_path)
                    cursor = db_conn.cursor()
                    cursor.execute(f"SELECT Uid, Name, IdNum FROM rcinfo WHERE Name='{name}'")
                    user_info = cursor.fetchone()
                    
                    if user_info:
                        user_code = user_info[0] or ""
                        user_name = user_info[1] or ""
                        id_num = user_info[2] or ""
                except Exception as e:
                    print(f"查询用户信息失败: {e}")
                finally:
                    if db_conn:
                        db_conn.close()
            
            return {
                "code": 200,
                "data": {
                    "msg": "success",
                    "errno": 0,
                    "data": {
                        "result": [{
                            "score": score * 100,
                            "group_id": "group",
                            "user_id": name,
                            "Uid": user_code,
                            "Name": user_name,
                            "IdNum": id_num
                        }],
                        "log_id": str(int(time.time() * 1000)),
                        "face_token": str(uuid.uuid4()).replace('-', ''),
                        "result_num": 1
                    }
                },
                "message": "SUCCESS"
            }
        else:
            return {
                "code": 200,
                "data": "未检测到人脸",
                "message": "SUCCESS"
            }
            
    except Exception as e:
        return JSONResponse(
            status_code=400,
            content={"code": 400, "data": str(e), "message": "FAILED"}
        )
    finally:
        # 确保临时文件被清理
        if temp_path and os.path.exists(temp_path):
            try:
                os.remove(temp_path)
            except Exception as e:
                print(f"删除临时文件失败: {e}")
        if temp_dir and os.path.exists(temp_dir):
            try:
                shutil.rmtree(temp_dir)
            except Exception as e:
                print(f"删除临时目录失败: {e}")

@app.post("/api/addFace", response_model=FaceRecognitionResponse)
async def add_face(
    image: UploadFile = File(...),
    userCode: str = Form(...),
    userName: Optional[str] = Form(None),
    idNum: Optional[str] = Form(None)
):
    """添加人脸数据API"""
    temp_dir = None
    temp_path = None
    
    try:
        if not userCode:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": "userCode is required", "message": "FAILED"}
            )
        
        # 设置默认值
        if not userName:
            userName = userCode
        if not idNum:
            idNum = userCode
        
        # 确保数据库和表存在
        InitDb()
        
        # 检查用户是否已存在
        try:
            # 确保数据库目录存在
            db_dir = os.path.join(current_dir, 'data/db')
            os.makedirs(db_dir, exist_ok=True)
            
            db_path = os.path.join(db_dir, 'recdb.db')
            db_conn = sqlite3.connect(db_path)
            cursor = db_conn.cursor()
            cursor.execute(f"SELECT * FROM rcinfo WHERE Uid='{userCode}'")
            existing_user = cursor.fetchone()
        except Exception as e:
            print(f"检查用户存在性时出错: {e}")
            existing_user = None
        finally:
            if 'db_conn' in locals():
                db_conn.close()
        
        if existing_user:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": None, "message": "record already exist"}
            )
        
        # 保存临时文件
        temp_dir = tempfile.mkdtemp()
        temp_path = os.path.join(temp_dir, image.filename)
        
        with open(temp_path, "wb") as buffer:
            content = await image.read()
            buffer.write(content)
        
        # 读取图像
        img = cv2.imread(temp_path)
        if img is None:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": f"Failed to load image: {temp_path}", "message": "FAILED"}
            )
        
        # 提取人脸特征
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = detector(img_gray, 1)
        
        if len(faces) == 0:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": "未检测到人脸", "message": "FAILED"}
            )
        
        # 使用第一张检测到的人脸
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        shape = predictor(img_rgb, faces[0])
        face_descriptor = facerec.compute_face_descriptor(img_rgb, shape)
        
        # 将特征向量转换为128个字段的值
        feat_values = list(face_descriptor)
        
        # 保存用户数据到数据库
        try:
            # 确保数据库目录存在
            db_dir = os.path.join(current_dir, 'data/db')
            os.makedirs(db_dir, exist_ok=True)
            
            db_path = os.path.join(db_dir, 'recdb.db')
            db_conn = sqlite3.connect(db_path)
            cursor = db_conn.cursor()
            
            # 构造插入语句，包含128个特征字段
            field_names = [f"facFeatData{i}" for i in range(128)]
            placeholders = ["?"] * (3 + 128)  # 3个基本信息字段 + 128个特征字段
            
            sql = f"INSERT INTO rcinfo (Uid, Name, IdNum, {', '.join(field_names)}) VALUES ({', '.join(placeholders)})"
            values = [userCode, userName, idNum] + feat_values
            
            cursor.execute(sql, values)
            db_conn.commit()
        except Exception as e:
            print(f"保存用户数据失败: {e}")
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": str(e), "message": "FAILED"}
            )
        finally:
            if 'db_conn' in locals():
                db_conn.close()
        
        # 创建用户目录并保存图像
        user_dir = os.path.join(path_images_from_camera, userCode)
        os.makedirs(user_dir, exist_ok=True)
        
        # 保存图像
        image_path = os.path.join(user_dir, f"{userCode}.jpg")
        cv2.imwrite(image_path, img)
        
        # 自动重载特征数据
        global features_known_arr
        features_known_arr = LoadFeaturesFromDb()
        print(f"[add_face] 用户数据已添加，已自动重载特征数据，当前特征数量: {len(features_known_arr)}")
        
        # 构建用户图像URL
        face_url = f"http://localhost:12316/images/{userCode}.jpg"
        face_url_placeholder = f"http://^API_BASE_URL^/images/{userCode}.jpg"
        
        return {
            "code": 200,
            "data": {
                "msg": "success",
                "errno": 0,
                "data": {
                    "log_id": str(int(time.time() * 1000)),
                    "message": "用户数据添加成功",
                    "faceUrl": face_url,
                    "faceUrl_Placeholder": face_url_placeholder
                }
            },
            "message": "SUCCESS"
        }
        
    except Exception as e:
        return JSONResponse(
            status_code=400,
            content={"code": 400, "data": str(e), "message": "FAILED"}
        )
    finally:
        # 确保临时文件被清理
        if temp_path and os.path.exists(temp_path):
            try:
                os.remove(temp_path)
            except Exception as e:
                print(f"删除临时文件失败: {e}")
        if temp_dir and os.path.exists(temp_dir):
            try:
                shutil.rmtree(temp_dir)
            except Exception as e:
                print(f"删除临时目录失败: {e}")

@app.post("/api/detectFace", response_model=FaceRecognitionResponse)
async def detect_face(image: UploadFile = File(...)):
    """人脸检测API"""
    temp_dir = None
    temp_path = None
    
    try:
        # 保存临时文件
        temp_dir = tempfile.mkdtemp()
        temp_path = os.path.join(temp_dir, image.filename)
        
        with open(temp_path, "wb") as buffer:
            content = await image.read()
            buffer.write(content)
        
        # 读取图像
        img = cv2.imread(temp_path)
        if img is None:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": f"Failed to load image: {temp_path}", "message": "FAILED"}
            )
        
        # 使用全局dlib模型检测人脸
        global detector
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = detector(img_gray, 1)
        
        # 处理检测结果
        if len(faces) > 0:
            faces_list = []
            for k, d in enumerate(faces):
                face_info = {
                    "location": {
                        "left": int(d.left()),
                        "top": int(d.top()),
                        "width": int(d.right() - d.left()),
                        "height": int(d.bottom() - d.top())
                    }
                }
                faces_list.append(face_info)
            
            return {
                "code": 200,
                "data": {
                    "faces": faces_list,
                    "face_num": len(faces_list)
                },
                "message": "SUCCESS"
            }
        else:
            return {
                "code": 200,
                "data": {
                    "faces": [],
                    "face_num": 0
                },
                "message": "未检测到人脸"
            }
            
    except Exception as e:
        return JSONResponse(
            status_code=400,
            content={"code": 400, "data": str(e), "message": "FAILED"}
        )
    finally:
        # 确保临时文件被清理
        if temp_path and os.path.exists(temp_path):
            try:
                os.remove(temp_path)
            except Exception as e:
                print(f"删除临时文件失败: {e}")
        if temp_dir and os.path.exists(temp_dir):
            try:
                shutil.rmtree(temp_dir)
            except Exception as e:
                print(f"删除临时目录失败: {e}")

@app.post("/api/getUserFaceUrl", response_model=FaceRecognitionResponse)
async def get_user_face_url(userCode: str = Form(...)):
    """获取用户人脸图像URL API"""
    try:
        if not userCode:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": None, "message": "userCode is required"}
            )
        
        # 检查用户是否存在
        db_conn = None
        try:
            # 确保数据库目录存在
            db_dir = os.path.join(current_dir, 'data/db')
            os.makedirs(db_dir, exist_ok=True)
            
            db_path = os.path.join(db_dir, 'recdb.db')
            db_conn = sqlite3.connect(db_path)
            cursor = db_conn.cursor()
            cursor.execute(f"SELECT * FROM rcinfo WHERE Uid='{userCode}'")
            user = cursor.fetchone()
        except Exception as e:
            print(f"查询用户信息失败: {e}")
            user = None
        finally:
            if db_conn:
                db_conn.close()
        
        if not user:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": None, "message": f"get user[{userCode}] image fail and error =-1005"}
            )
        
        # 检查图像文件是否存在
        image_path = os.path.join(path_images_from_camera, userCode, f"{userCode}.jpg")
        if not os.path.exists(image_path):
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": None, "message": f"get user[{userCode}] image fail and error =-1005"}
            )
        
        # 返回图像URL
        return {
            "code": 200,
            "data": f"http://localhost:12316/images/{userCode}.jpg",
            "message": "SUCCESS"
        }
        
    except Exception as e:
        return JSONResponse(
            status_code=400,
            content={"code": 400, "data": str(e), "message": "FAILED"}
        )

@app.post("/api/delFace", response_model=FaceRecognitionResponse)
async def del_face(userCode: str = Form(...)):
    """删除人脸数据API"""
    try:
        if not userCode:
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": "userCode is required", "message": "FAILED"}
            )
        
        # 确保数据库和表存在
        InitDb()
        
        # 检查用户是否存在并删除
        try:
            # 确保数据库目录存在
            db_dir = os.path.join(current_dir, 'data/db')
            os.makedirs(db_dir, exist_ok=True)
            
            db_path = os.path.join(db_dir, 'recdb.db')
            db_conn = sqlite3.connect(db_path)
            cursor = db_conn.cursor()
            cursor.execute(f"SELECT * FROM rcinfo WHERE Uid='{userCode}'")
            user = cursor.fetchone()
            
            if not user:
                return JSONResponse(
                    status_code=400,
                    content={"code": 400, "data": None, "message": "record not exist"}
                )
            
            # 删除数据库记录
            cursor.execute(f"DELETE FROM rcinfo WHERE Uid='{userCode}'")
            db_conn.commit()
        except Exception as e:
            print(f"数据库操作失败: {e}")
            return JSONResponse(
                status_code=400,
                content={"code": 400, "data": None, "message": "database operation failed"}
            )
        finally:
            if db_conn:
                db_conn.close()
        
        # 删除用户目录
        user_dir = os.path.join(path_images_from_camera, userCode)
        if os.path.exists(user_dir):
            import shutil
            shutil.rmtree(user_dir)
        
        # 自动重载特征数据
        global features_known_arr
        features_known_arr = LoadFeaturesFromDb()
        print(f"[del_face] 用户数据已删除，已自动重载特征数据，当前特征数量: {len(features_known_arr)}")
        
        return {
            "code": 200,
            "data": {
                "msg": "success",
                "errno": 0,
                "data": {
                    "log_id": str(int(time.time() * 1000)),
                    "message": "用户数据删除成功"
                }
            },
            "message": "SUCCESS"
        }
        
    except Exception as e:
        return JSONResponse(
            status_code=400,
            content={"code": 400, "data": str(e), "message": "FAILED"}
        )

@app.post("/api/reloadFeatures", response_model=FaceRecognitionResponse)
async def reload_features():
    """重新加载特征数据API"""
    try:
        global features_known_arr
        features_known_arr = LoadFeaturesFromDb()
        
        return {
            "code": 200,
            "data": {
                "msg": "success",
                "errno": 0,
                "data": {
                    "log_id": str(int(time.time() * 1000)),
                    "message": "特征数据重新加载成功",
                    "count": len(features_known_arr) if features_known_arr else 0
                }
            },
            "message": "SUCCESS"
        }
        
    except Exception as e:
        print(f"重新加载特征数据时发生错误: {e}")
        return JSONResponse(
            status_code=400,
            content={"code": 400, "data": str(e), "message": "FAILED"}
        )

@app.post("/api/getAllUsers", response_model=FaceRecognitionResponse)
async def get_all_users():
    """查询所有人员数据API"""
    try:
        # 确保数据库和表存在
        InitDb()
        
        # 查询数据库获取所有用户信息
        try:
            # 确保数据库目录存在
            db_dir = os.path.join(current_dir, 'data/db')
            os.makedirs(db_dir, exist_ok=True)
            
            db_path = os.path.join(db_dir, 'recdb.db')
            db_conn = sqlite3.connect(db_path)
            cursor = db_conn.cursor()
            cursor.execute("SELECT Uid, Name, IdNum FROM rcinfo")
            users = cursor.fetchall()
        except Exception as e:
            print(f"查询用户信息时出错: {e}")
            users = []
        finally:
            if 'db_conn' in locals():
                db_conn.close()
        
        # 构建用户列表
        user_list = []
        for user in users:
            user_id = user[0] or ""
            user_name = user[1] or ""
            id_num = user[2] or ""
            
            # 检查用户图像是否存在
            image_path = os.path.join(path_images_from_camera, user_id, f"{user_id}.jpg")
            face_url = f"http://localhost:12316/images/{user_id}.jpg" if os.path.exists(image_path) else ""
            
            user_list.append({
                "userCode": user_id,
                "userName": user_name,
                "idNum": id_num,
                "faceUrl": face_url,
                "faceUrl_Placeholder": f"http://^API_BASE_URL^/images/{user_id}.jpg"
            })
        
        return {
            "code": 200,
            "data": {
                "msg": "success",
                "errno": 0,
                "data": {
                    "users": user_list,
                    "count": len(user_list)
                }
            },
            "message": "SUCCESS"
        }
        
    except Exception as e:
        return JSONResponse(
            status_code=400,
            content={"code": 400, "data": str(e), "message": "FAILED"}
        )

@app.get("/images/{filename}")
async def serve_image(filename: str):
    """静态文件服务路由"""
    # 安全检查，防止路径遍历攻击
    if '..' in filename or filename.startswith('/'):
        raise HTTPException(status_code=404, detail="Not found")
    
    # 检查是否是用户目录下的图像
    user_id = filename.split('.')[0]
    image_path = os.path.join(path_images_from_camera, user_id, filename)
    
    # 如果文件不存在，尝试直接在图像目录中查找
    if not os.path.exists(image_path):
        image_path = os.path.join(path_images_from_camera, filename)
    
    # 检查文件是否存在
    if not os.path.exists(image_path):
        raise HTTPException(status_code=404, detail="Not found")
    
    # 返回图像文件
    return FileResponse(image_path)

def initialize_server():
    """初始化服务器"""
    print("[服务器初始化] 开始初始化服务器组件...")
    
    # 初始化数据库 - 确保在启动时创建表结构
    print("[服务器初始化] 开始初始化数据库...")
    InitDb()
    print("[服务器初始化] 数据库初始化完成")
    
    global features_known_arr, last_reload_time, user_info_map
    features_known_arr = []
    print("[服务器初始化] 开始加载人脸特征数据...")
    features_known_arr = LoadFeaturesFromDb()
    user_info_map = {}
    print(f"[服务器初始化] 人脸特征数据加载完成，当前特征数量: {len(features_known_arr)}")
    
    last_reload_time = 0
    try:
        if os.path.exists("reload_flag.txt"):
            last_reload_time = os.path.getmtime("reload_flag.txt")
            print(f"[initialize_server] 初始化最后重载时间为: {last_reload_time}")
    except Exception as e:
        print(f"[initialize_server] 获取重载标志文件修改时间失败: {e}")
        import traceback
        traceback.print_exc()
    
    print("[服务器初始化] 服务器组件初始化完成")

# 主程序入口点
if __name__ == "__main__":
    import uvicorn
    
    # 初始化服务器
    initialize_server()
    
    # 启动FastAPI应用
    print("FastAPI Web API服务已启动，监听端口 12316")
    uvicorn.run(app, host="0.0.0.0", port=12316)