package com.sw.mes.yb.seed.utils;

import com.sw.mes.base.factory.init.entity.FactoryModel;
import com.sw.mes.base.factory.init.service.FactoryModelService;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.redis.server.RedisUtils;
import com.sw.mes.yb.seed.entity.SeedData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.validation.constraints.NotNull;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 籽晶编号生成器
 *
 * @Author：wanjia
 * @Date：2024/1/9 14:38
 */
@Service
public class SeedCodeGenerator {

    private static final Logger logger = LoggerFactory.getLogger(SeedCodeGenerator.class);
    private final FactoryModelService factoryModelService;

    private final RedisUtils redisUtils;

    private static final String[] CHARACTER = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
            "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

    private static final String REDIS_KEY = "seed-code-flow";
    private static final String BATCH_NO_KEY = "seed-batch-no";

    public SeedCodeGenerator(FactoryModelService factoryModelService, RedisUtils redisUtils) {
        this.factoryModelService = factoryModelService;
        this.redisUtils = redisUtils;
    }


    /**
     * 籽晶晶编生成规则：
     * 1 基地，从工厂模型取，T:太原
     * 2 掺杂 U/N
     * 3 年
     * 4 月
     * 5-6 日期 01-31
     * 7 车间 从工厂模型取 1234车间
     * 8-10 流水号 001-999
     *
     * @return
     * @throws BusinessException 上层需要catch住
     */
    public String generator(@NotNull SeedData seed) throws BusinessException {
        StringBuilder sb = new StringBuilder();
        //查询工厂模型
        FactoryModel factoryModel = factoryModelService.findByCode(seed.getWorkShopCode());
        if (null == factoryModel) {
            logger.error("GET Factory model null code is {}", seed.getSeedCode());
            throw new BusinessException("缺少工厂模型数据");
        }
        //找到车间部门
        FactoryModel department = factoryModelService.findByChildIdAndTypeKey(factoryModel.getId(), "2");
        //1、第一位基地
        sb.append("T");
        //2、第二位掺杂
        sb.append(seed.getDopant());
        //3、年
        sb.append(buildYear());
        //4 构建月
        sb.append(buildMonth());
        // 5-6 构建日期
        sb.append(buildDay());
        // 7 构建车间
        sb.append(buildWorkshop(department));
        // 8-10 构建流水号
        sb.append(buildFlowNo());
        //最后check一下数据
        String result = sb.toString();
        if (result.length() != 10) {
            logger.error("error in check code length， the code is {}", result);
            throw new BusinessException("生成籽晶编号出错！！！ code:" + result);
        }
        return result;
    }

    /**
     * 籽晶批次号生成规则：
     * 1 基地，从工厂模型取，T:太原
     * 2 掺杂 U/N
     * 3 年
     * 4 月
     * 5-6 日期 01-31
     * 7 车间 从工厂模型取 1234车间
     * 8-10 流水号 001-999
     *
     * @return
     * @throws BusinessException 上层需要catch住
     */
    public String batchNoGenerator(@NotNull SeedData seed) throws BusinessException {
        StringBuilder sb = new StringBuilder();
        //查询工厂模型
        FactoryModel factoryModel = factoryModelService.findByCode(seed.getWorkShopCode());
        if (null == factoryModel) {
            logger.error("GET Factory model null code is {}", seed.getSeedCode());
            throw new BusinessException("缺少工厂模型数据");
        }
        //找到车间部门
        FactoryModel department = factoryModelService.findByChildIdAndTypeKey(factoryModel.getId(), "2");
        //1、第一位基地
        sb.append("T");
        //2、第二位掺杂
        sb.append(seed.getDopant());
        //3、年
        sb.append(buildYear());
        //4 构建月
        sb.append(buildMonth());
        // 5-6 构建日期
        sb.append(buildDay());
        // 7 构建车间
        sb.append(buildWorkshop(department));
        // 8-10 构建流水号
        sb.append(buildBatchNo());
        //最后check一下数据
        String result = sb.toString();
        if (result.length() != 10) {
            logger.error("error in check code length， the code is {}", result);
            throw new BusinessException("生成籽晶批次号出错！！！ code:" + result);
        }
        return result;
    }

    /**
     * 流水号，001-999 按天维度滚动
     * <p>
     * 实现逻辑，通过redis做一个锁，key为年月日，value为流水号
     * 跟产品确认过
     *
     * @return
     */
    private String buildFlowNo() {
        Long value = redisUtils.increment(REDIS_KEY);
        if (value < 10) {
            return "00" + value;
        } else if (value < 100) {
            return "0" + value;
        }
        return String.valueOf(value);
    }
    /**
     * 流水号，001-999 按天维度滚动
     * <p>
     * 实现逻辑，通过redis做一个锁，key为年月日，value为流水号
     * 跟产品确认过
     *
     * @return
     */
    private String buildBatchNo() {
        Long value = redisUtils.increment(BATCH_NO_KEY);
        if (value < 10) {
            return "00" + value;
        } else if (value < 100) {
            return "0" + value;
        }
        return String.valueOf(value);
    }


    /**
     * 构建车间信息,需要找到车间级别的数据
     *
     * @param factoryModel
     * @return
     */
    private String buildWorkshop(FactoryModel factoryModel) {
        if(!ObjectUtils.isEmpty(factoryModel)){
            return factoryModel.getCode().substring(
                    factoryModel.getCode().length()-1,factoryModel.getCode().length());
        }
       return  null;
    }

    /**
     * 构建日期
     *
     * @return
     */
    private String buildDay() {
        Calendar calendar = Calendar.getInstance();
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        if (day <= 9) {
            return "0" + day;
        }
        return String.valueOf(day);
    }

    /**
     * 构建月
     * 规则：
     * 1、1-9月返回数字
     * 2、10月A 11月B 12月C
     *
     * @return
     */
    private String buildMonth() {
        Calendar calendar = Calendar.getInstance();
        int month = calendar.get(Calendar.MONTH) + 1;//jdk里面取到的值会-1，所以外面需要加1
        if (month <= 9) {
            return String.valueOf(month);
        }
        if (month == 10) {
            return "A";
        } else if (month == 11) {
            return "B";
        } else if (month == 12) {
            return "C";
        }
        return "";
    }

    /**
     * 构建年的值
     * <p>
     * 规则：2023年取3，到2029年位置取9
     * 2030年开始用A,之后用字母循环使用
     *
     * @return
     */
    private String buildYear() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        String yyyy = format.format(new Date());
        int year = Integer.parseInt(yyyy);
        //如果时间小于2029年，则取尾数
        if (year <= 2029) {
            return yyyy.substring(3);
        }
        int mod = year - 2030;
        if (mod < 26) { //如果第一轮内
            return CHARACTER[mod];
        } else {
            return CHARACTER[mod % 26];
        }
    }
}
