package com.fjhx.service.water.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.StorageBaseEntity;
import com.fjhx.constants.StatusConstant;
import com.fjhx.entity.contract.ContractDetails;
import com.fjhx.entity.water.WaterBatch;
import com.fjhx.mapper.water.WaterBatchMapper;
import com.fjhx.params.water.WaterBatchVo;
import com.fjhx.service.contract.ContractDetailsService;
import com.fjhx.service.water.WaterBatchService;
import com.fjhx.service.water.WaterTagService;
import com.fjhx.utils.Assert;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * 批次 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-09-20
 */
@Service
public class WaterBatchServiceImpl extends ServiceImpl<WaterBatchMapper, WaterBatch> implements WaterBatchService {

    private static final Object ADD_OBJ = new Object();

    @Autowired
    @Lazy // 解决依赖循环问题
    private WaterTagService waterTagService;

    @Autowired
    @Lazy
    private ContractDetailsService contractDetailsService;

    @Override
    public Map<String, Object> getDetailsByContract(Long contractId) {
        Map<String, Object> result = baseMapper.getMaterialInfo(contractId);

        Assert.notEmpty(result, "没有找到合同信息");

        List<WaterBatch> list = list(WaterBatch::getContractId, contractId);

        // 二维码个数
        int tagTotal = 0;
        // 生成总数量
        BigDecimal quantityTotal = BigDecimal.ZERO;
        // 已发货
        BigDecimal shipped = BigDecimal.ZERO;
        // 未发货
        BigDecimal unshipped = BigDecimal.ZERO;

        for (WaterBatch waterBatch : list) {
            tagTotal += waterBatch.getTagCount();

            BigDecimal tagQuantitySum = waterBatch.getTagQuantitySum();
            quantityTotal = quantityTotal.add(tagQuantitySum);

            if (StatusConstant.YES.equals(waterBatch.getShipmentStatus())) {
                shipped = shipped.add(tagQuantitySum);
            } else {
                unshipped = unshipped.add(tagQuantitySum);
            }
        }

        // 出货金额
        BigDecimal amountMoney = shipped.multiply(Convert.toBigDecimal(result.get("price")));

        result.put("tagTotal", tagTotal);
        result.put("quantityTotal", quantityTotal);
        result.put("shipped", shipped);
        result.put("unshipped", unshipped);
        result.put("amountMoney", amountMoney);
        result.put("list", list);

        return result;
    }

    @Override
    public void add(WaterBatchVo waterBatchVo) {
        Long contractDetailsId = waterBatchVo.getContractDetailsId();
        Assert.notEmpty(contractDetailsId, "合同明细id不能为空");

        synchronized (ADD_OBJ) {

            ContractDetails contractDetails = contractDetailsService.getById(contractDetailsId);
            Assert.notEmpty(contractDetails, "没有找到合同明细");

            waterBatchVo.setMaterialId(contractDetails.getMaterialId());
            waterBatchVo.setSupplierId(contractDetails.getSupplierId());
            waterBatchVo.setPrice(contractDetails.getPrice());
            waterBatchVo.setApplyPurchaseId(contractDetails.getApplyPurchaseId());
            waterBatchVo.setApplyPurchaseDetailsId(contractDetails.getApplyPurchaseDetailsId());
            waterBatchVo.setContractId(contractDetails.getContractId());
            waterBatchVo.setContractCode(contractDetails.getContractCode());
            waterBatchVo.setContractDetailsId(contractDetails.getId());
            waterBatchVo.setContractDetailsCode(contractDetails.getCode());
            waterBatchVo.setTagCount(0);
            waterBatchVo.setTagQuantitySum(BigDecimal.ZERO);
            waterBatchVo.setShipmentStatus(StatusConstant.NO);

            String code = getCode(contractDetails.getContractCode());
            waterBatchVo.setCode(code);

            save(waterBatchVo);

        }
    }

    @Override
    public void delete(WaterBatchVo waterBatchVo) {
        Long id = waterBatchVo.getId();
        WaterBatch waterBatch = getById(id);
        Integer tagCount = waterBatch.getTagCount();
        Assert.eqZero(tagCount, "存在标签的批次不允许删除");

        removeById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void shipment(WaterBatch waterBatch) {
        Assert.notEmpty(waterBatch.getId(), "批次id不能为空");
        Assert.notEmpty(waterBatch.getShipmentWay(), "出货方式不能为空");

        waterBatch.setShipmentStatus(StatusConstant.YES);
        waterBatch.setShipmentTime(new Date());
        updateById(waterBatch);

        // 到货贴标
        waterTagService.shipment(waterBatch.getId());

        // 修改合同出货数量
        contractDetailsService.updateShipmentQuantity(waterBatch.getId());
    }

    @Override
    public void updateShipmentStatus(Set<Long> idSet) {
        update(Wrappers.<WaterBatch>lambdaUpdate()
                .in(StorageBaseEntity::getId, idSet)
                .set(WaterBatch::getShipmentStatus, StatusConstant.YES)
        );
    }

    @Override
    public void editTagCountAndQuantitySum(WaterBatch waterBatch, int tagCount, BigDecimal tagQuantitySum) {
        update(Wrappers.<WaterBatch>lambdaUpdate()
                .eq(StorageBaseEntity::getId, waterBatch.getId())
                .set(WaterBatch::getTagCount, waterBatch.getTagCount() + tagCount)
                .set(WaterBatch::getTagQuantitySum, waterBatch.getTagQuantitySum().add(tagQuantitySum))
                .set(StorageBaseEntity::getUpdateTime, new Date())
                .set(StorageBaseEntity::getUpdateUser, AuthUtil.getUserId())
        );
    }

    private String getCode(String contractCode) {

        Assert.notEmpty(contractCode, "合同编码不能为空");

        String codePrefix = contractCode + "-";

        WaterBatch waterBatch = getOne(Wrappers.<WaterBatch>lambdaQuery()
                .likeRight(WaterBatch::getCode, codePrefix)
                .orderByDesc(WaterBatch::getCode)
                .last("limit 1")
        );

        if (waterBatch == null) {
            return codePrefix + "001";
        }

        int codeSuffix = Convert.toInt(waterBatch.getCode().replace(codePrefix, "")) + 1;

        if (codeSuffix < 10) {
            return codePrefix + "00" + codeSuffix;
        } else if (codeSuffix < 100) {
            return codePrefix + "0" + codeSuffix;
        }
        return codePrefix + codeSuffix;
    }

}
