package jnpf.attendance.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Maps;
import jnpf.attendance.mapper.AttendanceShiftSettingMapper;
import jnpf.attendance.service.*;
import jnpf.attendance.service.handle.notification.AttendanceRuleNotificationHandle;
import jnpf.base.UserInfo;
import jnpf.base.service.SuperServiceImpl;
import jnpf.constants.RedisConstant;
import jnpf.entity.AttendanceGroup;
import jnpf.entity.AttendanceGroupUser;
import jnpf.entity.attendance.AttendanceFixedClassEntity;
import jnpf.entity.attendance.AttendanceShiftNameEntity;
import jnpf.entity.attendance.AttendanceShiftSettingEntity;
import jnpf.entity.attendance.AttendanceShiftSettingPeriodEntity;
import jnpf.exception.HandleException;
import jnpf.model.attendance.dto.AttendanceShiftDto;
import cn.hutool.core.util.StrUtil;
import jnpf.model.attendance.vo.*;
import jnpf.model.attendance.vo.attendance.FixedClassShiftVo;
import jnpf.model.attendance.vo.attendance.ShiftNameViewVo;
import jnpf.model.attendance.vo.attendance.ShiftNameVo;
import jnpf.util.*;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 考勤组配置-考勤配置 服务实现类
 * </p>
 *
 * @author ahua
 * @since 2023-11-22
 */
@Service
public class AttendanceShiftSettingServiceImpl extends SuperServiceImpl<AttendanceShiftSettingMapper, AttendanceShiftSettingEntity> implements AttendanceShiftSettingService {

    @Autowired
    private AttendanceShiftSettingPeriodService attendanceShiftSettingPeriodService;
    @Autowired
    private AttendanceDailyRuleService attendanceDailyRuleService;
    @Autowired
    private AttendanceGroupService attendanceGroupService;
    @Autowired
    private AttendanceUserService attendanceUserService;
    @Autowired
    private AttendanceFixedClassService attendanceFixedClassService;
    @Autowired
    private AttendanceShiftNameSettingService attendanceShiftNameSettingService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private AttendanceRuleNotificationHandle attendanceRuleNotificationHandle;

    @Override
    public Map<String, AttendanceShiftSettingVo> getEnableShiftSetting(List<String> groupIds, List<AttendanceGroup> attendanceGroupVos) {
        return getEnableShiftSetting(groupIds, attendanceGroupVos, Boolean.TRUE);
    }

    private Map<String, AttendanceShiftSettingVo> getAllShiftSetting(List<String> groupIds, List<AttendanceGroup> attendanceGroupVos) {
        return getEnableShiftSetting(groupIds, attendanceGroupVos, Boolean.FALSE);
    }

    private Map<String, AttendanceShiftSettingVo> getEnableShiftSetting(List<String> groupIds, List<AttendanceGroup> attendanceGroupVos, Boolean isFilterDisabled) {
        List<AttendanceShiftSettingVo> list = findAllByDate(attendanceGroupVos.stream().map(AttendanceGroup::getId).distinct().collect(Collectors.toList()), isFilterDisabled);
        Map<String, Boolean> collect1 = attendanceGroupVos.stream().collect(Collectors.toMap(AttendanceGroup::getId, group -> group.getAttendanceClassSetting() == 1));
        Map<String, AttendanceShiftSettingVo> collect = list.stream().filter(base -> collect1.getOrDefault(base.getGroupId(), Boolean.FALSE)).collect(Collectors.toMap(AttendanceShiftSettingVo::getGroupId, baseSetting -> baseSetting, (s1, s2) -> s2));
        Map<String, AttendanceShiftSettingVo> map = Maps.newHashMap();
        Map<String, String> groupIdToParent = attendanceGroupVos.stream().collect(Collectors.toMap(AttendanceGroup::getId, groupVo -> StringUtil.isBlank(groupVo.getParentId()) ? "-1" : groupVo.getParentId(), (g1, g2) -> g2));
        groupIds.forEach(groupId -> map.put(groupId, findNextBaseSetting(collect, groupIdToParent, groupId)));
        return map;
    }

    @Override
    public void initShiftSetting(String groupId) {
        List<AttendanceShiftNameEntity> list = attendanceShiftNameSettingService.list(new LambdaQueryWrapper<AttendanceShiftNameEntity>()
                .eq(AttendanceShiftNameEntity::getDeleteMark, Boolean.FALSE)
                .eq(AttendanceShiftNameEntity::getGroupId, groupId));
        if (CollUtil.isNotEmpty(list)) {
            return;
        }
        UserInfo user = UserProvider.getUser();
        List<AttendanceGroup> attendanceGroups = attendanceGroupService.queryDropList();
        Map<String, AttendanceShiftSettingVo> enableBaseSetting = getEnableShiftSetting(CollUtil.newArrayList(groupId), attendanceGroups);
        AttendanceShiftSettingVo attendanceLocationSetting = enableBaseSetting.get(groupId);
        if (Objects.nonNull(attendanceLocationSetting)) {
            AttendanceShiftSettingEntity attendanceShiftSettingEntity = BeanUtil.toBean(attendanceLocationSetting, AttendanceShiftSettingEntity.class);
            attendanceShiftSettingEntity.setId(RandomUtil.uuId());
            attendanceShiftSettingEntity.setGroupId(groupId);
            attendanceShiftSettingEntity.setCreatorTime(new Date());
            attendanceShiftSettingEntity.setCreatorUserId(user.getUserId());
            attendanceShiftSettingEntity.setTenantId(user.getTenantId());
            List<AttendanceFixedClassEntity> attendanceFixedClassEntities = CollUtil.newArrayList();
            List<AttendanceShiftNameEntity> attendanceShiftNameEntities = CollUtil.newArrayList();
            List<AttendanceShiftSettingPeriodEntity> periodEntitys = CollUtil.newArrayList();
            List<ShiftNameVo> shiftNameVos = attendanceLocationSetting.getSchedulingPeriods();
            Map<String, String> idMap = Maps.newHashMap();
            shiftNameVos.forEach(shiftNameVo -> {
                String id = RandomUtil.uuId();
                idMap.put(shiftNameVo.getId(), id);
                shiftNameVo.setId(id);
                shiftNameVo.setGroupId(groupId);
                shiftNameVo.setSettingId(attendanceShiftSettingEntity.getId());
                List<AttendanceShiftSettingPeriodVo> periods = shiftNameVo.getPeriods();
                List<AttendanceShiftSettingPeriodEntity> attendanceShiftSettingPeriodEntities = BeanUtil.copyToList(periods, AttendanceShiftSettingPeriodEntity.class);
                attendanceShiftSettingPeriodEntities.forEach(period -> {
                    period.setId(RandomUtil.uuId());
                    period.setGroupId(groupId);
                    period.setShiftId(id);
                    period.setSettingId(attendanceShiftSettingEntity.getId());
                    period.setCreatorTime(new Date());
                    period.setCreatorUserId(user.getUserId());
                    period.setTenantId(user.getTenantId());
                });
                periodEntitys.addAll(attendanceShiftSettingPeriodEntities);
            });
            attendanceShiftNameEntities.addAll(BeanUtil.copyToList(shiftNameVos, AttendanceShiftNameEntity.class));
            save(attendanceShiftSettingEntity);
            attendanceShiftNameSettingService.saveBatch(attendanceShiftNameEntities);
            attendanceShiftSettingPeriodService.saveBatch(periodEntitys);
            if (attendanceLocationSetting.getSystemType() == 1) {
                List<FixedClassShiftVo> shiftVos = attendanceLocationSetting.getFixedPeriods();
                shiftVos.forEach(vo -> {
                    List<ShiftNameVo> shiftNameVos2 = vo.getShiftNameVos();
                    shiftNameVos2.forEach(shiftNameVo -> {
                        AttendanceFixedClassEntity build = AttendanceFixedClassEntity.builder()
                                .id(RandomUtil.uuId())
                                .num(vo.getNum())
                                .settingId(attendanceShiftSettingEntity.getId())
                                .shiftNameId(idMap.get(shiftNameVo.getId()))
                                .shiftType(vo.getFixedType())
                                .build();
                        attendanceFixedClassEntities.add(build);
                    });
                });
            }
        }

    }

    private AttendanceShiftSettingVo findNextBaseSetting(Map<String, AttendanceShiftSettingVo> collect, Map<String, String> groupIdToParent, String groupId) {
        if (StringUtil.isBlank(groupId)) {
            return null;
        }
        if (!collect.containsKey(groupId)) {
            return findNextBaseSetting(collect, groupIdToParent, groupIdToParent.get(groupId));
        }
        return collect.get(groupId);
    }

    @Override
    public AttendanceShiftSettingVo findAllByGroupId(String groupId) {
        return findAllByDate(List.of(groupId), true).stream().findFirst().orElse(null);
    }

    private List<AttendanceShiftSettingVo> findAllByDate(List<String> groupIds, Boolean isFilterDisabled) {
        List<AttendanceShiftSettingEntity> list = lambdaQuery()
                .in(CollUtil.isNotEmpty(groupIds), AttendanceShiftSettingEntity::getGroupId, groupIds)
                .eq(AttendanceShiftSettingEntity::getEnable, isFilterDisabled)
                .orderByAsc(AttendanceShiftSettingEntity::getEnableTime)
                .list();
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newArrayList();
        }
        //查询固定班
        List<AttendanceFixedClassEntity> fixedClass = attendanceFixedClassService.list(new LambdaQueryWrapper<AttendanceFixedClassEntity>()
                .in(AttendanceFixedClassEntity::getGroupId, groupIds));
        Map<String, List<AttendanceFixedClassEntity>> fixedClassMap = CollUtil.isEmpty(fixedClass) ? Maps.newHashMap() : fixedClass.stream().collect(Collectors.groupingBy(AttendanceFixedClassEntity::getGroupId));
        //查询所有班次
        List<AttendanceShiftNameEntity> list2 = attendanceShiftNameSettingService.list(new LambdaQueryWrapper<AttendanceShiftNameEntity>()
                .eq(AttendanceShiftNameEntity::getDeleteMark, Boolean.FALSE)
                .in(AttendanceShiftNameEntity::getGroupId, groupIds));
        if (CollUtil.isEmpty(list2)) {
            return CollUtil.newArrayList();
        }
        Map<String, List<AttendanceShiftNameEntity>> shiftMap = CollUtil.isEmpty(list2) ? Maps.newHashMap() : list2.stream().collect(Collectors.groupingBy(AttendanceShiftNameEntity::getGroupId));
        List<String> collect1 = list2.stream().map(AttendanceShiftNameEntity::getId).distinct().collect(Collectors.toList());
        //查询涉及的所有时段
        List<AttendanceShiftSettingPeriodEntity> list1 = attendanceShiftSettingPeriodService.list(new LambdaQueryWrapper<AttendanceShiftSettingPeriodEntity>()
                .in(AttendanceShiftSettingPeriodEntity::getShiftId, collect1)
                .eq(AttendanceShiftSettingPeriodEntity::getDeleteMark, Boolean.FALSE));
        List<AttendanceShiftSettingPeriodVo> attendanceShiftSettingPeriods = CollUtil.isNotEmpty(list1) ? BeanUtil.copyToList(list1, AttendanceShiftSettingPeriodVo.class) : CollUtil.newArrayList();
        attendanceShiftSettingPeriods.forEach(period -> period.setValidDuration(period.calValidDuration()));
        Map<String, List<AttendanceShiftSettingPeriodVo>> periodMap = attendanceShiftSettingPeriods.stream().collect(Collectors.groupingBy(AttendanceShiftSettingPeriodVo::getShiftId));
        List<AttendanceShiftSettingVo> attendanceShiftSettings = BeanUtil.copyToList(list, AttendanceShiftSettingVo.class);
        List<FixedClassShiftVo> fixedClassShiftVos = CollUtil.newArrayList();
        List<ShiftNameVo> shiftNameVos = CollUtil.newArrayList();
        for (AttendanceShiftSettingVo setting : attendanceShiftSettings) {
            //查询当前班组所有班次
            List<AttendanceShiftNameEntity> shifts = shiftMap.getOrDefault(setting.getGroupId(), CollUtil.newArrayList());
            Map<String, AttendanceShiftNameEntity> shiftNameMap = shifts.stream().collect(Collectors.toMap(AttendanceShiftNameEntity::getId, shiftName -> shiftName));
            //划分固定班及排班
            if (Objects.equals(setting.getSystemType(), 1)) {
                fixedClassShiftVos.clear();
                //过滤固定班
                List<AttendanceFixedClassEntity> fixedClassList = fixedClassMap.getOrDefault(setting.getGroupId(), CollUtil.newArrayList());
                Map<Integer, List<AttendanceFixedClassEntity>> collect = fixedClassList.stream().collect(Collectors.groupingBy(AttendanceFixedClassEntity::getNum));
                collect.forEach((num, fixedList) -> {
                    shiftNameVos.clear();
                    fixedList.forEach(fixed -> {
                        if (Objects.isNull(fixed) || Objects.isNull(fixed.getType())) {
                            return;
                        }
                        if (fixed.getType() == 1 || fixed.getType() == 0) {
                            ShiftNameVo shiftName = new ShiftNameVo();
                            shiftName.setType(fixed.getType());
                            shiftNameVos.add(shiftName);
                            return;
                        }
                        if (StringUtil.isEmpty(fixed.getShiftNameId())) {
                            return;
                        }
                        AttendanceShiftNameEntity attendanceShiftNameEntity = shiftNameMap.get(fixed.getShiftNameId());
                        if (Objects.nonNull(attendanceShiftNameEntity)) {
                            ShiftNameVo shiftNameVo = BeanUtil.toBean(attendanceShiftNameEntity, ShiftNameVo.class);
                            shiftNameVo.setType(fixed.getType());
                            shiftNameVo.setPeriods(periodMap.get(shiftNameVo.getId()));
                            shiftNameVos.add(shiftNameVo);
                        }
                    });
                    fixedClassShiftVos.add(FixedClassShiftVo.builder()
                            .num(num)
                            .fixedType(fixedList.size() > 1 ? 1 : 0)
                            .shiftNameVos(BeanUtil.copyToList(shiftNameVos, ShiftNameVo.class))
                            .build());
                });
                setting.setFixedPeriods(BeanUtil.copyToList(fixedClassShiftVos, FixedClassShiftVo.class));
            }
            List<ShiftNameVo> shiftNameVo = BeanUtil.copyToList(shifts, ShiftNameVo.class);
            Iterator<ShiftNameVo> iterator = shiftNameVo.iterator();
            while (iterator.hasNext()) {
                ShiftNameVo shiftName = iterator.next();
                if (Objects.isNull(shiftName)) {
                    continue;
                }
                shiftName.setPeriods(periodMap.getOrDefault(shiftName.getId(), CollUtil.newArrayList()));
            }
            setting.setSchedulingPeriods(shiftNameVo);
        }
        return attendanceShiftSettings;
    }

    @Override
    public AttendanceShiftSettingVo findByGroupId(String groupId) {
        List<AttendanceGroup> attendanceGroups = attendanceGroupService.queryDropList();
        Map<String, AttendanceShiftSettingVo> enableShiftSetting = getEnableShiftSetting(CollUtil.newArrayList(groupId), attendanceGroups, Boolean.TRUE);
        AttendanceShiftSettingVo attendanceShiftSettingVo = enableShiftSetting.get(groupId);
        if (Objects.isNull(attendanceShiftSettingVo)) {
            attendanceShiftSettingVo = new AttendanceShiftSettingVo();
        }
        if (!StringUtil.equals(attendanceShiftSettingVo.getGroupId(), groupId)) {
            attendanceShiftSettingVo.setGroupId(groupId);
            attendanceShiftSettingVo.setEnable(0);
        }
        return attendanceShiftSettingVo;
    }

    @Override
    @Transactional
    public void save(AttendanceShiftDto dto) throws HandleException {
        Date time = null;
        if (Objects.equals(dto.getEnableType(), 1)) {
            dto.setEnableTime(DateUtil.getDayBegin());
        }
        if (Objects.equals(dto.getEnableType(), 2)) {
            AttendanceShiftSettingPeriodEntity one = attendanceShiftSettingPeriodService.getOne(new LambdaQueryWrapper<AttendanceShiftSettingPeriodEntity>()
                    .eq(AttendanceShiftSettingPeriodEntity::getGroupId, dto.getGroupId())
                    .orderByDesc(AttendanceShiftSettingPeriodEntity::getOutLackPoint)
                    .last(" limit 1"));
            Date outLackPoint = Objects.isNull(one) ? DateUtil.dateAddDays(DateUtil.getDayBegin(), 1) : DateDetail.getDateByPoint(new Date(), one.getOutLackPoint(), one.getOutLackType());
            Date dayBegin = DateUtil.dateAddDays(DateUtil.getDayBegin(), 1);
            if (outLackPoint != null) {
                dto.setEnableTime(outLackPoint.after(dayBegin) ? outLackPoint : dayBegin);
            }
            dto.setId(RandomUtil.uuId());
            time = new Date();
        }
        AttendanceShiftSettingEntity attendanceShiftSettingEntity = BeanUtil.toBean(dto, AttendanceShiftSettingEntity.class);
        UserInfo user = UserProvider.getUser();
        List<AttendanceShiftSettingEntity> list = lambdaQuery()
                .eq(AttendanceShiftSettingEntity::getGroupId, dto.getGroupId())
                .ge(Objects.nonNull(time), AttendanceShiftSettingEntity::getEnableTime, time)
                .eq(AttendanceShiftSettingEntity::getDeleteMark, Boolean.FALSE)
                .orderByDesc(AttendanceShiftSettingEntity::getEnableTime)
                .list();
        if (CollUtil.isEmpty(list)) {
            attendanceShiftSettingEntity.setId(RandomUtil.uuId());
            attendanceShiftSettingEntity.setCreatorTime(new Date());
            attendanceShiftSettingEntity.setCreatorUserId(user.getUserId());
            attendanceShiftSettingEntity.setTenantId(user.getTenantId());
            attendanceShiftSettingEntity.setEnable(1);
            attendanceShiftSettingEntity.setGroupId(dto.getGroupId());
        } else {
            AttendanceShiftSettingEntity attendanceShiftSettingEntity1 = list.get(0);
            if (Objects.equals(dto.getEnableType(), 1)) {
                if (list.size() > 1) {
                    removeById(list.get(1));
                }
            }
            attendanceShiftSettingEntity.setId(attendanceShiftSettingEntity1.getId());
            attendanceShiftSettingEntity.setGroupId(dto.getGroupId());
            attendanceShiftSettingEntity.setLastModifyTime(new Date());
            attendanceShiftSettingEntity.setEnable(1);
            attendanceShiftSettingEntity.setLastModifyUserId(user.getUserId());
        }
        List<AttendanceShiftSettingPeriodEntity> periodEntities = BeanUtil.copyToList(dto.getPeriods(), AttendanceShiftSettingPeriodEntity.class);
        if (CollUtil.isEmpty(periodEntities)) {
            throw new HandleException("未设置班制时段数据");
        }
        //判断固定班时段是否冲突
        if (!fixedPeriodConflict(dto.getSystemType(), periodEntities)) {
            throw new HandleException("当前固定班时段存在冲突");
        }
        //获取最后排序
        AttendanceShiftSettingPeriodEntity one = attendanceShiftSettingPeriodService.getOne(new LambdaQueryWrapper<AttendanceShiftSettingPeriodEntity>()
                .eq(AttendanceShiftSettingPeriodEntity::getGroupId, dto.getGroupId())
                .orderByDesc(AttendanceShiftSettingPeriodEntity::getCreatorTime)
                .last(" limit 1"));
        AtomicInteger sort = new AtomicInteger(Objects.isNull(one) ? 0 : one.getSort());
        periodEntities.forEach(entity -> {
            if (StringUtil.isEmpty(entity.getId())) {
                if (12 < sort.get()) {
                    sort.set(0);
                }
                entity.setSort(sort.addAndGet(1));
            }
            entity.setSystemType(attendanceShiftSettingEntity.getSystemType());
            entity.setSettingId(attendanceShiftSettingEntity.getId());
            if (StringUtil.isEmpty(entity.getId())) {
                entity.setGroupId(dto.getGroupId());
                entity.setCreatorTime(new Date());
                entity.setCreatorUserId(user.getUserId());
                entity.setTenantId(user.getTenantId());
                entity.setDeleteMark(0);
            } else {
                entity.setGroupId(dto.getGroupId());
                entity.setLastModifyTime(new Date());
                entity.setLastModifyUserId(user.getUserId());
                entity.setDeleteMark(0);
            }
        });
        List<String> collect = periodEntities.stream().map(AttendanceShiftSettingPeriodEntity::getId).collect(Collectors.toList());
        List<AttendanceShiftSettingPeriodEntity> shiftSettingPeriods = attendanceShiftSettingPeriodService.listByIds(collect);
        //切换班制类型，清除原规则
        changeSystemType(attendanceShiftSettingEntity.getGroupId(), attendanceShiftSettingEntity.getSystemType());
        String settingId = CollUtil.isEmpty(list) ? null : list.get(0).getId();
        attendanceShiftSettingPeriodService.update(new LambdaUpdateWrapper<AttendanceShiftSettingPeriodEntity>()
                .eq(AttendanceShiftSettingPeriodEntity::getGroupId, dto.getGroupId())
                .eq(StringUtil.isNotEmpty(settingId), AttendanceShiftSettingPeriodEntity::getSettingId, settingId)
                .eq(AttendanceShiftSettingPeriodEntity::getSystemType, dto.getSystemType())
                .set(AttendanceShiftSettingPeriodEntity::getDeleteMark, 1));
        attendanceShiftSettingPeriodService.saveOrUpdateBatch(periodEntities);
        if (Objects.equals(dto.getSystemType(), 2)) {
            return;
        }
        //固定班时段调整，变更现有排班规则
        AttendanceShiftSettingVo attendanceShiftSettingVo = new AttendanceShiftSettingVo();
        attendanceShiftSettingVo.setSystemType(1);
//        attendanceShiftSettingVo.setFixedPeriods(BeanUtil.copyToList(periodEntities, AttendanceShiftSettingPeriodVo.class));
        attendanceShiftSettingVo.setCycle(dto.getCycle());
        fixedPeriodChange(dto.getGroupId(), attendanceShiftSettingVo, shiftSettingPeriods, dto.getEnableTime());
    }

    private Boolean fixedPeriodConflict(Integer systemType, List<AttendanceShiftSettingPeriodEntity> periodEntities) {
        if (Objects.equals(systemType, 2)) {
            return Boolean.TRUE;
        }
        List<SecondmentDateVo> list = CollUtil.newArrayList();
        for (AttendanceShiftSettingPeriodEntity period : periodEntities) {
            if (!fixedPeriodSingleConflict(list, period)) {
                return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }

    private Boolean fixedPeriodSingleConflict(List<SecondmentDateVo> list, AttendanceShiftSettingPeriodEntity
            period) {
        Date date = new Date();
        Date inPoint = DateDetail.getDateByPoint(date, period.getInPoint(), period.getInType());
        Date outPoint = DateDetail.getDateByPoint(date, period.getOutPoint(), period.getOutType());
        if (CollUtil.isEmpty(list)) {
            list.add(SecondmentDateVo.builder().startTime(inPoint).endTime(outPoint).build());
            return Boolean.TRUE;
        }
        for (SecondmentDateVo vo : list) {
            if (outPoint != null && (DateDetail.checkTimeBetween(inPoint, vo.getStartTime(), vo.getEndTime())
                    || DateDetail.checkTimeBetween(outPoint, vo.getStartTime(), vo.getEndTime())
                    || DateDetail.checkTimeBetween(vo.getStartTime(), inPoint, outPoint)
                    || DateDetail.checkTimeBetween(vo.getEndTime(), inPoint, outPoint))) {
                return Boolean.FALSE;
            }
        }
        list.add(SecondmentDateVo.builder().startTime(inPoint).endTime(outPoint).build());
        return Boolean.TRUE;
    }

    private void fixedPeriodChange(String groupId, AttendanceShiftSettingVo shiftSettingVo, List<AttendanceShiftSettingPeriodEntity> oldPeriods, Date enableTime) {
//        Map<String, AttendanceShiftSettingPeriodEntity> collect = oldPeriods.stream().collect(Collectors.toMap(AttendanceShiftSettingPeriodEntity::getId, period -> period));
//        List<AttendanceShiftSettingPeriodVo> periodEntities = shiftSettingVo.getFixedPeriods();
//        List<AttendanceShiftSettingPeriodVo> collect1 = cycleUpdate ? periodEntities : periodEntities.stream().filter(period -> {
//            AttendanceShiftSettingPeriodEntity periodEntity = collect.get(period.getId());
//            if (Objects.isNull(periodEntity)) {
//                return Boolean.TRUE;
//            }
//            if (period.equalsPeriod(periodEntity)) {
//                return Boolean.FALSE;
//            }
//            return Boolean.TRUE;
//        }).collect(Collectors.toList());
//        if (CollUtil.isEmpty(collect1)) {
//            return;
//        }
//        List<AttendanceGroupVo> enableGroup = getEnableGroup(groupId);
//        List<String> collect2 = enableGroup.stream().map(AttendanceGroupVo::getId).collect(Collectors.toList());
//        collect2.add(groupId);
//        attendanceDailyRuleService.fixedPeriodChange(collect2, shiftSettingVo, enableTime);
    }

    @Override
    public void changeSystemType(String groupId, Integer systemType) {
        if (StringUtil.isEmpty(groupId)) {
            return;
        }
        AttendanceShiftSettingEntity byId = lambdaQuery()
                .eq(AttendanceShiftSettingEntity::getGroupId, groupId)
                .orderByDesc(AttendanceShiftSettingEntity::getCreatorTime)
                .last("limit 1")
                .one();
        if (Objects.isNull(byId)) {
            byId = new AttendanceShiftSettingEntity();
            byId.setId(RandomUtil.uuId());
            byId.setGroupId(groupId);
            byId.setSystemType(systemType);
            byId.setEnable(1);
            byId.setCreatorTime(new Date());
            byId.setCreatorUserId(UserProvider.getLoginUserId());
        }
        if (!Objects.equals(systemType, byId.getSystemType())) {
            sendNoticeBatch(groupId, systemType);
        }
        byId.setSystemType(systemType);
        byId.setEnable(1);
        saveOrUpdate(byId);
    }

    private void sendNoticeBatch(String groupId, Integer systemType) {
        List<String> selfAndChildrenGroupIds = attendanceGroupService.getSelfAndChildrenGroupIds(groupId, 3);
        attendanceRuleNotificationHandle.sendNoticeBatch(selfAndChildrenGroupIds, systemType);
    }

    private void sendNoticeByStatus(String groupId, Integer oldSystemType) {
        AttendanceShiftSettingVo byGroupId = findByGroupId(groupId);
        if (Objects.equals(oldSystemType, byGroupId.getSystemType())) {
            return;
        }
        List<String> selfAndChildrenGroupIds = attendanceGroupService.getSelfAndChildrenGroupIds(groupId, 3);
        attendanceRuleNotificationHandle.sendNoticeBatch(selfAndChildrenGroupIds, byGroupId.getSystemType());
    }


    @Override
    public void delPeriod(String periodId) {
        attendanceShiftSettingPeriodService.update(new LambdaUpdateWrapper<AttendanceShiftSettingPeriodEntity>()
                .set(AttendanceShiftSettingPeriodEntity::getDeleteMark, Boolean.TRUE)
                .set(AttendanceShiftSettingPeriodEntity::getDeleteUserId, UserProvider.getLoginUserId())
                .set(AttendanceShiftSettingPeriodEntity::getDeleteTime, new Date())
                .eq(AttendanceShiftSettingPeriodEntity::getId, periodId));
    }

    @Override
    public void changeStatus(String groupId, Integer enable, AttendanceShiftSettingVo shiftSettingVo) {
        RLock lock = redissonClient.getLock(String.format(RedisConstant.ATTENDANCE_CHANGE_GROUP_STATUS, UserProvider.getUser().getTenantId(), groupId));

        try {
            Assert.isFalse(lock.isLocked() || !lock.tryLock(5,60, TimeUnit.SECONDS), "当前考勤组切换班次操作正在执行中，请稍后再试");
            lambdaUpdate().eq(AttendanceShiftSettingEntity::getGroupId, groupId)
                    .set(AttendanceShiftSettingEntity::getEnable, enable).update();
            attendanceDailyRuleService.fixedPeriodChange(attendanceGroupService.getEnableGroupIds(groupId), findByGroupId(groupId), DateUtil.getDayBegin());
            sendNoticeByStatus(groupId, shiftSettingVo.getSystemType());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            if(lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    public List<ShiftPeriodVo> periodList(String groupId) {
        List<ShiftPeriodVo> resolved = periodListForIntelligentSchedule(groupId);
        return resolved == null ? CollUtil.newArrayList() : resolved;
    }

    @Override
    public List<ShiftPeriodVo> periodListForIntelligentSchedule(String groupId) {
        if (StrUtil.isBlank(groupId)) {
            return CollUtil.newArrayList();
        }
        List<AttendanceGroup> attendanceGroups = attendanceGroupService.queryDropList();
        Map<String, AttendanceShiftSettingVo> enableShiftSetting =
                getEnableShiftSetting(CollUtil.newArrayList(groupId), attendanceGroups, Boolean.TRUE);
        AttendanceShiftSettingVo byGroupId = enableShiftSetting.get(groupId);
        if (Objects.isNull(byGroupId)) {
            return null;
        }
        if (CollUtil.isEmpty(byGroupId.getSchedulingPeriods())) {
            return CollUtil.newArrayList();
        }
        return mapSchedulingPeriodsToShiftPeriodVo(byGroupId);
    }

    private List<ShiftPeriodVo> mapSchedulingPeriodsToShiftPeriodVo(AttendanceShiftSettingVo byGroupId) {
        return byGroupId.getSchedulingPeriods().stream()
                .map(
                        period -> {
                            ShiftNameViewVo shiftNameViewVo = BeanUtil.toBean(period, ShiftNameViewVo.class);
                            shiftNameViewVo.setPeriodNames(
                                    period.getPeriods().stream()
                                            .map(
                                                    p ->
                                                            PeriodNameVO.builder()
                                                                    .periodName(getName(p))
                                                                    .breakEnable(p.getBreakEnable())
                                                                    .inType(p.getInType())
                                                                    .inPoint(p.getInPoint())
                                                                    .outType(p.getOutType())
                                                                    .outPoint(p.getOutPoint())
                                                                    .breakStartType(p.getBreakStartType())
                                                                    .breakEndType(p.getBreakEndType())
                                                                    .breakStartPoint(p.getBreakStartPoint())
                                                                    .breakEndPoint(p.getBreakEndPoint())
                                                                    .timeSlotDay(p.getTimeSlotDay())
                                                                    .validDuration(p.getValidDuration())
                                                                    .build())
                                            .collect(Collectors.toList()));
                            return ShiftPeriodVo.builder()
                                    .id(period.getId())
                                    .name(period.getName())
                                    .shortName(period.getShortName())
                                    .sort(period.getFixedSort())
                                    .colour(period.getColour())
                                    .shiftType(period.getShiftType())
                                    .schedulingPeriod(shiftNameViewVo)
                                    .build();
                        })
                .collect(Collectors.toList());
    }

    @Override
    public List<ShiftPeriodVo> periodListForSelfScheduling() {
        String loginUserId = UserProvider.getLoginUserId();
        Date date = new Date();
        List<AttendanceGroupUser> attendanceGroupUsers = attendanceUserService.getAttendanceGroupUsersOfSecondment(date, date, List.of(loginUserId), null);
        Assert.isFalse(CollUtil.isEmpty(attendanceGroupUsers), "未查询到当前时间所在考勤组");
        AttendanceGroupUser groupUser = attendanceGroupUsers.stream().findFirst().orElse(null);
        String groupId = null;
        if (groupUser != null) {
            groupId = groupUser.getGroupId();
        }
        boolean isSecondment = Objects.equals(Objects.requireNonNull(groupUser).getType(), 2);
        List<SecondmentDateVo> dateVoList = isSecondment ? JsonUtil.getJsonToList(groupUser.getTimeJson(), SecondmentDateVo.class) : CollUtil.newArrayList();
        SecondmentDateVo secondmentDateVo = dateVoList.stream().filter(vo -> !date.before(vo.getStartTime()) && !date.after(vo.getEndTime())).findFirst().orElse(null);
        //当前排班为个人
        List<AttendanceGroup> attendanceGroups = attendanceGroupService.queryDropList();
        Map<String, AttendanceShiftSettingVo> enableShiftSetting = getEnableShiftSetting(CollUtil.newArrayList(groupId), attendanceGroups, Boolean.TRUE);
        AttendanceShiftSettingVo byGroupId = enableShiftSetting.get(groupId);
        if (Objects.isNull(byGroupId)) {
            return CollUtil.newArrayList();
        }
        if (CollUtil.isEmpty(byGroupId.getSchedulingPeriods())) {
            return CollUtil.newArrayList();
        }
        return byGroupId.getSchedulingPeriods().stream().map(shiftNameVo -> {
            List<AttendanceShiftSettingPeriodVo> periods = shiftNameVo.getPeriods();
            if (isSecondment) {
                boolean allMatch = periods.stream().allMatch(period -> {
                    Date inPoint = DateDetail.getDateByPoint(date, period.getInPoint(), period.getInType());
                    Date outPoint = DateDetail.getDateByPoint(date, period.getOutPoint(), period.getOutType());
                    if (secondmentDateVo != null) {
                        return !secondmentDateVo.getStartTime().before(inPoint) && !secondmentDateVo.getEndTime().after(outPoint);
                    }
                    return false;
                });
                if (!allMatch) {
                    return null;
                }
            }
            return ShiftPeriodVo.builder()
                    .id(shiftNameVo.getId())
                    .name(shiftNameVo.getName())
                    .shortName(shiftNameVo.getShortName())
                    .periodNames(periods.stream().map(this::getName2).reduce((r1, r2) -> r1 + " " + r2).orElse(""))
                    .sort(shiftNameVo.getFixedSort())
                    .colour(shiftNameVo.getColour())
                    .shiftType(shiftNameVo.getShiftType())
                    .build();
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public void hisShiftSetting(Map<String, String> group2orgMap, Map<String, String> org2GroupMap) {
        List<AttendanceShiftSettingEntity> list = lambdaQuery().in(AttendanceShiftSettingEntity::getDeleteMark, 0).list();
        list.forEach(item -> item.setGroupId(org2GroupMap.getOrDefault(group2orgMap.getOrDefault(item.getGroupId(), item.getGroupId()), item.getGroupId())));
        list.stream().collect(Collectors.groupingBy(AttendanceShiftSettingEntity::getGroupId)).forEach((key, value) -> {
            value.stream().skip(1).forEach(vo -> vo.setDeleteMark(1));
        });
        updateBatchById(list);
        Map<String, String> group2setting = list.stream().filter(vo -> Objects.equals(vo.getDeleteMark(), 0)).collect(Collectors.toMap(AttendanceShiftSettingEntity::getGroupId, AttendanceShiftSettingEntity::getId));
        List<AttendanceShiftNameEntity> list1 = attendanceShiftNameSettingService.list(new LambdaQueryWrapper<AttendanceShiftNameEntity>().in(AttendanceShiftNameEntity::getDeleteMark, 0));
        list1.forEach(item -> {
            item.setGroupId(org2GroupMap.getOrDefault(group2orgMap.getOrDefault(item.getGroupId(), item.getGroupId()), item.getGroupId()));
            item.setSettingId(group2setting.getOrDefault(item.getGroupId(), item.getSettingId()));
        });
        AtomicInteger i = new AtomicInteger(0);
        list1.stream().collect(Collectors.groupingBy(vo -> vo.getGroupId() + vo.getName())).forEach((vo,settings)->{
            i.set(0);
            settings.stream().skip(1).forEach(setting->setting.setName(setting.getName()+(i.incrementAndGet())));
        });
        attendanceShiftNameSettingService.updateBatchById(list1);
    }

    private String getName(AttendanceShiftSettingPeriodVo period) {
        return (Objects.equals(period.getInType(), 2) ? "次日" + period.getInPoint() : period.getInPoint()) + "-" +
                (period.getOutType() == 1 ? period.getOutPoint() : "次日" + period.getOutPoint());
    }


    private String getName2(AttendanceShiftSettingPeriodVo period) {
        return (Objects.equals(period.getInType(), 2) ? "次日" + period.getInPoint() : period.getInPoint()) + "至" +
                (period.getOutType() == 1 ? period.getOutPoint() : "次日" + period.getOutPoint());
    }
}
