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.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.attendance.mapper.EduAttendanceStaffRecordMapper;
import com.yida.data.attendance.service.*;
import com.yida.data.attendance.vo.StaffRecordVO;
import com.yida.data.common.core.entity.attendance.*;
import com.yida.data.common.core.entity.user.EduStaff;
import com.yida.data.common.core.entity.user.EduStaffDept;
import com.yida.data.common.service.CommonService;
import com.yida.data.user.feign.RemoteStaffService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

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

import static com.yida.data.common.core.entity.constant.CachePrefixConstant.STAFF_DATA;

/**
 * 教职工考勤-进出记录 Service实现
 *
 * @author ccl
 * @date 2021-09-27 18:56:19
 */
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class EduAttendanceStaffRecordServiceImpl extends ServiceImpl
        <EduAttendanceStaffRecordMapper, EduAttendanceStaffRecord> implements EduAttendanceStaffRecordService {

    private final EduAttendanceStaffResultService eduAttendanceStaffResultService;
    private final EduAttendanceStaffRuleService eduAttendanceStaffRuleService;
    private final EduAttendanceStaffRuleStaffService eduAttendanceStaffRuleStaffService;
    private final EduAttendanceStaffRuleTimeService eduAttendanceStaffRuleTimeService;
    private final EduAttendanceStaffRuleWhiteListService eduAttendanceStaffRuleWhiteListService;
    private final EduAttendanceStaffRuleSpecialDateService eduAttendanceStaffRuleSpecialDateService;

    private final RemoteStaffService remoteStaffService;
    private final CommonService commonService;
    private final RedisService redisService;


    @Override
    public IPage<StaffRecordVO> findPageStaffRecord(Page page, Long deptId, String nameOrPhone, String start, String end,
                                                    Long schoolId) {
        List<Long> staffId = remoteStaffService.listStaffByDeptId(deptId, nameOrPhone, schoolId).getData();
        if (CollectionUtil.isEmpty(staffId)) {
            return page;
        }
        List<EduStaffDept> data = remoteStaffService.getStaffDeptByStaffIds(staffId).getData();
        if (StringUtils.isNotEmpty(start)) {
            start = start + " 00:00:00";
        }
        if (StringUtils.isNotEmpty(end)) {
            end = end + " 23:59:59";
        }

        IPage<StaffRecordVO> staffRecordVO = baseMapper.findPageStaffRecord(page, schoolId, start, end, staffId);
        List<StaffRecordVO> records = staffRecordVO.getRecords();
        if (CollectionUtil.isEmpty(records)) {
            return staffRecordVO;
        }

        for (StaffRecordVO record : records) {
            for (EduStaffDept staffDept : data) {
                if (staffDept.getStaffId().equals(record.getStaffId())) {
                    EduStaff staff = (EduStaff) redisService.hget(STAFF_DATA, staffDept.getStaffId().toString());
                    if (ObjectUtil.isEmpty(staff)) {
                        staff = remoteStaffService.getStaff(staffDept.getStaffId()).getData();
                    }
                    List<EduStaffDept> staffDeptList = staff.getStaffDept();
                    StringBuilder deptName = new StringBuilder();
                    for (int i = 0; i < staffDeptList.size(); i++) {
                        if (i == staffDeptList.size() - 1) {
                            deptName.append(staffDeptList.get(i).getDeptName());
                        } else {
                            deptName.append(staffDeptList.get(i).getDeptName()).append(",");
                        }
                    }
                    if (ObjectUtil.isEmpty(deptName.toString())) {
                        deptName = new StringBuilder(staff.getSchoolName());
                    }
                    record.setDeptName(deptName.toString());
                    record.setPhone(staffDept.getMobile());
                    record.setStaffName(staffDept.getStaffName());
                    break;
                }
            }
            LocalDateTime time = record.getTime();
            record.setWeek("星期" + time.getDayOfWeek().getValue());
        }
        return staffRecordVO;
    }

    /**
     * 定时处理数据
     * 当天处理前一天的数据(凌晨一点执行)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void staffRecord() {

        // 当前日期
        LocalDate currentDate = LocalDate.now();

        // 查询所有考勤规则
        List<EduAttendanceStaffRule> staffRules = eduAttendanceStaffRuleService
                .list(Wrappers.lambdaQuery(new EduAttendanceStaffRule()));

        for (EduAttendanceStaffRule staffRule : staffRules) {
            // 查询规则对应的职工
            Long ruleId = staffRule.getId();
            List<EduAttendanceStaffRuleStaff> ruleStaffs = eduAttendanceStaffRuleStaffService
                    .list(Wrappers.lambdaQuery(new EduAttendanceStaffRuleStaff())
                            .eq(EduAttendanceStaffRuleStaff::getRuleId, ruleId));
            // 查询规则对应的白名单
            List<EduAttendanceStaffRuleWhiteList> whiteList = eduAttendanceStaffRuleWhiteListService
                    .list(Wrappers.lambdaQuery(new EduAttendanceStaffRuleWhiteList())
                            .eq(EduAttendanceStaffRuleWhiteList::getRuleId, ruleId));
            // 查询打卡时间段
            List<EduAttendanceStaffRuleTime> times = eduAttendanceStaffRuleTimeService
                    .list(Wrappers.lambdaQuery(new EduAttendanceStaffRuleTime())
                            .eq(EduAttendanceStaffRuleTime::getRuleId, ruleId));
            // 查询特殊节日
            List<EduAttendanceStaffRuleSpecialDate> specialDateList = eduAttendanceStaffRuleSpecialDateService
                    .list(Wrappers.lambdaQuery(new EduAttendanceStaffRuleSpecialDate())
                            .eq(EduAttendanceStaffRuleSpecialDate::getRuleId, ruleId));

            boolean isSpecialDate = false;
            // 判断是否为特殊日期
            LocalDate nowDate = LocalDate.now();
            if (CollUtil.isNotEmpty(specialDateList)) {
                for (EduAttendanceStaffRuleSpecialDate specialDate : specialDateList) {
                    if (nowDate.isEqual(specialDate.getDate())) {
                        isSpecialDate = true;
                        break;
                    }
                }
            }
            if (isSpecialDate) {
                return;
            }
            // 判断是否为节假日
            Boolean workDay = commonService.isWorkDay(nowDate);
            if (!workDay) {
                return;
            }

            // 循环考勤时间段
            for (int i = 0; i < times.size(); i++) {
                EduAttendanceStaffRuleTime ruleTime = times.get(i);
                // 考勤开始时间
                LocalTime startTime = ruleTime.getStartTime();
                // 考勤结束时间
                LocalTime endTime = ruleTime.getEndTime();
                Long ruleTimeId = ruleTime.getId();

                // 处理职工考勤数据
                for (EduAttendanceStaffRuleStaff ruleStaff : ruleStaffs) {
                    // 判断是否包含白名单. 白名单内不需要考勤
                    boolean whiteFlag = false;
                    if (CollUtil.isNotEmpty(whiteList)) {
                        List<Long> list = whiteList.stream()
                                .map(EduAttendanceStaffRuleWhiteList::getStaffId).collect(Collectors.toList());
                        whiteFlag = list.contains(ruleStaff.getStaffId());
                    }
                    // 判断前一天是否有生成的考勤结果
                    EduAttendanceStaffResult staffResult = eduAttendanceStaffResultService.getOne(
                            Wrappers.lambdaQuery(new EduAttendanceStaffResult())
                                    .eq(EduAttendanceStaffResult::getStaffId, ruleStaff.getStaffId())
                                    .eq(EduAttendanceStaffResult::getRuleId, ruleId)
                                    .eq(EduAttendanceStaffResult::getRuleTimeId, ruleTimeId)
                                    .eq(EduAttendanceStaffResult::getAttendanceDate, currentDate.plusDays(-1)));
                    // 0-正常，1-迟到，2-早退,3-旷工，4-迟到早退，5-上班未在打卡时间段，6-下班未在打卡时间段
                    if (Objects.isNull(staffResult)) {
                        staffResult = new EduAttendanceStaffResult();
                        staffResult.setStaffId(ruleStaff.getStaffId());
                        staffResult.setSchoolId(staffRule.getSchoolId());
                        staffResult.setRuleId(ruleId);
                        staffResult.setRuleTimeId(ruleTimeId);
                        staffResult.setAttendanceDate(currentDate.plusDays(-1));
                        staffResult.setStartStiTime(ruleTime.getStartEffectiveStatus() == 0 ?
                                startTime : ruleTime.getStartEffectiveStartTime());
                        staffResult.setEndStiTime(ruleTime.getEndEffectiveStatus() == 0 ?
                                endTime : ruleTime.getEndEffectiveStartTime());

                        staffResult.setStatus(whiteFlag ? 0 : 3);
                    } else {
                        if (Objects.isNull(staffResult.getStartRealTime())) {
                            staffResult.setStatus(whiteFlag ? 0 : 5);
                        } else if (Objects.isNull(staffResult.getEndRealTime())) {
                            staffResult.setStatus(whiteFlag ? 0 : 6);
                        }
                    }
//                    // 查询对应时段是否有通行记录
//                    if (ruleTime.getStartEffectiveStatus() == 1) {
//                        if (Objects.isNull(staffResult.getId()) || Objects.isNull(staffResult.getStartRealTime())) {
//
//                            // 没有当前时间段上班时间, 查询是否有通行记录
//                            EduAttendanceStaffRecord staffRecord = baseMapper.findTimeStaffRecord(ruleId, ruleTimeId,
//                                    LocalDateTime.of(currentDate.plusDays(-1), ruleTime.getStartEffectiveStartTime()),
//                                    LocalDateTime.of(currentDate.plusDays(-1), ruleTime.getStartEffectiveEndTime()));
//
//                            if (Objects.nonNull(staffRecord)) {
//
//                            }
//                        }
//                    }
                    // 查询前一天对应时段的同行记录
                    eduAttendanceStaffResultService.saveOrUpdate(staffResult);
                }
            }
        }
    }
}