package com.mortals.xhx.module.door.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.mortals.framework.common.Rest;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.xhx.common.code.DwMinorEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.module.attendance.model.AttendanceRecordHikEntity;
import com.mortals.xhx.module.attendance.service.AttendanceRecordHikService;
import com.mortals.xhx.module.door.dao.DoorDao;
import com.mortals.xhx.module.door.model.DoorEntity;
import com.mortals.xhx.module.door.service.DoorService;
import com.mortals.xhx.module.hik.door.model.req.door.HikDoorEventReq;
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.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* DoorService
* 门禁设备 service实现
*
* @author zxfei
* @date 2023-11-22
*/
@Service("doorService")
@Slf4j
public class DoorServiceImpl extends AbstractCRUDServiceImpl<DoorDao, DoorEntity, Long> implements DoorService {

    @Autowired
    private AttendanceRecordHikService recordHikService;

    @Autowired
    private StaffService staffService;

    @Autowired
    private IHikDoorService hikDoorService;

    @Override
    public Rest<Void> syncDoorDeviceEvents(DoorEntity doorEntity, HikDoorEventReq hikDoorEventReq) {
        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.setEventSource("门禁点");
                    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);
                    }
                }
            }
        }

        return null;
    }
}