#include "ANSFR.h"
#include <opencv2/imgcodecs.hpp>
#include "ANSOVFaceDetector.h"
#include "SCRFDFaceDetector.h"
#include "ANSFaceRecognizer.h"
#include <faiss/IndexIDMap.h>
#include <faiss/IndexFlat.h>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <json.hpp>

// Add this at the top of your header or before the function
//#define DEBUG_TIME

#ifdef DEBUG_TIME
#define TIME_POINT auto
#define START_TIMER(name) auto timer_##name = std::chrono::high_resolution_clock::now()
#define END_TIMER(name, label) \
    do { \
        auto timer_##name##_end = std::chrono::high_resolution_clock::now(); \
        auto duration_us = std::chrono::duration_cast<std::chrono::microseconds>(timer_##name##_end - timer_##name).count(); \
        std::cout << label << ": " << (duration_us / 1000.0) << " ms" << std::endl; \
    } while(0)
#define END_TIMER_STORE(name, var) \
    do { \
        auto timer_##name##_end = std::chrono::high_resolution_clock::now(); \
        var = std::chrono::duration_cast<std::chrono::microseconds>(timer_##name##_end - timer_##name).count(); \
    } while(0)
#else
#define START_TIMER(name)
#define END_TIMER(name, label)
#define END_TIMER_STORE(name, var)
#endif

static bool ansfrLicenceValid = false;
// Global once_flag to protect license checking
static std::once_flag ansfrLicenseOnceFlag;
namespace ANSCENTER {
    std::vector<FaceResultObject> FaceChecker::UniqueFaces(const std::vector<FaceResultObject>& faces) {
        std::lock_guard<std::recursive_mutex> lock(_mutex);
        try{
            std::unordered_map<std::string, FaceResultObject> uniqueFacesMap;
            for (const auto& face : faces) {
                std::string key = face.userId + "_" + face.userName + "_" + face.cameraId;

                // If the face with the same userId, userName, and cameraId is not in the map, add it
                if (uniqueFacesMap.find(key) == uniqueFacesMap.end()) {
                    uniqueFacesMap[key] = face;
                }
                else {
                    // If it already exists, compare confidence scores
                    if (face.confidence > uniqueFacesMap[key].confidence) {
                        // Update the map to store the face with the highest confidence
                        uniqueFacesMap[key] = face;
                    }
                }
            }

            std::vector<FaceResultObject> resultFaces;
            for (const auto& face : faces) {
                std::string key = face.userId + "_" + face.userName + "_" + face.cameraId;

                if (uniqueFacesMap[key].confidence == face.confidence) {
                    // Keep the highest confidence face
                    resultFaces.push_back(face);
                }
                else {
                    // Update the other duplicate face to be "Unknown"
                    FaceResultObject unknownFace = face;
                    unknownFace.userId = "0000";
                    unknownFace.userName = "Unknown";
                    resultFaces.push_back(unknownFace);
                }
            }

            return resultFaces;
        }
		catch (std::exception& e) {
			return std::vector<FaceResultObject>();
		}
      
    }
    std::vector<FaceResultObject> FaceChecker::ValidateDetectedFaces(const std::vector<FaceResultObject>& faces) {
        std::lock_guard<std::recursive_mutex> lock(_mutex);
        try {
            std::vector<FaceResultObject> detectedFaces;
            std::unordered_set<std::string> detectedFaceIds; // Store detected userIds for this frame

            for (const auto& faceResult : faces) {
                const std::string& cameraId = faceResult.cameraId;

                // Create a FaceDetection object
                FaceDetection detection;
                detection.faceObject = faceResult;
                detection.faceConfLevel = 1;

                // Get or create frame buffer for this camera
                auto& frameBuffer = frameBufferMap[cameraId];
                bool found = false;

                // If the face is already in the buffer, increase the confidence level and update the face in buffer
                for (auto& frame : frameBuffer) {
                    for (auto& detectionInBuffer : frame) {
                        if ((detectionInBuffer.faceObject.userId == detection.faceObject.userId) &&
                            (detectionInBuffer.faceObject.userName == detection.faceObject.userName) &&
                            (detectionInBuffer.faceObject.cameraId == detection.faceObject.cameraId) &&
                            (detection.faceObject.confidence > minScore))
                        {
                            // Found: Increase confidence & update face info
                            detectionInBuffer.faceConfLevel += 1;
							if (detectionInBuffer.faceConfLevel >= MAX_FACE_CHECKER_FRAMES) detectionInBuffer.faceConfLevel = MAX_FACE_CHECKER_FRAMES;
                            detectionInBuffer.faceObject = detection.faceObject;
                            detection.faceConfLevel = detectionInBuffer.faceConfLevel; // Sync confidence level
                            found = true;
                            break;
                        }
                    }
                }

                // Store detected faceId to avoid multiple decrements later
                detectedFaceIds.insert(detection.faceObject.userId);

                // If face not found in the buffer, add it (except for unknown faces)
                if (!found && detection.faceObject.userId != "0000") {
                    frameBuffer.push_back({ detection });
                }

                // Add face to the detected list
                if (detection.faceConfLevel >= FACE_CONFIDENT_LEVEL) {
                    detectedFaces.push_back(detection.faceObject);
                }
                else {
                    FaceResultObject unknownFace = detection.faceObject;
                    unknownFace.userId = "0000";
                    unknownFace.userName = "Unknown";
                    detectedFaces.push_back(unknownFace);
                }
            }

            // **Reduce confidence level for all faces in buffer ONCE if they were not detected**
            auto& frameBuffer = frameBufferMap[faces.empty() ? "" : faces[0].cameraId];  // Ensure buffer exists
            for (auto& frame : frameBuffer) {
                for (auto& detectionInBuffer : frame) {
                    if (detectedFaceIds.find(detectionInBuffer.faceObject.userId) == detectedFaceIds.end()) {
                        if (detectionInBuffer.faceConfLevel > 0) {
                            detectionInBuffer.faceConfLevel--; // Safe decrement
                        }
                    }
                }
            }

            // Remove faces in buffer if their confidence level is less than 0
            for (auto& frame : frameBuffer) {
                frame.erase(std::remove_if(frame.begin(), frame.end(),
                    [](const FaceDetection& detection) {
                        return detection.faceConfLevel < 0;
                    }),
                    frame.end());
            }

            // Remove empty frames from buffer
            frameBuffer.erase(std::remove_if(frameBuffer.begin(), frameBuffer.end(),
                [](const std::vector<FaceDetection>& frame) {
                    return frame.empty();
                }),
                frameBuffer.end());

            // If buffer reaches max size, remove the oldest frame
            if (frameBuffer.size() >= maxFrames) {
                frameBuffer.erase(frameBuffer.begin());
            }

            return UniqueFaces(detectedFaces);
        }
        catch (std::exception& e) {
            return std::vector<FaceResultObject>();
        }
    }
    /// <summary>
    /// Start Facial Recognition class
    /// </summary>
    static void VerifyGlobalANSFRLicense(const std::string& licenseKey) {
        try {
            ansfrLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1004, "ANSFR");//Default productId=1004 
            if (!ansfrLicenceValid) { // we also support ANSTS license
                ansfrLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1003, "ANSVIS");//Default productId=1003 (ANSVIS)
            }
        }
        catch (std::exception& e) {
			ansfrLicenceValid = false;
        }
    }
    void ANSFacialRecognition::CheckLicense() {   
        try {
            // Check once globally
            std::call_once(ansfrLicenseOnceFlag, [this]() {
                VerifyGlobalANSFRLicense(_licenseKey);
                });

            // Update this instance's local license flag
            _licenseValid = ansfrLicenceValid;
        }
        catch (const std::exception& e) {
            this->_logger.LogFatal("ANSODBase::CheckLicense. Error:", e.what(), __FILE__, __LINE__);
        }
    }
    ANSFacialRecognition::ANSFacialRecognition()
        : core(std::make_shared<ov::Core>()) 
    {
        _licenseValid = false;

    }
    int ANSFacialRecognition::Initialize(
        const std::string& licenseKey,
        const std::string& configFile,
        const std::string& databaseFilePath,
        const std::string& recognizerFilePath,
        const std::string& detectorFilePath,
        int precisionType,
        float knownPersonThreshold,
        bool enableAgeGender,
        bool enableFaceEmotions,
        bool enableHeadPose,
        int minFaceSize,
        float faceDetectorScoreThreshold,
        bool faceLiveness, 
        bool antiSpoofing)
    {
        try {
            // Store initialization parameters
            _licenseKey = licenseKey;
            _detectorFilePath = detectorFilePath;
            _recognizerFilePath = recognizerFilePath;
            _databaseFilePath = databaseFilePath;
            _precisionType = 2;  // Force FP32

            // Validate and set thresholds
            if (faceDetectorScoreThreshold <= 0.0f || faceDetectorScoreThreshold >= 1.0f) {
                _faceDetectorScoreThreshold = 0.5f;
                LogThreadSafe("ANSFacialRecognition::Initialize",
                    "Invalid detector threshold, using default: 0.5");
            }
            else {
                _faceDetectorScoreThreshold = faceDetectorScoreThreshold;
            }

            if (knownPersonThreshold <= 0.0f || knownPersonThreshold >= 1.0f) {
                _config._knownPersonThreshold = 0.35f;
                LogThreadSafe("ANSFacialRecognition::Initialize",
                    "Invalid known person threshold, using default: 0.35");
            }
            else {
                _config._knownPersonThreshold = knownPersonThreshold;
            }

            // Set minimum face size
            _minFaceSize = (minFaceSize > 0) ? minFaceSize : 50;

            // Configure feature flags
            {
                std::lock_guard<std::mutex> lock(_configMutex);

                _enableAgeGender = enableAgeGender;
                _enableFaceEmotions = enableFaceEmotions;
                _enableHeadPose = enableHeadPose;
                _enableAntiSpoof = antiSpoofing;
                _enableFaceliveness = faceLiveness;
                _enableFaceQueue = false;
                _queueSize = QUEUE_SIZE;
                _faceThresholdSize = FACE_THRESHOLD_SIZE;
                _removeFakeFaces = false;
            }

            // Validate license
            CheckLicense();
            if (!_licenseValid) {
                LogThreadSafe("ANSFacialRecognition::Initialize",
                    "Invalid license key");
                return 0;
            }

            // Detect hardware
#ifdef CPU_MODE
            engineType = EngineType::CPU;        
#else
            engineType = ANSLicenseHelper::CheckHardwareInformation();
#endif

            // Initialize configuration
            _config._databasePath = _databaseFilePath;
            _config._recOutputDim = 512;
            _config._detThresholdNMS = 0.5f;
            _config._detThresholdBbox = 0.80f;
            _config._videoFrameHeight = 480;
            _config._videoFrameWidth = 640;

            // Load config file if exists
            if (FileExist(configFile)) {
                if (!ANSFRHelper::LoadConfigFile(configFile, _config)) {
                    LogThreadSafe("ANSFacialRecognition::Initialize",
                        "Unable to load configuration file: " + configFile);
                }
                else {
                    // Restore database path if provided
                    if (!_databaseFilePath.empty()) {
                        _config._databasePath = _databaseFilePath;
                    }
                }
            }

            // Set model paths
            if (FileExist(_detectorFilePath)) {
                _config._detEngineFile = _detectorFilePath;
            }

            if (FileExist(_recognizerFilePath)) {
                _config._recEngineFile = _recognizerFilePath;
            }

            // Validate database path
            if (_config._databasePath.empty()) {
                LogThreadSafe("ANSFacialRecognition::Initialize",
                    "Invalid database path: empty");
                return -1;
            }

            // Create database folders
            std::string faceDatabaseFolder = GetParentFolder(_config._databasePath);
            if (!FolderExist(faceDatabaseFolder)) {
                std::filesystem::create_directories(faceDatabaseFolder);
            }

            _config._gen_imgSource = CreateFilePath(faceDatabaseFolder, "data");
            if (!FolderExist(_config._gen_imgSource)) {
                std::filesystem::create_directories(_config._gen_imgSource);
            }

            // Initialize database
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);

                if (!_db->Initialize(_config._databasePath, _config._recOutputDim, _config._gen_imgSource)) {
                    LogThreadSafe("ANSFacialRecognition::Initialize",
                        "Failed to initialize database: " + _config._databasePath);
                    return -2;
                }

                _userDict = _db->GetUserDict();
            }

            // Validate recognizer model
            if (!FileExist(_config._recEngineFile)) {
                LogThreadSafe("ANSFacialRecognition::Initialize",
                    "Recognizer model not found: " + _config._recEngineFile);
                return -3;
            }

            // Mark as initialized
            _isInitialized=true;

            return 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::Initialize",
                "Initialization failed: " + std::string(e.what()));

            _isInitialized=false;
            return -4;
        }
    }

    bool ANSFacialRecognition::LoadEngine() {
        try {
            // Unload existing engine (handles its own locking)
            UnloadEngine();

            // Initialize core components (lock during initialization)
            {
                std::lock_guard<std::mutex> lock(_configMutex);

                if (!InitializeDetector()) {
                    LogThreadSafe("ANSFacialRecognition::LoadEngine",
                        "Failed to initialize detector");
                    return false;
                }

                if (!InitializeRecognizer()) {
                    LogThreadSafe("ANSFacialRecognition::LoadEngine",
                        "Failed to initialize recognizer");
                    return false;
                }

                _recognizerModelFolder = _recognizer->GetModelFolder();
            }

            // Verify model folder exists
            if (!FolderExist(_recognizerModelFolder)) {
                LogThreadSafe("ANSFacialRecognition::LoadEngine",
                    "Model folder not found: " + _recognizerModelFolder);
                return false;
            }

            // Configure device
            std::string deviceName = GetOpenVINODevice();

            if (deviceName == "NPU") {
                // Configure NPU with GPU fallback
                try {
                    core->set_property("NPU",
                        ov::hint::performance_mode(ov::hint::PerformanceMode::LATENCY));
                    core->set_property("GPU",
                        ov::hint::performance_mode(ov::hint::PerformanceMode::LATENCY));
                    core->set_property("GPU",
                        ov::streams::num(ov::streams::AUTO));

                    deviceName = "AUTO:NPU,GPU";

                    LogThreadSafe("ANSFacialRecognition::LoadEngine",
                        "Configured NPU with GPU fallback");
                }
                catch (const std::exception& e) {
                    LogThreadSafe("ANSFacialRecognition::LoadEngine",
                        "Failed to configure NPU/GPU: " + std::string(e.what()));
                    // Fall back to default device
                }
            }

            // Initialize attribute detection models
            bool attributeModelsSuccess = true;

            if (!InitializeAntispoofingModel(deviceName)) {
                LogThreadSafe("ANSFacialRecognition::LoadEngine",
                    "Warning: Failed to initialize anti-spoofing model");
                attributeModelsSuccess = false;
            }

            if (!InitializeAgeGenderModel(deviceName)) {
                LogThreadSafe("ANSFacialRecognition::LoadEngine",
                    "Warning: Failed to initialize age-gender model");
                attributeModelsSuccess = false;
            }

            if (!InitializeEmotionModel(deviceName)) {
                LogThreadSafe("ANSFacialRecognition::LoadEngine",
                    "Warning: Failed to initialize emotion model");
                attributeModelsSuccess = false;
            }

            if (!InitializeHeadPoseModel(deviceName)) {
                LogThreadSafe("ANSFacialRecognition::LoadEngine",
                    "Warning: Failed to initialize head pose model");
                attributeModelsSuccess = false;
            }

            // Reload database/embeddings
            if (!Reload()) {
                LogThreadSafe("ANSFacialRecognition::LoadEngine",
                    "Failed to reload database/embeddings");
                return false;
            }

            // Mark as initialized
            {
                std::lock_guard<std::mutex> lock(_configMutex);
                _isInitialized = true;
            }

            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::LoadEngine", e.what());

            // Mark as not initialized on failure
            {
                std::lock_guard<std::mutex> lock(_configMutex);
                _isInitialized = false;
            }

            return false;
        }
    }
    void ANSFacialRecognition::UnloadEngine() {
        try {
            // Clean up detector
            {
                std::lock_guard<std::mutex> lock(_detectionMutex);
                if (_detector) _detector.reset();
            }

            // Clean up recognizer
            {
                std::lock_guard<std::mutex> lock(_recognitionMutex);
                if (_recognizer) _recognizer.reset();
            }

            // Clean up anti-spoofing detector
            {
                std::lock_guard<std::mutex> lock(_antispoofMutex);
                if (_antiSpoofDetector) _antiSpoofDetector.reset();
            }

            // Clean up age-gender detector
            {
                std::lock_guard<std::mutex> lock(_ageGenderMutex);
                if (_ageGenderDetector) _ageGenderDetector.reset();
            }

            // Clean up emotions detector
            {
                std::lock_guard<std::mutex> lock(_emotionsMutex);
                if (_emotionsDetector) _emotionsDetector.reset();
            }

            // Clean up head pose detector
            {
                std::lock_guard<std::mutex> lock(_headPoseMutex);
                if (_headPoseDetector) _headPoseDetector.reset();
            }

            // Clear user dictionary
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                _userDict.clear();
            }
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::UnloadEngine",
                "Error during unload: " + std::string(e.what()));
        }
    }
    bool ANSFacialRecognition::Reload() {
        try {
            // Skip rebuild if index is already up-to-date (no mutations since last Reload).
            // exchange(false) atomically reads + clears: if it was already false, nothing to do.
            if (!_reloadNeeded.exchange(false)) {
                LogThreadSafe("ANSFacialRecognition::Reload",
                    "Index already up-to-date, skipping rebuild", LogLevel::Debug);
                return true;
            }

            // Validate initialization first (without locks)
            if (!_recognizer) {
                LogThreadSafe("ANSFacialRecognition::Reload",
                    "Recognizer not initialized");
                _reloadNeeded.store(true);  // Restore flag — reload still needed
                return false;
            }

            if (!_db) {
                LogThreadSafe("ANSFacialRecognition::Reload",
                    "Database not initialized");
                _reloadNeeded.store(true);  // Restore flag — reload still needed
                return false;
            }

            // ============================================================
            // PHASE 1: Build new index in temporary structures (NO INDEX LOCK)
            //   Inference continues unblocked using the old index.
            // ============================================================

            auto* concreteRecognizer = dynamic_cast<ANSFaceRecognizer*>(_recognizer.get());
            if (!concreteRecognizer) {
                LogThreadSafe("ANSFacialRecognition::Reload",
                    "Recognizer is not ANSFaceRecognizer type");
                _reloadNeeded.store(true);  // Restore flag — reload still needed
                return false;
            }
            int embeddingSize = concreteRecognizer->GetEmbeddingSize();

            std::unordered_map<faiss::idx_t, std::string> newFaceIdToUserId;
            std::map<std::string, std::string> newUserDict;

            // Read all data from database into temporaries
            std::vector<float> allEmbeddings;
            std::vector<faiss::idx_t> allIds;

            {
                std::lock_guard<std::mutex> lock(_databaseMutex);

                std::vector<FaceEmbeddingRecord> records;
                int rc = _db->GetAllEmbeddingRecords(records);
                if (rc != 0) {
                    LogThreadSafe("ANSFacialRecognition::Reload",
                        "Failed to load embedding records from database");
                    _reloadNeeded.store(true);  // Restore flag — reload still needed
                    return false;
                }

                // Pre-allocate for bulk GPU transfer
                allEmbeddings.reserve(records.size() * embeddingSize);
                allIds.reserve(records.size());

                for (const auto& record : records) {
                    faiss::idx_t faceId = static_cast<faiss::idx_t>(record.faceId);
                    newFaceIdToUserId[faceId] = record.userId;
                    allIds.push_back(faceId);

                    // L2-normalize before storing (IP metric on unit vectors = cosine sim)
                    std::vector<float> normEmb = record.embedding;
                    ANSFaceRecognizer::L2NormalizeInPlace(normEmb);
                    allEmbeddings.insert(allEmbeddings.end(), normEmb.begin(), normEmb.end());
                }

                newUserDict = _db->GetUserDict();
            }

            // Always build FAISS index on CPU. This avoids thread-safety issues with
            // FAISS GPU StandardGpuResources (not thread-safe) — Reload() can run
            // concurrently with inference without sharing GPU memory pools.
            // CPU FAISS search is fast enough for face databases (<5ms for 10K faces)
            // and is a negligible fraction of total inference time.
            auto cpuIndex = new faiss::IndexFlatIP(embeddingSize);
            auto newFaissIndex = std::make_shared<faiss::IndexIDMap>(cpuIndex);
            newFaissIndex->own_fields = true;

            if (!allIds.empty()) {
                newFaissIndex->add_with_ids(
                    static_cast<faiss::idx_t>(allIds.size()),
                    allEmbeddings.data(), allIds.data());
            }

            LogThreadSafe("ANSFacialRecognition::Reload",
                "Built new index with " + std::to_string(newFaissIndex->ntotal) +
                " embeddings, " + std::to_string(newUserDict.size()) + " users", LogLevel::Info);

            // ============================================================
            // PHASE 2: Atomic swap (brief exclusive lock ~microseconds)
            //   Inference is blocked only during this swap.
            // ============================================================
            {
                std::unique_lock<std::shared_mutex> lock(_indexSwapMutex);
                concreteRecognizer->SwapIndex(
                    std::move(newFaissIndex),
                    std::move(newFaceIdToUserId));
                _userDict = std::move(newUserDict);
            }

            LogThreadSafe("ANSFacialRecognition::Reload",
                "Index swap completed successfully", LogLevel::Info);

            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::Reload",
                "Failed to reload: " + std::string(e.what()));
            _reloadNeeded.store(true);  // Restore flag — reload still needed
            return false;
        }
    }
    bool ANSFacialRecognition::UpdateUserDictionary() {
        try {
            // Validate database initialization first (without lock)
            if (!_db) {
                LogThreadSafe("ANSFacialRecognition::UpdateUserDictionary",
                    "Database not initialized");
                return false;
            }

            // Load user dictionary with database lock
            std::map<std::string, std::string>	newUserDict;

            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                newUserDict = _db->GetUserDict();
            }

            // Validate the loaded dictionary
            if (newUserDict.empty()) {
                LogThreadSafe("ANSFacialRecognition::UpdateUserDictionary",
                    "Warning: User dictionary is empty");
            }

            // Swap userDict under exclusive lock (same lock as Reload)
            {
                std::unique_lock<std::shared_mutex> lock(_indexSwapMutex);
                _userDict = std::move(newUserDict);
            }
            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::UpdateUserDictionary",
                "Failed to update user dictionary: " + std::string(e.what()));
            return false;
        }
    }
    ANSFacialRecognition::~ANSFacialRecognition() noexcept {
        try {
            // Destroy engine and resources
            Destroy();

            // Clean up camera data
            {
                std::lock_guard<std::mutex> lock(_cameraMutex);
                for (auto& [cameraId, cameraData] : _cameras) {
                    cameraData.clear();
                }
                _cameras.clear();
            }
        }
        catch (const std::exception& e) {
            // Log but don't throw from destructor
            LogThreadSafe("ANSFacialRecognition::Destructor",
                "Error during destruction: " + std::string(e.what()));
        }
        catch (...) {
            // Catch all other exceptions - never throw from destructor
        }
    }
    void ANSFacialRecognition::Destroy() {
        try {
            // Unload engine (handles its own locking)
            UnloadEngine();

            // Clean up database connection
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                if (_db) _db.reset();
            }
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::Destroy",
                "Error during cleanup: " + std::string(e.what()));
        }
    }
    ModelConfig ANSFacialRecognition::CreateDetectorModelConfig() {
        // NO LOCK NEEDED - Reading configuration values only
        try {
            ModelConfig config;
            config.modelType = ANSCENTER::ModelType::FACEDETECT;
            config.detectionType = ANSCENTER::DetectionType::FACEDETECTOR;
            config.precisionType = static_cast<ANSCENTER::PrecisionType>(_precisionType);
            config.autoGPUDetection = true;
            config.modelMNSThreshold = _config._detThresholdNMS;
            config.detectionScoreThreshold = _config._detThresholdBbox;
            config.modelConfThreshold = 0.48f;

            return config;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::CreateDetectorModelConfig",
                "Failed to create config: " + std::string(e.what()));
            return ModelConfig();
        }
    }

    bool ANSFacialRecognition::InitializeDetector() {
        try {
            // Create model configuration
            ModelConfig detectorConfig = CreateDetectorModelConfig();
            detectorConfig.detectionScoreThreshold = _faceDetectorScoreThreshold;

            // Create appropriate detector based on engine type
            if (engineType == EngineType::NVIDIA_GPU) {
                _detector = std::make_unique<ANSSCRFDFD>();
            }
            else {
                _detector = std::make_unique<ANSOVFD>();
            }

            // LOCK DURING INITIALIZATION
            bool initSuccess;
            {
                std::lock_guard<std::mutex> lock(_detectionMutex);

                std::string labelMap;
                initSuccess = _detector->Initialize(
                    _licenseKey,
                    detectorConfig,
                    _detectorFilePath,
                    "",
                    labelMap
                );

                if (initSuccess) {
                    // Update detection threshold after initialization
                    initSuccess = _detector->UpdateDetectionThreshold(_faceDetectorScoreThreshold);
                }
            }

            if (!initSuccess) {
                LogThreadSafe("ANSFacialRecognition::InitializeDetector",
                    "Failed to initialize detector - check file path: " + _detectorFilePath);
                return false;
            }

            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InitializeDetector",
                "Failed to initialize: " + std::string(e.what()));
            return false;
        }
    }
    bool ANSFacialRecognition::InitializeRecognizer() {
        try {
            // Create recognizer instance
            _recognizer = std::make_unique<ANSFaceRecognizer>();

            // Configure model
            ModelConfig recognizerConfig;
            recognizerConfig.modelType = ANSCENTER::ModelType::FACERECOGNIZE;
            recognizerConfig.detectionType = ANSCENTER::DetectionType::FACERECOGNIZER;
            recognizerConfig.precisionType = ANSCENTER::PrecisionType::FP32;
            recognizerConfig.autoGPUDetection = true;
            recognizerConfig.modelMNSThreshold = _config._detThresholdNMS;
            recognizerConfig.detectionScoreThreshold = _config._detThresholdBbox;
            recognizerConfig.modelConfThreshold = 0.48f;
            recognizerConfig.unknownPersonThreshold = _config._knownPersonThreshold;

            // LOCK DURING INITIALIZATION
            std::string labelMap;
            bool initSuccess;

            {
                std::lock_guard<std::mutex> lock(_recognitionMutex);

                initSuccess = _recognizer->Initialize(
                    _licenseKey,
                    recognizerConfig,
                    _recognizerFilePath,
                    "",
                    labelMap
                );
            }

            if (!initSuccess) {
                LogThreadSafe("ANSFacialRecognition::InitializeRecognizer",
                    "Failed to initialize recognizer - check file path: " + _recognizerFilePath);
                return false;
            }

            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InitializeRecognizer",
                "Failed to initialize: " + std::string(e.what()));
            return false;
        }
    }
    bool ANSFacialRecognition::InitializeAntispoofingModel(const std::string& deviceName) {
        try {
            std::string antispoofModelPath = CreateFilePath(_recognizerModelFolder, "antispoof.xml");

            if (!FileExist(antispoofModelPath)) {
                LogThreadSafe("ANSFacialRecognition::InitializeAntispoofingModel",
                    "Anti-spoofing model not found: " + antispoofModelPath);

                // Disable anti-spoofing if model not available
                {
                    std::lock_guard<std::mutex> lock(_configMutex);
                    _enableAntiSpoof = false;
                }

                return false;
            }

            // LOCK ONLY DURING MODEL INITIALIZATION
            {
                std::lock_guard<std::mutex> lock(_antispoofMutex);

                // Reset existing detector
                _antiSpoofDetector.reset();

                // Create new detector
                _antiSpoofDetector = std::make_unique<AntispoofingClassifier>(antispoofModelPath, true);

                // Compile model for target device
                ov::CompiledModel compiledModel = core->compile_model(
                    _antiSpoofDetector->read(*core),
                    deviceName
                );

                // Create inference request
                _antiSpoofDetector->request = compiledModel.create_infer_request();
                _antiSpoofDetector->inTensor = _antiSpoofDetector->request.get_input_tensor();
                _antiSpoofDetector->inTensor.set_shape(_antiSpoofDetector->inShape);
            }
            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InitializeAntispoofingModel",
                "Failed to initialize: " + std::string(e.what()));

            // Disable anti-spoofing on failure
            {
                std::lock_guard<std::mutex> lock(_configMutex);
                _enableAntiSpoof = false;
            }

            return false;
        }
    }
    bool ANSFacialRecognition::InitializeAgeGenderModel(const std::string& deviceName) {
        try {
            std::string ageGenderModelPath = CreateFilePath(_recognizerModelFolder, "agegender.xml");

            if (!FileExist(ageGenderModelPath)) {
                LogThreadSafe("ANSFacialRecognition::InitializeAgeGenderModel",
                    "Age-gender model not found: " + ageGenderModelPath);

                // Disable age-gender detection if model not available
                {
                    std::lock_guard<std::mutex> lock(_configMutex);
                    _enableAgeGender = false;
                }

                return false;
            }

            // LOCK ONLY DURING MODEL INITIALIZATION
            {
                std::lock_guard<std::mutex> lock(_ageGenderMutex);

                // Reset existing detector
                _ageGenderDetector.reset();

                // Create new detector
                _ageGenderDetector = std::make_unique<AgeGenderDetection>(ageGenderModelPath, true);

                // Compile model for target device
                ov::CompiledModel compiledModel = core->compile_model(
                    _ageGenderDetector->read(*core),
                    deviceName
                );

                // Create inference request
                _ageGenderDetector->request = compiledModel.create_infer_request();
                _ageGenderDetector->inTensor = _ageGenderDetector->request.get_input_tensor();
                _ageGenderDetector->inTensor.set_shape(_ageGenderDetector->inShape);
            }

            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InitializeAgeGenderModel",
                "Failed to initialize: " + std::string(e.what()));
            // Disable age-gender detection on failure
            {
                std::lock_guard<std::mutex> lock(_configMutex);
                _enableAgeGender = false;
            }

            return false;
        }
    }
    bool ANSFacialRecognition::InitializeEmotionModel(const std::string& deviceName) {
        try {
            std::string emotionModelPath = CreateFilePath(_recognizerModelFolder, "emotionsrecognition.xml");

            if (!FileExist(emotionModelPath)) {
                LogThreadSafe("ANSFacialRecognition::InitializeEmotionModel",
                    "Emotion model not found: " + emotionModelPath);

                // Disable emotion detection if model not available
                {
                    std::lock_guard<std::mutex> lock(_configMutex);
                    _enableFaceEmotions = false;
                }

                return false;
            }

            // LOCK ONLY DURING MODEL INITIALIZATION
            {
                std::lock_guard<std::mutex> lock(_emotionsMutex);

                // Reset existing detector
                _emotionsDetector.reset();

                // Create new detector
                _emotionsDetector = std::make_unique<EmotionsDetection>(emotionModelPath, true);

                // Compile model for target device
                ov::CompiledModel compiledModel = core->compile_model(
                    _emotionsDetector->read(*core),
                    deviceName
                );

                // Create inference request
                _emotionsDetector->request = compiledModel.create_infer_request();
                _emotionsDetector->inTensor = _emotionsDetector->request.get_input_tensor();
                _emotionsDetector->inTensor.set_shape(_emotionsDetector->inShape);
            }

            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InitializeEmotionModel",
                "Failed to initialize: " + std::string(e.what()));

            // Disable emotion detection on failure
            {
                std::lock_guard<std::mutex> lock(_configMutex);
                _enableFaceEmotions = false;
            }

            return false;
        }
    }
    bool ANSFacialRecognition::InitializeHeadPoseModel(const std::string& deviceName) {
        try {
            std::string headPoseModelPath = CreateFilePath(_recognizerModelFolder, "headpose.xml");

            if (!FileExist(headPoseModelPath)) {
                LogThreadSafe("ANSFacialRecognition::InitializeHeadPoseModel",
                    "Head pose model not found: " + headPoseModelPath);

                // Disable head pose detection if model not available
                {
                    std::lock_guard<std::mutex> lock(_configMutex);
                    _enableHeadPose = false;
                }

                return false;
            }

            // LOCK ONLY DURING MODEL INITIALIZATION
            {
                std::lock_guard<std::mutex> lock(_headPoseMutex);

                // Reset existing detector
                _headPoseDetector.reset();

                // Create new detector
                _headPoseDetector = std::make_unique<HeadPoseDetection>(headPoseModelPath, true);

                // Compile model for target device
                ov::CompiledModel compiledModel = core->compile_model(
                    _headPoseDetector->read(*core),
                    deviceName
                );

                // Create inference request
                _headPoseDetector->request = compiledModel.create_infer_request();
                _headPoseDetector->inTensor = _headPoseDetector->request.get_input_tensor();
                _headPoseDetector->inTensor.set_shape(_headPoseDetector->inShape);
            }
            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InitializeHeadPoseModel",
                "Failed to initialize: " + std::string(e.what()));

            // Disable head pose on failure
            {
                std::lock_guard<std::mutex> lock(_configMutex);
                _enableHeadPose = false;
            }

            return false;
        }
    }
    
    bool ANSFacialRecognition::UpdateParameters(
        float knownPersonThreshold,
        bool enableAgeGender,
        bool enableFaceEmotions,
        bool enableHeadPose,
        int minFaceSize,
        float faceDetectorScoreThreshold,
        bool faceLiveness, 
        bool antiSpoof,
        bool removeFakeFace)
    {
        // Validate inputs
        if (knownPersonThreshold < 0.0f || knownPersonThreshold > 1.0f) {
            LogThreadSafe("ANSFacialRecognition::UpdateParameters",
                "Invalid known person threshold: " + std::to_string(knownPersonThreshold) +
                " (valid range: 0.0-1.0)");
            return false;
        }

        if (faceDetectorScoreThreshold < 0.0f || faceDetectorScoreThreshold > 1.0f) {
            LogThreadSafe("ANSFacialRecognition::UpdateParameters",
                "Invalid detector threshold: " + std::to_string(faceDetectorScoreThreshold) +
                " (valid range: 0.0-1.0)");
            return false;
        }

        try {
            // Update configuration (with config lock)
            {
                std::lock_guard<std::mutex> lock(_configMutex);

                _enableAgeGender = enableAgeGender;
                _enableFaceEmotions = enableFaceEmotions;
                _enableHeadPose = enableHeadPose;
                _enableAntiSpoof = antiSpoof;
                _enableFaceliveness = faceLiveness;
				_removeFakeFaces = removeFakeFace;
                // Enforce minimum face size
                _minFaceSize = (minFaceSize > 0) ? minFaceSize : 30;
            }
            // Update recognizer (with recognition lock)
            bool recognizerUpdateResult = false;
            {
                std::lock_guard<std::mutex> lock(_recognitionMutex);

                if (_recognizer) {
                    recognizerUpdateResult = _recognizer->UpdateParamater(knownPersonThreshold);

                    if (recognizerUpdateResult) {
                        _config._knownPersonThreshold = knownPersonThreshold;
                    }
                    else {
                        LogThreadSafe("ANSFacialRecognition::UpdateParameters",
                            "Failed to update face recognizer with threshold " +
                            std::to_string(knownPersonThreshold));
                    }
                }
                else {
                    LogThreadSafe("ANSFacialRecognition::UpdateParameters",
                        "Recognizer not initialized");
                }
            }

            // Update detector (with detection lock)
            bool detectorUpdateResult = true;
            if (faceDetectorScoreThreshold > 0.0f) {
                std::lock_guard<std::mutex> lock(_detectionMutex);

                if (_detector) {
                    detectorUpdateResult = _detector->UpdateDetectionThreshold(faceDetectorScoreThreshold);

                    if (detectorUpdateResult) {
                        _faceDetectorScoreThreshold = faceDetectorScoreThreshold;
                    }
                    else {
                        LogThreadSafe("ANSFacialRecognition::UpdateParameters",
                            "Failed to update face detector with threshold " +
                            std::to_string(faceDetectorScoreThreshold));
                    }
                }
                else {
                    LogThreadSafe("ANSFacialRecognition::UpdateParameters",
                        "Detector not initialized");
                    detectorUpdateResult = false;
                }
            }

            return recognizerUpdateResult && detectorUpdateResult;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::UpdateParameters", e.what());
            return false;
        }
    }
    bool ANSFacialRecognition::GetFaceParameters(
        float& knownPersonThreshold,
        bool& enableAgeGender,
        bool& enableFaceEmotions,
        bool& enableHeadPose,
        int& minFaceSize,
        float& faceDetectorScoreThreshold,
        bool& faceLiveness,
        bool& antiSpoof,
        bool& removeFakeFaces)
    {
        try {
            // LOCK DURING CONFIGURATION READ
            std::lock_guard<std::mutex> lock(_configMutex);

            knownPersonThreshold = this->_config._knownPersonThreshold;
            enableAgeGender = this->_enableAgeGender;
            enableFaceEmotions = this->_enableFaceEmotions;
            enableHeadPose = this->_enableHeadPose;
            minFaceSize = this->_minFaceSize;
            faceLiveness = this->_enableFaceliveness;
			antiSpoof = this->_enableAntiSpoof;
			removeFakeFaces = this->_removeFakeFaces;

            // Detector threshold may need detection mutex if detector state can change
            if (_detector) {
                faceDetectorScoreThreshold = _detector->GetDetectionThreshold();
            }
            else {
                faceDetectorScoreThreshold = this->_faceDetectorScoreThreshold;
                LogThreadSafe("ANSFacialRecognition::GetFaceParameters",
                    "Detector not initialized");
            }

            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetFaceParameters", e.what());
            return false;
        }
    }


    bool ANSFacialRecognition::UpdateFaceQueue(int queueSize,int faceThresholdSize,bool enableFaceQueue)
    {
        try {
            // LOCK DURING CONFIGURATION UPDATE
            std::lock_guard<std::mutex> lock(_configMutex);

            _queueSize = queueSize;
            _faceThresholdSize = faceThresholdSize;
            _enableFaceQueue = enableFaceQueue;
            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::UpdateFaceQueue", e.what());
            return false;
        }
    }
    bool ANSFacialRecognition::GetFaceQueue(int& queueSize,int& faceThresholdSize,bool& enableFaceQueue)
    {
        try {
            std::lock_guard<std::mutex> lock(_configMutex);
            queueSize = _queueSize;
            faceThresholdSize = _faceThresholdSize;
            enableFaceQueue = _enableFaceQueue;
            return true;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetFaceQueue", e.what());
            return false;
        }
    }
    int ANSFacialRecognition::InsertUser(const std::string& userCode,const std::string& userName)
    {
        try {
            int userId;
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                userId = _db->InsertUser(userCode, userName);
            }

            if (userId <= 0) {
                LogThreadSafe("ANSFacialRecognition::InsertUser",
                    "Failed to insert user: " + userCode);
            }

            return userId;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InsertUser",
                "User code " + userCode + ": " + e.what());
            return 0;
        }
    }
    int ANSFacialRecognition::DeleteUser(int userId) {
        try {
            // First delete all faces for this user
            int result = DeleteFacesByUser(userId);
            // Then delete the user record (lock during database access)
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                result = _db->DeleteUser(userId);
            }

            if (result <= 0) {
                LogThreadSafe("ANSFacialRecognition::DeleteUser",
                    "Failed to delete user ID " + std::to_string(userId) + " from database");
            }
            else {
                // User record deleted — mark dirty so Reload() refreshes _userDict.
                // (DeleteFacesByUser above already reloaded for face removal;
                //  this second Reload rebuilds _userDict without the deleted user.)
                _reloadNeeded.store(true);
                Reload();
            }

            return result;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::DeleteUser",
                "User ID " + std::to_string(userId) + ": " + e.what());
            return 0;
        }
    }
    int ANSFacialRecognition::DeleteUsers(const std::vector<int>& userIds) {
        int deletedCount = 0;
        for (int userId : userIds) {
            try {
                // First delete all faces for this user
                DeleteFacesByUser(userId);
                // Then delete the user record (lock during database access)
                int result;
                {
                    std::lock_guard<std::mutex> lock(_databaseMutex);
                    result = _db->DeleteUser(userId);
                }
                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::DeleteUsers",
                        "Failed to delete user ID " + std::to_string(userId) + " from database");
                }
                else {
                    deletedCount++;
                }
            }
            catch (const std::exception& e) {
                LogThreadSafe("ANSFacialRecognition::DeleteUsers",
                    "User ID " + std::to_string(userId) + ": " + e.what());
            }
        }
        if (deletedCount > 0) {
            _reloadNeeded.store(true);
            Reload();
        }
        return deletedCount;
    }
    int ANSFacialRecognition::InsertFace(int userId, const cv::Mat& image) {
        // Early validation checks (read-only, thread-safe)
        if (!ValidateInput(image)) {
            return 0;
        }

        try {
            // Prepare input frame (CPU operation, independent)
            cv::Mat frame = PrepareInputFrame(image);
            if (frame.empty()) {
                LogThreadSafe("ANSFacialRecognition::InsertFace",
                    "Failed to prepare input frame for user ID " + std::to_string(userId));
                return 0;
            }

            // LOCK ONLY DURING DETECTION (shared detector)
            std::vector<Object> detectedFaces;
            {
                std::lock_guard<std::mutex> lock(_detectionMutex);
                detectedFaces = _detector->RunInference(frame, "", false, true, false);
            }

            if (detectedFaces.empty()) {
                LogThreadSafe("ANSFacialRecognition::InsertFace",
                    "No faces detected for user ID " + std::to_string(userId));
                return 0;
            }

            // Get largest face (CPU operation)
            Object faceObject = GetLargestObject(detectedFaces);

            // LOCK ONLY DURING RECOGNITION (shared recognizer)
            std::vector<float> embedding;
            {
                std::lock_guard<std::mutex> lock(_recognitionMutex);
                embedding = _recognizer->Feature(frame, faceObject);
            }

            // Validate embedding
            if (embedding.empty() || embedding.size() != _config._recOutputDim) {
                LogThreadSafe("ANSFacialRecognition::InsertFace",
                    "Invalid embedding generated for user ID " + std::to_string(userId) +
                    " (size: " + std::to_string(embedding.size()) + ")");
                return 0;
            }

            // Prepare storage folder (filesystem operation, no lock)
            std::string userImageFolderName = "User" + std::to_string(userId);
            std::string imageFolder = CreateFilePath(_config._gen_imgSource, userImageFolderName);

            if (!FolderExist(imageFolder)) {
                try {
                    std::filesystem::create_directory(imageFolder);
                }
                catch (const std::filesystem::filesystem_error& e) {
                    LogThreadSafe("ANSFacialRecognition::InsertFace",
                        "Failed to create directory for user ID " + std::to_string(userId) +
                        ": " + e.what());
                    return 0;
                }
            }

            // Generate unique filename
            boost::uuids::uuid uuid = boost::uuids::random_generator()();
            std::string imageFileName = Underscore2Dash(boost::uuids::to_string(uuid)) + ".jpg";
            std::string imagePath = CreateFilePath(imageFolder, imageFileName);

            // Save face image
            if (!cv::imwrite(imagePath, faceObject.mask)) {
                LogThreadSafe("ANSFacialRecognition::InsertFace",
                    "Failed to save face image for user ID " + std::to_string(userId));
                return 0;
            }

            // Verify file was created
            if (!FileExist(imagePath)) {
                LogThreadSafe("ANSFacialRecognition::InsertFace",
                    "Image file verification failed for user ID " + std::to_string(userId) +
                    " at path: " + imagePath);
                return 0;
            }

            // Insert into database (lock during database access)
            int faceId;
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                faceId = _db->InsertFace(userId, imagePath, embedding.data());
            }

            if (faceId <= 0) {
                LogThreadSafe("ANSFacialRecognition::InsertFace",
                    "Failed to insert face into database for user ID " + std::to_string(userId));
            }
            else {
                // Fix #3: Auto-reload FAISS index so new face is searchable immediately
                _reloadNeeded.store(true);
                Reload();
            }

            return faceId;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InsertFace",
                "User ID " + std::to_string(userId) + ": " + e.what());
            return 0;
        }
    }
    std::vector<int> ANSFacialRecognition::InsertMultipleFaces(int userId, const cv::Mat& image) {
        std::vector<int> faceIds;
        // Early validation checks (read-only, thread-safe)
        if (!ValidateInput(image)) {
            return faceIds;
        }

        try {
            // Prepare input frame (CPU operation, independent)
            cv::Mat frame = PrepareInputFrame(image);
            if (frame.empty()) {
                LogThreadSafe("ANSFacialRecognition::InsertMultipleFaces",
                    "Failed to prepare input frame for user ID " + std::to_string(userId));
                return faceIds;
            }

            // LOCK ONLY DURING DETECTION (shared detector)
            std::vector<Object> detectedFaces;
            {
                std::lock_guard<std::mutex> lock(_detectionMutex);
                detectedFaces = _detector->RunInference(frame, "", false, true, false);
            }

            if (detectedFaces.empty()) {
                LogThreadSafe("ANSFacialRecognition::InsertMultipleFaces",
                    "No faces detected for user ID " + std::to_string(userId));
                return faceIds;
            }

            // Get largest face
            Object faceObject = GetLargestObject(detectedFaces);

            // LOCK ONLY DURING RECOGNITION (shared recognizer)
            std::vector<float> embedding;
            {
                std::lock_guard<std::mutex> lock(_recognitionMutex);
                embedding = _recognizer->Feature(frame, faceObject);
            }

            if (embedding.empty() || embedding.size() != _config._recOutputDim) {
                LogThreadSafe("ANSFacialRecognition::InsertMultipleFaces",
                    "Invalid embedding generated for user ID " + std::to_string(userId));
                return faceIds;
            }

            // Prepare storage folder (filesystem operation, no lock)
            std::string userImageFolderName = "User" + std::to_string(userId);
            std::string imageFolder = CreateFilePath(_config._gen_imgSource, userImageFolderName);

            if (!FolderExist(imageFolder)) {
                std::filesystem::create_directory(imageFolder);
            }

            // Generate unique filename
            boost::uuids::uuid uuid = boost::uuids::random_generator()();
            std::string imageFileName = Underscore2Dash(boost::uuids::to_string(uuid)) + ".jpg";
            std::string imagePath = CreateFilePath(imageFolder, imageFileName);

            // Save face image
            if (!cv::imwrite(imagePath, faceObject.mask)) {
                LogThreadSafe("ANSFacialRecognition::InsertMultipleFaces",
                    "Failed to save face image for user ID " + std::to_string(userId));
                return faceIds;
            }

            if (!FileExist(imagePath)) {
                LogThreadSafe("ANSFacialRecognition::InsertMultipleFaces",
                    "Image file verification failed for user ID " + std::to_string(userId));
                return faceIds;
            }

            // Insert into database (lock during database access)
            int faceId;
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                faceId = _db->InsertFace(userId, imagePath, embedding.data());
            }

            if (faceId > 0) {
                faceIds.push_back(faceId);
            }
            else {
                LogThreadSafe("ANSFacialRecognition::InsertMultipleFaces",
                    "Failed to insert face into database for user ID " + std::to_string(userId));
            }

            // Auto-reload FAISS index so newly inserted faces are searchable
            if (!faceIds.empty()) {
                _reloadNeeded.store(true);
                Reload();
            }

            return faceIds;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::InsertMultipleFaces",
                "User ID " + std::to_string(userId) + ": " + e.what());
            return faceIds;
        }
    }  
    int ANSFacialRecognition::DeleteFace(int faceId) {
        try {
            int result;
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                result = _db->DeleteFace(faceId);
            }

            if (result <= 0) {
                LogThreadSafe("ANSFacialRecognition::DeleteFace",
                    "Failed to delete face ID " + std::to_string(faceId));
            }
            else {
                // Fix #3: Auto-reload FAISS index so deleted face is no longer searchable
                _reloadNeeded.store(true);
                Reload();
            }

            return result;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::DeleteFace",
                "Face ID " + std::to_string(faceId) + ": " + e.what());
            return 0;
        }
    }
    int ANSFacialRecognition::UpdateUser(int userId, const std::string& userCode, const std::string& userName)
    {
        try {
            // Validate input
            if (userId <= 0) {
                LogThreadSafe("ANSFacialRecognition::UpdateUser",
                    "Invalid user ID: " + std::to_string(userId));
                return 0;
            }

            if (userCode.empty() && userName.empty()) {
                LogThreadSafe("ANSFacialRecognition::UpdateUser",
                    "Both userCode and userName are empty for user ID " + std::to_string(userId));
                return 0;
            }

            // Validate database initialization
            if (!_db) {
                LogThreadSafe("ANSFacialRecognition::UpdateUser",
                    "Database not initialized");
                return 0;
            }

            // Update user in database
            int result;
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                result = _db->UpdateUser(userId, userCode, userName);
            }

            if (result <= 0) {
                LogThreadSafe("ANSFacialRecognition::UpdateUser",
                    "Failed to update user ID " + std::to_string(userId) + " in database");
                return 0;
            }

            // Update user dictionary to reflect changes
            if (!UpdateUserDictionary()) {
                LogThreadSafe("ANSFacialRecognition::UpdateUser",
                    "Warning: User ID " + std::to_string(userId) +
                    " updated in database but failed to refresh user dictionary");
                // Consider: Should this be a critical error?
                // return 0; // Uncomment if dictionary sync is critical
            }

            LogThreadSafe("ANSFacialRecognition::UpdateUser",
                "Successfully updated user ID " + std::to_string(userId));

            return result;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::UpdateUser",
                "Error updating user ID " + std::to_string(userId) + ": " + e.what());
            return 0;
        }
    }

    int ANSFacialRecognition::GetUser(int userId, UserRecord& userRecord) {
        try {
            // Validate input
            if (userId <= 0) {
                LogThreadSafe("ANSFacialRecognition::GetUser",
                    "Invalid user ID: " + std::to_string(userId));
                return 0;
            }

            // Validate database initialization
            if (!_db) {
                LogThreadSafe("ANSFacialRecognition::GetUser",
                    "Database not initialized");
                return 0;
            }

            // Initialize user ID
            userRecord.UserId = userId;

            // LOCK ONLY DURING DATABASE ACCESS
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);

                // Get user basic information
                int result = _db->GetUser(userId, userRecord.UserCode, userRecord.UserName);
                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::GetUser",
                        "User ID " + std::to_string(userId) + " not found in database");
                    return 0;
                }

                // Get user's face IDs
                result = _db->GetFaceIdsByUser(userId, userRecord.FaceIds);
                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::GetUser",
                        "No faces found for user ID " + std::to_string(userId));
                    // Consider: Should this be an error or just a warning?
                    // A user might exist but have no registered faces yet
                    return 0;
                }
            }

            // Optional: Log successful retrieval
            LogThreadSafe("ANSFacialRecognition::GetUser",
                "Successfully retrieved user ID " + std::to_string(userId) +
                " with " + std::to_string(userRecord.FaceIds.size()) + " face(s)");

            return 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetUser",
                "Error retrieving user ID " + std::to_string(userId) + ": " + e.what());
            return 0;
        }
    }
    int ANSFacialRecognition::GetUser(int userId, const std::string& userCode,const std::string& userName, UserRecord& userRecord) {
        try {
            // Initialize user ID
            userRecord.UserId = userId;
            userRecord.UserCode = userCode;
            userRecord.UserName = userName;

            // LOCK ONLY DURING DATABASE ACCESS
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                // Get user's face IDs
                int result = _db->GetFaceIdsByUser(userId, userRecord.FaceIds);
                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::GetUser",
                        "No faces found for user ID " + std::to_string(userId));
                    return 0;
                }
            }

            return 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetUser",
                "User ID " + std::to_string(userId) + ": " + e.what());
            return 0;
        }
    }
    int ANSFacialRecognition::GetUsers(std::vector<UserRecord>& userRecords,std::vector<int>& userIds)
    {
        // Clear output parameters
        userRecords.clear();
        userIds.clear();

        try {
            std::vector<std::string> userCodes;
            std::vector<std::string> userNames;
            std::vector<std::vector<int>> faceIdsByUser;

            // Fix #12: Single batch query with JOIN replaces N+1 individual queries
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                int result = _db->GetUsersWithFaceIds(userIds, userCodes, userNames, faceIdsByUser);
                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::GetUsers",
                        "Failed to query users from database");
                    return 0;
                }
            }

            if (userIds.empty()) {
                return 0;
            }

            // Build UserRecord objects directly from batch results
            userRecords.reserve(userIds.size());
            for (size_t i = 0; i < userIds.size(); ++i)
            {
                UserRecord userRecord;
                userRecord.UserId = userIds[i];
                userRecord.UserCode = std::move(userCodes[i]);
                userRecord.UserName = std::move(userNames[i]);
                userRecord.FaceIds = std::move(faceIdsByUser[i]);
                userRecords.push_back(std::move(userRecord));
            }

            return static_cast<int>(userRecords.size());
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetUsers", e.what());
            userRecords.clear();
            userIds.clear();
            return 0;
        }
    }
    int ANSFacialRecognition::GetFace(int faceId, FaceRecord& faceRecord) {
        try {
            // Initialize the record with the face ID
            faceRecord.FaceId = faceId;

            // LOCK ONLY DURING DATABASE ACCESS
            int result;
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                result = _db->GetFaceById(faceId, faceRecord.UserId, faceRecord.ImagePath);
            }

            if (result <= 0) {
                LogThreadSafe("ANSFacialRecognition::GetFace",
                    "Face ID " + std::to_string(faceId) + " not found in database");
            }

            return result;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetFace",
                "Face ID " + std::to_string(faceId) + ": " + e.what());
            return 0;
        }
    }
    int ANSFacialRecognition::GetFaces(int userId, std::vector<FaceRecord>& faceRecords) {
        // Clear output parameter
        faceRecords.clear();

        try {
            // Get face IDs from database (lock during database access)
            std::vector<int> faceIds;
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                int result = _db->GetFaceIdsByUser(userId, faceIds);

                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::GetFaces",
                        "Failed to query face IDs for user " + std::to_string(userId));
                    return 0;
                }
            }

            if (faceIds.empty()) {
                return 0;
            }

            // Reserve space for efficiency
            faceRecords.reserve(faceIds.size());

            // Retrieve each face record
            for (int faceId : faceIds) {
                FaceRecord faceRecord;
                int result = GetFace(faceId, faceRecord);

                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::GetFaces",
                        "Failed to retrieve face ID " + std::to_string(faceId) +
                        " for user " + std::to_string(userId));
                    faceRecords.clear();  // Clear partial results on error
                    return 0;
                }

                faceRecords.push_back(std::move(faceRecord));
            }

            return static_cast<int>(faceRecords.size());
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetFaces",
                std::string("User ") + std::to_string(userId) + ": " + e.what());
            faceRecords.clear();
            return 0;
        }
    }
    int ANSFacialRecognition::DeleteFacesByUser(int userId) {
        try {
            std::vector<int> faceIds;

            // Get face IDs for this user (lock during database access)
            {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                int result = _db->GetFaceIdsByUser(userId, faceIds);

                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::DeleteFacesByUser",
                        "Failed to query faces for user ID " + std::to_string(userId));
                    return 0;
                }
            }

            if (faceIds.empty()) {
                LogThreadSafe("ANSFacialRecognition::DeleteFacesByUser",
                    "No faces found for user ID " + std::to_string(userId));
                return 0;
            }

            // Delete each face from database (lock per deletion)
            for (int faceId : faceIds) {
                std::lock_guard<std::mutex> lock(_databaseMutex);
                int result = _db->DeleteFace(faceId);

                if (result <= 0) {
                    LogThreadSafe("ANSFacialRecognition::DeleteFacesByUser",
                        "Failed to delete face ID " + std::to_string(faceId) +
                        " for user ID " + std::to_string(userId));
                    return 0;
                }
            }

            // Delete user's image folder (filesystem operation, no lock needed)
            std::string userImageFolderName = "User" + std::to_string(userId);
            std::string imageFolder = CreateFilePath(_config._gen_imgSource, userImageFolderName);

            if (FolderExist(imageFolder)) {
                DeleteFolder(imageFolder);
            }

            // Fix #3: Auto-reload FAISS index after batch face deletion
            _reloadNeeded.store(true);
            Reload();

            return 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::DeleteFacesByUser",
                "User ID " + std::to_string(userId) + ": " + e.what());
            return 0;
        }
    }   
    int ANSFacialRecognition::GetUser(int userId, std::string& userRecord) {
        // NO LOCK NEEDED - Delegates to another method that handles locking

        try {
            UserRecord record;

            // Get user record (this method handles its own locking)
            int result = GetUser(userId, record);

            if (result <= 0) {
                userRecord.clear();
                return 0;
            }

            // Serialize to JSON (CPU operation, thread-safe)
            userRecord = ANSFRHelper::UserRecordToJsonString(record);

            return 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetUser",
                "User ID " + std::to_string(userId) + ": " + e.what());
            userRecord.clear();
            return 0;
        }
    }
    int ANSFacialRecognition::GetUsers(std::string& userRecords, std::vector<int>& userIds) {
        // NO LOCK NEEDED - Delegates to another method that handles locking

        // Clear output parameters
        userRecords.clear();
        userIds.clear();

        try {
            std::vector<UserRecord> records;

            // Get user records (this method handles its own locking)
            int result = GetUsers(records, userIds);

            if (result <= 0 || records.empty()) {
                return 0;
            }

            // Serialize to JSON (CPU operation, thread-safe)
            userRecords = ANSFRHelper::UserRecordsToJsonString(records);

            return 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetUsers", e.what());
            userRecords.clear();
            userIds.clear();
            return 0;
        }
    }
    int ANSFacialRecognition::GetFace(int faceId, std::string& faceRecord) {
        // NO LOCK NEEDED - Delegates to another method that handles locking

        try {
            FaceRecord record;

            // Get face record (this method handles its own locking)
            int result = GetFace(faceId, record);

            if (result <= 0) {
                faceRecord.clear();
                return 0;
            }

            // Serialize to JSON (CPU operation, thread-safe)
            faceRecord = ANSFRHelper::FaceRecordToJsonString(record);

            return 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetFace",
                "Face ID " + std::to_string(faceId) + ": " + e.what());
            faceRecord.clear();
            return 0;
        }
    }
    int ANSFacialRecognition::GetFaces(int userId, std::string& faceRecords)
    {
        // NO LOCK NEEDED - Delegates to another method that handles locking if needed

        try {
            std::vector<FaceRecord> records;

            // Get face records (this method should handle its own locking if needed)
            int result = GetFaces(userId, records);

            if (result <= 0 || records.empty()) {
                faceRecords.clear();
                return 0;
            }

            // Serialize to JSON (CPU operation, thread-safe)
            faceRecords = ANSFRHelper::FaceRecordsToJsonString(records);

            return 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::GetFaces", e.what());
            faceRecords.clear();
            return 0;
        }
    }


    int ANSFacialRecognition::CheckFace(const cv::Mat& image) {
        // Early validation checks (read-only, thread-safe)
        if (!ValidateInput(image)) {
            return 0;
        }

        try {
            // Prepare input frame (CPU operation, independent)
            cv::Mat frame = PrepareInputFrame(image);
            if (frame.empty()) {
                LogThreadSafe("ANSFacialRecognition::CheckFace",
                    "Failed to prepare input frame");
                return 0;
            }

            // LOCK ONLY DURING DETECTION (shared detector)
            std::vector<Object> detectedFaces;
            {
                std::lock_guard<std::mutex> lock(_detectionMutex);
                detectedFaces = _detector->RunInference(frame, "", false, true, false);
            }

            if (detectedFaces.empty()) {
                return 0;
            }

            // Filter faces (CPU operation, independent)
            auto validFaces = CheckFaces(detectedFaces,true);

            return validFaces.empty() ? 0 : 1;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::CheckFace", e.what());
            return 0;
        }
    }
    std::vector<FaceResultObject> ANSFacialRecognition::Recognize(const cv::Mat& input) {
		return Recognize(input, "FRCAM");
    } 
    std::vector<FaceResultObject> ANSFacialRecognition::Recognize(const cv::Mat& input, const std::string& camera_id) {
        
        std::vector<FaceResultObject> resultObjects;
        // Early validation checks (read-only, thread-safe)
        if (!ValidateInitialization() || !ValidateInput(input) || !ValidateComponents()) {
            return resultObjects;
        }

        try {
            // Prepare input frame (CPU operation, independent per camera)
            cv::Mat frame = PrepareInputFrame(input);
            if (frame.empty()) {
                LogError("ANSFacialRecognition::Recognize",
                    "Failed to prepare input frame", camera_id);
                return resultObjects;
            }

            // Sanity check config dimensions
            if (_config._recInputShape.size() < 3) {
                LogError("ANSFacialRecognition::Recognize",
                    "Invalid _recInputShape size", camera_id);
                return resultObjects;
            }

            int target_height = _config._recInputShape[1];
            int target_width = _config._recInputShape[2];

            // Resize if needed
            if (frame.cols != target_width || frame.rows != target_height) {
                cv::resize(frame, frame, cv::Size(target_width, target_height));
            }

            // Prepare dummy detection (1 full-frame face box)
            std::vector<Object> outputBbox;
            Object bbox;
            bbox.box = cv::Rect(0, 0, std::min(target_width, frame.cols), std::min(target_height, frame.rows));
            bbox.confidence = 1.0f;
            bbox.mask = frame;
            bbox.cameraId = camera_id;
            outputBbox.push_back(bbox);

            // LOCK ONLY DURING RECOGNITION (shared recognizer with GPU buffers)
            std::vector<FaceResultObject> recognizedFaces;
            {
                std::lock_guard<std::mutex> lock(_recognitionMutex);
                recognizedFaces = RecognizeFaces(frame, outputBbox);
            }

            resultObjects = UpdateFaceAttributes(recognizedFaces, camera_id);
            return resultObjects;

        }
        catch (const std::exception& e) {
            LogError("ANSFacialRecognition::Recognize", e.what(), camera_id);
        }
        catch (...) {
            LogError("ANSFacialRecognition::Recognize", "Unknown exception", camera_id);
        }


        return std::vector<FaceResultObject>();
    }

    std::vector<FaceResultObject> ANSFacialRecognition::Inference(const cv::Mat& input) {
		return Inference(input, "FRCAM");
    }  
    
    std::vector<FaceResultObject> ANSFacialRecognition::Inference(const cv::Mat& input, const std::string& camera_id)
    {
        START_TIMER(total);

        std::vector<FaceResultObject> resultObjects;

        // Early validation checks (read-only, thread-safe)
        START_TIMER(validate_init);
        bool init_valid = ValidateInitialization();
        END_TIMER(validate_init, "ValidateInitialization Time");

        if (!init_valid) {
            END_TIMER(total, "Total Inference Time (early exit - init)");
            return resultObjects;
        }

        START_TIMER(validate_input);
        bool input_valid = ValidateInput(input);
        END_TIMER(validate_input, "ValidateInput Time");

        if (!input_valid) {
            END_TIMER(total, "Total Inference Time (early exit - input)");
            return resultObjects;
        }

        START_TIMER(validate_components);
        bool components_valid = ValidateComponents();
        END_TIMER(validate_components, "ValidateComponents Time");

        if (!components_valid) {
            END_TIMER(total, "Total Inference Time (early exit - components)");
            return resultObjects;
        }

        try {
            // Prepare input frame (CPU operation, independent per camera)
            START_TIMER(prepare_frame);
            cv::Mat frame = PrepareInputFrame(input);
            END_TIMER(prepare_frame, "PrepareInputFrame Time");

            if (frame.empty()) {
                LogError("ANSFacialRecognition::Inference",
                    "Failed to prepare input frame", camera_id);
                END_TIMER(total, "Total Inference Time (early exit - empty frame)");
                return resultObjects;
            }

            // LOCK ONLY DURING DETECTION (shared detector)
            std::vector<Object> detectedFaces;
            {
                START_TIMER(detection);
                std::lock_guard<std::mutex> lock(_detectionMutex);

                START_TIMER(detection_actual);
                detectedFaces = DetectFaces(frame, camera_id);
                END_TIMER(detection_actual, "Face Detection (actual) Time");

                END_TIMER(detection, "Face Detection (with lock) Time");
            }

            if (detectedFaces.empty()) {
                END_TIMER(total, "Total Inference Time (no faces detected)");
                return resultObjects;
            }

            // Filter faces (CPU operation, independent per camera)
            START_TIMER(filter);
            std::vector<Object> validFaces = CheckFaces(detectedFaces, true);
            END_TIMER(filter, "Filter Faces Time");

            if (validFaces.empty()) {
                END_TIMER(total, "Total Inference Time (no valid faces)");
                return resultObjects;
            }

            // LOCK ONLY DURING RECOGNITION (shared recognizer with GPU buffers)
			std::vector<FaceResultObject> recognizedFaces;
            {
                START_TIMER(recognition);
                std::lock_guard<std::mutex> lock(_recognitionMutex);

                START_TIMER(recognition_actual);
                recognizedFaces = RecognizeFaces(frame, validFaces);
                END_TIMER(recognition_actual, "Face Recognition (actual) Time");

                END_TIMER(recognition, "Face Recognition (with lock) Time");
            }

            // Post-process faces (CPU operation, independent per camera)
            if (!recognizedFaces.empty()) {
                START_TIMER(postprocess);
                resultObjects=UpdateFaceAttributes(recognizedFaces, camera_id);
                END_TIMER(postprocess, "Update Face Attributes Time");
            }
        }
        catch (const std::exception& e) {
            LogError("ANSFacialRecognition::Inference", e.what(), camera_id);
            END_TIMER(total, "Total Inference Time (exception)");
            return resultObjects;
        }
        catch (...) {
            LogError("ANSFacialRecognition::Inference", "Unknown exception", camera_id);
            END_TIMER(total, "Total Inference Time (unknown exception)");
            return resultObjects;
        }

        END_TIMER(total, "Total Inference Time");
        // Fix #9: std::cout removed from production DLL

        return resultObjects;
    }
  
    std::vector<FaceResultObject> ANSFacialRecognition::Detect(const cv::Mat& input) {
		return Detect(input, "FRCAM");
    }
    std::vector<FaceResultObject> ANSFacialRecognition::Detect(const cv::Mat& input,const std::string& camera_id)
    {
        std::vector<FaceResultObject> resultObjects;

        // Early validation checks (read-only, thread-safe)
        if (!ValidateInitialization() || !ValidateInput(input) || !ValidateComponents()) {
            return resultObjects;
        }

        try {
            // Prepare input frame (CPU operation, independent per camera)
            cv::Mat frame = PrepareInputFrame(input);
            if (frame.empty()) {
                LogError("ANSFacialRecognition::Detect",
                    "Failed to prepare input frame", camera_id);
                return resultObjects;
            }

            // LOCK ONLY DURING DETECTION (shared detector)
            std::vector<Object> detectedFaces;
            {
                std::lock_guard<std::mutex> lock(_detectionMutex);
                detectedFaces = DetectFaces(frame, camera_id);
            }

            if (detectedFaces.empty()) {
                return resultObjects;
            }

            // Filter faces (CPU operation, independent per camera)
            auto validFaces = CheckFaces(detectedFaces, true);
            if (validFaces.empty()) {
                return resultObjects;
            }

            // Build face result objects with attributes (CPU/GPU mixed operations)
            resultObjects = BuildFaceResultObjects(validFaces, input, camera_id);
            return resultObjects;
        }
        catch (const std::exception& e) {
            LogError("ANSFacialRecognition::Detect", e.what(), camera_id);
        }
        catch (...) {
            LogError("ANSFacialRecognition::Detect", "Unknown exception", camera_id);
        }

        return resultObjects;
    }
   
    std::vector<Object> ANSFacialRecognition::FaceDetect(const cv::Mat& input) {
		return FaceDetect(input, "FRCAM");
    }
    std::vector<Object> ANSFacialRecognition::FaceDetect(const cv::Mat& input,const std::string& camera_id)
    {
        std::vector<Object> resultObjects;

        // Early validation checks (read-only, thread-safe)
        if (!ValidateInitialization() || !ValidateInput(input)) {
            return resultObjects;
        }

        try {
            // Prepare input frame (CPU operation, independent per camera)
            cv::Mat frame = PrepareInputFrame(input);
            if (frame.empty()) {
                LogError("ANSFacialRecognition::FaceDetect",
                    "Failed to prepare input frame", camera_id);
                return resultObjects;
            }

            // LOCK ONLY DURING DETECTION (shared detector)
            std::vector<Object> detectedFaces;
            {
                std::lock_guard<std::mutex> lock(_detectionMutex);
                detectedFaces = DetectFaces(frame, camera_id);
            }

            if (detectedFaces.empty()) {
                return resultObjects;
            }

            // Filter faces (CPU operation, independent per camera)
            auto validFaces = CheckFaces(detectedFaces);

            return validFaces;
        }
        catch (const std::exception& e) {
            LogError("ANSFacialRecognition::FaceDetect", e.what(), camera_id);
        }
        catch (...) {
            LogError("ANSFacialRecognition::FaceDetect", "Unknown exception", camera_id);
        }

        return resultObjects;
    }
    
    
    std::vector<FaceResultObject> ANSFacialRecognition::PostProcess(const std::vector<FaceResultObject>& detectedObjects,const std::string& cameraId)
    {
        //ScopedTimer("Post Process");
        if (!_enableFaceQueue) {
            return detectedObjects;
        }

        // Lock ONLY for queue operations
        std::lock_guard<std::mutex> lock(_faceQueueMutex);

        // Enqueue current detection
        EnqueueDetection(detectedObjects, cameraId);

        // Dequeue and process
        std::deque<std::vector<FaceResultObject>> faceQueue = DequeueDetection(cameraId);
        std::vector<FaceResultObject> faceObjects = FindFrequentFaces(faceQueue,detectedObjects,this->_faceThresholdSize);
        return faceObjects;
    }
    std::string ANSFacialRecognition::PolygonToString(const std::vector<cv::Point2f>& polygon) {
        if (polygon.empty()) {
            return "";
        }

        try {
            std::string result;
            result.reserve(polygon.size() * 20);

            char buffer[64];
            for (size_t i = 0; i < polygon.size(); ++i) {
                if (i > 0) {
                    snprintf(buffer, sizeof(buffer), ";%.3f;%.3f", polygon[i].x, polygon[i].y);
                }
                else {
                    snprintf(buffer, sizeof(buffer), "%.3f;%.3f", polygon[i].x, polygon[i].y);
                }
                result += buffer;
            }

            return result;
        }
        catch (const std::exception& e) {
            this->_logger.LogFatal("ANSFacialRecognition::PolygonToString()", e.what(), __FILE__, __LINE__);
            return "";
        }
    }
    std::string ANSFacialRecognition::KeypointsToString(const std::vector<float>& kps) {
        if (kps.empty()) {
            return "";
        }
        try {
            // Pre-allocate: each float ~10 chars (e.g., "123.456;")
            std::string result;
            result.reserve(kps.size() * 10);

            char buffer[32];
            for (size_t i = 0; i < kps.size(); ++i) {
                if (i > 0) result += ';';
                snprintf(buffer, sizeof(buffer), "%.3f", kps[i]);
                result += buffer;
            }

            return result;
        }
        catch (const std::exception& e) {
            this->_logger.LogFatal("ANSFacialRecognition::KeypointsToString()", e.what(), __FILE__, __LINE__);
            return "";
        }
    }

    // Using nlohmann/json (much faster)
    std::string ANSFacialRecognition::FaceObjectsToJsonString(const std::vector<FaceResultObject>& faces) {
        START_TIMER(json_total);

        try {
            nlohmann::json root;
            auto& results = root["results"] = nlohmann::json::array();

            START_TIMER(json_build);
            for (const auto& face : faces) {
                results.push_back({
                    {"user_id", face.userId},
                    {"user_name", face.userName},
                    {"similarity", std::to_string(face.similarity)},
                    {"is_unknown", std::to_string(face.isUnknown)},
                    {"prob", std::to_string(face.confidence)},
                    {"x", std::to_string(face.box.x)},
                    {"y", std::to_string(face.box.y)},
                    {"width", std::to_string(face.box.width)},
                    {"height", std::to_string(face.box.height)},
                    {"extra_info", face.extraInformation},
                    {"camera_id", face.cameraId},
                    {"track_id", std::to_string(face.trackId)},
                    {"polygon", PolygonToString(face.polygon)},
                    {"kps", KeypointsToString(face.kps)}
                    });
            }
            END_TIMER(json_build, "JSON Build Time");

            START_TIMER(json_serialize);
            std::string result = root.dump();
            END_TIMER(json_serialize, "JSON Serialize Time");

            END_TIMER(json_total, "JSON Conversion Total Time");
            return result;
        }
        catch (const std::exception& e) {
            END_TIMER(json_total, "JSON Conversion Time (error)");
            LogThreadSafe("ANSFacialRecognition::FaceObjectsToJsonString", e.what());
            return R"({"results":[],"error":"Serialization failed"})";
        }
    }
    std::string ANSFacialRecognition::FaceToJsonString(const std::vector<Object>& dets) {
        nlohmann::json root;
        nlohmann::json detectedObjects = nlohmann::json::array();

        for (const auto& det : dets) {
            nlohmann::json detectedNode;
            detectedNode["class_id"] = std::to_string(det.classId);
            detectedNode["track_id"] = std::to_string(det.trackId);
            detectedNode["class_name"] = det.className;
            detectedNode["prob"] = std::to_string(det.confidence);
            detectedNode["x"] = std::to_string(det.box.x);
            detectedNode["y"] = std::to_string(det.box.y);
            detectedNode["width"] = std::to_string(det.box.width);
            detectedNode["height"] = std::to_string(det.box.height);
            detectedNode["mask"] = "";  // TODO: convert masks to comma separated string
            detectedNode["extra_info"] = det.extraInfo;
            detectedNode["camera_id"] = det.cameraId;
            detectedNode["polygon"] = PolygonToString(det.polygon);
            detectedNode["kps"] = KeypointsToString(det.kps);

            detectedObjects.push_back(detectedNode);
        }

        root["results"] = detectedObjects;

        return root.dump();  // or root.dump(4) for pretty-printed JSON with 4-space indent
    }
     
    // Validation helper methods
    bool ANSFacialRecognition::ValidateInitialization() {
		//ScopedTimer("Validate Initialization");
        if (!_isInitialized) {
            _logger.LogError("ANSFacialRecognition::Inference()",
                "Models are not initialized.", __FILE__, __LINE__);
            return false;
        }
        return true;
    }

    bool ANSFacialRecognition::ValidateInput(const cv::Mat& input) {
        //ScopedTimer("ValidateInput");
        constexpr int MIN_DIMENSION = 10;

        if (input.empty() || input.cols < MIN_DIMENSION || input.rows < MIN_DIMENSION) {
            _logger.LogFatal("ANSFacialRecognition::Inference()",
                "Input image is invalid or too small", __FILE__, __LINE__);
            return false;
        }
        return true;
    }

    bool ANSFacialRecognition::ValidateComponents() {
		//ScopedTimer("ValidateComponents");
        if (!_detector) {
            _logger.LogFatal("ANSFacialRecognition::Inference()",
                "_detector is null", __FILE__, __LINE__);
            return false;
        }

        if (!_recognizer) {
            _logger.LogFatal("ANSFacialRecognition::Inference()",
                "_recognizer is null", __FILE__, __LINE__);
            return false;
        }

        return true;
    }

    // Frame preparation
    cv::Mat ANSFacialRecognition::PrepareInputFrame(const cv::Mat& input) {
        // If input is already BGR and you don't modify it downstream
        if (input.channels() == 3) {
            return input;  // Just return reference (no copy!)
        }

        // Only convert if grayscale
        cv::Mat frame;
        cv::cvtColor(input, frame, cv::COLOR_GRAY2BGR);
        return frame;
    }
    void ANSFacialRecognition::ensureUniqueUserIdWithHighestConfidence(std::vector<FaceResultObject>& resultObjects) 
    {
        // NO LOCK NEEDED - Operating on thread-local resultObjects
        // Each camera has its own vector, no shared state

        if (resultObjects.empty()) {
            return;
        }

        // Map userId to index of face with highest confidence
        std::unordered_map<std::string, size_t> highestConfidenceIndices;
        highestConfidenceIndices.reserve(resultObjects.size());

        for (size_t i = 0; i < resultObjects.size(); ++i) {
            const std::string& userId = resultObjects[i].userId;

            // Skip unknown faces
            if (userId == "0000") {
                continue;
            }

            auto it = highestConfidenceIndices.find(userId);

            if (it == highestConfidenceIndices.end()) {
                // First occurrence of this userId
                highestConfidenceIndices[userId] = i;
            }
            else {
                // Duplicate userId found - keep only highest confidence
                size_t existingIndex = it->second;

                if (resultObjects[i].confidence > resultObjects[existingIndex].confidence) {
                    // Current face has higher confidence - mark previous as unknown
                    MarkAsUnknown(resultObjects[existingIndex]);
                    highestConfidenceIndices[userId] = i;
                }
                else {
                    // Existing face has higher confidence - mark current as unknown
                    MarkAsUnknown(resultObjects[i]);
                }
            }
        }
    }

    std::vector<Object> ANSFacialRecognition::CheckFaces(const std::vector<Object>& faceObjects,bool checkFaceSize)
    {
        // NO LOCK NEEDED - Pure filtering operation on local data
        std::vector<Object> validFaceObjects;
        validFaceObjects.reserve(faceObjects.size());

        try {
            for (const auto& face : faceObjects) {
                // Skip faces smaller than minimum size if checking is enabled
                if (checkFaceSize &&
                    (face.box.width <= _minFaceSize || face.box.height <= _minFaceSize)) {
                    continue;
                }
                validFaceObjects.push_back(face);
            }
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::CheckFaces", e.what());
        }

        return validFaceObjects;
    }
    // Pipeline stage methods with timing
    std::vector<Object> ANSFacialRecognition::DetectFaces(const cv::Mat& frame, const std::string& camera_id)
    {
        //ScopedTimer timer("Face Detection");
        return _detector->RunInference(frame, camera_id, true, _enableHeadPose, _enableFaceliveness);
    }

  

    std::vector<FaceResultObject> ANSFacialRecognition::RecognizeFaces(const cv::Mat& frame, const std::vector<Object>& validFaces)
    {
        // Hold shared lock during the entire Match operation to prevent
        // Reload() from swapping the index while we're using it.
        // Fix #6: Pass _userDict by const& — shared_lock guarantees it won't
        // be modified during Match (only unique_lock in Reload can write).
        std::shared_lock<std::shared_mutex> lock(_indexSwapMutex);
        return _recognizer->Match(frame, validFaces, _userDict);
    }
    std::string ANSFacialRecognition::GetOpenVINODevice() {
        ov::Core core;
        std::vector<std::string> available_devices = core.get_available_devices();
        // Prioritize devices: NPU > GPU > CPU
        std::vector<std::string> priority_devices = { "NPU","GPU","CPU" };
        for (const auto& device : priority_devices) {
            if (std::find(available_devices.begin(), available_devices.end(), device) != available_devices.end()) {
                return device; // Return the first available device based on priority
            }
        }
        return "CPU";
    }

    std::vector<FaceResultObject> ANSFacialRecognition::UpdateFaceAttributes(
        const std::vector<FaceResultObject>& resultObjects,
        const std::string& camera_id)
    {
		std::vector<FaceResultObject> updatedResults;
        try {
            const size_t faceCount = resultObjects.size();
            if (faceCount == 0) return updatedResults;

            // Determine if this is a full-attribute frame or head-pose-only frame
            bool runSlowAttributes = true;
            CameraData* camDataPtr = nullptr;
            if (!camera_id.empty() && _attributeInterval > 1) {
                camDataPtr = &GetCameraData(camera_id);

                // ── Adaptive interval (#5): adjust based on scene stability ──
                // Count current trackIds
                int currentTrackIdCount = static_cast<int>(faceCount);
                if (currentTrackIdCount == camDataPtr->previousTrackIdCount) {
                    camDataPtr->stableFrameCount++;
                } else {
                    camDataPtr->stableFrameCount = 0;
                }
                camDataPtr->previousTrackIdCount = currentTrackIdCount;

                // Adapt interval: stable scene → increase (max 10), changes → decrease (min 2)
                if (camDataPtr->stableFrameCount > 30) {
                    camDataPtr->currentAttributeInterval = std::min(10, _attributeInterval * 2);
                } else if (camDataPtr->stableFrameCount > 10) {
                    camDataPtr->currentAttributeInterval = _attributeInterval;
                } else {
                    camDataPtr->currentAttributeInterval = std::max(2, _attributeInterval / 2);
                }

                camDataPtr->attributeFrameCounter++;
                if (camDataPtr->attributeFrameCounter >= camDataPtr->currentAttributeInterval) {
                    camDataPtr->attributeFrameCounter = 0;
                    runSlowAttributes = true;
                } else {
                    runSlowAttributes = false;
                }
            }

            // Pre-allocate per-face working data
            std::vector<FaceResultObject> results(resultObjects.begin(), resultObjects.end());
            std::vector<cv::Mat> masks(faceCount);
            std::vector<bool> maskValid(faceCount, false);
            std::vector<bool> skipAttributes(faceCount, false);
            std::vector<bool> runAgeGender(faceCount, false);
            std::vector<bool> runEmotions(faceCount, false);
            std::vector<bool> runHeadPose(faceCount, false);
            std::vector<bool> useCachedAttrs(faceCount, false);
            std::vector<AgeGenderResults> ageGenderResults(faceCount, AgeGenderResults{});
            std::vector<std::map<std::string, float>> emotionsResults(faceCount);
            std::vector<HeadPoseResults> headPoseResults(faceCount, HeadPoseResults{});

            std::vector<Face> faces;
            faces.reserve(faceCount);

            START_TIMER(attr_phase1);
            // ---- Phase 1: Setup + antispoof (sequential) ----
            for (size_t i = 0; i < faceCount; i++) {
                cv::Rect faceBox = resultObjects[i].box;
                faces.emplace_back(i, faceBox);
                Face& face = faces[i];

                face.ageGenderEnable(this->_enableAgeGender && _ageGenderDetector && _ageGenderDetector->enabled());
                face.emotionsEnable(this->_enableFaceEmotions && _emotionsDetector && _emotionsDetector->enabled());
                face.headPoseEnable(this->_enableHeadPose && _headPoseDetector && _headPoseDetector->enabled());
                face.antispoofingEnable(this->_enableAntiSpoof && _antiSpoofDetector && _antiSpoofDetector->enabled());
                face.faceLivenessEnable(this->_enableFaceliveness);

                // Clone mask once per face
                masks[i] = (!results[i].mask.empty()) ? resultObjects[i].mask.clone() : cv::Mat();
                maskValid[i] = !masks[i].empty() && masks[i].cols >= 5 && masks[i].rows >= 5;

                // Check if we can use cached attributes for this face
                bool hasCachedAttrs = false;
                if (!runSlowAttributes && camDataPtr) {
                    auto it = camDataPtr->cachedAttributes.find(resultObjects[i].trackId);
                    if (it != camDataPtr->cachedAttributes.end()) {
                        hasCachedAttrs = true;
                    }
                }

                // Determine if slow attributes should run for this face
                bool runSlowForThisFace = runSlowAttributes || !hasCachedAttrs;

                bool fakeFaceDetected = false;
                if (face.isFaceLivenessEnabled() && !results[i].extraInformation.empty()) {
                    const std::string& livenessResult = results[i].extraInformation;
                    if (livenessResult == "real") {
                        face.updateFaceLiveness(1);
                    }
                    else if (livenessResult == "fake") {
                        face.updateFaceLiveness(0);
                        fakeFaceDetected = true;
                    }
                }

                // Antispoof: only on full-attribute frames or new faces
                if (runSlowForThisFace && !fakeFaceDetected && face.isAntispoofingEnabled() && maskValid[i]) {
                    float confidence;
                    {
                        std::lock_guard<std::mutex> lock(_antispoofMutex);
                        confidence = _antiSpoofDetector->runInfer(masks[i]);
                    }
                    face.updateRealFaceConfidence(confidence);
                    if (!face.isReal()) fakeFaceDetected = true;
                }

                if (_removeFakeFaces && fakeFaceDetected) {
                    skipAttributes[i] = true;
                    MarkAsUnknown(results[i]);
                }

                // Skip attribute inference for faces below minimum size threshold
                if (!skipAttributes[i] &&
                    (resultObjects[i].box.width < _minFaceSize ||
                     resultObjects[i].box.height < _minFaceSize)) {
                    skipAttributes[i] = true;
                    MarkAsUnknown(results[i]);
                }

                // Slow attributes: only on attribute frames or new faces
                runAgeGender[i] = !skipAttributes[i] && runSlowForThisFace && face.isAgeGenderEnabled() && maskValid[i];
                runEmotions[i] = !skipAttributes[i] && runSlowForThisFace && face.isEmotionsEnabled() && maskValid[i];
                // Head pose: ALWAYS runs (every frame)
                runHeadPose[i] = !skipAttributes[i] && face.isHeadPoseEnabled() && maskValid[i];
                // Track whether to use cache for output
                useCachedAttrs[i] = !skipAttributes[i] && !runSlowForThisFace && hasCachedAttrs;
            }

            END_TIMER(attr_phase1, "  [Attr] Phase1 (setup+antispoof)");

            // ---- Phase 2: Run attribute models sequentially ----
            // On cached frames: only head pose runs. AgeGender + Emotions are skipped.
            START_TIMER(attr_agegender);
            {
                std::lock_guard<std::mutex> lock(_ageGenderMutex);
                for (size_t i = 0; i < faceCount; i++) {
                    if (!runAgeGender[i]) continue;
                    ageGenderResults[i] = _ageGenderDetector->runInfer(masks[i]);
                }
            }
            END_TIMER(attr_agegender, "  [Attr] AgeGender (all faces)");

            START_TIMER(attr_emotions);
            {
                std::lock_guard<std::mutex> lock(_emotionsMutex);
                for (size_t i = 0; i < faceCount; i++) {
                    if (!runEmotions[i]) continue;
                    emotionsResults[i] = _emotionsDetector->runInfer(masks[i]);
                }
            }
            END_TIMER(attr_emotions, "  [Attr] Emotions (all faces)");

            // Head pose: ALWAYS runs (every frame, real-time accuracy)
            START_TIMER(attr_headpose);
            {
                std::lock_guard<std::mutex> lock(_headPoseMutex);
                for (size_t i = 0; i < faceCount; i++) {
                    if (!runHeadPose[i]) continue;
                    headPoseResults[i] = _headPoseDetector->runInfer(masks[i]);
                }
            }
            END_TIMER(attr_headpose, "  [Attr] HeadPose (all faces)");

            // ---- Phase 3: Collect results and build output ----
            for (size_t i = 0; i < faceCount; i++) {
                if (skipAttributes[i]) continue;

                Face& face = faces[i];
                FaceResultObject& resultObject = results[i];

                if (useCachedAttrs[i] && camDataPtr) {
                    // Cached frame: use cached JSON but splice in fresh head pose
                    auto& cached = camDataPtr->cachedAttributes[resultObjects[i].trackId];

                    if (runHeadPose[i]) {
                        // Check extreme head pose → mark unknown
                        if (std::abs(headPoseResults[i].angle_y) > 60 ||
                            std::abs(headPoseResults[i].angle_r) > 60 ||
                            std::abs(headPoseResults[i].angle_p) > 60) {
                            MarkAsUnknown(resultObject);
                        }

                        // Replace Pose(r,p,y) in cached JSON with fresh values
                        std::string json = cached.attributeJson;
                        std::string newPose = "(" + std::to_string(static_cast<int>(headPoseResults[i].angle_r)) +
                            ", " + std::to_string(static_cast<int>(headPoseResults[i].angle_p)) +
                            ", " + std::to_string(static_cast<int>(headPoseResults[i].angle_y)) + ")";
                        // Find and replace the pose value in the JSON
                        size_t poseKeyPos = json.find("\"Pose(r,p,y)\"");
                        if (poseKeyPos != std::string::npos) {
                            size_t valueStart = json.find("\"(", poseKeyPos + 13);
                            size_t valueEnd = json.find(")\"", valueStart + 1);
                            if (valueStart != std::string::npos && valueEnd != std::string::npos) {
                                json.replace(valueStart + 1, valueEnd - valueStart, newPose);
                            }
                        }
                        resultObject.extraInformation = json;
                    } else {
                        resultObject.extraInformation = cached.attributeJson;
                    }

                    if (cached.isUnknown) MarkAsUnknown(resultObject);
                } else {
                    // Full attribute frame: build from scratch
                    if (runAgeGender[i]) {
                        face.updateGender(ageGenderResults[i].maleProb);
                        face.updateAge(ageGenderResults[i].age);
                    }
                    if (runEmotions[i]) {
                        face.updateEmotions(emotionsResults[i]);
                    }
                    if (runHeadPose[i]) {
                        face.updateHeadPose(headPoseResults[i]);
                        if (std::abs(headPoseResults[i].angle_y) > 60 ||
                            std::abs(headPoseResults[i].angle_r) > 60 ||
                            std::abs(headPoseResults[i].angle_p) > 60) {
                            MarkAsUnknown(resultObject);
                        }
                    }

                    std::string faceAtt = ANSFRHelper::FaceAttributeToJsonString(face);
                    resultObject.extraInformation = faceAtt;

                    // Cache for future frames
                    if (camDataPtr) {
                        CachedFaceAttributes& cache = camDataPtr->cachedAttributes[resultObjects[i].trackId];
                        cache.attributeJson = faceAtt;
                        cache.isUnknown = resultObject.isUnknown;
                    }
                }

				updatedResults.push_back(resultObject);
            }

            // Clean up stale cache entries (trackIds not seen this frame)
            if (camDataPtr && runSlowAttributes) {
                std::unordered_set<int> activeTrackIds;
                for (const auto& r : resultObjects)
                    activeTrackIds.insert(r.trackId);
                for (auto it = camDataPtr->cachedAttributes.begin(); it != camDataPtr->cachedAttributes.end(); ) {
                    if (activeTrackIds.find(it->first) == activeTrackIds.end())
                        it = camDataPtr->cachedAttributes.erase(it);
                    else
                        ++it;
                }
            }

			return updatedResults;
        }
        catch (const std::bad_alloc& e) {
            LogThreadSafe("ANSFacialRecognition::updateFaceAttributes",
                std::string("Memory allocation failed: ") + e.what());
			return updatedResults;
        }
        catch (const std::exception& e) {
            LogThreadSafe("ANSFacialRecognition::updateFaceAttributes", e.what());
            return updatedResults;
        }
    }
    std::vector<FaceResultObject> ANSFacialRecognition::BuildFaceResultObjects(const std::vector<Object>& validFaces,const cv::Mat& originalInput,const std::string& camera_id) 
    {
        std::vector<FaceResultObject> resultObjects;
        resultObjects.reserve(validFaces.size());

        for (size_t i = 0; i < validFaces.size(); ++i) {
            const Object& faceObj = validFaces[i];

            // Create face attribute object
            cv::Rect rect = faceObj.box;
            Face face(i, rect);

            // Enable attributes based on configuration
            face.ageGenderEnable(_enableAgeGender && _ageGenderDetector && _ageGenderDetector->enabled());
            face.emotionsEnable(_enableFaceEmotions && _emotionsDetector && _emotionsDetector->enabled());
            face.headPoseEnable(_enableHeadPose && _headPoseDetector && _headPoseDetector->enabled());
            face.antispoofingEnable(_enableAntiSpoof && _antiSpoofDetector && _antiSpoofDetector->enabled());

            // Process face attributes if mask is valid
            if (!faceObj.mask.empty() && faceObj.mask.cols > 4 && faceObj.mask.rows > 4) {
                ProcessFaceAttributes(face, faceObj.mask);
            }
            // Build result object
            FaceResultObject result;
            result.isUnknown = true;
            result.userId = "0";
            result.userName = "Unknown";
            result.similarity = 0.0f;
            result.confidence = 1.0f;
            result.cameraId = camera_id;
            result.trackId = faceObj.trackId;

            // Clamp bounding box to image boundaries
            result.box.x = std::max(0.0f, static_cast<float>(faceObj.box.x));
            result.box.y = std::max(0.0f, static_cast<float>(faceObj.box.y));
            result.box.width = std::min(
                static_cast<float>(originalInput.cols) - result.box.x,
                static_cast<float>(faceObj.box.width)
            );
            result.box.height = std::min(
                static_cast<float>(originalInput.rows) - result.box.y,
                static_cast<float>(faceObj.box.height)
            );

            // Copy face data
            result.mask = faceObj.mask;
            result.polygon = faceObj.polygon;
            result.kps = faceObj.kps;

            // Serialize face attributes to JSON
            result.extraInformation = ANSFRHelper::FaceAttributeToJsonString(face);

            resultObjects.push_back(result);
        }

        return resultObjects;
    }
    void ANSFacialRecognition::ProcessFaceAttributes(Face& face,const cv::Mat& mask)
    {
        // Age & Gender
        if (face.isAgeGenderEnabled()) {
            AgeGenderResults ageGenderResult;
            {
                std::lock_guard<std::mutex> lock(_ageGenderMutex);
                ageGenderResult = _ageGenderDetector->runInfer(mask);
            }
            face.updateGender(ageGenderResult.maleProb);
            face.updateAge(ageGenderResult.age);
        }

        // Emotions
        if (face.isEmotionsEnabled()) {
            std::map<std::string, float> emotions;
            {
                std::lock_guard<std::mutex> lock(_emotionsMutex);
                emotions = _emotionsDetector->runInfer(mask);
            }
            face.updateEmotions(emotions);
        }

        // Head Pose
        if (face.isHeadPoseEnabled()) {
            HeadPoseResults headPoseResult;
            {
                std::lock_guard<std::mutex> lock(_headPoseMutex);
                headPoseResult = _headPoseDetector->runInfer(mask);
            }
            face.updateHeadPose(headPoseResult);
        }

        // Anti-Spoofing
        if (face.isAntispoofingEnabled()) {
            float confidence;
            {
                std::lock_guard<std::mutex> lock(_antispoofMutex);
                confidence = _antiSpoofDetector->runInfer(mask);
            }
            face.updateRealFaceConfidence(confidence);
        }
    }

    void ANSFacialRecognition::MarkAsUnknown(FaceResultObject& face) {
        face.userId = "0000";
        face.isUnknown = true;
        face.userName = "Unknown";
        face.confidence = 1.0;
    }
    void ANSFacialRecognition::EnqueueDetection(const std::vector<FaceResultObject>& detectedObjects, const std::string& cameraId) {
        try {
            CameraData& camera = GetCameraData(cameraId);// Retrieve camera data
            if (camera._detectionQueue.size() == this->_queueSize) {
                camera._detectionQueue.pop_front();  // Remove the oldest element if the queue is full
            }
            camera._detectionQueue.push_back(detectedObjects);  // Add the new detection, even if empty
        }
		catch (const std::exception& e) {
			this->_logger.LogFatal("ANSFacialRecognition::EnqueueDetection()", e.what(), __FILE__, __LINE__);
		}
    }
    std::deque<std::vector<FaceResultObject>>ANSFacialRecognition::DequeueDetection(const std::string& cameraId) {
        try {
            CameraData& camera = GetCameraData(cameraId);// Retrieve camera data
            return camera._detectionQueue;
        }
        catch (const std::exception& e) {
            this->_logger.LogFatal("ANSFacialRecognition::DequeueDetection()", e.what(), __FILE__, __LINE__);
            return std::deque<std::vector<FaceResultObject>>();
        }
    }

    Object ANSFacialRecognition::GetLargestObject(const std::vector<Object>& objects) {
        try {
            if (!objects.empty()) {
                // Find the object with the largest size
                auto largestObjectIt = std::max_element(objects.begin(), objects.end(),
                    [](const Object& a, const Object& b) {
                        return (a.box.width * a.box.height) <
                            (b.box.width * b.box.height);
                    });

                return *largestObjectIt; // Return the largest object
            }
            return Object();
        }
        catch (const std::exception& e) {
            this->_logger.LogFatal("ANSFacialRecognition::GetLargestObject()", e.what(), __FILE__, __LINE__);
            return Object();
        }
    }

    bool ANSFacialRecognition::AreFacesSimilar(const FaceResultObject& face1, const FaceResultObject& face2) {
        // Check if both faces belong to the same camera and user
        return  face1.cameraId == face2.cameraId &&
                face1.userId == face2.userId &&
                face1.userName == face2.userName;
    }

    // Helper function to generate a hash for a face based on AreFacesSimilar
    size_t ANSFacialRecognition::GenerateFaceHash(const FaceResultObject & face, const std::vector<FaceResultObject>&detectedObjects) {
        for (size_t i = 0; i < detectedObjects.size(); ++i) {
            if (AreFacesSimilar(face, detectedObjects[i])) {
                return i; // Use index of `detectedObjects` as the hash key
            }
        }
        return static_cast<size_t>(-1); // Invalid index if not similar
    }
    std::vector<FaceResultObject> ANSFacialRecognition::FindFrequentFaces(const std::deque<std::vector<FaceResultObject>>&faceQueue,
            const std::vector<FaceResultObject>&detectedObjects,
            int occurrenceThreshold) 
    {
        try {
            // Map to count occurrences of each detected face using detectedObjects as keys
            std::unordered_map<size_t, int> faceCount;
            // Iterate over the face queue to count occurrences
            for (const auto& faceArray : faceQueue) {
                for (const auto& face : faceArray) {
                    if (face.userName != "Unknown") { // Skip checking "Unknown" faces
                        size_t hash = GenerateFaceHash(face, detectedObjects);
                        if (hash != static_cast<size_t>(-1)) { // Valid hash
                            faceCount[hash]++;
                        }
                    }
                }
            }
            // Collect frequent faces from detectedObjects
            std::vector<FaceResultObject> frequentFaces;
            for (size_t i = 0; i < detectedObjects.size(); ++i) {
                const auto& detectedFace = detectedObjects[i];
                if (detectedFace.userName == "Unknown") {
                    // Add "Unknown" faces directly without checking
                    frequentFaces.push_back(detectedFace);
                }
                else if (faceCount[i] >= occurrenceThreshold) {
                    // Add frequent known faces
                    frequentFaces.push_back(detectedFace);
                }
            }

            return frequentFaces;
        }
		catch (const std::exception& e) {
			this->_logger.LogFatal("ANSFacialRecognition::FindFrequentFaces()", e.what(), __FILE__, __LINE__);
			return std::vector<FaceResultObject>();
		}
    }

    // Helper methods with proper thread safety
    void ANSFacialRecognition::LogError(const std::string& function, const std::string& message, const std::string& camera_id)
    {
        std::ostringstream oss;
        oss << "Camera " << camera_id << ": " << message;

        std::lock_guard<std::mutex> lock(_loggerMutex);
        _logger.LogError(function, oss.str(), __FILE__, __LINE__);
    }

    // Helper methods
    void ANSFacialRecognition::LogThreadSafe(const std::string& function, const std::string& message,
        LogLevel level) {
        std::lock_guard<std::mutex> lock(_loggerMutex);
        switch (level) {
        case LogLevel::Debug: _logger.LogDebug(function, message, __FILE__, __LINE__); break;
        case LogLevel::Info:  _logger.LogDebug(function, message, __FILE__, __LINE__);  break;
        case LogLevel::Warn:  _logger.LogWarn(function, message, __FILE__, __LINE__);  break;
        case LogLevel::Fatal: _logger.LogFatal(function, message, __FILE__, __LINE__); break;
        case LogLevel::Error:
        default:              _logger.LogError(function, message, __FILE__, __LINE__); break;
        }
    }
};


// Working version
//std::vector<FaceResultObject> ANSFacialRecognition::Inference(
//    const cv::Mat& input,
//    const std::string& camera_id)
//{
//    std::lock_guard<std::recursive_mutex> lock(_mutex);
//    std::vector<FaceResultObject> resultObjects;
//
//    // Early validation checks
//    if (!ValidateInitialization() || !ValidateInput(input) || !ValidateComponents()) {
//        return resultObjects;
//    }
//
//    try {
//        // Start total timing
//        auto t_total_start = std::chrono::high_resolution_clock::now();
//
//        // Prepare input frame
//        auto t_prepare_start = std::chrono::high_resolution_clock::now();
//        cv::Mat frame = PrepareInputFrame(input);
//        auto t_prepare_end = std::chrono::high_resolution_clock::now();
//        float prepare_ms = std::chrono::duration<float, std::milli>(t_prepare_end - t_prepare_start).count();
//
//        if (frame.empty()) {
//            _logger.LogFatal("ANSFacialRecognition::Inference()",
//                "Failed to prepare input frame", __FILE__, __LINE__);
//            return resultObjects;
//        }
//
//        // Detect faces
//        auto t_detect_start = std::chrono::high_resolution_clock::now();
//        auto detectedFaces = DetectFaces(frame, camera_id);
//        auto t_detect_end = std::chrono::high_resolution_clock::now();
//        float detect_ms = std::chrono::duration<float, std::milli>(t_detect_end - t_detect_start).count();
//
//        if (detectedFaces.empty()) {
//            _logger.LogDebug("ANSFacialRecognition::Inference()",
//                "No faces detected", __FILE__, __LINE__);
//            return resultObjects;
//        }
//
//        // Filter faces
//        auto t_filter_start = std::chrono::high_resolution_clock::now();
//        auto validFaces = FilterFaces(detectedFaces);
//        auto t_filter_end = std::chrono::high_resolution_clock::now();
//        float filter_ms = std::chrono::duration<float, std::milli>(t_filter_end - t_filter_start).count();
//
//        if (validFaces.empty()) {
//            _logger.LogDebug("ANSFacialRecognition::Inference()",
//                "No valid faces after filtering", __FILE__, __LINE__);
//            return resultObjects;
//        }
//
//        // Recognize faces (BATCH INFERENCE HAPPENS HERE)
//        auto t_recognize_start = std::chrono::high_resolution_clock::now();
//        resultObjects = RecognizeFaces(frame, validFaces);
//        auto t_recognize_end = std::chrono::high_resolution_clock::now();
//        float recognize_ms = std::chrono::duration<float, std::milli>(t_recognize_end - t_recognize_start).count();
//
//        // Post-process faces
//        auto t_postproc_start = std::chrono::high_resolution_clock::now();
//        PostProcessFaces(resultObjects);
//        auto t_postproc_end = std::chrono::high_resolution_clock::now();
//        float postproc_ms = std::chrono::duration<float, std::milli>(t_postproc_end - t_postproc_start).count();
//
//        // Apply head pose filtering if enabled
//        float headpose_ms = 0.0f;
//        if (_enableHeadPose) {
//            auto t_headpose_start = std::chrono::high_resolution_clock::now();
//            resultObjects = PostProcessDetection(resultObjects, camera_id);
//            auto t_headpose_end = std::chrono::high_resolution_clock::now();
//            headpose_ms = std::chrono::duration<float, std::milli>(t_headpose_end - t_headpose_start).count();
//        }
//
//        // Calculate total time
//        auto t_total_end = std::chrono::high_resolution_clock::now();
//        float total_ms = std::chrono::duration<float, std::milli>(t_total_end - t_total_start).count();
//
//        // Calculate measured sum
//        float measured_sum = prepare_ms + detect_ms + filter_ms + recognize_ms + postproc_ms + headpose_ms;
//        float unaccounted_ms = total_ms - measured_sum;
//
//        // Detailed logging
//        _logger.LogDebug("ANSFacialRecognition::Inference()",
//            "=== Timing Breakdown (Faces: " + std::to_string(validFaces.size()) + ") ===\n"
//            "  Prepare Frame:    " + std::to_string(prepare_ms) + " ms\n"
//            "  Face Detection:   " + std::to_string(detect_ms) + " ms\n"
//            "  Face Filter:      " + std::to_string(filter_ms) + " ms\n"
//            "  Face Recognition: " + std::to_string(recognize_ms) + " ms (" +
//            std::to_string(recognize_ms / validFaces.size()) + " ms/face)\n"
//            "  Post-Process:     " + std::to_string(postproc_ms) + " ms\n"
//            "  Head Pose:        " + std::to_string(headpose_ms) + " ms\n"
//            "  --------------------------------\n"
//            "  Measured Sum:     " + std::to_string(measured_sum) + " ms\n"
//            "  Actual Total:     " + std::to_string(total_ms) + " ms\n"
//            "  Unaccounted:      " + std::to_string(unaccounted_ms) + " ms\n"
//            "  ================================",
//            __FILE__, __LINE__);
//
//        return resultObjects;
//    }
//    catch (const std::exception& e) {
//        _logger.LogFatal("ANSFacialRecognition::Inference()",
//            e.what(), __FILE__, __LINE__);
//    }
//    catch (...) {
//        _logger.LogFatal("ANSFacialRecognition::Inference()",
//            "Unknown exception occurred", __FILE__, __LINE__);
//    }
//    return resultObjects;
//}

// Old code
// std::vector<FaceResultObject> ANSFacialRecognition::Detect(const cv::Mat& input, const std::string& camera_id) {
   //     std::lock_guard<std::recursive_mutex> lock(_mutex);
   //     if (!_isInitialized) {
   //         std::vector<Object>			  _outputBbox;
   //         _outputBbox.clear();
   //         std::vector<FaceResultObject> resultObjects;
   //         this->_logger.LogError("ANSFacialRecognition::Detect()", "Models are not initialized.", __FILE__, __LINE__);
   //         return resultObjects;
   //     }
   //     try {
   //         std::vector<Object>			  _rawOutputBbox;
   //         std::vector<Object>			  _outputBbox;

   //         std::vector<FaceResultObject> resultObjects;
   //         resultObjects.clear();
   //         if (input.empty()) {
   //             this->_logger.LogFatal("ANSFacialRecognition::Detect()", "image frame is empty", __FILE__, __LINE__);
   //             return resultObjects;
   //         }
   //         if ((input.cols < 10) || (input.rows < 10)) return resultObjects;
   //         // Convert grayscale images to 3-channel BGR if needed
   //         cv::Mat frame;
   //         if (input.channels() == 1) {
   //             cv::cvtColor(input, frame, cv::COLOR_GRAY2BGR);
   //         }
   //         else {
   //             frame = input.clone();
   //         }


   //         _rawOutputBbox = _detector->RunInference(frame,camera_id);
   //         if (_rawOutputBbox.empty()) {
   //             return resultObjects;
   //         }
   //         // For every detected face
   //         for (size_t i = 0; i < _rawOutputBbox.size(); i++) {
   //             cv::Rect rect = _rawOutputBbox[i].box;
   //             Face face(i, rect);
   //             face.ageGenderEnable(this->_enableAgeGender && _ageGenderDetector->enabled());
   //             face.emotionsEnable(this->_enableFaceEmotions && _emotionsDetector->enabled());
   //             face.headPoseEnable(this->_enableHeadPose && _headPoseDetector->enabled());
   //             face.antispoofingEnable(this->_enableAntiProof && _antisproofDetector->enabled());

   //             if (face.isAgeGenderEnabled()) {
   //                 if (!_rawOutputBbox[i].mask.empty()) {
            //			cv::Mat mask = _rawOutputBbox[i].mask.clone();
            //			if (mask.empty()) continue;
            //			if ((mask.cols < 5) && (mask.rows < 5)) continue;
   //                     AgeGenderResults ageGenderResult = _ageGenderDetector->runInfer(mask);
   //                     face.updateGender(ageGenderResult.maleProb);
   //                     face.updateAge(ageGenderResult.age);
            //			mask.release();
   //                 }
   //             }
   //             if (face.isEmotionsEnabled()) {
   //                 if (!_rawOutputBbox[i].mask.empty()) {
   //                     cv::Mat mask = _rawOutputBbox[i].mask.clone();
   //                     if (mask.empty()) continue;
   //                     if ((mask.cols < 5) && (mask.rows < 5)) continue;
            //			std::map<std::string, float> emotions = _emotionsDetector->runInfer(mask);
   //                     face.updateEmotions(emotions);
            //			mask.release();
   //                 }
   //             }
   //             if (face.isHeadPoseEnabled()) {
   //                 if (!_rawOutputBbox[i].mask.empty()) {
   //                     cv::Mat mask = _rawOutputBbox[i].mask.clone();
   //                     if (mask.empty()) continue;
   //                     if ((mask.cols < 5) && (mask.rows < 5)) continue;
            //			HeadPoseResults headPoseResult = _headPoseDetector->runInfer(mask);
   //                     face.updateHeadPose(headPoseResult);
            //			mask.release();
   //                 }
   //             }
   //             if (face.isAntispoofingEnabled()) {
   //                 if (!_rawOutputBbox[i].mask.empty()) {
   //                     cv::Mat mask = _rawOutputBbox[i].mask.clone();
   //                     if (mask.empty()) continue;
   //                     if ((mask.cols < 5) && (mask.rows < 5)) continue;
            //			float confidence = _antisproofDetector->runInfer(mask);
   //                     face.updateRealFaceConfidence(confidence);
            //			mask.release();
   //                 }
   //             }
   //             // convert face into string to add-into extra information
   //             bool isUnknown;
   //             isUnknown = false;
   //             FaceResultObject resultObject;
   //             resultObject.isUnknown = isUnknown;
   //             resultObject.userId = "0000";
   //             resultObject.userName = "Unknown";
   //             resultObject.similarity = 0;
   //             resultObject.confidence = 1.0;
   //             float x = _rawOutputBbox[i].box.x;
   //             float y = _rawOutputBbox[i].box.y;
   //             float w = _rawOutputBbox[i].box.width;;
   //             float h = _rawOutputBbox[i].box.height;
   //             resultObject.box.x = x;
   //             resultObject.box.y = y;
   //             resultObject.box.width = w;
   //             resultObject.box.height = h;

            //	resultObject.box.x = MAX(0.0f, resultObject.box.x);
            //	resultObject.box.y = MAX(0.0f, resultObject.box.y);
            //	resultObject.box.width = MIN((float)input.cols - resultObject.box.x, resultObject.box.width);
            //	resultObject.box.height = MIN((float)input.rows - resultObject.box.y, resultObject.box.height);

   //             resultObject.mask = _rawOutputBbox[i].mask;
   //             resultObject.polygon = _rawOutputBbox[i].polygon;
   //             resultObject.kps = _rawOutputBbox[i].kps;
   //             std::string faceAtt = ANSFRHelper::FaceAttributeToJsonString(face);
   //             resultObject.extraInformation = faceAtt;//coversion from face to string
            //	resultObject.cameraId = camera_id;
   //             resultObject.trackId = _rawOutputBbox[i].trackId;
   //             resultObjects.push_back(resultObject);
   //         }

   //         frame.release();
   //         _outputBbox.clear();
   //         return PostProcessDetection(resultObjects, camera_id);
   //     }
   //     catch (std::exception& e) {
   //         this->_logger.LogFatal("ANSFacialRecognition::Detect()", e.what(), __FILE__, __LINE__);
   //         std::vector<FaceResultObject> resultObjects;
   //         resultObjects.clear();
   //         return resultObjects;
   //     }
   // }

 // std::vector<FaceResultObject> ANSFacialRecognition::Inference(const cv::Mat& input, const std::string& camera_id) {
   //     std::lock_guard<std::recursive_mutex> lock(_mutex);
   //     if (!_isInitialized) {
   //         std::vector<Object>			  _outputBbox;
   //         _outputBbox.clear();
   //         std::vector<FaceResultObject> resultObjects;
   //         this->_logger.LogError("ANSFacialRecognition::Inference()", "Models are not initialized.", __FILE__, __LINE__);
   //         return resultObjects;
   //     }
   //     try {
   //         std::vector<FaceResultObject> resultObjects;
   //         std::vector<Object> _outputBbox;
   //         if (input.empty()) {
   //             this->_logger.LogFatal("ANSFacialRecognition::Inference()", "image frame is empty", __FILE__, __LINE__);
   //             return resultObjects;
   //         }
   //         if ((input.cols < 10) || (input.rows < 10)) return resultObjects;
   //         // Convert grayscale images to 3-channel BGR if needed
   //         cv::Mat frame;
   //         if (input.channels() == 1) {
   //             cv::cvtColor(input, frame, cv::COLOR_GRAY2BGR);
   //         }
   //         else {
   //             frame = input.clone();
   //         }


   //         _outputBbox = _detector->RunInference(frame,camera_id);
   //         if (_outputBbox.empty()) {
   //             return resultObjects;
   //         }
   //         // Filter out the faces that are too small
   //         std::vector<Object> validFaces=checkFaces(_outputBbox, true);
   //         resultObjects = _recognizer->Match(frame, validFaces, _userDict);
   //         updateFaceAttributes(resultObjects);
   //         ensureUniqueUserIdWithHighestConfidence(resultObjects);
   //         frame.release();
   //         return PostProcessDetection(resultObjects, camera_id);
   //     }
   //     catch (std::exception& e) {
   //         this->_logger.LogFatal("ANSFacialRecognition::Inference()", e.what(), __FILE__, __LINE__);
   //         return std::vector<FaceResultObject>();
   //     }
   // }

    //int ANSFacialRecognition::GetUser(int userId, UserRecord& userRecord) {
    //    try {
    //        // Initialize user ID
    //        userRecord.UserId = userId;

    //        // LOCK ONLY DURING DATABASE ACCESS
    //        {
    //            std::lock_guard<std::mutex> lock(_databaseMutex);

    //            // Get user basic information
    //            int result = _db->GetUser(userId, userRecord.UserCode, userRecord.UserName);
    //            if (result <= 0) {
    //                LogThreadSafe("ANSFacialRecognition::GetUser",
    //                    "User ID " + std::to_string(userId) + " not found in database");
    //                return 0;
    //            }

    //            // Get user's face IDs
    //            result = _db->GetFaceIdsByUser(userId, userRecord.FaceIds);
    //            if (result <= 0) {
    //                LogThreadSafe("ANSFacialRecognition::GetUser",
    //                    "No faces found for user ID " + std::to_string(userId));
    //                return 0;
    //            }
    //        }

    //        return 1;
    //    }
    //    catch (const std::exception& e) {
    //        LogThreadSafe("ANSFacialRecognition::GetUser",
    //            "User ID " + std::to_string(userId) + ": " + e.what());
    //        return 0;
    //    }
    //}
    //int ANSFacialRecognition::GetUser(int userId, std::string userCode, std::string userName, UserRecord& userRecord) {
    //    try {
    //        // Initialize user ID
    //        userRecord.UserId = userId;
    //        userRecord.UserCode = userCode;
    //        userRecord.UserName = userName;

    //        // LOCK ONLY DURING DATABASE ACCESS
    //        {
    //            std::lock_guard<std::mutex> lock(_databaseMutex);
    //            // Get user's face IDs
    //            int result = _db->GetFaceIdsByUser(userId, userRecord.FaceIds);
    //            if (result <= 0) {
    //                LogThreadSafe("ANSFacialRecognition::GetUser",
    //                    "No faces found for user ID " + std::to_string(userId));
    //                return 0;
    //            }
    //        }

    //        return 1;
    //    }
    //    catch (const std::exception& e) {
    //        LogThreadSafe("ANSFacialRecognition::GetUser",
    //            "User ID " + std::to_string(userId) + ": " + e.what());
    //        return 0;
    //    }
    //}

    //bool ANSFacialRecognition::UpdateUserDictionary() {
    //    try {
    //        // Load embeddings and user dictionary (with database lock)
    //        {
    //            std::lock_guard<std::mutex> lock(_databaseMutex);

    //            if (!_db) {
    //                LogThreadSafe("ANSFacialRecognition::UpdateUserDictionary",
    //                    "Database not initialized");
    //                return false;
    //            }

    //            _userDict = _db->GetUserDict();
    //        }
    //        return true;
    //    }
    //    catch (const std::exception& e) {
    //        LogThreadSafe("ANSFacialRecognition::UpdateUserDictionary",
    //            "Failed to update user dictiornary: " + std::string(e.what()));
    //        return false;
    //    }
    //}