package jnpf.enums.attendance;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.util.StringUtil;
import jnpf.model.attendance.model.BatchNumberResult;
import jnpf.model.attendance.vo.attendance.MonthStatisticsQueryVo;
import lombok.Data;
import lombok.Getter;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Data
public class StatisticsEnumUtil {
    /**
     * 记录类型(1-请假 2-迟到 3-早退 4-缺卡 5-旷工 6-补卡 7-外勤 8-加班 9-借调 10-出差 11-外出)
     */
    @Getter
    public enum DataTypeEnum {
        QJ(1, "请假") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().filter(x -> StringUtil.isNotEmpty(x.getLeaveTimes())).mapToInt(x -> x.getLeaveTimes().split(",").length).sum();
            }
        },
        CD(2, "迟到") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().mapToInt(MonthStatisticsQueryVo::getLateTimes).sum();
            }
        },
        ZT(3, "早退") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().mapToInt(MonthStatisticsQueryVo::getEarlyLeaveTimes).sum();
            }
        },
        QK(4, "缺卡") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().mapToInt(MonthStatisticsQueryVo::getAbsenceCardTimes).sum();
            }
        },
        QQ(5, "旷工") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().mapToInt(MonthStatisticsQueryVo::getAbsenceTimes).sum();
            }
        },
        BK(6, "补卡") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().mapToInt(MonthStatisticsQueryVo::getMakeUpCardTimes).sum();
            }
        },
        WQ(7, "外勤") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().mapToInt(MonthStatisticsQueryVo::getOutworkTimes).sum();
            }
        },
        JB(8, "加班") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().mapToInt(MonthStatisticsQueryVo::getOvertimeTimes).sum();
            }
        },
        JD(9, "借调") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().mapToInt(MonthStatisticsQueryVo::getSelfGroupTimes).sum();
            }
        },
        CC(10, "出差") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                return monthStatistics.stream().filter(x -> StringUtil.isNotEmpty(x.getBusTimes())).mapToInt(x -> x.getBusTimes().split(",").length).sum();
            }
        },
        WC(11, "外出") {
            @Override
            public Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics) {
                long count = 0;
                for (MonthStatisticsQueryVo item : monthStatistics) {
                    List<BatchNumberResult> outTimesList = MonthStatisticsQueryVo.getOutTimesList(item.getOutTimes());
                    if (CollUtil.isNotEmpty(outTimesList)) {
                        count += outTimesList.stream().map(BatchNumberResult::getBatchNumberId).distinct().count();
                    }
                }
                return Math.toIntExact(count);
            }
        };
        final Integer code;
        final String msg;

        DataTypeEnum(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public static DataTypeEnum getDataTypeEnum(Integer code) {

            DataTypeEnum[] values = DataTypeEnum.values();
            for (DataTypeEnum value : values) {
                if (Objects.equals(value.getCode(), code)) {
                    return value;
                }
            }
            return null;
        }

        public abstract Integer getTimes(List<MonthStatisticsQueryVo> monthStatistics);
    }

    /**
     * tab数据类型(1-全部 2-休息 3-迟到 4-早退 5-请假 6-缺卡 7-旷工 8-借调 9-补卡 10-外勤 11-加班 12-出差 13-外出)
     */
    @Getter
    public enum TabDataTypeEnum {
        QB(1, "全部") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return list;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return null;
            }
        },
        XX(2, "休息") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getRestTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return null;
            }
        },
        CD(3, "迟到") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getLateTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return monthStatistics.getLateTimes();
            }
        },
        ZT(4, "早退") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getEarlyLeaveTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return monthStatistics.getEarlyLeaveTimes();
            }
        },
        QJ(5, "请假") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> StringUtil.isNotEmpty(x.getLeaveTimes()))
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return Math.toIntExact(StrUtil.isNotBlank(monthStatistics.getLeaveTimes()) ? Arrays.stream(monthStatistics.getLeaveTimes().split(",")).distinct().count() : 0);
            }
        },
        QK(6, "缺卡") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getAbsenceCardTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return monthStatistics.getAbsenceCardTimes();
            }
        },
        QQ(7, "旷工") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getAbsenceTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return monthStatistics.getAbsenceTimes();
            }
        },
        JD(8, "借调") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getSelfGroupTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return null;
            }
        },
        BK(9, "补卡") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getMakeUpCardTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return monthStatistics.getMakeUpCardTimes();
            }
        },
        WQ(10, "外勤") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getOutworkTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return monthStatistics.getOutworkTimes();
            }
        },
        JB(11, "加班") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> x.getOvertimeTimes() > 0)
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return monthStatistics.getOvertimeTimes();
            }
        },
        CC(12, "出差") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x -> StringUtil.isNotEmpty(x.getBusTimes())).collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                return StrUtil.isNotBlank(monthStatistics.getBusTimes()) ? monthStatistics.getBusTimes().split(",").length : 0;
            }
        },
        WC(13, "外出") {
            @Override
            public List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list) {
                return CollUtil.isNotEmpty(list) ? list.stream().filter(x ->
                                CollUtil.isNotEmpty(MonthStatisticsQueryVo.getOutTimesList(x.getOutTimes())))
                        .collect(Collectors.toList()) : null;
            }

            @Override
            public Integer getTimes(MonthStatisticsQueryVo monthStatistics) {
                List<BatchNumberResult> outTimesList = MonthStatisticsQueryVo.getOutTimesList(monthStatistics.getOutTimes());
                return Math.toIntExact(CollUtil.isNotEmpty(outTimesList) ? outTimesList.stream().map(BatchNumberResult::getBatchNumberId).count() : 0);
            }
        };
        final Integer code;
        final String msg;

        TabDataTypeEnum(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public static TabDataTypeEnum getTabDataTypeEnum(Integer code) {
            TabDataTypeEnum[] values = TabDataTypeEnum.values();
            for (TabDataTypeEnum value : values) {
                if (Objects.equals(value.getCode(), code)) {
                    return value;
                }
            }
            return null;
        }

        public abstract List<MonthStatisticsQueryVo> dataFilter(List<MonthStatisticsQueryVo> list);

        public abstract Integer getTimes(MonthStatisticsQueryVo monthStatistics);
    }

    @Getter
    public enum StatisticsTypeEnum {
        QB(1, "全部"),
        XX(2, "休息"),
        CD(3, "迟到"),
        ZT(4, "早退"),
        QJ(5, "请假"),
        QK(6, "缺卡"),
        KG(7, "旷工"),
        JD(8, "借调"),
        BK(9, "补卡"),
        WQ(10, "外勤"),
        JB(11, "加班"),
        JQ(12, "假期"),
        YCQ(15, "应出勤"),
        SJCQ(19, "实际出勤"),
        CC(19, "出差"),
        WC(20, "外出");


        final Integer code;
        final String msg;

        StatisticsTypeEnum(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    }

    @Getter
    public enum TabStaBlockEnum {
        QB(1, "全部条数", null),
        ZC(2, "正常条数", null),
        CD(3, "迟到条数", "F_LateTimes"),
        ZT(4, "早退条数", "F_EarlyLeaveTimes"),
        WPB(5, "未排班条数", "F_IsScheduling"),
        QK(6, "缺卡条数", "F_AbsenceCardTimes"),
        QQ(7, "旷工条数", "F_AbsenceTimes"),
        QJ(8, "请假条数", "F_LeaveHours"),
        CC(9, "出差条数", "F_BusHours"),
        WC(10, "外出条数", "F_OutHours"),
        JD(11, "借调条数", "F_SelfGroup"),
        JB(12, "加班条数", "F_OvertimeTimes");
        /**
         * 编码
         */
        final Integer code;
        /**
         * 说明
         */
        final String msg;
        /**
         * 字段名
         */
        final String fieldName;

        TabStaBlockEnum(Integer code, String msg, String fieldName) {
            this.code = code;
            this.msg = msg;
            this.fieldName = fieldName;
        }

        public static TabStaBlockEnum getTabDataTypeEnum(Integer code) {

            TabStaBlockEnum[] values = TabStaBlockEnum.values();
            for (TabStaBlockEnum value : values) {
                if (Objects.equals(value.getCode(), code)) {
                    return value;
                }
            }
            return null;
        }
    }

    @Getter
    public enum TabStaBlockMonthEnum {
        QB(1, "全部条数", null),
        ZC(2, "正常条数", "F_NormalCount"),
        CD(3, "迟到条数", "F_LateTimes"),
        ZT(4, "早退条数", "F_EarlyLeaveTimes"),
        WPB(5, "未排班条数", "F_IsSchedulingCount"),
        QK(6, "缺卡条数", "F_AbsenceCardTimes"),
        QQ(7, "旷工条数", "F_AbsenceTimes"),
        QJ(8, "请假条数", "F_LeaveTimes"),
        CC(9, "出差条数", "F_BusTimes"),
        WC(10, "外出条数", "F_OutTimes"),
        JD(11, "借调条数", "F_SelfGroupTimes"),
        JB(12, "加班条数", "F_OvertimeTimes");
        /**
         * 编码
         */
        final Integer code;
        /**
         * 说明
         */
        final String msg;
        /**
         * 字段名
         */
        final String fieldName;

        TabStaBlockMonthEnum(Integer code, String msg, String fieldName) {
            this.code = code;
            this.msg = msg;
            this.fieldName = fieldName;
        }

        public static TabStaBlockMonthEnum getTabDataTypeEnum(Integer code) {

            TabStaBlockMonthEnum[] values = TabStaBlockMonthEnum.values();
            for (TabStaBlockMonthEnum value : values) {
                if (Objects.equals(value.getCode(), code)) {
                    return value;
                }
            }
            return null;
        }
    }

    @Getter
    public enum WorkStatusEnum {
        QB("0", "全部"),
        YRZ("301", "预入职"),
        SY("302", "试用"),
        ZS("303", "正式"),
        DLZ("304", "待离职"),
        LZ("305", "离职");
        /**
         * 编码
         */
        final String code;
        /**
         * 说明
         */
        final String msg;

        WorkStatusEnum(String code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public static WorkStatusEnum getWorkStatusEnum(String code) {
            WorkStatusEnum[] values = WorkStatusEnum.values();
            for (WorkStatusEnum value : values) {
                if (value.getCode().equals(code)) {
                    return value;
                }
            }
            return null;
        }
    }

    @Getter
    public enum ConstantStatusEnum {
        NUM_FALSE(0, "否"),
        NUM_TRUE(1, "是");
        final Integer code;
        final String message;

        ConstantStatusEnum(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    }

    @Getter
    public enum SettlementTypeEnum {
        DAY(1, "日统计"),
        MONTH(2, "月统计"),
        TEAM_MONTH(3, "团队统计");
        final Integer code;
        final String msg;

        SettlementTypeEnum(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    }

    @Getter
    public enum DailySituationEnum {
        ZC(1, "正常天数"),
        CD(2, "迟到天数"),
        ZT(3, "早退天数"),
        WPB(4, "未排班天数"),
        QK(5, "缺卡天数"),
        QQ(6, "旷工天数"),
        QJ(7, "请假天数"),
        CC(8, "出差天数"),
        WC(9, "外出天数"),
        JD(10, "借调天数"),
        JB(11, "加班天数");
        /**
         * 编码
         */
        final Integer code;
        /**
         * 说明
         */
        final String msg;

        DailySituationEnum(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public static DailySituationEnum getDailySituationEnum(Integer code) {
            DailySituationEnum[] values = DailySituationEnum.values();
            for (DailySituationEnum value : values) {
                if (Objects.equals(value.getCode(), code)) {
                    return value;
                }
            }
            return null;
        }
    }

    @Getter
    public enum AttendanceConfirmStatusEnum {
        WCK(0, "未查看"),
        YCK_WQR(1, "已查看未确认"),
        YQR(2, "已确认"),
        YYQ(2, "已逾期"),
        YQ_YQR(2, "逾期已确认");
        final Integer code;
        final String msg;

        AttendanceConfirmStatusEnum(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    }

    @Getter
    public enum AttendanceClockEnum {
        DAY_STATISTICS("%s-%s-%s-%s", "生成日统计唯一key");
        final String key;
        final String msg;

        AttendanceClockEnum(String key, String msg) {
            this.key = key;
            this.msg = msg;
        }
    }
}
