package jnpf.attendance.excel.listener;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import jnpf.enums.attendance.AttendanceTypeEnum;
import jnpf.enums.attendance.ScheduleImportEnum;
import jnpf.model.attendance.model.ScheduleImportFailModel;
import jnpf.model.attendance.vo.*;
import jnpf.model.attendance.vo.attendance.ShiftNameVo;
import jnpf.permission.model.user.PartUserInfoVo;
import jnpf.util.StringUtil;
import jnpf.util.attendance.RuleExcelImportUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;

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

// 有个很重要的点 DemoDataListener 不能被spring管理，要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class SchedulesDataListener extends AnalysisEventListener<Map<Integer, String>> {

    /**
     * 缓存的数据
     */
    private final List<SchedulesV2Vo> cachedDataList;
    private final List<ScheduleImportFailModel> failList;

    private final Date month;

    private final List<String> heads;

    private final Map<String, ShiftNameVo> shiftMap;
    private final Map<String, PartUserInfoVo> userMap;

    private static final String format = "yyyy-MM-dd";

    private int headRow = 0;

    public SchedulesDataListener(List<SchedulesV2Vo> cachedDataList, List<ScheduleImportFailModel> failList, List<String> heads, Date month, Map<String, ShiftNameVo> shiftMap, Map<String, PartUserInfoVo> userMap) {
        this.cachedDataList = cachedDataList;
        this.failList = failList;
        this.heads = heads;
        this.month = month;
        this.shiftMap = shiftMap;
        this.userMap = userMap;
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        // 处理表头数据
        // headMap的key是列索引，value是表头名称
        headRow++;
        if (context.readRowHolder().getRowIndex() < 2) {
            return;
        }
        Assert.isFalse(heads.size() != headMap.size() ||
                !CollectionUtils.isEqualCollection(heads, headMap.values()), ScheduleImportEnum.IMPORT_ERROR_FORMAT_WRONG.getMessage());
    }

    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        Assert.isFalse(headRow != 3, ScheduleImportEnum.IMPORT_ERROR_FORMAT_WRONG.getMessage());
        // 处理每一行数据
        // data的key是列索引，value是单元格值
        //用户人员信息校验
        String userName = data.get(0);
        String phone = data.get(1);
        if (RuleExcelImportUtil.addFail(StringUtil.isEmpty(userName) || StringUtil.isEmpty(phone), ScheduleImportEnum.IMPORT_ERROR_UNIDENTIFIED_MEMBER, userName, failList)) {
            return;
        }
        PartUserInfoVo userEntity = userMap.get(phone);
        if (RuleExcelImportUtil.addFail(Objects.isNull(userEntity), ScheduleImportEnum.IMPORT_ERROR_MEMBER_NOT_IN_GROUP, userName, failList)) {
            return;
        }
        if (RuleExcelImportUtil.addFail(!userEntity.getRealName().equals(userName), ScheduleImportEnum.IMPORT_ERROR_UNIDENTIFIED_MEMBER, userName, failList)) {
            return;
        }
        if (RuleExcelImportUtil.addFail(cachedDataList.stream().anyMatch(vo -> vo.getUserId().equals(userEntity.getUserId())), ScheduleImportEnum.IMPORT_ERROR_DUPLICATE_MEMBERS, userEntity.getRealName(), failList)) {
            return;
        }
        LinkedHashMap<String, SchedulesDayVo> schedulesDaySetDto = new LinkedHashMap<>();
        cachedDataList.add(SchedulesV2Vo.builder()
                .userId(userEntity.getUserId())
                .mobilePhone(userEntity.getMobilePhone())
                .realName(userEntity.getRealName())
                .val(schedulesDaySetDto)
                .build());
        //班次信息校验
        data.forEach((index, shiftNameSrt) -> {
            if (index < 3 || heads.size() < index - 1) {
                return;
            }
            String head = heads.get(index);
            String dayIndex = head.split("\n")[1];
            DateTime day = DateUtil.offsetDay(month, Integer.parseInt(dayIndex) - 1);
            String dayStr = DateUtil.format(day, format);
            if (StringUtil.isEmpty(shiftNameSrt)) {
                //清空
                schedulesDaySetDto.put(dayStr, SchedulesDayVo.builder().itemVos(List.of(SchedulesItemVo.builder().type(0).build())).build());
                return;
            }
            String[] shiftNameArr = shiftNameSrt.split("\\|");
            int length = shiftNameArr.length;
            ArrayList<SchedulesItemVo> list = Lists.newArrayList();
            schedulesDaySetDto.put(dayStr, SchedulesDayVo.builder().itemVos(list).build());
            for (int i = 0; i < shiftNameArr.length; i++) {
                //上午半天是否为休
                boolean isAMOff = list.stream().anyMatch(vo -> Objects.equals(vo.getType(), 1) || Objects.equals(vo.getType(), 3) || Objects.equals(vo.getType(), 4));
                String shiftName = shiftNameArr[i];
                //判断班次类型
                ShiftNameVo shiftPeriodVo = shiftMap.get(shiftName);
                if (Objects.nonNull(shiftPeriodVo)) {
                    //是否为全天班
                    if (length > 1 && Arrays.stream(shiftNameArr).noneMatch(vo -> StringUtil.equals(vo, AttendanceTypeEnum.REST.getMsg()))) {
                        RuleExcelImportUtil.addFail(true, ScheduleImportEnum.IMPORT_ERROR_SHIFT_NAME_INVALID, userEntity.getRealName(), failList);
                        return;
                    }
                    //是否为全天班设置了两次
                    List<SchedulesItemVo> collect = list.stream().filter(vo -> Objects.equals(vo.getShiftId(), shiftPeriodVo.getId())).peek(vo -> vo.setSchedulesType(0)).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(collect)) {
                        continue;
                    }
                    list.add(SchedulesItemVo.builder()
                            .schedulesType(length < 2 ? 0 : i + 1)
                            .type(2)
                            .sort(length < 2 ? 0 : i + 1)
                            .shiftId(shiftPeriodVo.getId())
                            .name(shiftPeriodVo.getName())
                            .shortName(shiftPeriodVo.getShortName())
                            .colour(shiftPeriodVo.getColour())
                            .build());
                    continue;
                }
                //秀
                if (!isAMOff && StringUtil.equals(shiftName, AttendanceTypeEnum.REST.getMsg())) {
                    list.add(SchedulesItemVo.builder()
                            .schedulesType(length < 2 ? 0 : i + 1)
                            .type(1)
                            .build());
                    continue;
                }
                if (!isAMOff && StringUtil.equals(shiftName, AttendanceTypeEnum.DEDUCTION_HOLIDAYS.getMsg())) {
                    list.add(SchedulesItemVo.builder()
                            .schedulesType(length < 2 ? 0 : i + 1)
                            .type(3)
                            .build());
                    continue;
                }
                if (!isAMOff && StringUtil.equals(shiftName, AttendanceTypeEnum.EXCHANGE_HOLIDAYS.getMsg())) {
                    list.add(SchedulesItemVo.builder()
                            .schedulesType(length < 2 ? 0 : i + 1)
                            .type(4)
                            .build());
                    continue;
                }
                RuleExcelImportUtil.addFail(true, ScheduleImportEnum.IMPORT_ERROR_SHIFT_NAME_INVALID, userEntity.getRealName(), failList);
                return;

            }

        });
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 所有数据解析完成后的操作
        log.error("所有数据解析完成");
    }


}