package com.yida.data.attendance.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.attendance.dto.AddAttendanceRecordDTO;
import com.yida.data.attendance.dto.AddAttendanceRuleWifiDTO;
import com.yida.data.attendance.dto.AttendanceUserCheckInDTO;
import com.yida.data.attendance.dto.H5AttendanceRuleWifiDTO;
import com.yida.data.attendance.mapper.AttendanceRuleMapper;
import com.yida.data.attendance.service.AttendanceCheckInService;
import com.yida.data.attendance.service.AttendanceRecordService;
import com.yida.data.attendance.service.AttendanceResultService;
import com.yida.data.attendance.service.ErrorRecordMsgService;
import com.yida.data.attendance.vo.AttendanceRuleVO;
import com.yida.data.attendance.vo.AttendanceUserCheckInVO;
import com.yida.data.attendance.vo.AttendanceWifiVO;
import com.yida.data.common.core.entity.ErrorRecordMsg;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceRecord;
import com.yida.data.common.core.entity.attendance.attendance.AttendanceResult;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.user.EduStaff;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.MsgChannel;
import com.yida.data.common.core.enums.RecordTypeEnum;
import com.yida.data.common.core.enums.UserTypeEnum;
import com.yida.data.common.core.enums.attendance.AttendanceModeTypeEnum;
import com.yida.data.common.core.enums.attendance.AttendanceResultEnum;
import com.yida.data.common.core.enums.attendance.AttendanceWifiStatusEnum;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.service.CommonService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * WIFI打卡service
 *
 * @author ZYJ
 * @date 2023/11/1 16:44
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS)
public class AttendanceCheckInServiceImpl implements AttendanceCheckInService {

    private final RedisService redisService;
    private final CommonService commonService;

    private final AttendanceRecordService attendanceRecordService;
    private final AttendanceResultService attendanceResultService;
    private final AttendanceRuleMapper attendanceRuleMapper;

    @Override
    public AttendanceWifiVO findByUserIdAndDateTime(H5AttendanceRuleWifiDTO dto) {
        AttendanceWifiVO vo = new AttendanceWifiVO();
        AttendanceRuleVO attendanceRuleVO = new AttendanceRuleVO();
        //查询学校是否开启会员使用WiFi打卡
//        Boolean isWifiOpen = remoteEduSchoolFuncationConfigService
//            .checkSchoolFunctionCode(dto.getSchoolId(), FunctionConfigCode.ATTENDANCE_WIFI.getCode()).getData();
//        if (isWifiOpen) {
//            //查询会员
//            if (!remoteStudentApplyService.hasApply(dto.getUserId(), FunctionConfigCode.ATTENDANCE_WIFI.getCode()).getData()) {
//                vo.setStatus(AttendanceWifiStatusEnum.NON_MEMBER.getValue());
//                return vo;
//            }
//        }

        List<AttendanceRuleVO> ruleVOList = new ArrayList<>();

        //缓存用户匹配的考勤规则
        if (redisService.hHasKey(CachePrefixConstant.ATTENDANCE_STUDENT_RULE, String.valueOf(dto.getUserId()))) {
            String ruleVOListStr = (String) redisService
                    .hget(CachePrefixConstant.ATTENDANCE_STUDENT_RULE, String.valueOf(dto.getUserId()));
            ruleVOList = JSONUtil.toList(ruleVOListStr, AttendanceRuleVO.class);
        } else {
            Long userId = dto.getUserId();
            if (UserTypeEnum.STAFF_USER_TYPE.getType().equals(dto.getUserType())) {
                //教职工
                EduStaff staff = commonService.getStaffById(userId);
                if (Objects.isNull(staff)) {
                    log.error("职工不存在,id:[{}]", userId);
                    throw new FebsException("职工信息不存在：【{" + userId + "}】");
                }
            } else {
                EduStudent student = commonService.getStudentById(userId);
                if (ObjectUtil.isNull(student)) {
                    log.error("学生信息不存在,id:[{}]", userId);
                    throw new FebsException("学生信息不存在：【{" + userId + "}】");
                }
                //用户匹配规则
                ruleVOList = attendanceRuleMapper
                        .findUserMatchRuleByUserId(dto.getUserType(), dto.getUserId());
                if (CollUtil.isNotEmpty(ruleVOList)) {
                    redisService
                            .hset(CachePrefixConstant.ATTENDANCE_STUDENT_RULE, String.valueOf(dto.getUserId()),
                                    JSONUtil.toJsonStr(ruleVOList));
                }
            }
        }

        //wifi匹配的规则
        List<AttendanceRuleVO> matchList = new ArrayList<>();

        if (CollUtil.isEmpty(ruleVOList)) {
            vo.setStatus(AttendanceWifiStatusEnum.RULE_NO.getValue());
            return vo;
        } else {
            //查询所有WiFi打卡的规则
            //匹配对应的考勤规则  根据BSSID判断
            for (AttendanceRuleVO ruleVO : ruleVOList) {
                boolean contains = ruleVO.getWifiDTOList().stream().map(AddAttendanceRuleWifiDTO::getWifiBssid)
                        .collect(Collectors.toList()).contains(dto.getWifiBssid());
                if (contains) {
                    matchList.add(ruleVO);
                }
            }
        }

        if (CollUtil.isEmpty(matchList)) {
            vo.setStatus(AttendanceWifiStatusEnum.RANGE_OUT.getValue());
            return vo;
        } else {
            for (AttendanceRuleVO ruleVO : matchList) {
                if (ruleVO.getWeek().contains(String.valueOf(dto.getCurrentDateTime().getDayOfWeek().getValue()))) {
                    attendanceRuleVO = ruleVO;
                    Map<String, List<AddAttendanceRuleWifiDTO>> wifiMap = ruleVO.getWifiDTOList().stream()
                            .collect(Collectors.groupingBy(AddAttendanceRuleWifiDTO::getWifiBssid));
                    vo.setWifiName(wifiMap.get(dto.getWifiBssid()).get(0).getWifiName());
                    break;
                }
            }
        }

        if (ObjectUtil.isNull(attendanceRuleVO)) {
            vo.setStatus(AttendanceWifiStatusEnum.REST.getValue());
            return vo;
        } else {
            vo.setRuleType(attendanceRuleVO.getType());
            vo.setRuleId(attendanceRuleVO.getId());
            vo.setRuleName(attendanceRuleVO.getName());
            vo.setRuleFaceTake(attendanceRuleVO.getFaceTake());
            //默认一个考勤时段
            vo.setRuleTimeId(attendanceRuleVO.getTimeDTOList().get(0).getId());
            vo.setStartTime(attendanceRuleVO.getTimeDTOList().get(0).getStartTime());
            vo.setEndTime(attendanceRuleVO.getTimeDTOList().get(0).getEndTime());

            //判断是否在打卡时段
            if (LocalTime.now().isBefore(attendanceRuleVO.getTimeDTOList().get(0).getStartEffectiveStartTime()) || LocalTime.now()
                    .isAfter(attendanceRuleVO.getTimeDTOList().get(0).getEndEffectiveEndTime())) {
                vo.setStatus(AttendanceWifiStatusEnum.TIME_OUT.getValue());
            } else {
                AttendanceResult result = attendanceResultService.getOne(Wrappers.lambdaQuery(new AttendanceResult())
                        .eq(AttendanceResult::getRuleId, attendanceRuleVO.getId())
                        .eq(AttendanceResult::getRuleTimeId, attendanceRuleVO.getTimeDTOList().get(0).getId())
                        .eq(AttendanceResult::getUserId, dto.getUserId())
                        .eq(AttendanceResult::getAttendanceDate, dto.getCurrentDateTime().toLocalDate()));

                if (ObjectUtil.isNotNull(result)) {
                    vo.setStartRealTime(result.getStartRealTime());
                    vo.setStartStatus(result.getStartStatus());
                    vo.setEndRealTime(result.getEndRealTime());
                    vo.setEndStatus(result.getEndStatus());
                    vo.setStartImg(result.getStartPicUrl());
                    vo.setEndImg(result.getEndPicUrl());
                }
                //判断是上班还是下班打卡
                if (ObjectUtil.equals(AttendanceModeTypeEnum.FREE.getValue(), attendanceRuleVO.getType())) {
                    //自由打卡
                    vo.setStatus(AttendanceWifiStatusEnum.WORK_ON.getValue());
                } else {
                    if (dto.getCurrentDateTime().toLocalTime()
                            .isAfter(attendanceRuleVO.getTimeDTOList().get(0).getStartEffectiveStartTime()) && dto
                            .getCurrentDateTime().toLocalTime()
                            .isBefore(attendanceRuleVO.getTimeDTOList().get(0).getStartEffectiveEndTime())) {
                        if (ObjectUtil.isNotNull(result) && ObjectUtil.isNotNull(result.getStartStatus())) {
                            vo.setStatus(AttendanceWifiStatusEnum.WORK_OFF.getValue());
                        } else {
                            vo.setStatus(AttendanceWifiStatusEnum.WORK_ON.getValue());
                        }
                    } else if (dto.getCurrentDateTime().toLocalTime()
                            .isAfter(attendanceRuleVO.getTimeDTOList().get(0).getEndEffectiveStartTime())) {
                        vo.setStatus(AttendanceWifiStatusEnum.WORK_OFF.getValue());
                    }
                }
            }
        }
        return vo;
    }

    @Override
    public AttendanceUserCheckInVO userCheckIn(AttendanceUserCheckInDTO dto) {
        AddAttendanceRecordDTO param = new AddAttendanceRecordDTO();
        param.setUserId(dto.getUserId());
        param.setUserType(dto.getUserType());
        param.setSchoolId(dto.getSchoolId());
        param.setWifiBssid(dto.getWifiBssid());
        param.setCreateTime(dto.getCurrentDateTime());
        param.setPicUrl(dto.getAvatar());
        param.setRuleId(dto.getRuleId());
        param.setRuleTimeId(dto.getRuleTimeId());
        AttendanceRecord record = attendanceRecordService.addRecord(param);
        AttendanceUserCheckInVO vo = new AttendanceUserCheckInVO();
        if (record.getRuleTimeType() == 0) {
            //上班打卡
            if (record.getStatus().equals(AttendanceResultEnum.ABNORMAL.getValue())) {
                vo.setStatus(AttendanceResultEnum.LATE.getValue());
            } else {
                vo.setStatus(record.getStatus());
            }
        } else {
            //下班打卡
            if (record.getStatus().equals(AttendanceResultEnum.ABNORMAL.getValue())) {
                vo.setStatus(AttendanceResultEnum.LEAVE.getValue());
            } else {
                vo.setStatus(AttendanceResultEnum.NORMAL.getValue());
            }
        }
        vo.setCheckInDateTime(dto.getCurrentDateTime());
        vo.setAvatar(dto.getAvatar());
        return vo;
    }
}
