package com.mortals.xhx.daemon.task;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.service.ITask;
import com.mortals.framework.service.ITaskExcuteService;
import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.common.code.GenderEnum;
import com.mortals.xhx.common.code.RecognitionResourceEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.key.Constant;
import com.mortals.xhx.common.key.ParamKey;
import com.mortals.xhx.module.appointment.model.*;
import com.mortals.xhx.module.appointment.service.AppointmentConfigService;
import com.mortals.xhx.module.appointment.service.AppointmentConfigTimesService;
import com.mortals.xhx.module.appointment.service.AppointmentPersonService;
import com.mortals.xhx.module.device.model.DeviceEntity;
import com.mortals.xhx.module.device.model.DeviceQuery;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.face.model.*;
import com.mortals.xhx.module.face.service.FaceGroupPersonService;
import com.mortals.xhx.module.face.service.FaceGroupService;
import com.mortals.xhx.module.face.service.FacePlanService;
import com.mortals.xhx.module.hik.face.model.req.face.FaceInfo;
import com.mortals.xhx.module.hik.face.model.req.face.FacePic;
import com.mortals.xhx.module.hik.face.model.req.face.FaceReq;
import com.mortals.xhx.module.hik.face.model.req.group.FaceGroupReq;
import com.mortals.xhx.module.hik.face.model.req.plan.PlanRecognListReq;
import com.mortals.xhx.module.hik.face.model.req.plan.PlanRecognReq;
import com.mortals.xhx.module.hik.face.model.req.plan.TimeBlockListItem;
import com.mortals.xhx.module.hik.face.model.req.plan.TimeRangeItem;
import com.mortals.xhx.module.hik.face.model.rsp.face.FaceDataInfo;
import com.mortals.xhx.module.hik.face.model.rsp.plan.PlanRecognInfo;
import com.mortals.xhx.module.hik.face.service.IHikFaceService;
import com.mortals.xhx.module.hik.face.service.IHikPlanService;
import com.mortals.xhx.module.person.model.PersonEntity;
import com.mortals.xhx.module.person.service.PersonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.mortals.xhx.common.key.ParamKey.PARAM_FACE_GROUP_REGISTER;

/**
 * 每日创建预约人员监控计划
 * 创建计划前删除之前计划
 * <p>
 * 每日更新陌生人员监控计划
 *
 * @author:
 * @date: 2023/4/17 17:52
 */
@Slf4j
@Service("CreateBlackPlanToHikByDayTask")
public class CreateBlackPlanToHikByDayTaskImpl implements ITaskExcuteService {

    @Autowired
    private PersonService personService;
    @Autowired
    private IHikFaceService hikFaceService;
    @Autowired
    private IHikPlanService hikPlanService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private FacePlanService facePlanService;
    @Autowired
    private UploadService uploadService;
    @Autowired
    private FaceGroupService faceGroupService;
    @Autowired
    private FaceGroupPersonService faceGroupPersonService;
    @Autowired
    private AppointmentPersonService appointmentPersonService;
    @Autowired
    private AppointmentConfigService appointmentConfigService;
    @Autowired
    private AppointmentConfigTimesService appointmentConfigTimesService;

    @Override
    public void excuteTask(ITask task) throws AppException {

        log.info("{}=>创建陌生人计划任务", DateUtils.getCurrStrDate());
        createStrangerPlanByDay();
        log.info("{}=>创建陌生人计划任务完成", DateUtils.getCurrStrDate());

        log.info("{}=>创建预约计划任务", DateUtils.getCurrStrDate());
        createAppointmentPlanByDay();
        log.info("{}=>创建预约计划任务完成", DateUtils.getCurrStrDate());
    }

    private void createStrangerPlanByDay() {
        int threshold = GlobalSysInfo.getParamIntValue(ParamKey.PARAM_FACE_THRESHOLD, 80);
        //创建或者更新
        PlanRecognListReq planRecognListReq = new PlanRecognListReq();
        Rest<List<PlanRecognInfo>> planRecognWhiteListRest = hikPlanService.findPlanRecognWhiteList(planRecognListReq);
        if (planRecognWhiteListRest.getCode() == YesNoEnum.YES.getValue()) {
            PlanRecognInfo planRecognWhiteInfo = planRecognWhiteListRest.getData().stream().map(i -> {
                i.getName();
                if (i.getName().equals(Constant.STRANGER_PLAN)) {
                    return i;
                }
                return null;
            }).filter(f -> f != null).findFirst().orElseGet(() -> null);
            // todo 创建陌生人计划
            //初始化新增取号监控识别计划
            PlanRecognReq planRecognBlackReq = new PlanRecognReq();
            planRecognBlackReq.setName(Constant.STRANGER_PLAN);
            planRecognBlackReq.setDescription(Constant.STRANGER_PLAN);
            planRecognBlackReq.setThreshold(threshold);
            //设置人脸分组
            FaceGroupEntity faceGroupEntity = faceGroupService.selectOne(new FaceGroupQuery().name(PARAM_FACE_GROUP_REGISTER));
            if (ObjectUtils.isEmpty(faceGroupEntity)) {
                log.info("人脸组不存在！");
                return;
            }
            List<String> faceGroupIndexCodes = new ArrayList<>();
            faceGroupIndexCodes.add(faceGroupEntity.getIndexCode());
            planRecognBlackReq.setFaceGroupIndexCodes(faceGroupIndexCodes);
            //设置监控点
            List<String> cameraIndexCodes = deviceService.find(new DeviceQuery()).stream().map(DeviceEntity::getDeviceCode).collect(Collectors.toList());
            planRecognBlackReq.setCameraIndexCodes(cameraIndexCodes);
            //设置识别方式
            planRecognBlackReq.setRecognitionResourceType(RecognitionResourceEnum.COMPARISON.getValue());
            //设置时间段 默认全天候
            if (ObjectUtils.isEmpty(planRecognWhiteInfo)) {
                Rest<String> planRecognWhiteAddRest = hikPlanService.planRecognWhiteAdd(planRecognBlackReq);
                if (planRecognWhiteAddRest.getCode() == YesNoEnum.YES.getValue()) {
                    FacePlanEntity planEntity = new FacePlanEntity();
                    planEntity.initAttrValue();
                    planEntity.setIndexCode(planRecognWhiteAddRest.getData());
                    planEntity.setName(Constant.STRANGER_PLAN);
                    planEntity.setDescription(Constant.STRANGER_PLAN);
                    planEntity.setCreateTime(new Date());
                    planEntity.setCreateUserId(1L);
                    planEntity.setCreateUserName("admin");
                    facePlanService.save(planEntity);
                }
            } else {
                //更新计划
                planRecognBlackReq.setIndexCode(planRecognWhiteInfo.getIndexCode());
                Rest<Boolean> planRecognWhiteUpdateRest = hikPlanService.planRecognWhiteUpdate(planRecognBlackReq);
                if (planRecognWhiteUpdateRest.getCode() == YesNoEnum.YES.getValue() && planRecognWhiteUpdateRest.getData()) {

                    FacePlanEntity whitePlan = facePlanService.selectOne(new FacePlanQuery().indexCode(planRecognWhiteInfo.getIndexCode()));
                    whitePlan.setUpdateTime(new Date());
                    whitePlan.setUpdateUserId(1L);
                    whitePlan.setUpdateUserName("system");
                    facePlanService.update(whitePlan);

                }

            }


        }

    }


    private void createAppointmentPlanByDay() {
        PlanRecognListReq planRecognBlackListReq = new PlanRecognListReq();
        Rest<List<PlanRecognInfo>> planRecognBlackRest = hikPlanService.findPlanRecognBlackList(planRecognBlackListReq);
        if (planRecognBlackRest.getCode() == YesNoEnum.YES.getValue()) {
            List<PlanRecognInfo> delPlanList = planRecognBlackRest.getData().stream().map(i -> {
                if (StrUtil.startWith(i.getName(), Constant.APPOINTMENT_PLAN_PREFIX) && !i.getName().equals(Constant.APPOINTMENT_GROUP_PREFIX + DateUtils.getCurrStrDate())) {
                    return i;
                }
                return null;
            }).filter(f -> f != null).collect(Collectors.toList());
            if (!ObjectUtils.isEmpty(delPlanList)) {
                //删除计划
                PlanRecognReq planRecognBlackReq = new PlanRecognReq();
                planRecognBlackReq.setRecognitionResourceIndexCodes(delPlanList.stream().map(i -> i.getIndexCode()).collect(Collectors.toList()));
                Rest<Boolean> delRest = hikPlanService.planRecognBlackDel(planRecognBlackReq);
                if (delRest.getCode() == YesNoEnum.YES.getValue() && delRest.getData()) {
                    log.info("预约计划删除成功！");
                }
            }
        }
        log.info("每日创建预约人员监控计划");
        //获取当天预约
        AppointmentPersonQuery appointmentPersonQuery = new AppointmentPersonQuery();
        appointmentPersonQuery.setAppointmentStartTimeStart(DateUtils.getCurrStrDate());
        appointmentPersonQuery.setAppointmentStartTimeEnd(DateUtils.getCurrStrDate());
        List<AppointmentPersonEntity> appointmentPersonEntities = appointmentPersonService.find(appointmentPersonQuery);
        if (!ObjectUtils.isEmpty(appointmentPersonEntities)) {
            //创建人脸分组
            String group = Constant.APPOINTMENT_GROUP_PREFIX + DateUtils.getCurrStrDate();
            FaceGroupEntity faceGroup = faceGroupService.selectOne(new FaceGroupQuery().name(group));
            if (ObjectUtils.isEmpty(faceGroup)) {
                //创建分组
                log.info("创建人脸分组...");
                FaceGroupReq faceGroupReq = new FaceGroupReq();
                faceGroupReq.setName(group);
                faceGroupReq.setDescription(group);
                Rest<FaceGroupEntity> rest = faceGroupService.saveFaceGroupToHik(faceGroupReq);
                if (rest.getCode() == YesNoEnum.YES.getValue()) {
                    FaceGroupEntity newFaceGroupEntity = rest.getData();
                    //创建人脸tohik
                    for (AppointmentPersonEntity appointmentPersonEntity : appointmentPersonEntities) {
                        PersonEntity personEntity = personService.getCache(appointmentPersonEntity.getPersonId().toString());
                        if (ObjectUtils.isEmpty(personEntity)) {
                            log.info("注册人员未空，persionId:{}", appointmentPersonEntity.getPersonId());
                            continue;
                        }
                        //查询图片并转成base64
                        if (!ObjectUtils.isEmpty(personEntity.getPhoto())) {
                            String filePath = uploadService.getFilePath(personEntity.getPhoto());
                            byte[] bytes = FileUtil.readBytes(filePath);
                            if (bytes.length > 0) {
                                String picBase64Data = Base64.encode(bytes);
                                FaceReq faceReq = new FaceReq();
                                FaceInfo faceInfo = new FaceInfo();
                                faceInfo.setName(personEntity.getName());
                                faceInfo.setSex(personEntity.getGender() == GenderEnum.男.getValue() ? "1" : "2");
                                faceInfo.setCertificateType("111");
                                faceInfo.setCertificateNum(personEntity.getIdCard());
                                faceReq.setFaceInfo(faceInfo);
                                FacePic facePic = new FacePic();
                                facePic.setFaceBinaryData(picBase64Data);
                                faceReq.setFacePic(facePic);
                                faceReq.setFaceGroupIndexCode(faceGroup.getIndexCode());
                                Rest<FaceDataInfo> faceDataInfoRest = hikFaceService.faceSingleAdd(faceReq);
                                if (faceDataInfoRest.getCode() == YesNoEnum.YES.getValue()) {
                                    //人脸添加成功，保存人脸组
                                    FaceGroupPersonEntity faceGroupPersonEntity = new FaceGroupPersonEntity();
                                    faceGroupPersonEntity.initAttrValue();
                                    faceGroupPersonEntity.setFaceGroupId(newFaceGroupEntity.getId());
                                    faceGroupPersonEntity.setIndexCode(faceDataInfoRest.getData().getIndexCode());
                                    faceGroupPersonEntity.setCreateTime(new Date());
                                    faceGroupPersonEntity.setCreateUserId(1L);
                                    faceGroupPersonService.save(faceGroupPersonEntity);
                                } else {
                                    log.info("添加人脸异常=>{}", faceDataInfoRest.getMsg());
                                }
                            } else {
                                log.info("图片数据为空，filePath=>{}", filePath);
                            }
                        } else {
                            log.info("人员图片photo为空，person=>{}", personEntity.getName());
                        }
                    }

                    log.info("添加当天预约监控计划");
                    String appointPlanName = Constant.APPOINTMENT_GROUP_PREFIX + DateUtils.getCurrStrDate();
                    int threshold = GlobalSysInfo.getParamIntValue(ParamKey.PARAM_FACE_THRESHOLD, 80);
                    //初始化新增取号监控识别计划
                    PlanRecognReq planRecognBlackReq = new PlanRecognReq();
                    planRecognBlackReq.setName(appointPlanName);
                    planRecognBlackReq.setDescription(appointPlanName);
                    planRecognBlackReq.setThreshold(threshold);
                    //设置人脸分组
                    List<String> faceGroupIndexCodes = new ArrayList<>();
                    faceGroupIndexCodes.add(newFaceGroupEntity.getIndexCode());
                    planRecognBlackReq.setFaceGroupIndexCodes(faceGroupIndexCodes);
                    //设置监控点
                    List<String> cameraIndexCodes = deviceService.find(new DeviceQuery()).stream().map(DeviceEntity::getDeviceCode).collect(Collectors.toList());
                    planRecognBlackReq.setCameraIndexCodes(cameraIndexCodes);
                    //设置识别方式
                    planRecognBlackReq.setRecognitionResourceType(RecognitionResourceEnum.FACE_RECOGNITION_SERVER.getValue());
                    //设置时间段 默认全天候
                    AppointmentConfigEntity appointmentConfigEntity = appointmentConfigService.selectOne(new AppointmentConfigQuery());
                    if (!ObjectUtils.isEmpty(appointmentConfigEntity)) {
                        List<AppointmentConfigTimesEntity> timesEntities = appointmentConfigTimesService.find(new AppointmentConfigTimesQuery().aotoCheckCfgId(appointmentConfigEntity.getId()));
                        if (!ObjectUtils.isEmpty(timesEntities)) {
                            List<TimeBlockListItem> timeBlockList = new ArrayList<>();

                            TimeBlockListItem timeBlockListItem = new TimeBlockListItem();
                            //周一至周日
                            timeBlockListItem.setDayOfWeek("1-7");
                            List<TimeRangeItem> timeRange = new ArrayList<>();
                            for (AppointmentConfigTimesEntity timesEntity : timesEntities) {
                                TimeRangeItem timeRangeItem = new TimeRangeItem();
                                String startTimeStr = DateUtils.convertTime2Str(timesEntity.getServiceTimeStart().getTime(), "HH:ss");
                                String endTimeStr = DateUtils.convertTime2Str(timesEntity.getServiceTimeEnd().getTime(), "HH:ss");
                                timeRangeItem.setStartTime(startTimeStr);
                                timeRangeItem.setEndTime(endTimeStr);
                                timeRange.add(timeRangeItem);
                            }
                            timeBlockListItem.setTimeRange(timeRange);
                            timeBlockList.add(timeBlockListItem);
                            planRecognBlackReq.setTimeBlockList(timeBlockList);
                        }
                    }

                    Rest<String> planRecognBlackAddRest = hikPlanService.planRecognBlackAdd(planRecognBlackReq);
                    if (planRecognBlackAddRest.getCode() == YesNoEnum.YES.getValue()) {
                        FacePlanEntity planEntity = new FacePlanEntity();
                        planEntity.initAttrValue();
                        planEntity.setIndexCode(planRecognBlackAddRest.getData());
                        planEntity.setName(appointPlanName);
                        planEntity.setDescription(appointPlanName);
                        planEntity.setCreateTime(new Date());
                        planEntity.setCreateUserId(1L);
                        planEntity.setCreateUserName("admin");
                        facePlanService.save(planEntity);
                    }
                } else {
                    log.info("人员分组创建失败=>{}", rest.getMsg());
                }
            } else {
                log.info("当天人员分组以存在，人员分组名称=>{}", group);
            }
        } else {
            log.info("当天无预约人员，不创建监控计划=>{}", DateUtils.getCurrStrDate());
        }
    }


    @Override
    public void stopTask(ITask task) throws AppException {

    }


}
