package org.nl.system.service.coderule.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.nl.common.domain.query.PageQuery;
import org.nl.common.exception.BadRequestException;
import org.nl.common.utils.SecurityUtils;
import org.nl.config.MapOf;
import org.nl.system.service.coderule.ISysCodeRuleService;
import org.nl.system.service.coderule.dao.SysCodeRule;
import org.nl.system.service.coderule.dao.SysCodeRuleDetail;
import org.nl.system.service.coderule.dao.mapper.SysCodeRuleDetailMapper;
import org.nl.system.service.coderule.dao.mapper.SysCodeRuleMapper;
import org.nl.system.service.coderule.utils.CodeRuleTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * 编码规则表 服务实现类
 * </p>
 *
 * @author generator
 * @since 2022-12-19
 */
@Service
public class SysCodeRuleServiceImpl extends ServiceImpl<SysCodeRuleMapper, SysCodeRule> implements ISysCodeRuleService {
    @Autowired
    private SysCodeRuleMapper codeRuleMapper;
    @Autowired
    private SysCodeRuleDetailMapper codeRuleDetailMapper;

    @Override
    public IPage<SysCodeRule> queryAll(Map form, PageQuery pageable) {
        String blurry = ObjectUtil.isNotEmpty(form.get("blurry"))?form.get("blurry").toString():null;
        LambdaQueryWrapper<SysCodeRule> lam = new LambdaQueryWrapper<>();
        lam.like(ObjectUtil.isNotEmpty(blurry), SysCodeRule::getCode, blurry)
                .or(ObjectUtil.isNotEmpty(blurry))
                .like(ObjectUtil.isNotEmpty(blurry), SysCodeRule::getName, blurry);
        IPage<SysCodeRule> page = new Page<>(pageable.getPage() + 1, pageable.getSize());
        codeRuleMapper.selectPage(page, lam);
        page.getRecords().forEach(sysCodeRule -> sysCodeRule.setDemo(codeDemo(MapOf.of("flag", "0", "code", sysCodeRule.getCode()))));
        return page;
    }

    @Override
    public synchronized String codeDemo(Map form) {
        String code = (String) form.get("code");
        String id = codeRuleMapper.selectOne(new LambdaQueryWrapper<SysCodeRule>().eq(SysCodeRule::getCode, code)).getId();
        // 如果flag = 1就执行更新数据库的操作
        String flag = (String) form.get("flag");
        List<SysCodeRuleDetail> ruleDetails = codeRuleDetailMapper.selectList(new LambdaQueryWrapper<SysCodeRuleDetail>().eq(SysCodeRuleDetail::getCode_rule_id, id));
        String demo = "";
        boolean isSame = true;
        for(SysCodeRuleDetail detail : ruleDetails) {
            String value = "";
            String type = detail.getType();
            //固定直接取值
            if (type.equals(CodeRuleTypeEnum.FIXED.getType())) {
                value = detail.getInit_value();
            }
            //日期判断数据库的值与当前值是否相同来决定顺序的值
            if (type.equals(CodeRuleTypeEnum.DATE.getType())) {
                String currentValue = detail.getCurrent_value();
                Date date = DateUtil.date();
                String format = detail.getFormat();
                String nowDate = DateUtil.format(date, format);
                if (!nowDate.equals(currentValue)) {
                    isSame = false;
                }
                if (flag.equals("1")) {
                    detail.setInit_value(nowDate);
                    detail.setCurrent_value(nowDate);
                }
                value = nowDate;
            }
            //顺序的值：如果日期一样就+步长，等于最大值就归为初始值；日期不一样就归为初始值
            if (type.equals(CodeRuleTypeEnum.ORDER.getType())) {
                String numValue = "";
                int step = Integer.parseInt(detail.getStep());
                Long maxValue = Long.valueOf(detail.getMax_value());
                if (!isSame && (Long.valueOf(detail.getCurrent_value()) + step) > maxValue) {
                    numValue = detail.getInit_value();
                } else {
                    numValue = Integer.parseInt(detail.getCurrent_value()) + step + "";
                }
                int size = numValue.length();
                int length = detail.getLength();
                String fillchar = detail.getFillchar();
                for (int m = 0; m < (length - size); m++) {
                    value += fillchar;
                }
                value += numValue;
                if (flag.equals("1")) {
                    if (!isSame) {
                        int initValue = Integer.parseInt(detail.getInit_value());
                        if (StrUtil.isEmpty((initValue + ""))) {
                            throw new BadRequestException("请完善编码数值的初始值！");
                        }
                        detail.setCurrent_value(String.valueOf(initValue));
                    } else {
                        int numCurr = Integer.parseInt(detail.getCurrent_value());
                        if (numCurr >= maxValue) {
                            numCurr = Integer.parseInt(detail.getInit_value());
                            detail.setCurrent_value(String.valueOf(numCurr));
                        }else{
                            detail.setCurrent_value(String.valueOf(numCurr + step));
                        }
                    }
                }
            }
            demo += value;
            if (flag.equals("1")) {
                codeRuleDetailMapper.updateById(detail);
            }
        }
        return demo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(SysCodeRule codeRule) {
        String currentUserId = SecurityUtils.getCurrentUserId();
        String currentUsername = SecurityUtils.getCurrentUsername();
        String now = DateUtil.now();
        List<SysCodeRule> sysCodeRules = codeRuleMapper.selectList(new LambdaQueryWrapper<SysCodeRule>().eq(SysCodeRule::getCode, codeRule.getCode()));
        if (ObjectUtil.isNotEmpty(sysCodeRules)) throw new BadRequestException("编号[" + sysCodeRules.get(0).getCode() + "]已存在");
        codeRule.setId(IdUtil.getSnowflake(1,1).nextIdStr());
        codeRule.setCreate_id(currentUserId);
        codeRule.setCreate_name(currentUsername);
        codeRule.setCreate_time(now);
        codeRule.setUpdate_id(currentUserId);
        codeRule.setUpdate_name(currentUsername);
        codeRule.setUpdate_time(now);
        codeRuleMapper.insert(codeRule);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCodeRule(Set<String> ids) {
        ids.forEach(id -> {
            codeRuleMapper.deleteById(id);
            codeRuleDetailMapper.delete(new LambdaQueryWrapper<SysCodeRuleDetail>().eq(SysCodeRuleDetail::getCode_rule_id, id));
        });
    }

    @Override
    public void updateCodeRule(SysCodeRule codeRule) {
        List<SysCodeRule> sysCodeRules = codeRuleMapper.selectList(new LambdaQueryWrapper<SysCodeRule>()
                .eq(SysCodeRule::getCode, codeRule.getCode())
                .ne(SysCodeRule::getId, codeRule.getId()));
        if (ObjectUtil.isNotEmpty(sysCodeRules)) throw new BadRequestException("该编码code已存在，请校验！");
        String currentUserId = SecurityUtils.getCurrentUserId();
        String currentUsername = SecurityUtils.getCurrentUsername();
        String now = DateUtil.now();
        codeRule.setUpdate_id(currentUserId);
        codeRule.setUpdate_name(currentUsername);
        codeRule.setUpdate_time(now);
        codeRuleMapper.updateById(codeRule);
    }

}
