package com.chinaweal.aiccs.aiccs.inspect.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chinaweal.aiccs.aiccs.abnormal.entity.Gzaiccode;
import com.chinaweal.aiccs.aiccs.abnormal.service.IGzaiccodeService;
import com.chinaweal.aiccs.aiccs.inspect.entity.TSWorkNo;
import com.chinaweal.aiccs.aiccs.inspect.mapper.TSWorkNoMapper;
import com.chinaweal.aiccs.aiccs.inspect.service.TSWorkNoService;
import com.chinaweal.aiccs.common.constant.Constant;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.common.util.WorkNoUtil;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.BaseServiceImpl;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 系统当前已使用监管文书流水号 服务实现类
 * </p>
 *
 * @author <a href="https://blog.lroyia.top">lroyia</a>
 * @since 2021-01-25
 */
@Service
public class TSWorkNoServiceImpl extends BaseServiceImpl<TSWorkNoMapper, TSWorkNo> implements TSWorkNoService {

    @Resource
    @Lazy
    private IGzaiccodeService iGzaiccodeService;

    @Override
    @Transactional(propagation=Propagation.NOT_SUPPORTED)
    public synchronized String getOperatingWrirsno(String workNoType, String aicID) {
        if (StringUtils.isBlank(workNoType) || StringUtils.isBlank(aicID)) return null;
        Calendar a = Calendar.getInstance();
        TSWorkNo paramModel = new TSWorkNo();
        Map<String, String> map = Constant.NM_REGION_CODE_SHORTNAME;
        String shortName = map.get(aicID.substring(0, 4) + "00");
//        String shortName = "穗";
//        for (String code : map.keySet()) {
//            if (code.equals(aicID) && !map.get(code).equals("穗")) {
//                shortName += map.get(code);
//                break;
//            }
//        }
        paramModel.setAicid(aicID.length() > 6 ? aicID.substring(0, 6) : aicID);
        paramModel.setWorkNoType(workNoType);
        String genRule = "";
        TSWorkNo tsWorkNoModels = baseMapper.selectTSWorkNoListByTypeComment(paramModel);
        String uuid = UUID.randomUUID().toString();
        if (tsWorkNoModels == null) {
            TSWorkNo workNo1 = new TSWorkNo();
            workNo1.setWorkNoType(workNoType);
            TSWorkNo tsWorkNoModelDB = baseMapper.selectTSWorkNoListByTypeComment(workNo1);
            TSWorkNo workNo = new TSWorkNo();
            workNo.setWorknoid(uuid);
            workNo.setAicid(aicID);
            workNo.setCurrentNo(1);
            workNo.setYears(LocalDate.now().getYear());
            workNo.setWorkNoType(workNoType);
            workNo.setGenrule(tsWorkNoModelDB== null ? WorkNoUtil.getWorkNoGenrule(workNoType)
                    : tsWorkNoModelDB.getGenrule());
            workNo.setTypecomment(tsWorkNoModelDB== null ? WorkNoUtil.getWorkNoTypeName(workNoType)
                    : tsWorkNoModelDB.getTypecomment());
            workNo.setAreaCode(aicID.length() > 6 ? aicID.substring(0, 6) : aicID);
            workNo.setLauptime(LocalDateTime.now());
            int insert = baseMapper.insert(workNo);
            if (insert == 1) {
                tsWorkNoModels = workNo;
            }
        }
        //TODO 年份更新
        genRule = tsWorkNoModels.getGenrule();

        int currentNo = tsWorkNoModels.getCurrentNo();
        //{ShortName}监检字[{year}年]第{CurrentNo}号
        genRule = genRule.replaceAll("\\u007BShortName\\u007D", shortName);
        genRule = genRule.replaceAll("\\u007BshortName\\u007D", shortName);
        genRule = genRule.replaceAll("\\u007Byear\\u007D", String.valueOf(a.get(Calendar.YEAR)));
        genRule = genRule.replaceAll("\\u007BCurrentNo\\u007D", beforeZeroFill(currentNo, 4));// 填充4位
        genRule = genRule.replaceAll("\\u007BcurrentNo\\u007D", beforeZeroFill(currentNo, 4));// 填充4位

        paramModel.setCurrentNo(currentNo + 1);//文号下移
        baseMapper.updateTSWorkNoByTypeComment(paramModel);
        return genRule;
    }

    @Override
    @Transactional(propagation=Propagation.NOT_SUPPORTED)
    public synchronized List<String> getOperatingWrirsnoBatch(String workNoType, String aicID, int number) {
        List<String> wrisnoList = new ArrayList<>();
        if (StringUtils.isBlank(workNoType) || StringUtils.isBlank(aicID)) return null;
        Calendar a = Calendar.getInstance();
        TSWorkNo paramModel = new TSWorkNo();
        Map<String, String> map = Constant.NM_REGION_CODE_SHORTNAME;
        String shortName = "蒙";
        for (String code : map.keySet()) {
            if (code.equals(aicID) && !map.get(code).equals("蒙")) {
                shortName += map.get(code);
                break;
            }
        }
        paramModel.setAicid(aicID.length() > 6 ? aicID.substring(0, 6) : aicID);
        paramModel.setWorkNoType(workNoType);
        String genRule = "";
        TSWorkNo tsWorkNoModels = baseMapper.selectTSWorkNoListByTypeComment(paramModel);
        String uuid = UUID.randomUUID().toString();
        if (tsWorkNoModels == null) {
            TSWorkNo workNo1 = new TSWorkNo();
            workNo1.setWorkNoType(workNoType);
            TSWorkNo tsWorkNoModelDB = baseMapper.selectTSWorkNoListByTypeComment(workNo1);
            TSWorkNo workNo = new TSWorkNo();
            workNo.setWorknoid(uuid);
            workNo.setAicid(aicID);
            workNo.setCurrentNo(1);
            workNo.setYears(LocalDate.now().getYear());
            workNo.setWorkNoType(workNoType);
            workNo.setGenrule(tsWorkNoModelDB.getGenrule());
            workNo.setTypecomment(tsWorkNoModelDB.getTypecomment());
            workNo.setAreaCode(aicID.length() > 6 ? aicID.substring(0, 6) : aicID);
            workNo.setLauptime(LocalDateTime.now());
            int insert = baseMapper.insert(workNo);
            if (insert == 1) {
                tsWorkNoModels = workNo;
            }
        }
        //TODO 年份更新
        genRule = tsWorkNoModels.getGenrule();

        int currentNo = tsWorkNoModels.getCurrentNo();
        //{ShortName}监检字[{year}年]第{CurrentNo}号
        for (int i=0; i<number; i++) {
            String genRuleParam = genRule;
            genRuleParam = genRuleParam.replaceAll("\\u007BShortName\\u007D", shortName);
            genRuleParam = genRuleParam.replaceAll("\\u007Byear\\u007D", String.valueOf(a.get(Calendar.YEAR)));
            genRuleParam = genRuleParam.replaceAll("\\u007BCurrentNo\\u007D", beforeZeroFill(currentNo, 4));// 填充4位
            wrisnoList.add(genRuleParam);
            currentNo ++;
        }

        paramModel.setCurrentNo(currentNo);//文号下移
        baseMapper.updateTSWorkNoByTypeComment(paramModel);
        return wrisnoList;
    }

    @Override
    public synchronized Map<String, Object> getBatchWrirsno(String workNoType, String aicID, int num) {
        if (StringUtils.isBlank(workNoType) || StringUtils.isBlank(aicID)) return null;
        HashMap<String, Object> resultMap = new HashMap<>();
        Calendar a = Calendar.getInstance();
        TSWorkNo paramModel = new TSWorkNo();

        String shortName;
        String littleID = aicID.length() > 6 ? aicID.substring(0, 6) : aicID;

        Map<String, String> map = Constant.NM_REGION_CODE_SHORTNAME;
        shortName = "蒙";
        for (String code : map.keySet()) {
            if (code.equals(aicID) && !map.get(code).equals("蒙")) {
                shortName += map.get(code);
                break;
            }
        }
        paramModel.setAicid(aicID.length() > 6 ? aicID.substring(0, 6) : aicID);
        paramModel.setWorkNoType(workNoType);
        String genRule = "";
        TSWorkNo tsWorkNoModels = baseMapper.selectTSWorkNoListByTypeComment(paramModel);
        String uuid = UUID.randomUUID().toString();
        if (tsWorkNoModels == null) {
            TSWorkNo workNo1 = new TSWorkNo();
            workNo1.setWorkNoType(workNoType);
            workNo1.setAicid("150000");
            TSWorkNo tsWorkNoModelDB = baseMapper.selectTSWorkNoListByTypeComment(workNo1);
            TSWorkNo workNo = new TSWorkNo();
            workNo.setWorknoid(uuid);
            workNo.setAicid(aicID);
            workNo.setCurrentNo(1);
            workNo.setYears(LocalDate.now().getYear());
            workNo.setWorkNoType(workNoType);
            workNo.setGenrule(tsWorkNoModelDB.getGenrule());
            workNo.setTypecomment(tsWorkNoModelDB.getTypecomment());
            workNo.setAreaCode(aicID.length() > 6 ? aicID.substring(0, 6) : aicID);
            workNo.setLauptime(LocalDateTime.now());
            int insert = baseMapper.insert(workNo);
            if (insert == 1) {
                tsWorkNoModels = workNo;
            }
        }
        genRule = tsWorkNoModels.getGenrule();
//        String shortName = tsWorkNoModels.getShortname();
        // 流水号填充的位数
//        int zeroFill = 4;// 其他类型填充4位
//        if(WorkNoUtil.WORKNOTYPE_32.equals(workNoType) || WorkNoUtil.WORKNOTYPE_33.equals(workNoType)){
//            zeroFill = 5;// 批吊通知书，批吊行政处罚决定书 5位
//        }


        int currentNo = tsWorkNoModels.getCurrentNo();
        resultMap.put("currentNo", currentNo);
        genRule = genRule.replaceAll("\\u007BShortName\\u007D", shortName);
        genRule = genRule.replaceAll("\\u007Byear\\u007D", String.valueOf(a.get(Calendar.YEAR)));
        genRule = genRule.replaceAll("\\u007BCurrentNo\\u007D", beforeZeroFill(currentNo, 5));
        resultMap.put("genRule", genRule);
        paramModel.setCurrentNo(currentNo + num);//文号下移
        baseMapper.updateTSWorkNoByTypeComment(paramModel);
        return resultMap;
    }

    @Override
    public String getOperatingWrirsNoCourrentNo(String workNoType, String aicID) {
        if (StringUtils.isBlank(workNoType) || StringUtils.isBlank(aicID)) return null;

        Calendar a = Calendar.getInstance();
        TSWorkNo paramModel = new TSWorkNo();
        paramModel.setAicid(aicID);
        paramModel.setWorkNoType(workNoType);
        String genRule = ""; // 粤监检字[2018]年第10号
        TSWorkNo tsWorkNoModels = baseMapper.selectTSWorkNoListByTypeComment(paramModel);
        genRule = tsWorkNoModels.getGenrule();
        String shortName = tsWorkNoModels.getShortname();
        int CourrentNo = tsWorkNoModels.getCurrentNo();
        //{ShortName}监检字[{year}年]第{CurrentNo}号
        genRule = genRule.replaceAll("\\u007BShortName\\u007D", shortName);
        genRule = genRule.replaceAll("\\u007Byear\\u007D", String.valueOf(a.get(Calendar.YEAR)));
        genRule = genRule.replaceAll("\\u007BCurrentNo\\u007D", String.valueOf(CourrentNo));

        return genRule;
    }

    @Override
    public String updateWritsNo(String writsNo, int num) {
        if (StringUtils.isEmpty(writsNo)) return null;
        // 例：穗市监处字[2021]00059号
        String result = writsNo.substring(0, writsNo.length() - 6);
        result = result + beforeZeroFill(num, 5) + "号";
        return result;
    }

    @Override
    public synchronized String generateSeriousIncludeDocNo(String decorg) {
        String docNo;
        //获取当前年份
        int year = LocalDate.now().getYear();
        //获取简称
        String shortname = byOrgCodeShortname(decorg);
        //获取序列号
        LambdaQueryWrapper<TSWorkNo> lqw = Wrappers.lambdaQuery();
        lqw.eq(TSWorkNo::getShortname, shortname)
                .eq(TSWorkNo::getYears, year)
                .eq(TSWorkNo::getWorkNoType, WorkNoUtil.WORKNOTYPE_21)
                .eq(TSWorkNo::getAreaCode, decorg);
        TSWorkNo tsWorkNo = getOne(lqw);
        if (tsWorkNo == null) {
            tsWorkNo = new TSWorkNo();
            //不存在，则新建初始化
            tsWorkNo.setYears(year);
            tsWorkNo.setShortname(shortname);
            tsWorkNo.setAreaCode(decorg);
            tsWorkNo.setTypecomment("列入严重违法失信企业名单决定书文号");
            tsWorkNo.setGenrule("{shortName}市监列严字[{year}]{currentNo}号");
            tsWorkNo.setWorkNoType(WorkNoUtil.WORKNOTYPE_21);
            tsWorkNo.setLauptime(LocalDateTime.now());
            tsWorkNo.setCurrentNo(1);
            save(tsWorkNo);

        } else {
            //存在累加
            tsWorkNo.setCurrentNo(tsWorkNo.getCurrentNo() + 1);
            updateById(tsWorkNo);
        }
        Integer currentNo = tsWorkNo.getCurrentNo();

        docNo = tsWorkNo.getGenrule().replace("{shortName}", shortname)
                .replace("{year}", year + "")
                .replace("{currentNo}", String.format("%04d", currentNo));

        return docNo;
    }

    @Override
    public String forIllOperatingBnNo(String decorg) {
        String docNo;
        int year = LocalDate.now().getYear();
        Map<String, String> map = Constant.NM_REGION_CODE_SHORTNAME;
        String shortname = "蒙";
        for (String code : map.keySet()) {
            if (code.equals(decorg) && !map.get(code).equals("蒙")) {
                shortname += map.get(code);
                break;
            }
        }
        LambdaQueryWrapper<TSWorkNo> lqw = Wrappers.lambdaQuery();
        lqw.eq(TSWorkNo::getShortname, shortname)
                .eq(TSWorkNo::getYears, year)
                .eq(TSWorkNo::getWorkNoType, WorkNoUtil.WORKNOTYPE_20)
                .eq(TSWorkNo::getAreaCode, decorg);
        TSWorkNo tsWorkNo = getOne(lqw);
        if (tsWorkNo == null) {
            tsWorkNo = new TSWorkNo();
            tsWorkNo.setYears(year);
            tsWorkNo.setShortname(shortname);
            tsWorkNo.setAreaCode(decorg);
            tsWorkNo.setTypecomment("拟列入严重违法失信企业名单决定书文号");
            tsWorkNo.setGenrule("{shortName}市监提列严字[{year}]{currentNo}号");
            tsWorkNo.setWorkNoType(WorkNoUtil.WORKNOTYPE_20);
            tsWorkNo.setLauptime(LocalDateTime.now());
            tsWorkNo.setCurrentNo(1);
            save(tsWorkNo);
        } else {
            tsWorkNo.setCurrentNo(tsWorkNo.getCurrentNo() + 1);
            updateById(tsWorkNo);
        }
        Integer currentNo = tsWorkNo.getCurrentNo();
        docNo = tsWorkNo.getGenrule().replace("{shortName}", shortname)
                .replace("{year}", year + "")
                .replace("{currentNo}", String.format("%04d", currentNo));

        return docNo;
    }

    @Override
    public String getWriteNo(String workNoType, String aicID, String currentNo) {
        if (StringUtils.isBlank(workNoType) || StringUtils.isBlank(aicID)) return null;
        Calendar a = Calendar.getInstance();
        TSWorkNo paramModel = new TSWorkNo();
        Map<String, String> map = Constant.NM_REGION_CODE_SHORTNAME;
        String shortName = "蒙";
        for (String code : map.keySet()) {
            if (code.equals(aicID) && !map.get(code).equals("蒙")) {
                shortName += map.get(code);
                break;
            }
        }
        paramModel.setAicid(aicID.length() > 6 ? aicID.substring(0, 6) : aicID);
        paramModel.setWorkNoType(workNoType);
        String genRule = "{ShortName}市监列异[{year}]第{CurrentNo}号";


        //{ShortName}监检字[{year}年]第{CurrentNo}号
        genRule = genRule.replaceAll("\\u007BShortName\\u007D", shortName);
        genRule = genRule.replaceAll("\\u007Byear\\u007D", String.valueOf(a.get(Calendar.YEAR)));
        genRule = genRule.replaceAll("\\u007BCurrentNo\\u007D", beforeZeroFill(currentNo, 4));// 填充4位

        return genRule;
    }

    @Override
    public TSWorkNo selectTSWorkNoListByTypeComment(TSWorkNo tsWorkNoModel) {
        return baseMapper.selectTSWorkNoListByTypeComment(tsWorkNoModel);
    }

    /**
     * @param number 需要填充0的数字
     * @param length 需要多少位
     * @return
     */
    private String beforeZeroFill(int number, int length) {
        return beforeZeroFill(String.valueOf(number), length);
    }

    private String beforeZeroFill(String number, int length) {
        String tmp = number;
        for (int i = 0; i < length - number.length(); i++) {
            tmp = "0" + tmp;
        }
        return tmp;
    }

    public String byOrgCodeShortname(String orgCode) {
        LambdaQueryWrapper<Gzaiccode> lqw = Wrappers.lambdaQuery();
        lqw.eq(Gzaiccode::getScountrycode, orgCode);
        Gzaiccode gzaiccode = iGzaiccodeService.getOne(lqw);
        if (gzaiccode == null) {
            return "蒙";
        } else {
            return gzaiccode.getShortname();
        }
        // 不再维护gzaiccode表
//        Map<String, String> map = Constant.NM_REGION_CODE_SHORTNAME;
//        String shortName = "穗";
//        for (String code : map.keySet()) {
//            if (code.equals(orgCode) && !map.get(code).equals("穗")) {
//                shortName += map.get(code);
//                break;
//            }
//        }
//        return shortName;
    }

    @Override
    public String getWritsNoCurrency(String workNoType, String decorg) {
        String docNo;
        int year = LocalDate.now().getYear();
        Map<String, String> map = Constant.NM_REGION_CODE_SHORTNAME;
        String shortname = "蒙";
        for (String code : map.keySet()) {
            if (code.equals(decorg) && !map.get(code).equals("蒙")) {
                shortname += map.get(code);
                break;
            }
        }
        LambdaQueryWrapper<TSWorkNo> lqw = Wrappers.lambdaQuery();
        lqw.eq(TSWorkNo::getShortname, shortname)
                .eq(TSWorkNo::getYears, year)
                .eq(TSWorkNo::getWorkNoType, workNoType)
                .eq(TSWorkNo::getAreaCode, decorg);
        TSWorkNo tsWorkNo = getOne(lqw);
        if (tsWorkNo == null) {
            tsWorkNo = new TSWorkNo();
            tsWorkNo.setYears(year);
            tsWorkNo.setShortname(shortname);
            tsWorkNo.setAreaCode(decorg);
            tsWorkNo.setTypecomment(WorkNoUtil.getWorkNoTypeName(workNoType));
            tsWorkNo.setGenrule(WorkNoUtil.getWorkNoGenrule(workNoType));
            tsWorkNo.setWorkNoType(workNoType);
            tsWorkNo.setLauptime(LocalDateTime.now());
            tsWorkNo.setCurrentNo(1);
            save(tsWorkNo);
        } else {
            tsWorkNo.setCurrentNo(tsWorkNo.getCurrentNo() + 1);
            updateById(tsWorkNo);
        }
        Integer currentNo = tsWorkNo.getCurrentNo();
        docNo = tsWorkNo.getGenrule().replace("{shortName}", shortname)
                .replace("{year}", year + "")
                .replace("{currentNo}", String.format("%04d", currentNo));
        return docNo;
    }

    // 通用方法generateDocNo
    @Override
    public String generateDocNo(String writsType, String areaCode) {
        String docNo;
        //获取当前年份
        int year = LocalDate.now().getYear();
        //获取简称
        String shortname = "蒙";
        LambdaQueryWrapper<Gzaiccode> gzaiccodeLambdaQueryWrapper = Wrappers.lambdaQuery();
        gzaiccodeLambdaQueryWrapper.eq(Gzaiccode::getScountrycode, areaCode);
        Gzaiccode gzaiccode = iGzaiccodeService.getOne(gzaiccodeLambdaQueryWrapper);
        if (gzaiccode != null) {
            return gzaiccode.getShortname();
        }
        //获取序列号
        LambdaQueryWrapper<TSWorkNo> lqw = Wrappers.lambdaQuery();
        lqw.eq(TSWorkNo::getYears, year)
                .eq(TSWorkNo::getWorkNoType, writsType)
                .eq(TSWorkNo::getAreaCode, areaCode);
        TSWorkNo xrWorkNo = getOne(lqw);
        String typeComment = WorkNoUtil.getWorkNoTypeName(writsType) + "文号";
        String genRule = WorkNoUtil.getWorkNoGenrule(writsType);

        xrWorkNo = getXrWorkNo(writsType, areaCode, year, shortname, xrWorkNo, typeComment, genRule);
        Integer currentNo = xrWorkNo.getCurrentNo();
        docNo = getDocNo(year, shortname, xrWorkNo, currentNo);
        return docNo;
    }

    // 通用方法getXrWorkNo
    private TSWorkNo getXrWorkNo(String writsType, String areaCode, int year, String shortname, TSWorkNo xrWorkNo, String typeComment, String genRule) {
        if (xrWorkNo == null) {
            xrWorkNo = new TSWorkNo();
            //不存在，则新建初始化
            xrWorkNo.setYears(year);
            xrWorkNo.setShortname(shortname);
            xrWorkNo.setAreaCode(areaCode);
            xrWorkNo.setTypecomment(typeComment);
            xrWorkNo.setGenrule(genRule);
            xrWorkNo.setWorkNoType(writsType);
            xrWorkNo.setCurrentNo(1);
            save(xrWorkNo);
        } else {
            //存在累加
            xrWorkNo.setCurrentNo(xrWorkNo.getCurrentNo() + 1);
            updateById(xrWorkNo);
        }
        return xrWorkNo;
    }

    // 通用方法getDocNo
    private static String getDocNo(int year, String shortname, TSWorkNo xrWorkNo, Integer currentNo) {
        String docNo;
        docNo = xrWorkNo.getGenrule().replace("{shortName}", shortname)
                .replace("{year}", String.valueOf(year))
                .replace("{currentNo}", String.format("%06d", currentNo));
        return docNo;
    }

}
