package com.mortals.xhx.daemon.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.service.ITask;
import com.mortals.framework.service.ITaskExcuteService;
import com.mortals.framework.util.DataUtil;
import com.mortals.xhx.common.code.DwMinorEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.key.RedisKey;
import com.mortals.xhx.module.attendance.model.AttendanceRecordHikEntity;
import com.mortals.xhx.module.attendance.model.AttendanceRecordHikQuery;
import com.mortals.xhx.module.attendance.service.AttendanceRecordHikService;
import com.mortals.xhx.module.door.model.DoorEntity;
import com.mortals.xhx.module.door.model.DoorQuery;
import com.mortals.xhx.module.door.service.DoorService;
import com.mortals.xhx.module.hik.door.model.req.door.DoorEventReq;
import com.mortals.xhx.module.hik.door.model.req.door.HikDoorEventReq;
import com.mortals.xhx.module.hik.door.model.rsp.door.DoorEventDataInfo;
import com.mortals.xhx.module.hik.door.model.rsp.door.info.EventInfo;
import com.mortals.xhx.module.hik.door.model.rsp.door.info.StruTime;
import com.mortals.xhx.module.hik.door.service.IHikDoorService;
import com.mortals.xhx.module.staff.model.StaffEntity;
import com.mortals.xhx.module.staff.service.StaffService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 同步获取当天海康门禁事件
 */
@Slf4j
@Service("SyncDoorsEventByDevicesTask")
public class SyncDoorsEventByDevicesTaskImpl implements ITaskExcuteService {

    @Autowired
    private AttendanceRecordHikService recordHikService;

    @Autowired
    private StaffService staffService;

    @Autowired
    private IHikDoorService hikDoorService;

    private Integer day;
    @Autowired
    private ICacheService cacheService;

    @Autowired
    private DoorService doorService;


    @Override
    public void excuteTask(ITask task) throws AppException {
        //同步多久时间段的 偏移量为天 默认当天
        String excuteParam = task.getExcuteParam();
        if (!ObjectUtils.isEmpty(excuteParam)) {
            day = DataUtil.converStr2Int(excuteParam, 0);
        } else {
            day = 0;
        }
        Date beginDateTime = DateUtil.parseDateTime(DateUtil.today() + " 08:00:00");
        Date endDateTime = DateUtil.parseDateTime(DateUtil.today() + " 20:30:00");

        //boolean in = DateUtil.isIn(new Date(), beginDateTime, endDateTime);
        boolean in = true;
        if (in) {
            List<DoorEntity> doorEntities = doorService.find(new DoorQuery());
            for (DoorEntity doorEntity : doorEntities) {
                syncDoorEvents(doorEntity);
            }
        }
    }

    /**
     * 查询当前间隔时间的门禁事件
     *
     * @param doorEntity
     */
    private void syncDoorEvents(DoorEntity doorEntity) {

        HikDoorEventReq hikDoorEventReq = new HikDoorEventReq();
        //当前时间前一个小时
       // Date startTime = DateUtil.offsetHour(new Date(), -1).toJdkDate();
        Date startTime = DateUtil.offsetDay(new Date(), -1).toJdkDate();
        Date endTime = new Date();

        hikDoorEventReq.setStartTime(startTime);
        hikDoorEventReq.setEndTime(endTime);
        Rest<List<EventInfo>> listRest = hikDoorService.searchDoorEventsList(hikDoorEventReq, doorEntity);

        if (listRest.getCode() == YesNoEnum.YES.getValue()) {
            List<EventInfo> list = listRest.getData();

            List<AttendanceRecordHikEntity> attRecords = list.stream().map(item -> {
                AttendanceRecordHikEntity recordHikEntity = new AttendanceRecordHikEntity();
                recordHikEntity.initAttrValue();
                String jobNo = "";
                byte[] byEmployeeNo = item.getStruAcsEventInfo().getByEmployeeNo();
                if (ObjectUtils.isEmpty(new String(byEmployeeNo).trim())) {
                    int dwEmployeeNo = item.getStruAcsEventInfo().getDwEmployeeNo();
                    if (dwEmployeeNo == 0) {
                        //log.info("jobNo is null ==>{}", JSON.toJSONString(item));
                        return null;
                    } else {
                        jobNo = String.valueOf(dwEmployeeNo);
                    }
                } else {
                    jobNo = new String(byEmployeeNo).trim();
                }
                log.info("jobNo==>{}",jobNo);
                //查看考勤状态
                int dwMajor = item.getDwMajor();//报警主类型
                int dwMinor = item.getDwMinor();//报警次类型

                String dwMinorStr = Integer.toHexString(dwMinor);
                //判断次类型 是否在白名单里面
                Set<String> dwSet = DwMinorEnum.getEnumMap().keySet();
                if (dwSet.contains(dwMinorStr)) {
                    //符号考勤 添加到考勤里面
                    StruTime struTime = item.getStruTime();
                    //格式化时间 年月日 时分秒 yyyy-MM-dd HH:mm:ss
                    int dwYear = struTime.getDwYear();
                    int dwMonth = struTime.getDwMonth();
                    int dwDay = struTime.getDwDay();
                    int dwHour = struTime.getDwHour();
                    int dwMinute = struTime.getDwMinute();
                    int dwSecond = struTime.getDwSecond();

                    LocalDateTime localDateTime = LocalDateTime.of(dwYear, dwMonth, dwDay, dwHour, dwMinute, dwSecond);
                    ZoneId zoneId = ZoneId.systemDefault();
                    ZonedDateTime zdt = localDateTime.atZone(zoneId);

                    Date attendDate = Date.from(zdt.toInstant());

                    StaffEntity staffCache = staffService.getExtCache(StrUtil.padPre(jobNo, 8, "0"));
                    if (ObjectUtils.isEmpty(staffCache)) {
                        log.info("staff is null !staffCode:{}", jobNo);
                        return null;
                    }

                    recordHikEntity.setStaffId(staffCache.getId());
                    recordHikEntity.setStaffName(staffCache.getName());
                    recordHikEntity.setWorkNum(staffCache.getWorkNum());
                    recordHikEntity.setDeptId(staffCache.getDeptId());
                    recordHikEntity.setDeptName(staffCache.getDeptName());
                    recordHikEntity.setPositionId(staffCache.getPositionId());
                    recordHikEntity.setPositionName(staffCache.getPositionName());

                    recordHikEntity.setAttendanceDate(attendDate);
                    // recordHikEntity.setAttendanceAddress(item.getDoorName());
                    recordHikEntity.setEventSource("门禁点");
                    //recordHikEntity.setRemark(item.getEventId());
                    recordHikEntity.setCreateTime(new Date());
                    recordHikEntity.setCreateUserName("系统管理员");
                    recordHikEntity.setCreateUserId(1L);
                    return recordHikEntity;
                } else {
                    log.info("考勤次类型dwMinorCode:" + dwMinorStr);
                    return null;
                }
            }).filter(f -> f != null).collect(Collectors.toList());

            log.info("attRecords size:{}", attRecords.size());

            if (!ObjectUtils.isEmpty(attRecords)) {
                //单个插入 去掉重复时间段的打卡记录
                for (AttendanceRecordHikEntity recordHikEntity : attRecords) {
                    try {
                        recordHikService.getDao().insert(recordHikEntity);
                    } catch (Exception e) {
                        log.error("基础考勤数据保存异常", e.getMessage());
                    }
                }
            }
        }

    }

    private void syncDoorEvents() {
        DoorEventReq doorEventReq = new DoorEventReq();
        List<Integer> eventTypes = new ArrayList<>();
        eventTypes.add(196885);
        eventTypes.add(196887);
        eventTypes.add(196893);
        eventTypes.add(196888);
        eventTypes.add(196889);
        eventTypes.add(196890);
        eventTypes.add(196891);
        doorEventReq.setEventTypes(eventTypes);
        // 获取当天的开始时间
        //Date todayStart = DateUtil.offsetHour(new Date(), -5).toJdkDate();
        Date todayStart = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), day > 0 ? -day : 0));
        // 获取当天的结束时间
        Date todayEnd = DateUtil.endOfDay(new Date());
        doorEventReq.setStartTime(todayStart);
        doorEventReq.setEndTime(todayEnd);
        doorEventReq.setPageNo(1);
        doorEventReq.setPageSize(1);

        Rest<DoorEventDataInfo> doorEventsRest = hikDoorService.getDoorEvents(doorEventReq);
        log.info("doorEventsRest:{} msg:{}", doorEventsRest.getCode(), doorEventsRest.getMsg());
        if (doorEventsRest.getCode() == YesNoEnum.YES.getValue()) {
            //分页获取考勤数据
            Integer total = doorEventsRest.getData().getTotal();
            int pageCount = PageUtil.totalPage(total, 1000);
            for (int i = 1; i <= pageCount; i++) {
                doorEventReq.setPageNo(i);
                doorEventReq.setPageSize(1000);
                doorEventsRest = hikDoorService.getDoorEvents(doorEventReq);
                log.info("doorEventsRest:{} msg:{},page:{}", doorEventsRest.getCode(), doorEventsRest.getMsg(), doorEventReq.getPageNo());
                getDoorEvents(doorEventsRest);
            }
        }
    }

    private void getDoorEvents(Rest<DoorEventDataInfo> doorEventsRest) {
        //同步当前考勤数据
        List<AttendanceRecordHikEntity> attRecords = doorEventsRest.getData().getList().stream().map(item -> {
            AttendanceRecordHikEntity recordHikEntity = new AttendanceRecordHikEntity();
            recordHikEntity.initAttrValue();

            if (ObjectUtils.isEmpty(item.getJobNo())) {
                log.info("jobNo is null ==>{}", JSON.toJSONString(item));
                return null;
            }
            StaffEntity staffCache = staffService.getExtCache(StrUtil.padPre(item.getJobNo(), 8, "0"));
            if (ObjectUtils.isEmpty(staffCache)) {
                log.info("staff is null !staffCode:{}", item.getJobNo());
                return null;
            }

            recordHikEntity.setStaffId(staffCache.getId());
            recordHikEntity.setStaffName(staffCache.getName());
            recordHikEntity.setWorkNum(staffCache.getWorkNum());
            recordHikEntity.setDeptId(staffCache.getDeptId());
            recordHikEntity.setDeptName(staffCache.getDeptName());
            recordHikEntity.setPositionId(staffCache.getPositionId());
            recordHikEntity.setPositionName(staffCache.getPositionName());

            recordHikEntity.setAttendanceDate(item.getEventTime());
            recordHikEntity.setAttendanceAddress(item.getDoorName());
            recordHikEntity.setEventSource("门禁点");
            recordHikEntity.setRemark(item.getEventId());
            recordHikEntity.setCreateTime(new Date());
            recordHikEntity.setCreateUserName("系统管理员");
            recordHikEntity.setCreateUserId(1L);
            return recordHikEntity;
        }).filter(f -> f != null).collect(Collectors.toList());
        log.info("attRecords size:{}", attRecords.size());
        List<String> eventIds = attRecords.parallelStream().filter(f -> !ObjectUtils.isEmpty(f) && !ObjectUtils.isEmpty(f.getRemark())).map(i -> i.getRemark()).collect(Collectors.toList());

        //查询当天考勤记录是否有重复的 有的 则不添加
        AttendanceRecordHikQuery recordHikQuery = new AttendanceRecordHikQuery();
        recordHikQuery.setAttendanceDateStart(DateUtil.format(DateUtil.beginOfDay(new Date()), "yyyy-MM-dd"));
        recordHikQuery.setAttendanceDateEnd(DateUtil.format(DateUtil.beginOfDay(new Date()), "yyyy-MM-dd"));
        recordHikQuery.setRemarkList(eventIds);
        Set<String> eventIdSet = recordHikService.find(recordHikQuery).parallelStream().map(i -> i.getRemark()).collect(Collectors.toSet());

        //去重 时分秒打卡的 也要去掉重复。
        List<AttendanceRecordHikEntity> saveRecordList = attRecords.stream().filter(f -> !eventIdSet.contains(f.getRemark())).collect(Collectors.toList());
        if (!ObjectUtils.isEmpty(saveRecordList)) {
            //单个插入 去掉重复时间段的打卡记录
            for (AttendanceRecordHikEntity recordHikEntity : saveRecordList) {
                try {
                    recordHikService.getDao().insert(recordHikEntity);
                } catch (Exception e) {
                    //log.error("基础考勤数据保存异常", e.getMessage());
                }
            }
            // recordHikService.save(saveRecordList);
        }
        log.info("saveRecordList size:{}", saveRecordList.size());

        AttendanceRecordHikQuery hikQuery = new AttendanceRecordHikQuery();
        hikQuery.setAttendanceDateStart(DateUtil.beginOfMonth(new Date()).toDateStr());
        hikQuery.setAttendanceDateEnd(DateUtil.today());

        Long totalCache = recordHikService.find(hikQuery).parallelStream().map(item -> item.getStaffId()).distinct().count();
        cacheService.hset(RedisKey.KEY_ATTENC_TOTOAL_CACHE, DateUtil.format(new Date(), "yyyy-MM"), totalCache);

    }


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

    }
}
