package com.yunzhupaas.base.service.impl;


import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yunzhupaas.base.model.billrule.BillRulePagination;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.Pagination;
import com.yunzhupaas.base.entity.BillRuleEntity;
import com.yunzhupaas.base.mapper.BillRuleMapper;
import com.yunzhupaas.base.service.BillRuleService;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 单据规则
 *
 * @author 云筑产品开发平台组
 * @version V3.1.0
 * @copyright 深圳市乐程软件有限公司
 * @date 2023/09/27
 */
@Service
public class BillRuleServiceImpl extends SuperServiceImpl<BillRuleMapper, BillRuleEntity> implements BillRuleService {

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<BillRuleEntity> getList(BillRulePagination pagination) {
        // 定义变量判断是否需要使用修改时间倒序
        boolean flag = false;
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        if (!StringUtil.isEmpty(pagination.getKeyword())) {
            flag = true;
            queryWrapper.lambda().and(
                    t -> t.like(BillRuleEntity::getFullName, pagination.getKeyword())
                            .or().like(BillRuleEntity::getEnCode, pagination.getKeyword())
            );
        }
        if (!StringUtil.isEmpty(pagination.getCategoryId())) {
            flag = true;
            queryWrapper.lambda().and(
                    t -> t.like(BillRuleEntity::getCategory, pagination.getCategoryId())
            );
        }
        if (pagination.getEnabledMark() != null) {
            flag = true;
            queryWrapper.lambda().eq(BillRuleEntity::getEnabledMark, pagination.getEnabledMark());
        }
        // 排序
        queryWrapper.lambda().orderByAsc(BillRuleEntity::getSortCode).orderByDesc(BillRuleEntity::getCreatorTime);
        if (flag) {
            queryWrapper.lambda().orderByDesc(BillRuleEntity::getLastModifyTime);
        }
        Page<BillRuleEntity> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
        IPage<BillRuleEntity> userPage = this.page(page, queryWrapper);
        return pagination.setData(userPage.getRecords(), page.getTotal());
    }

    @Override
    public List<BillRuleEntity> getList() {
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BillRuleEntity::getEnabledMark, 1);
        // 排序
        queryWrapper.lambda().orderByAsc(BillRuleEntity::getSortCode).orderByDesc(BillRuleEntity::getCreatorTime);
        return this.list(queryWrapper);
    }

    @Override
    public BillRuleEntity getInfo(String id) {
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BillRuleEntity::getId, id);
        return this.getOne(queryWrapper);
    }

    @Override
    public boolean isExistByFullName(String fullName, String id) {
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BillRuleEntity::getFullName, fullName);
        if (!StringUtil.isEmpty(id)) {
            queryWrapper.lambda().ne(BillRuleEntity::getId, id);
        }
        return this.count(queryWrapper) > 0 ? true : false;
    }

    @Override
    public boolean isExistByEnCode(String enCode, String id) {
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BillRuleEntity::getEnCode, enCode);
        if (!StringUtil.isEmpty(id)) {
            queryWrapper.lambda().ne(BillRuleEntity::getId, id);
        }
        return this.count(queryWrapper) > 0 ? true : false;
    }

    @Override
    @DSTransactional
    public String getNumber(String enCode) throws DataException {
        StringBuilder strNumber = new StringBuilder();
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BillRuleEntity::getEnCode, enCode);
        BillRuleEntity entity = this.getOne(queryWrapper);
        if (entity != null) {
            Integer startNumber = StringUtil.isEmpty(entity.getStartNumber()) ? 0 : Integer.parseInt(entity.getStartNumber());
            //拼接单据编码
            strNumber.append(StringUtil.isNotEmpty(entity.getPrefix()) ? entity.getPrefix() : "");
            if (ObjectUtil.equal(entity.getType(), 2)) {
                // 随机数编号
                if (ObjectUtil.equal(entity.getRandomType(), 1)) {
                    strNumber.append(cn.hutool.core.util.RandomUtil.randomNumbers(entity.getRandomDigit()));
                } else {
                    strNumber.append(cn.hutool.core.util.RandomUtil.randomStringUpper(entity.getRandomDigit()));
                }
            } else if (ObjectUtil.equal(entity.getType(), 3)) {
                // UUID
                strNumber.append(IdUtil.randomUUID().toUpperCase());
            } else {
                // 时间格式
                String dateFor = entity.getDateFormat();
                String dateForValue = "no";
                switch (dateFor) {
                    case "YYYY":
                        dateForValue = "yyyy";
                        break;
                    case "YYYYMM":
                        dateForValue = "yyyyMM";
                        break;
                    case "YYYYMMDD":
                        dateForValue = "yyyyMMdd";
                        break;
                    case "YYYYMMDDHH":
                        dateForValue = "yyyyMMddHH";
                        break;
                    case "YYYYMMDDHHmm":
                        dateForValue = "yyyyMMddHHmm";
                        break;
                    case "YYYYMMDDHHmmss":
                        dateForValue = "yyyyMMddHHmmss";
                        break;
                    case "YYYYMMDDHHmmssSSS":
                        dateForValue = "yyyyMMddHHmmssSSS";
                        break;
                }
                //处理隔天流水号归0
                if (entity.getOutputNumber() != null) {
                    String serialDate = "";
                    entity.setThisNumber(entity.getThisNumber() + 1);
                    if (!"no".equals(dateForValue)) {
                        String thisDate = DateUtil.dateNow(dateForValue);
                        int suffixLength = entity.getSuffix() != null ? entity.getSuffix().length() : 0;
                        try{
                            serialDate= entity.getOutputNumber().substring((entity.getOutputNumber().length() - dateForValue.length() - entity.getDigit() - suffixLength), (entity.getOutputNumber().length() - entity.getDigit() - suffixLength));
                        }catch (Exception e){
                        }
                        if (!serialDate.equals(thisDate)) {
                            entity.setThisNumber(0);
                        }
                    }
                } else {
                    entity.setThisNumber(0);
                }
                if (!"no".equals(dateForValue)) {
                    strNumber.append(DateUtil.dateNow(dateForValue));
                }
                strNumber.append(PadUtil.padRight(String.valueOf(startNumber + entity.getThisNumber()), entity.getDigit(), '0'));
            }
            strNumber.append(StringUtil.isNotEmpty(entity.getSuffix()) ? entity.getSuffix() : "");
            //更新流水号
            entity.setOutputNumber(strNumber.toString());
            this.updateById(entity);
        } else {
            throw new DataException("单据规则不存在");
        }
        return strNumber.toString();
    }

    @Override
    public void create(BillRuleEntity entity) {
        entity.setId(RandomUtil.uuId());
        entity.setCreatorUserId(UserProvider.getUser().getUserId());
        this.save(entity);
    }

    @Override
    public boolean update(String id, BillRuleEntity entity) {
        entity.setId(id);
        entity.setLastModifyTime(new Date());
        entity.setLastModifyUserId(UserProvider.getUser().getUserId());
        return this.updateById(entity);
    }

    @Override
    public void delete(BillRuleEntity entity) {
        this.removeById(entity.getId());
    }

    @Override
    @DSTransactional
    public boolean first(String id) {
        boolean isOk = false;
        //获取要上移的那条数据的信息
        BillRuleEntity upEntity = this.getById(id);
        Long upSortCode = upEntity.getSortCode() == null ? 0 : upEntity.getSortCode();
        //查询上几条记录
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .lt(BillRuleEntity::getSortCode, upSortCode)
                .orderByDesc(BillRuleEntity::getSortCode);
        List<BillRuleEntity> downEntity = this.list(queryWrapper);
        if (downEntity.size() > 0) {
            //交换两条记录的sort值
            Long temp = upEntity.getSortCode();
            upEntity.setSortCode(downEntity.get(0).getSortCode());
            downEntity.get(0).setSortCode(temp);
            this.updateById(downEntity.get(0));
            this.updateById(upEntity);
            isOk = true;
        }
        return isOk;
    }

    @Override
    @DSTransactional
    public boolean next(String id) {
        boolean isOk = false;
        //获取要下移的那条数据的信息
        BillRuleEntity downEntity = this.getById(id);
        Long upSortCode = downEntity.getSortCode() == null ? 0 : downEntity.getSortCode();
        //查询下几条记录
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .gt(BillRuleEntity::getSortCode, upSortCode)
                .orderByAsc(BillRuleEntity::getSortCode);
        List<BillRuleEntity> upEntity = this.list(queryWrapper);
        if (upEntity.size() > 0) {
            //交换两条记录的sort值
            Long temp = downEntity.getSortCode();
            downEntity.setSortCode(upEntity.get(0).getSortCode());
            upEntity.get(0).setSortCode(temp);
            this.updateById(upEntity.get(0));
            this.updateById(downEntity);
            isOk = true;
        }
        return isOk;
    }

    @Override
    public String getBillNumber(String enCode, boolean isCache) throws DataException {
        String strNumber;
        String tenantId = !StringUtil.isEmpty(UserProvider.getUser().getTenantId()) ? UserProvider.getUser().getTenantId() : "";
        if (isCache) {
            String cacheKey = tenantId + UserProvider.getUser().getUserId() + enCode;
            if (!redisUtil.exists(cacheKey)) {
                strNumber = this.getNumber(enCode);
                redisUtil.insert(cacheKey, strNumber);
            } else {
                strNumber = String.valueOf(redisUtil.getString(cacheKey));
            }
        } else {
            strNumber = this.getNumber(enCode);
        }
        return strNumber;
    }

    @Override
    public void useBillNumber(String enCode) {
        String cacheKey = UserProvider.getUser().getTenantId() + UserProvider.getUser().getUserId() + enCode;
        redisUtil.remove(cacheKey);
    }

    @Override
    @Transactional
    public ActionResult ImportData(BillRuleEntity entity, Integer type) throws DataException {
        if (entity != null) {
            StringJoiner stringJoiner = new StringJoiner("、");
            QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(BillRuleEntity::getId, entity.getId());
            if (this.count(queryWrapper) > 0) {
                if (Objects.equals(type, 0)) {
                    stringJoiner.add("ID");
                } else {
                    entity.setId(RandomUtil.uuId());
                }
            }
            queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(BillRuleEntity::getEnCode, entity.getEnCode());
            if (this.count(queryWrapper) > 0) {
                stringJoiner.add("编码");
            }
            queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(BillRuleEntity::getFullName, entity.getFullName());
            if (this.count(queryWrapper) > 0) {
                stringJoiner.add("名称");
            }
            if (stringJoiner.length() > 0 && ObjectUtil.equal(type, 1)) {
                String copyNum = UUID.randomUUID().toString().substring(0, 5);
                entity.setFullName(entity.getFullName() + ".副本" + copyNum);
                entity.setEnCode(entity.getEnCode() + copyNum);
            } else if (ObjectUtil.equal(type, 0) && stringJoiner.length() > 0) {
                return ActionResult.fail(stringJoiner.toString() + "重复");
            }
            entity.setCreatorTime(new Date());
            entity.setCreatorUserId(UserProvider.getLoginUserId());
            entity.setLastModifyTime(null);
            entity.setLastModifyUserId(null);
            try {
                this.setIgnoreLogicDelete().removeById(entity);
                entity.setEnabledMark(0);
                entity.setThisNumber(null);
                entity.setOutputNumber(null);
                this.setIgnoreLogicDelete().saveOrUpdate(entity);
            } catch (Exception e) {
                throw new DataException(MsgCode.IMP003.get());
            }finally {
                this.clearIgnoreLogicDelete();
            }
            return ActionResult.success(MsgCode.IMP001.get());
        }
        return ActionResult.fail(MsgCode.IMP004.get());
    }
    @Override
    public List<BillRuleEntity> getListByCategory(String id,Pagination pagination) {
        // 定义变量判断是否需要使用修改时间倒序
        boolean flag = false;
        QueryWrapper<BillRuleEntity> queryWrapper = new QueryWrapper<>();
        if (!StringUtil.isEmpty(pagination.getKeyword())) {
            flag = true;
            queryWrapper.lambda().and(
                    t -> t.like(BillRuleEntity::getFullName, pagination.getKeyword())
                            .or().like(BillRuleEntity::getEnCode, pagination.getKeyword())
            );
        }
        if (!StringUtil.isEmpty(id)) {
            flag = true;
            queryWrapper.lambda().eq(BillRuleEntity::getCategory, id);
        }
        queryWrapper.lambda().eq(BillRuleEntity::getEnabledMark, 1);
        // 排序
        queryWrapper.lambda().orderByAsc(BillRuleEntity::getSortCode).orderByDesc(BillRuleEntity::getCreatorTime);
        if (flag) {
            queryWrapper.lambda().orderByDesc(BillRuleEntity::getLastModifyTime);
        }
        Page<BillRuleEntity> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
        IPage<BillRuleEntity> userPage = this.page(page, queryWrapper);
        return pagination.setData(userPage.getRecords(), page.getTotal());
    }
}

