package com.mortals.xhx.module.hik.event.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.util.DataUtil;
import com.mortals.framework.util.DateUtils;
import com.mortals.framework.utils.ServletUtils;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.common.code.CheckInMethodEnum;
import com.mortals.xhx.common.code.HikEventTypeEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.key.ParamKey;
import com.mortals.xhx.module.appointment.model.AppointmentPersonEntity;
import com.mortals.xhx.module.appointment.model.AppointmentPersonQuery;
import com.mortals.xhx.module.appointment.model.AppointmentRecordsEntity;
import com.mortals.xhx.module.appointment.model.AppointmentRecordsQuery;
import com.mortals.xhx.module.appointment.service.AppointmentPersonService;
import com.mortals.xhx.module.appointment.service.AppointmentRecordsService;
import com.mortals.xhx.module.hik.event.model.req.callback.*;
import com.mortals.xhx.module.hik.event.model.req.callback.recognition.EventData;
import com.mortals.xhx.module.hik.event.model.req.callback.recognition.FaceMatchItem;
import com.mortals.xhx.module.hik.event.model.req.callback.recognition.FaceRecognitionResult;
import com.mortals.xhx.module.hik.event.model.req.callback.recognition.Snap;
import com.mortals.xhx.module.hik.face.model.req.img.ImgReq;
import com.mortals.xhx.module.hik.face.service.IHikFaceService;
import com.mortals.xhx.module.monitor.model.MonitorAlarmEntity;
import com.mortals.xhx.module.monitor.model.MonitorAlarmQuery;
import com.mortals.xhx.module.monitor.model.MonitorAlarmRecordEntity;
import com.mortals.xhx.module.monitor.service.MonitorAlarmRecordService;
import com.mortals.xhx.module.monitor.service.MonitorAlarmService;
import com.mortals.xhx.module.person.model.PersonEntity;
import com.mortals.xhx.module.person.service.PersonService;
import com.mortals.xhx.module.realtime.model.RealtimeDataflowEntity;
import com.mortals.xhx.module.realtime.service.RealtimeDataflowService;
import com.mortals.xhx.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 重点人员识别
 * 预约人员识别
 *
 * @author:
 * @date: 2023/4/17 9:27
 */
@Slf4j
public class BlackPlanRecoginze extends EventTypeAbstract {

    private AppointmentRecordsService appointmentRecordsService;

    private PersonService personService;

    private AppointmentPersonService appointmentPersonService;

    private RealtimeDataflowService dataflowService;

    private MonitorAlarmService monitorAlarmService;

    private MonitorAlarmRecordService monitorAlarmRecordService;

    private IHikFaceService faceService;

    private UploadService uploadService;


    public BlackPlanRecoginze(int type) {
        super(type);
        this.dataflowService = SpringUtils.getBean(RealtimeDataflowService.class);
        this.appointmentRecordsService = SpringUtils.getBean(AppointmentRecordsService.class);
        this.personService = SpringUtils.getBean(PersonService.class);
        this.appointmentPersonService = SpringUtils.getBean(AppointmentPersonService.class);
        this.monitorAlarmService = SpringUtils.getBean(MonitorAlarmService.class);
        this.monitorAlarmRecordService = SpringUtils.getBean(MonitorAlarmRecordService.class);
        this.faceService = SpringUtils.getBean(IHikFaceService.class);
        this.uploadService = SpringUtils.getBean(UploadService.class);
    }

    @Override
    int getType() {
        return HikEventTypeEnum.重点人员识别事件.getValue();
    }


    @Override
    public void saveEventData(EventsItem event) {
        log.info("预约人员识别事件,event:{}", JSON.toJSONString(event));
        Double similarity = DataUtil.converStr2Double(GlobalSysInfo.getParamValue(ParamKey.PARAM_FACE_SIMILARITY, "0.8"), 0);
        EventData eventData = event.getData();
        //识别结果
        FaceRecognitionResult faceRecognitionResult = eventData.getFaceRecognitionResult();
        //抓拍信息
        Snap snap = faceRecognitionResult.getSnap();
        //处理重点人员事件
        //匹配的结果
        List<FaceMatchItem> faceMatchs = faceRecognitionResult.getFaceMatch();
        for (FaceMatchItem faceMatch : faceMatchs) {
            //根据匹配结果 保存业务数据
            if (faceMatch.getSimilarity() > similarity) {
                //判断当前识别是否为注册用户
                if (ObjectUtils.isEmpty(faceMatch.getCertificate())) {
                    log.info("证件号不能为空！  faceMatch:{}", JSON.toJSONString(faceMatch));
                    continue;
                }

                PersonEntity personCache = personService.getExtCache(faceMatch.getCertificate());
                if (ObjectUtils.isEmpty(personCache)) {
                    log.info("识别人员未在注册库中！证件号:{}", faceMatch.getCertificate());
                    continue;
                }
                //保存人流信息
                savedataFlow(event, eventData, snap, personCache);

                //查询当前是否为当天预约人员
                AppointmentPersonQuery appointmentPersonQuery = new AppointmentPersonQuery();
                appointmentPersonQuery.setPersonId(personCache.getId());
                appointmentPersonQuery.setAppointmentStartTimeStart(DateUtils.getCurrStrDate());
                appointmentPersonQuery.setAppointmentStartTimeEnd(DateUtils.getCurrStrDate());
                List<AppointmentPersonEntity> appointmentPersonEntities = appointmentPersonService.find(appointmentPersonQuery);

                for (AppointmentPersonEntity appointmentPersonEntity : appointmentPersonEntities) {
                    //当为预约用户的时候，判断当前用户是否在今天已经存在了业务 如果没有 则新增。
                    AppointmentRecordsQuery appointmentRecordsQuery = new AppointmentRecordsQuery();
                    appointmentRecordsQuery.setPersonId(personCache.getId());
                    appointmentRecordsQuery.setReservationService(appointmentPersonEntity.getBussinessName());
                    appointmentRecordsQuery.setCreateTimeStart(DateUtils.getCurrStrDate());
                    appointmentRecordsQuery.setCreateTimeEnd(DateUtils.getCurrStrDate());
                    //设置
                    int count = appointmentRecordsService.count(appointmentRecordsQuery, null);
                    if (count == 0) {
                        //当前人员今天不存在次业务 新增预约业务记录数据
                        //保存当前识别结果到记录表中
                        AppointmentRecordsEntity appointmentRecordsEntity = new AppointmentRecordsEntity();
                        appointmentRecordsEntity.initAttrValue();
                        appointmentRecordsEntity.setSiteId(appointmentPersonEntity.getSiteId());
                        appointmentRecordsEntity.setSiteName(personCache.getSiteName());
                        appointmentRecordsEntity.setPersonId(appointmentPersonEntity.getPersonId());
                        appointmentRecordsEntity.setName(personCache.getName());
                        appointmentRecordsEntity.setContactInfo(personCache.getPhoto());
                        appointmentRecordsEntity.setIdNumber(personCache.getIdCard());
                        appointmentRecordsEntity.setReservationService(appointmentPersonEntity.getBussinessName());
                        appointmentRecordsEntity.setReservationNumber(appointmentPersonEntity.getAppontmentNumber());
                        appointmentRecordsEntity.setMonitorTime(event.getHappenTime());
                        appointmentRecordsEntity.setMonitorDevice(eventData.getResInfo().stream().map(i -> i.getIndexCode()).collect(Collectors.joining(",")));
                        appointmentRecordsEntity.setCheckInMethod(CheckInMethodEnum.自动签到.getValue());
                        appointmentRecordsEntity.setPicUri(faceMatch.getFacePicUrl());
                        appointmentRecordsEntity.setCreateUserId(1L);
                        appointmentRecordsEntity.setCreateTime(new Date());
                        appointmentRecordsEntity.setCreateUserName("system");
                        appointmentRecordsService.save(appointmentRecordsEntity);

                        //新增当天的访问预警统计信息，如果已存在 则更新频次加1
                        MonitorAlarmQuery monitorAlarmQuery = new MonitorAlarmQuery();
                        monitorAlarmQuery.setPersonId(personCache.getId());
                        monitorAlarmQuery.setYear(DataUtil.converStr2Int(DateUtils.getThisYear(), 2023));
                        monitorAlarmQuery.setMonth(DataUtil.converStr2Int(DateUtils.getCurrMonth(), 1));
                        monitorAlarmQuery.setDay(DateUtils.getCurrentMonthDay());
                        MonitorAlarmEntity monitorAlarm = monitorAlarmService.selectOne(monitorAlarmQuery, null);
                        if (ObjectUtils.isEmpty(monitorAlarm)) {
                            //新增
                            monitorAlarm = new MonitorAlarmEntity();
                            monitorAlarm.initAttrValue();
                            monitorAlarm.setSiteId(personCache.getSiteId());
                            monitorAlarm.setSiteName(personCache.getSiteName());
                            monitorAlarm.setPersonId(personCache.getId());
                            monitorAlarm.setName(personCache.getName());
                            monitorAlarm.setContact(personCache.getPhone());
                            monitorAlarm.setIdNumber(personCache.getIdCard());
                            monitorAlarm.setLastIdentifyTime(event.getHappenTime());
                            monitorAlarm.setYear(DataUtil.converStr2Int(DateUtils.getThisYear(), 2023));
                            monitorAlarm.setMonth(DataUtil.converStr2Int(DateUtils.getCurrMonth(), 1));
                            monitorAlarm.setDay(DateUtils.getCurrentMonthDay());
                            monitorAlarm.setCreateTime(new Date());
                            monitorAlarm.setCreateUserName("system");
                            monitorAlarm.setCreateUserId(1L);
                            monitorAlarmService.save(monitorAlarm);
                        } else {
                            MonitorAlarmQuery condition = new MonitorAlarmQuery();
                            condition.setId(monitorAlarm.getId());
                            condition.setIdentifyNumIncrement(1);
                            condition.setUpdateUserId(1L);
                            condition.setUpdateUserName("system");
                            condition.setUpdateTime(new Date());
                            monitorAlarmService.update(condition);
                        }
                        //新增当前用户信息告警详细记录
                        MonitorAlarmRecordEntity monitorAlarmRecordEntity = new MonitorAlarmRecordEntity();
                        monitorAlarmRecordEntity.setAlarmId(monitorAlarm.getId());
                        monitorAlarmRecordEntity.setReservationService(appointmentRecordsEntity.getReservationService());
                        monitorAlarmRecordEntity.setReservationNumber(appointmentRecordsEntity.getReservationNumber());
                        monitorAlarmRecordEntity.setMonitorTime(event.getHappenTime());
                        monitorAlarmRecordEntity.setMonitorDevice(eventData.getResInfo().stream().map(i -> i.getIndexCode()).collect(Collectors.joining(",")));
                        monitorAlarmRecordEntity.setCheckInMethod(CheckInMethodEnum.自动签到.getValue());
                        monitorAlarmRecordEntity.setPicUri(faceMatch.getFacePicUrl());
                        //保存faceurl
                        ImgReq imgReq = new ImgReq();
                        imgReq.setUrl(faceMatch.getFacePicUrl());
                        Rest<String> rest = faceService.downloadPicture(imgReq);
                        if (YesNoEnum.YES.getValue() == rest.getCode()) {
                            byte[] bytes = Base64.decode(rest.getData());
                            if (!org.springframework.util.ObjectUtils.isEmpty(bytes)) {
                                InputStream inputStream = new ByteArrayInputStream(bytes);
                                MultipartFile file = ServletUtils.getMultipartFile(inputStream, "snap.jpg");
                                String filePath = uploadService.saveFileUpload(file, "file/fileupload/snap/" + DateUtil.today(), null);
                                monitorAlarmRecordEntity.setMonitorCertificate(filePath);
                            }
                        }
                        monitorAlarmRecordEntity.setCreateTime(new Date());
                        monitorAlarmRecordEntity.setCreateUserName("system");
                        monitorAlarmRecordEntity.setCreateUserId(1L);
                        monitorAlarmRecordService.save(monitorAlarmRecordEntity);
                    } else {
                        log.info("当前人员:{}已经存在预约业务:{}记录数据", personCache.getName(), appointmentPersonEntity.getBussinessName());
                    }
                }
            } else {
                log.info("相似度低于设定值 相似度值:{} ,设定阈值:{}", faceMatch.getSimilarity(), similarity);
            }
        }
    }

    private void savedataFlow(EventsItem event, EventData eventData, Snap snap, PersonEntity personCache) {
        RealtimeDataflowEntity realtimeDataflowEntity = new RealtimeDataflowEntity();
        realtimeDataflowEntity.setDetectTime(event.getHappenTime());
        String resIndexCodes = eventData.getResInfo().stream().map(i -> i.getIndexCode()).collect(Collectors.joining(","));
        realtimeDataflowEntity.setDevice(resIndexCodes);
        realtimeDataflowEntity.setPicUri(snap.getFaceUrl());
        realtimeDataflowEntity.setEventId(event.getEventId());
        realtimeDataflowEntity.setSiteId(personCache.getSiteId());
        realtimeDataflowEntity.setSiteName(personCache.getSiteName());
        realtimeDataflowEntity.setIdNumber(personCache.getIdCard());
        realtimeDataflowEntity.setName(personCache.getName());
        realtimeDataflowEntity.setIsBooking(YesNoEnum.YES.getValue());
        realtimeDataflowEntity.setContact(personCache.getPhoto());
        realtimeDataflowEntity.setEventType(HikEventTypeEnum.重点人员识别事件.getValue().longValue());
        realtimeDataflowEntity.setCreateUserId(1L);
        realtimeDataflowEntity.setCreateTime(new Date());
        realtimeDataflowEntity.setCreateUserName("system");


        ImgReq imgReq = new ImgReq();
        imgReq.setUrl(realtimeDataflowEntity.getPicUri());
        Rest<String> rest = faceService.downloadPicture(imgReq);
        if (YesNoEnum.YES.getValue() == rest.getCode()) {
            byte[] bytes = Base64.decode(rest.getData());
            if (!org.springframework.util.ObjectUtils.isEmpty(bytes)) {
                InputStream inputStream = new ByteArrayInputStream(bytes);
                MultipartFile file = ServletUtils.getMultipartFile(inputStream, "snap.jpg");
                String filePath = uploadService.saveFileUpload(file, "file/fileupload/snap/" + DateUtil.today(), null);
                realtimeDataflowEntity.setPicture(filePath);
            }
        }


        dataflowService.save(realtimeDataflowEntity);
    }
}
