package com.fjhx.service.bom.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.BaseEntity;
import com.fjhx.constants.IotManagementLockConstant;
import com.fjhx.constants.ErrorMsgConstant;
import com.fjhx.constants.StatusConstant;
import com.fjhx.entity.FileInfo;
import com.fjhx.entity.bom.Bom;
import com.fjhx.enums.bom.BomTypeEnum;
import com.fjhx.mapper.bom.BomMapper;
import com.fjhx.params.bom.BomEx;
import com.fjhx.params.bom.BomVo;
import com.fjhx.service.bom.BomService;
import com.fjhx.utils.Assert;
import com.fjhx.utils.FileClientUtil;
import com.fjhx.utils.UserClientUtil;
import com.fjhx.utils.WrapperUtil;
import lombok.RequiredArgsConstructor;
import org.springblade.core.redis.lock.RedisLockClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * bom 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-07-01
 */
@Service
@RequiredArgsConstructor
public class BomServiceImpl extends ServiceImpl<BomMapper, Bom> implements BomService {

    private final RedisLockClient redisLockClient;

    @Override
    public Page<BomEx> getPage(Map<String, String> condition) {

        QueryWrapper<?> wrapper = WrapperUtil.init(condition)
                .eq("p.classify_id", "classifyId") // 分类查询
                .keyword("p.name", "p.code") // 关键字查询
                .eqTenantId("b") // 租户id
                .notDelete("b", "p") // 未删除
                .getWrapper();

        wrapper.eq("b.type", BomTypeEnum.PRODUCT_TYPE.getCode()); // 产品bom
        wrapper.eq("b.current_edition", StatusConstant.YES); // 当前版本
        wrapper.orderByAsc("p.code"); // 产品编码排序

        Page<BomEx> result = baseMapper.getPage(createPage(condition), wrapper);
        List<BomEx> records = result.getRecords();

        // 赋值最后修改人
        Map<Long, String> userNameMap = UserClientUtil.getUserNameMap(records, Bom::getUpdateUser);

        // 文件信息
        Map<Long, FileInfo> fileInfoMap = FileClientUtil.getFileInfoMap(
                records.stream().map(BaseEntity::getId).collect(Collectors.toList()));

        records.forEach(item -> {
            item.setUpdateUserName(userNameMap.get(item.getUpdateUser()));
            item.setFileInfo(fileInfoMap.get(item.getId()));
        });

        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(BomVo bomVo) {

        Long productId = bomVo.getProductId();
        Assert.notEmpty(productId, "产品id不能为空");
        Assert.notEmpty(bomVo.getEdition(), "版本号不能为空");

        // 保证每个租户物料编码唯一
        Boolean flag = redisLockClient.lockFair(IotManagementLockConstant.BOM_EDITION_LOCK + productId,
                () -> {
                    Long count = count(Bom::getProductId, productId);
                    bomVo.setCurrentEdition(count == 0 ? StatusConstant.YES : StatusConstant.NO);
                    save(bomVo);
                    return true;
                });

        Assert.eqTrue(flag, ErrorMsgConstant.SYSTEM_BUSY_ERROR);

        // 绑定文件
        FileClientUtil.bindingFile(bomVo.getId(), bomVo.getFileInfo());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(BomVo bomVo) {

        Long productId = bomVo.getProductId();

        Integer currentEdition = bomVo.getCurrentEdition();

        Assert.notEmpty(currentEdition, "是否启用版本不能为空");

        if (StatusConstant.YES.equals(currentEdition)) {
            // 保证每个租户物料编码唯一
            Boolean flag = redisLockClient.lockFair(IotManagementLockConstant.BOM_EDITION_LOCK + productId,
                    () -> {
                        update(Wrappers.<Bom>lambdaUpdate().set(Bom::getCurrentEdition, StatusConstant.NO).eq(Bom::getProductId, productId));
                        updateById(bomVo);
                        return true;
                    });
            Assert.eqTrue(flag, ErrorMsgConstant.SYSTEM_BUSY_ERROR);
        }

        // 重新绑定
        FileClientUtil.againBindingFile(bomVo.getId(), bomVo.getFileInfo());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(BomVo bomVo) {
        removeById(bomVo.getId());
        FileClientUtil.relieveBindingFile(bomVo.getId());
    }

    @Override
    public List<Map<String, Object>> getBomRelationProductClassify() {
        return baseMapper.getBomRelationProductClassify();
    }

}
