package com.sw.mes.yb.production.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 org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 回收料生产批次号号生成方法
 *
 * @Author：wanjia
 * @Date：2024/1/9 14:38
 */
@Service
public class RecycledBatchGenerator {

    private static final Logger logger = LoggerFactory.getLogger(RecycledBatchGenerator.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 = "recycled-code-flow";
    private static final String BATCH_NO_KEY = "recycled-batch-no";

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


    /**
     * * 回收料批次号生成规则：基地+定向标识+掺杂剂+年+月+日期+车间+三位流水
     * *       例如: 3代表2023年，以此类推;2030年用A，以此类推，字母用完循环使用
     * *            圆棒月份:1~9用数字，10月用A,11月用B，12月用C
     * * 1 基地，从工厂模型取，T:太原
     * * 2 定向标识 (定向标识位空，  第二位为F,定向标识为非空时，第二位为D)
     * * 3 掺杂 U/N
     * * 4 年
     * * 5 月
     * * 6 车间 从工厂模型取 1234车间
     * * 7-9 流水号 001-999
     *
     * @param directionalSign
     * @param dopant
     * @param workShop
     * @return
     * @throws BusinessException 上层需要catch住
     */

    public String batchNoGenerator(String directionalSign, String dopant, String workShop) throws BusinessException {
        StringBuilder sb = new StringBuilder();

        //1、第一位基地
        sb.append("T");
        //2、第二位定向标识
        if (StringUtils.isBlank(directionalSign) || "非定向".equals(directionalSign)) {
            directionalSign = "F";
        } else {
            directionalSign = "D";
        }
        sb.append(directionalSign);
        //2、第三位位掺杂
        sb.append(dopant);
        //4、年
        sb.append(buildYear());
        //5 构建月
        sb.append(buildMonth());
        // 6-7 构建日期
        sb.append(buildDay());
        // 8 构建车间
        sb.append(workShop);
        // 9-11 构建流水号
        sb.append(buildBatchNo());
        //最后check一下数据
        String result = sb.toString();
        return result;
    }

    /**
     * * 回收料批次号生成规则：基地+定向标识+掺杂剂+年+月+日期+车间+三位流水
     * *       例如: 3代表2023年，以此类推;2030年用A，以此类推，字母用完循环使用
     * *            圆棒月份:1~9用数字，10月用A,11月用B，12月用C
     * * 1 定向标识 (定向标识位空，  第二位为F,定向标识为非空时，第二位为D)
     * * 2 产出部门 (L ：拉制车间 2；Q：切方车间,截断、刀剖；G：硅料车间,硅料车间1,籽晶5；)
     * * 3 定向类别 (瓦克定向:E；OCIM 定向:F ；拉晶车间产出新定向:A，Q切方车间产出新定向：B，硅料车间产出新定向：C
     * 永祥新能源和永祥多晶硅用于供欧定向："H"；内蒙新特用于供欧定向:I（不区分厂家）用于供欧定向：J；非定向不区分类别：0)
     * * 4-5 年 23
     * * 6 月 A(入库日期），10、11、12月用A、B、C
     * * 7-8 日 13
     * * 9 流水号 产出车间：用阿拉伯数字表示（1：1-5拉晶生产车间；2：5-8硅加工车间，硅加工一车间从数字5开始）
     * * 10 流水号 基地代码（四川：1；青海：2  ；新疆：3；上饶：4；玉山：5；金昌：6；鄱阳：7；乐山：8；山西：9
     * @param directionalSign 定向标识
     * @param directionalSignType 定向类别
     * @param workShop 实际产出车间代码
     * @param factoryWorkType (成本中心)
     * @return
     * @throws BusinessException 上层需要catch住
     */

    public String dataBatchNoGenerator(String directionalSign, String directionalSignType, String workShop, String factoryWorkType) throws BusinessException {
        StringBuilder sb = new StringBuilder();
        //1、第一位定向标识
        if (StringUtils.isBlank(directionalSign) || "非定向".equals(directionalSign)) {
            directionalSign = "F";
        } else {
            directionalSign = "D";
        }
        sb.append(directionalSign);
        //2、第二位产出部门
        switch (factoryWorkType) {
            case "1":
            case "5":
                sb.append("G");
                break;
            case "2":
                sb.append("L");
                break;
            case "3":
            case "4":
                sb.append("Q");
                break;
        }
        // 单晶计划工单里的 zorientationind
        //3、第三位定向类别
        sb.append(directionalSignType);
        //4-5、年
        sb.append(buildTowYear());
        //6 构建月
        sb.append(buildMonth());
        // 7-8 构建日期
        sb.append(buildDay());
        // 9 构建车间代码
        sb.append(workShop);
        // 10 构建流水号 山西:固定9
        sb.append("9");
        //最后check一下数据
        String result = sb.toString();
        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];
        }
    }

    /**
     * 构建年的值
     * <p>
     * 规则：2023年取23
     *
     * @return
     */
    private String buildTowYear() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        String yyyy = format.format(new Date());
       return yyyy.substring(2);
    }

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

    /**
     * 生成虚拟单晶余料条码编号
     * 流水号，0001-9999 按天维度滚动
     * <p>
     * 实现逻辑，通过redis做一个锁，key为年月日，value为流水号
     * 跟产品确认过
     *
     * @return
     */
    public String buildVirtuallySurplusBatchNo(String key) {
        StringBuilder sb = new StringBuilder();
        sb.append(key);
        //4、年
        sb.append(buildYear());
        //5 构建月
        sb.append(buildMonth());
        // 6-7 构建日期
        sb.append(buildDay());
        // 8 构建车间

        Long value = redisUtils.increment(sb.toString());
        String valueStr = String.valueOf(value);
        if (value < 10) {
            valueStr = "000" + value;
        } else if (value < 100) {
            valueStr = "00" + value;
        } else if (value < 1000) {
            valueStr = "0" + value;
        }
        String surplusCode = sb + valueStr;
        return surplusCode;
    }

}
