package com.shkj.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.shkj.common.annotation.DataScopeConsignor;
import com.shkj.common.core.domain.Result;
import com.shkj.common.enums.IsDelEnum;
import com.shkj.common.utils.SecurityUtils;
import com.shkj.wms.domain.SysSeqMana;
import com.shkj.wms.mapper.SysSeqManaMapper;
import com.shkj.wms.service.ISysSeqManaService;
import com.shkj.wms.bo.SysSeqManaAddBo;
import com.shkj.wms.bo.SysSeqManaEditBo;
import com.shkj.wms.bo.SysSeqManaQueryBo;
import com.shkj.wms.enums.NumberPreEnum;
import com.shkj.wms.vo.SysSeqManaVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * 号码管理Service业务层处理
 *
 * @author lch
 * @date 2022-04-11
 */
@Slf4j
@Service
public class SysSeqManaServiceImpl extends ServiceImpl<SysSeqManaMapper, SysSeqMana> implements ISysSeqManaService {

    /**
     * 时间格式
     */
    private final static String[] arrDate = {"yyyy", "yyyyMM", "yyyyMMdd"};

    @Override
    public Result<SysSeqManaVo> queryById(Long id) {
        SysSeqMana db = this.baseMapper.selectById(id);
        SysSeqManaVo vo = BeanUtil.toBean(db, SysSeqManaVo.class);
        return Result.ok().data(vo);
    }

    @Override
    @DataScopeConsignor(branchAlias = "s")
    public List<SysSeqManaVo> queryList(SysSeqManaQueryBo bo) {
//        LambdaQueryWrapper<SysSeqMana> lqw = Wrappers.lambdaQuery();
//        lqw.like(StrUtil.isNotBlank(bo.getSeqName()), SysSeqMana::getSeqName, bo.getSeqName());
//        lqw.eq(StrUtil.isNotBlank(bo.getSeqType()), SysSeqMana::getSeqType, bo.getSeqType());
//        lqw.eq(StrUtil.isNotBlank(bo.getSeqCode()), SysSeqMana::getSeqCode, bo.getSeqCode());
//        lqw.eq(StrUtil.isNotBlank(bo.getSeqPrefix()), SysSeqMana::getSeqPrefix, bo.getSeqPrefix());
//        lqw.eq(StrUtil.isNotBlank(bo.getSeqDigit()), SysSeqMana::getSeqDigit, bo.getSeqDigit());
//        lqw.eq(StrUtil.isNotBlank(bo.getSeqDate()), SysSeqMana::getSeqDate, bo.getSeqDate());
//        lqw.eq(bo.getSeqIncrease() != null, SysSeqMana::getSeqIncrease, bo.getSeqIncrease());
//        lqw.eq(bo.getSeqMax() != null, SysSeqMana::getSeqMax, bo.getSeqMax());
//        lqw.eq(bo.getSeqCurrent() != null, SysSeqMana::getSeqCurrent, bo.getSeqCurrent());
//        lqw.eq(SysSeqMana::getBranchId, SecurityUtils.getCurrentBranchId());
//        lqw.eq(SysSeqMana::getIsDel, IsDelEnum.NORMAL.getValue());
//        lqw.orderByDesc(SysSeqMana::getCreateTime);

        return this.baseMapper.queryList(bo);

//        List<SysSeqManaVo> voList = entity2Vo(this.list(lqw));
//        return voList;

    }

    /**
     * 实体类转化成视图对象
     *
     * @param collection 实体类集合
     * @return
     */
    private List<SysSeqManaVo> entity2Vo(Collection<SysSeqMana> collection) {
        List<SysSeqManaVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, SysSeqManaVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<SysSeqMana> page = (Page<SysSeqMana>) collection;
            Page<SysSeqManaVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page, pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        return voList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Boolean> insertByAddBo(SysSeqManaAddBo bo) {
        SysSeqMana add = BeanUtil.toBean(bo, SysSeqMana.class);
        add.setBranchId(SecurityUtils.getCurrentBranchId());
        Result result = checkSeq(add);
        if (!Result.isOk(result)) {
            return Result.err().msg(result.getMsg());
        }
        this.save(add);
        return Result.ok();
    }

    /**
     * 校验数据
     *
     * @param entity
     * @return
     */
    private Result checkSeq(SysSeqMana entity) {
        String seqDate = entity.getSeqDate();
//        if (!Arrays.asList(arrDate).contains(seqDate)) {
//            return Result.err().msg("序列号日期格式不正确");
//        }

        Long id = entity.getId() != null ? entity.getId() : -1L;
        LambdaQueryWrapper<SysSeqMana> wrapper = new LambdaQueryWrapper<SysSeqMana>()
                .eq(SysSeqMana::getBranchId, entity.getBranchId())
                .eq(SysSeqMana::getSeqType, entity.getSeqType())
                .eq(SysSeqMana::getSeqCode, entity.getSeqCode())
                .eq(SysSeqMana::getIsDel, IsDelEnum.NORMAL.getValue());
        SysSeqMana one = getOne(wrapper);
        if (one != null && !id.equals(one.getId())) {
            return Result.err().msg("已存在号码生成规则");
        }
        return Result.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Boolean> updateByEditBo(SysSeqManaEditBo bo) {
        SysSeqMana one = getById(bo.getId());
        if (one == null) {
            return Result.err().msg("不存在");
        }
        SysSeqMana update = BeanUtil.toBean(bo, SysSeqMana.class);
        update.setBranchId(SecurityUtils.getCurrentBranchId());
        Result result = checkSeq(update);
        if (!Result.isOk(result)) {
            return Result.err().msg(result.getMsg());
        }

        this.updateById(update);
        return Result.ok();
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Boolean> deleteWithValidById(List<Long> ids, Boolean isValid) {
        SysSeqMana del = new SysSeqMana();
        del.setIsDel(IsDelEnum.DELETED.getValue());
        LambdaQueryWrapper<SysSeqMana> wrapper = new LambdaQueryWrapper<SysSeqMana>().in(SysSeqMana::getId, ids)
                .eq(SysSeqMana::getBranchId, SecurityUtils.getCurrentBranchId());
        this.update(del, wrapper);
        return Result.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<String> generatorCode(String seqCode, String seqType, Long branchId) {
        Lock lock = new ReentrantLock();
        String number;
        try {
            boolean b = lock.tryLock(5, TimeUnit.SECONDS);
            if (!b) {
                return Result.err().msg("号码正常生成中请重试");
            }
            LambdaQueryWrapper<SysSeqMana> wrapper = new LambdaQueryWrapper<SysSeqMana>().eq(SysSeqMana::getBranchId, branchId)
                    .eq(SysSeqMana::getSeqType, seqType)
                    .eq(SysSeqMana::getSeqCode, seqCode)
                    .eq(SysSeqMana::getIsDel, IsDelEnum.NORMAL.getValue());
            SysSeqMana one = this.getOne(wrapper);
            if (one == null) {
                NumberPreEnum preEnum = NumberPreEnum.getNumberPreEnum(seqCode);
                return Result.err().msg((preEnum != null ? preEnum.getDesc() : "") + "没有号码生成规则");
            }

            String no = calcIncrementNo(one);
            SimpleDateFormat sdf = new SimpleDateFormat(one.getSeqDate());
            //产生的code由于仓库不同、生成的code可能会重复、所以加上当前仓库id
            number = one.getSeqPrefix() + SecurityUtils.getCurrentBranchId() + sdf.format(new Date()) + no;
            //更新
            one.setSeqCurrent(Long.parseLong(no));
            this.updateById(one);
        } catch (Exception e) {
            log.error("e  = {}", e);
            return Result.err().msg("号码正常生成中请重试");
        } finally {
            lock.unlock();
        }
        return Result.ok().data(number);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> saveOrUpdateSeqMana(List<SysSeqManaEditBo> bo) {
        List<SysSeqMana> addList = new ArrayList<>();
        List<SysSeqMana> updList = new ArrayList<>();
        for (SysSeqManaEditBo manaEditBo : bo) {
            if (manaEditBo.getId() != null) {
                SysSeqMana one = getById(manaEditBo.getId());
                if (one == null) {
                    return Result.err().msg("不存在");
                }
                SysSeqMana update = BeanUtil.toBean(manaEditBo, SysSeqMana.class);
                update.setBranchId(one.getBranchId());
                Result result = checkSeq(update);
                if (!Result.isOk(result)) {
                    return Result.err().msg(result.getMsg());
                }
                updList.add(update);
            } else {
                SysSeqMana add = BeanUtil.toBean(manaEditBo, SysSeqMana.class);
                add.setBranchId(SecurityUtils.getCurrentBranchId());
                Result result = checkSeq(add);
                if (!Result.isOk(result)) {
                    return Result.err().msg(result.getMsg());
                }
                addList.add(add);
            }
        }

        this.updateBatchById(updList);
        this.saveBatch(addList);
        return Result.ok();
    }


    /**
     * 计算号位数
     *
     * @param sysSeqMana
     * @return
     */
    private String calcIncrementNo(SysSeqMana sysSeqMana) {
        // 1逻辑编号 2流水号
        Long calcNo = 1L;
        //序列号编码+日期格式+流水号位数（当前流水号+序列号增量，位数为序列号位数，位数不足前面补0）
        Long current = sysSeqMana.getSeqCurrent() == null ? 0L : sysSeqMana.getSeqCurrent();
        Long tempNo = sysSeqMana.getSeqIncrease() + current;
        if (tempNo <= sysSeqMana.getSeqMax()) {
            calcNo = tempNo;
        }
        String format = String.valueOf(calcNo);
        double length = 10D;
        if (calcNo < Math.pow(length, sysSeqMana.getSeqDigit() - 1)) {
            //前面补0
            format = String.format("%0" + sysSeqMana.getSeqDigit() + "d", calcNo);
        }
        return format;
    }
}
