package thyyxxk.webserver.service.settings.SchedulingClass;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.Week;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import thyyxxk.webserver.dao.his.settings.SchedulingClassDao;
import thyyxxk.webserver.entity.dictionary.CodeName;
import thyyxxk.webserver.entity.schedulingClass.data.SchedulingClass;
import thyyxxk.webserver.utils.DateUtil;
import thyyxxk.webserver.utils.SnowFlakeId;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class CreateMonth {
    private DateTime month;
    /**
     * 这个月的第一天
     */
    @Getter
    private DateTime firstDayOfMonth;

    /**
     * 这个月的最后一天
     */
    @Getter
    private DateTime lastDayOfMonth;

    /**
     * 循环的当前日期
     */
    private DateTime currentDay;

    /**
     * 排序列表
     */
    private List<CodeName> sortCode;

    /**
     * dao类
     */
    private static final SchedulingClassDao dao = SpringUtil.getBean(SchedulingClassDao.class);


    /**
     * 返回结果
     */
    private List<SchedulingClass> rst = new ArrayList<>();

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    private static class FindCodeName {
        private int current;
        private String code;
        private String name;
    }

    public CreateMonth(String month, List<CodeName> sortCode) {
        this.month = cn.hutool.core.date.DateUtil.parse(month, "yyyy-MM");
        this.sortCode = sortCode;
        init();
    }

    private void init() {
        // 获取第一个月
        firstDayOfMonth = DateUtil.beginOfMonth(month);
        // 获取最后一个月
        lastDayOfMonth = DateUtil.endOfMonth(month);
        currentDay = firstDayOfMonth;
    }

    private void forEach() {
        while (currentDay.compareTo(lastDayOfMonth) <= 0) {
            int i = currentDay.dayOfWeek();
            // 如果是周一的话就要看周四的了
            if (i == Week.MONDAY.getValue()) {
                rst.add(day(-4));
                // 周五用和流日一起
            } else if (i == Week.FRIDAY.getValue()) {
                // 周六周日排除
                SchedulingClass day = day(-7);
                rst.add(day);
                currentDay = DateUtil.offsetDay(currentDay, 1);
                rst.add(day.cloneData(currentDay));
                currentDay = DateUtil.offsetDay(currentDay, 1);
                rst.add(day.cloneData(currentDay));
            } else if (i == Week.SATURDAY.getValue() || i == Week.SUNDAY.getValue()) {
                continue;
            } else {
                rst.add(day(-1));
            }
            currentDay = DateUtil.offsetDay(currentDay, 1);
        }
    }

    private SchedulingClass day(int offset) {
        DateTime previous = DateUtil.offsetDay(currentDay, offset);
        // 如果在上一个月的话那就去数据库查询
        CodeName codeName = new CodeName();
        if (previous.compareTo(firstDayOfMonth) < 0) {
            codeName = dao.selectByDate(previous);
        } else {
            SchedulingClass byDate = findByDate(previous);
            codeName.setCode(byDate.getCode());
        }
        // 获取到了上一次上班的人然后，获取排序的人
        FindCodeName byCode = findByCode(codeName.getCode());
        int nextIndex = byCode.getCurrent() + 1;
        if (nextIndex >= sortCode.size()) {
            nextIndex = 0;
        }
        CodeName nextCodeName = sortCode.get(nextIndex);
        SchedulingClass vo = new SchedulingClass();

        vo.setCode(nextCodeName.getCode());
        vo.setId(SnowFlakeId.instance().nextId());
        vo.setSchedulingDate(currentDay);
        return vo;
    }

    private SchedulingClass findByDate(DateTime date) {
        for (SchedulingClass item : rst) {
            if (item.getSchedulingDate().compareTo(date) == 0) {
                return item;
            }
        }
        SchedulingClass vo = new SchedulingClass();
        CodeName codeName = sortCode.get(0);
        vo.setCode(codeName.getCode());
        return vo;
    }


    private FindCodeName findByCode(String code) {
        for (int i = 0; i < sortCode.size(); i++) {
            CodeName item = sortCode.get(i);
            if (item.getCode().equals(code)) {
                return new FindCodeName(i, item.getCode(), item.getName());
            }
        }
        CodeName codeName = sortCode.get(0);
        return new FindCodeName(-1, codeName.getCode(), codeName.getName());
    }


    public List<SchedulingClass> computed() {
        forEach();
        log.info("数据：{}", JSONObject.toJSONStringWithDateFormat(rst, "yyyy-MM-dd"));
        return rst;
    }


}
