package jnpf.attendance.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import jnpf.attendance.mapper.AttendanceQuickTemplateMapper;
import jnpf.attendance.service.*;
import jnpf.base.UserInfo;
import jnpf.base.service.SuperServiceImpl;
import jnpf.entity.attendance.AttendanceQuickTemplateEntity;
import jnpf.entity.attendance.AttendanceQuickTemplateItemEntity;
import jnpf.entity.attendance.AttendanceShiftSettingPeriodEntity;
import jnpf.model.attendance.dto.*;
import jnpf.model.attendance.vo.*;
import jnpf.model.attendance.vo.attendance.FixedClassShiftVo;
import jnpf.model.attendance.vo.attendance.QuickTemVo;
import jnpf.model.attendance.vo.attendance.ShiftNameVo;
import jnpf.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 考勤配置-快速模板 服务实现类
 * </p>
 *
 * @author ahua
 * @since 2023-11-28
 */
@Service
public class AttendanceQuickTemplateServiceImpl extends SuperServiceImpl<AttendanceQuickTemplateMapper, AttendanceQuickTemplateEntity> implements AttendanceQuickTemplateService {
    @Autowired
    private AttendanceQuickTemplateItemService attendanceQuickTemplateItemService;
    @Autowired
    private AttendanceShiftSettingPeriodService attendanceShiftSettingPeriodService;
    @Autowired
    private AttendanceQuickTemplateMapper attendanceQuickTemplateMapper;
    @Autowired
    private AttendanceShiftSettingService attendanceShiftSettingService;
    @Autowired
    private AttendanceShiftNameSettingService shiftNameSettingService;


    @Override
    public List<AttendanceQuickTemplateVo> findList(String groupId) {
        List<AttendanceQuickTemplateEntity> list = lambdaQuery().eq(AttendanceQuickTemplateEntity::getGroupId, groupId)
                .eq(AttendanceQuickTemplateEntity::getDeleteMark, Boolean.FALSE)
                .list();
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newArrayList();
        }
        List<String> ids = list.stream().map(AttendanceQuickTemplateEntity::getId).collect(Collectors.toList());
        List<AttendanceQuickTemplateItemEntity> list1 = attendanceQuickTemplateItemService.list(new LambdaQueryWrapper<AttendanceQuickTemplateItemEntity>()
                .in(AttendanceQuickTemplateItemEntity::getTemplateId, ids));
        Map<String, List<AttendanceQuickTemplateItemEntity>> itemMap = list1.stream().collect(Collectors.groupingBy(AttendanceQuickTemplateItemEntity::getTemplateId));

        return list.stream().map(temp -> {
            List<String> periodIds = CollUtil.newArrayList();
            List<AttendanceQuickTemplateItemEntity> attendanceQuickTemplateItemEntities = itemMap.get(temp.getId());
            List<AttendanceQuickTemplateItemVo> collect = attendanceQuickTemplateItemEntities.stream().map(item -> {
                AttendanceQuickTemplateItemVo attendanceQuickTemplateItemVo = new AttendanceQuickTemplateItemVo();
                attendanceQuickTemplateItemVo.setId(item.getId());
                attendanceQuickTemplateItemVo.setSort(item.getSort());
                attendanceQuickTemplateItemVo.setTemplateId(item.getTemplateId());
                List<QuickPeriodsVo> quickPeriodsVos = JsonUtil.getJsonToList(item.getPeriods(), QuickPeriodsVo.class);
                periodIds.addAll(quickPeriodsVos.stream().map(QuickPeriodsVo::getPeriodId).collect(Collectors.toList()));
                attendanceQuickTemplateItemVo.setPeriods(quickPeriodsVos);
                return attendanceQuickTemplateItemVo;
            }).collect(Collectors.toList());
            List<AttendanceShiftSettingPeriodEntity> attendanceShiftSettingPeriodEntities = attendanceShiftSettingPeriodService.listByIds(periodIds.stream().distinct().collect(Collectors.toList()));
            String periodStr = attendanceShiftSettingPeriodEntities.stream().map(period -> period.getInPoint() + "-" + (Objects.equals(period.getOutType(), 2) ? "次日" : "") + period.getOutPoint()).distinct().reduce((r1, r2) -> r1 + "," + r2).orElse("");
            AttendanceQuickTemplateVo attendanceQuickTemplateVo = BeanUtil.toBean(temp, AttendanceQuickTemplateVo.class);
            attendanceQuickTemplateVo.setItems(collect);
            attendanceQuickTemplateVo.setPeriodicity(collect.size());
            attendanceQuickTemplateVo.setPeriodStr(periodStr);
            return attendanceQuickTemplateVo;
        }).collect(Collectors.toList());
    }

    @Override
    public AttendanceQuickTemplateVo findOne(String templateId) {
        AttendanceQuickTemplateEntity one = lambdaQuery().eq(AttendanceQuickTemplateEntity::getId, templateId)
                .eq(AttendanceQuickTemplateEntity::getDeleteMark, Boolean.FALSE)
                .one();
        List<AttendanceQuickTemplateItemEntity> list1 = attendanceQuickTemplateItemService.list(new LambdaQueryWrapper<AttendanceQuickTemplateItemEntity>()
                .eq(AttendanceQuickTemplateItemEntity::getTemplateId, templateId));
        List<AttendanceQuickTemplateItemVo> itemVos = list1.stream().map(item -> {
            AttendanceQuickTemplateItemVo attendanceQuickTemplateItemVo = new AttendanceQuickTemplateItemVo();
            attendanceQuickTemplateItemVo.setId(item.getId());
            attendanceQuickTemplateItemVo.setSort(item.getSort());
            attendanceQuickTemplateItemVo.setTemplateId(item.getTemplateId());
            List<QuickPeriodsVo> quickPeriodsVos = JsonUtil.getJsonToList(item.getPeriods(), QuickPeriodsVo.class);
            attendanceQuickTemplateItemVo.setPeriods(quickPeriodsVos);
            return attendanceQuickTemplateItemVo;
        }).collect(Collectors.toList());
        AttendanceQuickTemplateVo attendanceQuickTemplateVo = BeanUtil.toBean(one, AttendanceQuickTemplateVo.class);
        attendanceQuickTemplateVo.setItems(itemVos);
        attendanceQuickTemplateVo.setPeriodicity(itemVos.size());
        return attendanceQuickTemplateVo;
    }

    @Override
    public void save(QuickTemplateDto dto) {
        List<AttendanceQuickTemplateEntity> list = lambdaQuery().eq(AttendanceQuickTemplateEntity::getName, dto.getName())
                .eq(AttendanceQuickTemplateEntity::getGroupId, dto.getGroupId())
                .eq(AttendanceQuickTemplateEntity::getDeleteMark, Boolean.FALSE)
                .list();
        Assert.isFalse(CollUtil.isNotEmpty(list), "模板名称不能重复");
        List<String> periodIds = CollUtil.newArrayList();
        List<SchedulesSetItemDto> items1 = dto.getItems();
        items1.forEach(item -> {
            if (Objects.nonNull(item)) {
                periodIds.addAll(item.getPeriodIds());
            }
        });
        List<AttendanceShiftSettingPeriodEntity> attendanceShiftSettingPeriodEntities = CollUtil.isEmpty(periodIds) ? CollUtil.newArrayList() : attendanceShiftSettingPeriodService.listByIdsIgnoreLogic(periodIds);
        Map<String, AttendanceShiftSettingPeriodEntity> periodMap = attendanceShiftSettingPeriodEntities.stream().collect(Collectors.toMap(AttendanceShiftSettingPeriodEntity::getId, period -> period));
        AttendanceQuickTemplateEntity build = AttendanceQuickTemplateEntity.builder().id(dto.getId()).name(dto.getName()).build();
        UserInfo user = UserProvider.getUser();
        if (StringUtil.isNotEmpty(build.getId())) {
            build.setLastModifyTime(new Date());
            build.setLastModifyUserId(user.getUserId());
        } else {
            build.setId(RandomUtil.uuId());
            build.setCreatorTime(new Date());
            build.setCreatorUserId(user.getUserId());
            build.setTenantId(user.getTenantId());
            build.setGroupId(dto.getGroupId());
        }
        int sort = 0;
        List<AttendanceQuickTemplateItemEntity> itemEntities = CollUtil.newArrayList();
        List<SchedulesSetItemDto> items = dto.getItems();
        for (SchedulesSetItemDto item : items) {
            List<QuickPeriodsVo> collect = CollUtil.newArrayList();
            if (item.getType() == 2) {
                List<QuickPeriodsVo> collect1 = item.getPeriodIds().stream().map(periodId -> {
                    AttendanceShiftSettingPeriodEntity periodEntity = periodMap.get(periodId);
                    return QuickPeriodsVo.builder()
                            .periodId(periodId)
                            .sort(periodEntity.getSort())
                            .name(periodEntity.getInPoint() + "-" + (periodEntity.getOutType() == 1 ? periodEntity.getOutPoint() : "次日" + periodEntity.getOutPoint()))
                            .type(item.getType()).build();
                }).collect(Collectors.toList());
                collect.addAll(collect1);
            } else {
                collect.add(QuickPeriodsVo.builder().type(item.getType()).build());
            }
            itemEntities.add(AttendanceQuickTemplateItemEntity.builder().templateId(build.getId()).sort(sort++).periods(JSON.toJSONString(collect)).build());
        }
        attendanceQuickTemplateItemService.remove(new LambdaUpdateWrapper<AttendanceQuickTemplateItemEntity>().eq(AttendanceQuickTemplateItemEntity::getTemplateId, build.getId()));
        attendanceQuickTemplateItemService.saveBatch(itemEntities);
        saveOrUpdate(build);
    }

    @Override
    public void del(String id) {
        lambdaUpdate().set(AttendanceQuickTemplateEntity::getDeleteMark, Boolean.TRUE)
                .set(AttendanceQuickTemplateEntity::getDeleteUserId, UserProvider.getLoginUserId())
                .set(AttendanceQuickTemplateEntity::getDeleteTime, new Date())
                .eq(AttendanceQuickTemplateEntity::getId, id)
                .update();
        // 删除之前绑定的班次信息
        attendanceQuickTemplateMapper.deleteClass(id);
    }

    @Transactional
    @Override
    public void saveOrUpdateNew(QuickTemDto dto) {
        List<AttendanceQuickTemplateEntity> list1 = lambdaQuery().eq(AttendanceQuickTemplateEntity::getName, dto.getName())
                .eq(AttendanceQuickTemplateEntity::getGroupId, dto.getGroupId())
                .eq(AttendanceQuickTemplateEntity::getDeleteMark, Boolean.FALSE)
                .list();
        Assert.isFalse(CollUtil.isNotEmpty(list1) && list1.stream().noneMatch(vo -> Objects.equals(vo.getId(), dto.getId())), "模板名称不能重复");
        String userId = UserProvider.getUser().getUserId();
        AttendanceShiftSettingVo byGroupId = attendanceShiftSettingService.findByGroupId(dto.getGroupId());
        List<ShiftNameVo> schedulingPeriods = byGroupId.getSchedulingPeriods();
        Map<String, ShiftNameVo> collect = schedulingPeriods.stream().collect(Collectors.toMap(ShiftNameVo::getId, Function.identity()));
        Date date = new Date();
        List<SecondmentDateVo> dateList = CollUtil.newArrayList();
        if (null != dto.getId() && !dto.getId().isEmpty()) {
            // 修改快速模板
            attendanceQuickTemplateMapper.updateTemplate(dto, userId);
            // 删除之前绑定的班次信息
            attendanceQuickTemplateMapper.deleteClass(dto.getId());
        } else {
            dto.setId(FtbUtil.getId());
            //新增快速模板
            attendanceQuickTemplateMapper.saveTemplate(dto, userId);
        }
        if (null != dto.getFixedClassDtos() && !dto.getFixedClassDtos().isEmpty()) {
            List<FixedClassSaveDto> list = new ArrayList<>();
            int index = 0;
            for (FixedClassDto v : dto.getFixedClassDtos()) {
                // 生成偏移日期：按索引递增天数偏移基准日期
                DateTime dateTime = cn.hutool.core.date.DateUtil.offsetDay(date, ++index);
                if (CollUtil.isEmpty(v.getFixedBases())) {
                    FixedClassSaveDto fixedClassSaveDto = new FixedClassSaveDto(FtbUtil.getId(), v.getNum(), v.getShiftType(), dto.getId(), 0, null, 1);
                    list.add(fixedClassSaveDto);
                } else {
                    v.getFixedBases().forEach(value -> {
                        // 模板Id赋值到组Id做替换
                        FixedClassSaveDto fixedClassSaveDto = new FixedClassSaveDto(FtbUtil.getId(), v.getNum(), v.getShiftType(), dto.getId(), value.getType(), value.getShiftNameId(), value.getSort());
                        list.add(fixedClassSaveDto);
                    });
                }
                for (FixedBaseDto fixedClassSaveDto : v.getFixedBases()) {
                    if (StringUtil.isNotEmpty(fixedClassSaveDto.getShiftNameId()) && collect.containsKey(fixedClassSaveDto.getShiftNameId())) {
                        ShiftNameVo shiftNameVo = collect.get(fixedClassSaveDto.getShiftNameId());
                        if (Objects.equals(v.getShiftType(), 0)) {
                            for (AttendanceShiftSettingPeriodVo periodVo : shiftNameVo.getPeriods()) {
                                Assert.isTrue(shiftNameSettingService.fixedPeriodSingleConflict(dateTime, dateList, periodVo), "班次时间段冲突");
                            }
                        } else {
                            Assert.isTrue(shiftNameSettingService.fixedPeriodSingleConflict(dateTime, dateList, shiftNameVo.getPeriods().get(shiftNameVo.getPeriods().size() < 2 ? 0 : fixedClassSaveDto.getSort() - 1)), "班次时间段冲突");
                        }
                    }
                }
            }
            if (!list.isEmpty()) {
                // 保存本次传入的内容
                attendanceQuickTemplateMapper.saveClass(list);
            }
        }
    }

    @Override
    public List<QuickTemVo> findNewList(String groupId) {
        List<QuickTemVo> quickTemVos = attendanceQuickTemplateMapper.getTemByGroupId(groupId);
        if (null != quickTemVos && !quickTemVos.isEmpty()) {
            // 考勤组下所有模板
            List<String> temIds = quickTemVos.stream().map(QuickTemVo::getId).collect(Collectors.toList());
            // 模板下拼接下面的班次信息
            List<ShiftNameVo> shiftNameVos = attendanceQuickTemplateMapper.getShiftByTemIds(temIds);
            if (null != shiftNameVos && !shiftNameVos.isEmpty()) {
                List<ShiftNameVo> workMap = shiftNameVos.stream().filter(t -> 2 == t.getType()).collect(Collectors.toList());
                // 组装时间段
                List<String> shiftIds = workMap.stream().distinct().map(ShiftNameVo::getId).collect(Collectors.toList());
                if (!shiftIds.isEmpty()) {
                    List<AttendanceShiftSettingPeriodEntity> list = attendanceShiftSettingPeriodService.list(new LambdaQueryWrapper<AttendanceShiftSettingPeriodEntity>()
                            .in(AttendanceShiftSettingPeriodEntity::getShiftId, shiftIds)
                            .eq(AttendanceShiftSettingPeriodEntity::getDeleteMark, Boolean.FALSE));
                    Map<String, List<AttendanceShiftSettingPeriodEntity>> shiftMap = list.stream().collect(Collectors.groupingBy(AttendanceShiftSettingPeriodEntity::getShiftId));
                    workMap.forEach(v -> {
                        // 赋值时段信息
                        List<AttendanceShiftSettingPeriodEntity> attendanceShiftSettingPeriodEntities = shiftMap.get(v.getId());
                        if (null != attendanceShiftSettingPeriodEntities && !attendanceShiftSettingPeriodEntities.isEmpty()) {
                            // 排序
                            List<AttendanceShiftSettingPeriodEntity> shiftList = attendanceShiftSettingPeriodEntities.stream().sorted(Comparator.comparing(AttendanceShiftSettingPeriodEntity::getType)).collect(Collectors.toList());
                            List<AttendanceShiftSettingPeriodVo> periodEntities = BeanUtil.copyToList(shiftList, AttendanceShiftSettingPeriodVo.class);
                            v.setPeriods(periodEntities);
                        }
                    });
                }
                // 组装数据
                Map<String, List<ShiftNameVo>> temMap = shiftNameVos.stream().collect(Collectors.groupingBy(ShiftNameVo::getTemplateId));
                quickTemVos.forEach(v -> {
                    // 指定模板下班次信息
                    List<ShiftNameVo> shiftList = temMap.get(v.getId());
                    if (null != shiftList && !shiftList.isEmpty()) {
                        List<FixedClassShiftVo> fixedList = new ArrayList<>();
                        Map<Integer, List<ShiftNameVo>> numMap = shiftList.stream().collect(Collectors.groupingBy(ShiftNameVo::getNum));
                        int cycle = 0;
                        for (Map.Entry<Integer, List<ShiftNameVo>> integerListEntry : numMap.entrySet()) {
                            FixedClassShiftVo fixedClassShiftVo = new FixedClassShiftVo();
                            fixedClassShiftVo.setNum(integerListEntry.getKey());
                            fixedClassShiftVo.setFixedType(integerListEntry.getValue().get(0).getFixedType());
                            fixedClassShiftVo.setShiftNameVos(integerListEntry.getValue());
                            fixedList.add(fixedClassShiftVo);
                            cycle = cycle + 1;
                        }
                        v.setCycle(cycle);
                        v.setList(fixedList.stream().sorted(Comparator.comparing(FixedClassShiftVo::getNum)).collect(Collectors.toList()));
                    }
                });
            }
        }
        return quickTemVos;
    }
}
