package com.foreverwin.mesnac.common.helper;

import cn.hutool.core.util.StrUtil;
import com.foreverwin.mesnac.common.constant.CustomFieldConstant;
import com.foreverwin.mesnac.common.model.NextNumber;
import com.foreverwin.mesnac.common.model.NextNumberCode;
import com.foreverwin.mesnac.common.service.NextNumberCodeService;
import com.foreverwin.mesnac.common.service.NextNumberService;
import com.foreverwin.mesnac.common.util.DateUtil;
import com.foreverwin.mesnac.common.util.StringUtil;
import com.foreverwin.modular.core.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;

@Component
public class NextNumberHelper {

    @Autowired
    NextNumberService nextNumberService;
    @Autowired
    NextNumberCodeService nextNumberCodeService;

    static public final String KW_YY = "{YY}";

    static public final String KW_YYYY = "{YYYY}";

    static public final String KW_MM = "{MM}";

    static public final String KW_DD = "{DD}";

    static public final String KW_HH = "{HH}";

    static public final String KW_YY_MM_DD = "{YYMMDD}";

    static public final String KW_YYYY_MM_DD = "{YYYYMMDD}";


    public List<String> getNextNumber(String site, String numberType, int qty) {
        return this.getNextNumber(site, numberType, qty, null);
    }

    public List<String> getNextNumber(String site, String numberType, int qty, Map paramMap) {
        if (qty <= 0) throw BusinessException.build("common.nextNumber.qty.error", null);
        //-------------------------------------------------------------------------------------------------------------------------------------
        NextNumber nextNumber = nextNumberService.selectOne(site, numberType);
        if (nextNumber == null) throw BusinessException.build("common.nextNumber.type.error", numberType);
        //-------------------------------------------------------------------------------------------------------------------------------------
        String prefix = nextNumber.getPrefix() != null ? StrUtil.toString(nextNumber.getPrefix()) : "";
        String code = preparePrefix(prefix);
        //-------------------------------------------------------------------------------------------------------------------------------------
        String postfix = nextNumber.getPostfix() != null ? StrUtil.toString(nextNumber.getPostfix()) : "";
        postfix = preparePrefix(postfix);
        String sequenceLength = StrUtil.toString(nextNumber.getSequenceLength());
        //-------------------------------------------------------------------------------------------------------------------------------------
        //判断是否传入自定义字段
        if (paramMap != null) {
            //postfix 替换自定义字段
            postfix = preparePrefix(postfix, paramMap);
            //code增加自定义字段
            code = preparePrefix(code, paramMap);
        }//if
        //-------------------------------------------------------------------------------------------------------------------------------------
        int currentMaxSequence = 0;
        if (StringUtil.toBoolean(nextNumber.getSkipNumber())) {
            currentMaxSequence = nextNumberCodeService.getCodeSequenceByIsolatedTransaction(site, qty, code, nextNumber);
        } else {
            currentMaxSequence = nextNumberCodeService.getCodeSequence(site, qty, code, nextNumber);
        }//if
        //-------------------------------------------------------------------------------------------------------------------------------------
        //生成编号结果集
        List<String> numberList = new ArrayList();
        for (int i = 1; i <= qty; i++) {
            String lastNumber = "";
            int seq = currentMaxSequence + i;
            lastNumber = code + space(seq, Integer.parseInt(sequenceLength)) + postfix;
            numberList.add(lastNumber);
        }//for
        //-------------------------------------------------------------------------------------------------------------------------------------
        return numberList;
    }

    private String preparePrefix(String prefix, Map paramMap) {
        Iterator<Map.Entry<String, String>> iterator = paramMap.entrySet().iterator();
        //-------------------------------------------------------------------------------------------------------------------------------------
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            String key = entry.getKey();
            String value = entry.getValue();
            prefix = replace(prefix, "{" + key + "}", value);
        }//while
        //-------------------------------------------------------------------------------------------------------------------------------------
        return prefix;
    }

    private String preparePrefix(String prefix) {
        String temp = "";
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Timestamp(System.currentTimeMillis()));
        //-------------------------------------------------------------------------------------------------------------------------------------
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DATE);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        temp = space(year, 4);
        prefix = replace(prefix, KW_YYYY, temp);
        temp = space(year % 100, 2);
        prefix = replace(prefix, KW_YY, temp);
        temp = space(month, 2);
        prefix = replace(prefix, KW_MM, temp);
        temp = space(day, 2);
        prefix = replace(prefix, KW_DD, temp);
        temp = space(hour, 2);
        prefix = replace(prefix, KW_HH, temp);
        //-------------------------------------------------------------------------------------------------------------------------------------
        temp =  space(year % 100, 2) +space(month, 2)+space(day, 2);
        prefix = replace(prefix, KW_YY_MM_DD, temp);
        temp =  space(year, 4)+space(month, 2)+space(day, 2);
        prefix = replace(prefix, KW_YYYY_MM_DD, temp);
        //-------------------------------------------------------------------------------------------------------------------------------------
        return prefix;
    }

    public String space(String value, int slotcnt) {
        return space(value, '0', slotcnt);
    }

    public String space(int value, int slotcnt) {
        return space(value + "", '0', slotcnt);
    }

    public String space(String str, char spacer, int slotcnt) {
        if (slotcnt <= 0) return "";
        if (str.length() >= slotcnt) return str;
        //-------------------------------------------------------------------------------------------------------------------------------------
        StringBuffer str_buf = new StringBuffer();
        slotcnt = slotcnt - str.length();
        for (int i = 0; i < slotcnt; i++) {
            str_buf.append(spacer);
        }
        //-------------------------------------------------------------------------------------------------------------------------------------
        str_buf.append(str);
        //-------------------------------------------------------------------------------------------------------------------------------------
        return str_buf.toString();
    }

    public String replace(String str, String replaced, String replacement) {
        if (str == null)  return null;
        if (str.equals(""))  return "";
        //-------------------------------------------------------------------------------------------------------------------------------------
        StringBuilder str_buf = new StringBuilder();
        int start = 0, i = 0;
        i = str.indexOf(replaced, start);
        while (i >= 0) {
            str_buf.append(str.substring(start, i));
            str_buf.append(replacement);
            start = i + replaced.length();
            i = str.indexOf(replaced, start);
        }//while
        //-------------------------------------------------------------------------------------------------------------------------------------
        if (start < str.length()) str_buf.append(str.substring(start));
        //-------------------------------------------------------------------------------------------------------------------------------------
        return str_buf.toString();
    }

    public static boolean isReset(NextNumberCode nextNumberCode, String reset)
    {
        if (nextNumberCode == null) return false;
        if (reset.equalsIgnoreCase("N")) return false;
        //-------------------------------------------------------------------------------------------------------------------------------------
        LocalDateTime modifyDate = nextNumberCode.getModifiedDateTime();
        if (reset.equalsIgnoreCase("Y")) {
            if (DateUtil.lessEqual(DateUtil.getDateByYear(DateUtil.getBeginDateByDay(DateUtil.toDate(modifyDate)), 1))) return true;
        } else if(reset.equalsIgnoreCase("M")) {
            if (DateUtil.lessEqual(DateUtil.getDateByMonth(DateUtil.getBeginDateByDay(DateUtil.toDate(modifyDate)), 1))) return true;
        } else if(reset.equalsIgnoreCase("D")) {
            if (DateUtil.lessEqual(DateUtil.getDateByDay(DateUtil.getBeginDateByDay(DateUtil.toDate(modifyDate)), 1))) return true;
        }//if
        //-------------------------------------------------------------------------------------------------------------------------------------
        return false;
    }
}
