package com.foreverwin.mesnac.common.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.foreverwin.mesnac.common.enums.HandleEnum;
import com.foreverwin.mesnac.common.helper.NextNumberHelper;
import com.foreverwin.mesnac.common.mapper.NextNumberCodeMapper;
import com.foreverwin.mesnac.common.model.NextNumber;
import com.foreverwin.mesnac.common.model.NextNumberCode;
import com.foreverwin.mesnac.common.service.NextNumberCodeService;
import com.foreverwin.modular.core.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 编号生成 服务实现类
 * </p>
 *
 * @author Roc Li
 * @since 2020-09-03
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class NextNumberCodeServiceImpl extends ServiceImpl<NextNumberCodeMapper, NextNumberCode> implements NextNumberCodeService {
    @Autowired
    private NextNumberCodeMapper nextNumberCodeMapper;

    @Override
    public NextNumberCode selectForUpdateById(String id) {
        return nextNumberCodeMapper.selectForUpdateById(id);
    }

    @Override
    public NextNumberCode selectOne(String code, String nextNumberBo) {
        LambdaQueryWrapper<NextNumberCode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NextNumberCode::getCode, code);
        queryWrapper.eq(NextNumberCode::getNextNumberBo, nextNumberBo);
        //---------------------------------------------------------------------------------------------------------------------------------------------
        List<NextNumberCode> resultList = super.list(queryWrapper);
        //---------------------------------------------------------------------------------------------------------------------------------------------
        return  resultList != null && resultList.size() > 0 ? resultList.get(0) : null;
    }

    @Override
    public Long getMaxCurrentSeq(String nextNumberBo) {
        return nextNumberCodeMapper.getMaxCurrentSeq(nextNumberBo);
    }

    @Override
    public boolean updateCurrentSeqByNextNumber(BigDecimal currentSeq, String nextNumberBo) {
        NextNumberCode entity = new NextNumberCode();
        entity.setCurrentSeq(currentSeq);
        entity.setModifiedDateTime(LocalDateTime.now());
        //---------------------------------------------------------------------------------------------------------------------------------------------
        LambdaQueryWrapper<NextNumberCode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NextNumberCode::getNextNumberBo, nextNumberBo);
        //---------------------------------------------------------------------------------------------------------------------------------------------
        return super.update(entity, queryWrapper);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Integer getCodeSequenceByIsolatedTransaction(String site, int qty, String code, NextNumber nextNumber) {
        return getCodeSequence(site, qty, code, nextNumber);
    }

    @Override
    public Integer getCodeSequence(String site, int qty, String code, NextNumber nextNumber) {
        //查询编号是否存在
        String currentSeq;
        String sequenceLength = StrUtil.toString(nextNumber.getSequenceLength());
        String handle = HandleEnum.NEXT_NUMBER_CODE.getHandle(site, nextNumber.getNumberType(), code);
        NextNumberCode nextNumberCode = selectForUpdateById(handle);
        //计算当前序列号：编号不存在时，当前序列等于生成编号的个数,否则等于查询的序列号+生成编号个数
        if (nextNumberCode == null) {
            if (nextNumber.getStartSequence() == null) {
                currentSeq = qty + "";
            } else {
                currentSeq = (nextNumber.getStartSequence().intValue() -1 + qty) + "";
            }
        } else {
            String reset = StrUtil.toString(nextNumber.getRepetition());
            boolean isReset = NextNumberHelper.isReset(nextNumberCode, reset);
            if (isReset) {
                if (nextNumber.getStartSequence() == null) {
                    currentSeq = qty + "";
                } else {
                    currentSeq = (nextNumber.getStartSequence().intValue() -1 + qty) + "";
                }
            } else {
                currentSeq = (nextNumberCode.getCurrentSeq().longValue() + qty) + "";
            }
        }//if
        //-------------------------------------------------------------------------------------------------------------------------------------
        //流水号检测最大值
        String temp = "";
        for (long i = 0; i < Long.parseLong(sequenceLength); i++) {
            temp = "9" + temp;
        }
        temp = (temp == null || temp.equals("") ? "0" : temp);
        if (Long.parseLong(temp) < Long.parseLong(currentSeq)) throw BusinessException.build("common.nextNumber.maxLimited.error", nextNumber.getNumberType());
        //-------------------------------------------------------------------------------------------------------------------------------------
        String _currentSeq;
        if (nextNumberCode == null) {
            //新增
            if (nextNumber.getStartSequence() == null) {
                _currentSeq = "0";
            } else {
                _currentSeq = (nextNumber.getStartSequence().intValue()-1) + "";
            }//if
            //-------------------------------------------------------------------------------------------------------------------------------------
            NextNumberCode entity = new NextNumberCode();
            entity.setHandle(handle);
            entity.setSite(site);
            entity.setNextNumberBo(nextNumber.getHandle());
            entity.setCode(code);
            entity.setCurrentSeq(new BigDecimal(currentSeq));
            entity.setModifiedDateTime(LocalDateTime.now());
            //-------------------------------------------------------------------------------------------------------------------------------------
            save(entity);
        } else {
            //修改
            String reset = StrUtil.toString(nextNumber.getRepetition());
            boolean isReset = NextNumberHelper.isReset(nextNumberCode, reset);
            if (isReset) {
                if (nextNumber.getStartSequence() == null) {
                    _currentSeq = "0";
                } else {
                    _currentSeq = (nextNumber.getStartSequence().intValue()-1) + "";
                }
            } else {
                _currentSeq = nextNumberCode.getCurrentSeq().longValue() + "";
            }
            nextNumberCode.setCurrentSeq(new BigDecimal(currentSeq));
            nextNumberCode.setModifiedDateTime(LocalDateTime.now());
            //-------------------------------------------------------------------------------------------------------------------------------------
            updateById(nextNumberCode);
        }//if
        //-------------------------------------------------------------------------------------------------------------------------------------
        return Integer.parseInt(_currentSeq);
    }
}