package com.ycwl.basic.integration.kafka.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.facebody.entity.AddFaceResp;
import com.ycwl.basic.integration.kafka.dto.FaceProcessingMessage;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.task.DynamicTaskGenerator;
import com.ycwl.basic.integration.common.manager.DeviceConfigManager;
// 不再需要SnowFlakeUtil，使用外部传入的ID
import com.ycwl.basic.utils.JacksonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service;

import java.time.ZoneId;
import java.util.Date;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 人脸处理Kafka消费服务
 * 消费外部系统发送到zt-face topic的消息
 */
@Slf4j
@Service
@RequiredArgsConstructor
@ConditionalOnProperty(name = "kafka.enabled", havingValue = "true")
public class FaceProcessingKafkaService {

    private static final String ZT_FACE_TOPIC = "zt-face";

    private final FaceSampleMapper faceSampleMapper;
    private final TaskFaceService taskFaceService;
    private final ScenicService scenicService;
    private final DeviceRepository deviceRepository;
    private final ThreadPoolExecutor faceRecognitionExecutor;

    /**
     * 消费外部系统发送的人脸处理消息
     * 先保存人脸样本数据，再进行异步人脸识别处理
     */
    @KafkaListener(topics = ZT_FACE_TOPIC, containerFactory = "manualCommitKafkaListenerContainerFactory")
    public void processFaceMessage(String message, Acknowledgment ack) {
        try {
            FaceProcessingMessage faceMessage = JacksonUtil.parseObject(message, FaceProcessingMessage.class);
            log.debug("接收到外部人脸处理消息, scenicId: {}, deviceId: {}, faceUrl: {}",
                    faceMessage.getScenicId(), faceMessage.getDeviceId(), faceMessage.getFaceUrl());

            // 使用外部传入的faceSampleId
            Long externalFaceId = faceMessage.getFaceSampleId();
            if (externalFaceId == null) {
                log.error("外部消息中未包含faceSampleId");
                // 即使消息格式错误，也消费消息避免重复处理
                ack.acknowledge();
                return;
            }
            
            // 先保存人脸样本数据
            boolean saved = saveFaceSample(faceMessage, externalFaceId);

            // 然后异步进行人脸识别处理（使用专用线程池）
            if (saved) {
                faceRecognitionExecutor.execute(() -> processFaceRecognitionAsync(faceMessage));
                log.debug("人脸识别任务已提交至线程池, faceSampleId: {}, 活跃线程: {}, 队列大小: {}",
                        externalFaceId, faceRecognitionExecutor.getActiveCount(),
                        faceRecognitionExecutor.getQueue().size());
            } else {
                log.warn("人脸样本保存失败，但消息仍将被消费, faceSampleId: {}", externalFaceId);
            }

            // 无论处理是否成功，都消费消息
            ack.acknowledge();

        } catch (Exception e) {
            log.error("处理外部人脸消息失败: {}", e.getMessage(), e);
            // 即使发生异常也消费消息，避免消息堆积
            ack.acknowledge();
        }
    }

    /**
     * 保存人脸样本数据到数据库
     * @param faceMessage 人脸处理消息
     * @param externalFaceId 外部传入的人脸ID
     * @return 是否保存成功
     */
    private boolean saveFaceSample(FaceProcessingMessage faceMessage, Long externalFaceId) {
        try {
            FaceSampleEntity faceSample = new FaceSampleEntity();
            faceSample.setId(externalFaceId); // 使用外部传入的ID
            faceSample.setScenicId(faceMessage.getScenicId());
            faceSample.setDeviceId(faceMessage.getDeviceId());
            faceSample.setStatus(0); // 初始状态
            faceSample.setFaceUrl(faceMessage.getFaceUrl());
            
            // 转换时间格式
            if (faceMessage.getShotTime() != null) {
                Date shotTime = faceMessage.getShotTime();
                faceSample.setCreateAt(shotTime);
            } else {
                faceSample.setCreateAt(new Date());
            }

            // 保存到数据库
            faceSampleMapper.add(faceSample);

            return true;
        } catch (Exception e) {
            log.error("保存人脸样本数据失败, 外部faceId: {}, scenicId: {}, deviceId: {}", 
                    externalFaceId, faceMessage.getScenicId(), faceMessage.getDeviceId(), e);
            return false;
        }
    }

    /**
     * 异步执行人脸识别处理逻辑
     * 对已保存的人脸样本进行识别处理
     */
    private void processFaceRecognitionAsync(FaceProcessingMessage message) {
        Long faceSampleId = message.getFaceSampleId();
        Long scenicId = message.getScenicId();
        String faceUrl = message.getFaceUrl();

        // 直接使用faceSampleId作为唯一标识
        String faceUniqueId = faceSampleId.toString();

        // 获取人脸识别适配器
        IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(scenicId);
        if (faceBodyAdapter == null) {
            log.error("人脸识别适配器不存在, scenicId: {}", scenicId);
            updateFaceSampleStatus(faceSampleId, -1);
            return;
        }

        try {
            // 更新状态为处理中
            updateFaceSampleStatus(faceSampleId, 1);

            // 确保人脸数据库存在
            taskFaceService.assureFaceDb(faceBodyAdapter, scenicId.toString());

            // 添加人脸到识别服务（使用faceSampleId作为唯一标识）
            AddFaceResp addFaceResp = faceBodyAdapter.addFace(
                scenicId.toString(),
                faceSampleId.toString(),
                faceUrl,
                faceUniqueId // 即faceSampleId.toString()
            );

            if (addFaceResp != null) {
                // 更新人脸样本得分和状态
                faceSampleMapper.updateScore(faceSampleId, addFaceResp.getScore());
                updateFaceSampleStatus(faceSampleId, 2);
                log.debug("人脸识别处理成功, faceSampleId: {}", faceSampleId);

                // 查询设备配置，判断是否启用预订功能
                Long deviceId = message.getDeviceId();
                DeviceConfigManager deviceConfig = deviceRepository.getDeviceConfigManager(deviceId);
                if (deviceConfig != null &&
                    Integer.valueOf(1).equals(deviceConfig.getInteger("enable_pre_book"))) {
                    DynamicTaskGenerator.addTask(faceSampleId);
                }
            } else {
                log.warn("人脸添加返回空结果, faceSampleId: {}", faceSampleId);
                updateFaceSampleStatus(faceSampleId, -1);
            }

        } catch (Exception e) {
            log.error("人脸识别处理失败, faceSampleId: {}, error: {}",
                    faceSampleId, e.getMessage(), e);

            // 标记人脸样本为处理失败状态
            updateFaceSampleStatus(faceSampleId, -1);
        }
    }

    /**
     * 更新人脸样本状态
     */
    private void updateFaceSampleStatus(Long faceSampleId, Integer status) {
        try {
            faceSampleMapper.updateStatus(faceSampleId, status);
        } catch (Exception e) {
            log.error("更新人脸样本状态失败, faceSampleId: {}", faceSampleId, e);
        }
    }

    /**
     * 重试失败的人脸识别
     * 用于手动重试状态为-1的人脸样本
     *
     * @param faceSampleId 人脸样本ID
     * @return 是否成功提交重试任务
     */
    public boolean retryFaceRecognition(Long faceSampleId) {
        try {
            // 查询人脸样本信息
            FaceSampleEntity faceSample = faceSampleMapper.getEntity(faceSampleId);
            if (faceSample == null) {
                log.error("人脸样本不存在, faceSampleId: {}", faceSampleId);
                return false;
            }

            // 检查状态是否为失败状态(-1)
            if (faceSample.getStatus() != -1) {
                log.warn("人脸样本状态不是失败状态, 无需重试, faceSampleId: {}, status: {}",
                        faceSampleId, faceSample.getStatus());
                return false;
            }

            // 构造人脸处理消息
            FaceProcessingMessage message = FaceProcessingMessage.builder()
                    .faceSampleId(faceSample.getId())
                    .scenicId(faceSample.getScenicId())
                    .deviceId(faceSample.getDeviceId())
                    .faceUrl(faceSample.getFaceUrl())
                    .shotTime(faceSample.getCreateAt())
                    .createTime(new Date())
                    .source("retry-manual")
                    .build();

            // 提交到线程池进行异步处理
            faceRecognitionExecutor.execute(() -> processFaceRecognitionAsync(message));

            log.info("人脸识别重试任务已提交, faceSampleId: {}, 活跃线程: {}, 队列大小: {}",
                    faceSampleId, faceRecognitionExecutor.getActiveCount(),
                    faceRecognitionExecutor.getQueue().size());

            return true;

        } catch (Exception e) {
            log.error("提交人脸识别重试任务失败, faceSampleId: {}", faceSampleId, e);
            return false;
        }
    }
}