package com.ycwl.basic.task;

import com.alibaba.fastjson.JSONObject;
import com.ycwl.basic.biz.TemplateBiz;
import com.ycwl.basic.facebody.FaceBodyFactory;
import com.ycwl.basic.facebody.adapter.AliFaceBodyAdapter;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.ScenicMapper;
import com.ycwl.basic.mapper.TemplateMapper;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.repository.TemplateRepository;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.service.task.TaskService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;

@Component
@EnableScheduling
@Slf4j
public class DynamicTaskGenerator {
    @Autowired
    private ScenicMapper scenicMapper;
    @Autowired
    private TemplateMapper templateMapper;
    @Autowired
    private FaceMapper faceMapper;
    @Autowired
    private TaskFaceService faceService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private TemplateBiz templateBiz;
    @Autowired
    private FaceSampleMapper faceSampleMapper;
    @Autowired
    private ScenicRepository scenicRepository;
    @Autowired
    private TemplateRepository templateRepository;
    @Autowired
    private FaceRepository faceRepository;

    @Data
    @AllArgsConstructor
    public static class Task implements Delayed {
        public Long faceSampleId;
        public Date startTime;

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(startTime.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed o) {
            return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));
        }
    }

    public static DelayQueue<Task> queue = new DelayQueue<>();

    public static void addTask(Long faceSampleId) {
        Date createTime = new Date();
        // 半分钟后
        createTime.setTime(createTime.getTime() + 30000L);
        queue.add(new Task(faceSampleId, createTime));
    }

    @Scheduled(fixedDelay = 1000L)
    public void doTask() {
        Task task = queue.poll();
        if (task == null) {
            return;
        }
        // 根据人脸照片获取人脸样本ID
        FaceSampleRespVO faceSample = faceSampleMapper.getById(task.getFaceSampleId());
        if (faceSample == null) {
            log.debug("人脸样本ID{}不存在", task.getFaceSampleId());
            return;
        }
        if (faceSample.getScore() == null) {
            log.debug("人脸样本ID{}人脸质量为空", task.getFaceSampleId());
            return;
        }
        ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(faceSample.getScenicId());
        if (scenicConfig == null) {
            log.debug("当前景区{}，无配置", faceSample.getScenicId());
            return;
        }
        if (!Integer.valueOf(5).equals(scenicConfig.getBookRoutine())) {
            log.debug("当前景区{}未启用预约流程，跳过", faceSample.getScenicId());
            return;
        }
        log.info("开始执行任务：{}", task);
        IFaceBodyAdapter faceBodyAdapter;
        if (scenicConfig.getFaceType() != null) {
            faceBodyAdapter = FaceBodyFactory.getAdapter(scenicConfig.getFaceType());
            faceBodyAdapter.loadConfig(JSONObject.parseObject(scenicConfig.getFaceConfigJson(), Map.class));
        } else {
            faceBodyAdapter = FaceBodyFactory.use();
        }
        SearchFaceRespVo userDbSearchResult = faceService.searchFace(faceBodyAdapter, USER_FACE_DB_NAME+faceSample.getScenicId(), faceSample.getFaceUrl(), "预约流程检索");
        // 如果人脸样本ID在人脸样本库中，则创建任务
        if (!userDbSearchResult.getSampleListIds().isEmpty()) {
            log.info("人脸样本ID在人脸样本库中，创建任务：{}", task);
            // 找
            List<Long> faceIdList = userDbSearchResult.getSampleListIds().stream().filter(faceId -> {
                FaceEntity face = faceRepository.getFace(faceId);
                if (face == null) {
                    return false;
                }
                return face.getScenicId().equals(faceSample.getScenicId());
            }).collect(Collectors.toList());
            if (faceIdList.isEmpty()) {
                log.info("本景区人脸样本ID不在人脸样本库中，忽略任务：{}", task);
                return;
            }
            faceIdList.forEach(faceId -> {
                // 每一个都重新匹配
                faceService.searchFace(faceId);
            });
            faceIdList.forEach(faceId -> {
                log.info("自动下发任务，人脸ID：{}", faceId);
                taskService.autoCreateTaskByFaceId(faceId);
            });
        } else {
            log.info("人脸样本ID不在人脸样本库中，忽略任务：{}", task);
        }
    }
}
