package com.fjhx.service.check.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.Condition;
import com.fjhx.entity.check.CheckDetails;
import com.fjhx.entity.check.CheckInfo;
import com.fjhx.entity.stock.Stock;
import com.fjhx.entity.warehouse.Warehouse;
import com.fjhx.mapper.check.CheckInfoMapper;
import com.fjhx.params.check.CheckInfoVo;
import com.fjhx.service.check.CheckDetailsService;
import com.fjhx.service.check.CheckInfoService;
import com.fjhx.service.form.FormOverflowLossService;
import com.fjhx.service.stock.StockService;
import com.fjhx.uitl.code.CodeEnum;
import com.fjhx.utils.Assert;
import com.fjhx.utils.UserClientUtil;
import com.fjhx.utils.wrapperUtil.IWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-12-23
 */
@Service
public class CheckInfoServiceImpl extends ServiceImpl<CheckInfoMapper, CheckInfo> implements CheckInfoService {

    @Autowired
    private CheckDetailsService checkDetailsService;

    @Autowired
    private StockService stockService;

    @Autowired
    private FormOverflowLossService formOverflowLossService;

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

        IWrapper<CheckInfo> wrapper = IWrapper.getWrapper(condition);
        wrapper.eq("w", Warehouse::getType, condition.get("warehouseType"))
                .eq("ci", CheckInfo::getResultType)
                .eq("ci", CheckInfo::getCode)
                .like("w", Warehouse::getName, condition.get("warehouseName"))
                .eq("ci", CheckInfo::getCreateUser)
                .periodTime("ci", CheckInfo::getCreateTime)
                .orderByDesc("ci", CheckInfo::getId)
        ;

        Page<Map<String, Object>> page = baseMapper.getPage(condition.getPage(), wrapper);

        List<Map<String, Object>> records = page.getRecords();
        UserClientUtil.setUserName(records, "createUser", "createUserName");
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(CheckInfoVo checkInfoVo) {
        Long id = IdWorker.getId();

        Long warehouseId = checkInfoVo.getWarehouseId();
        Assert.notEmpty(warehouseId, "仓库id不能为空");

        // 最总盘点结论（0正常 1异常）类型
        int checkResultType = 0;

        List<CheckDetails> checkDetailsList = checkInfoVo.getCheckDetailsList();

        // 盘盈金额
        BigDecimal overflowAmount = BigDecimal.ZERO;

        // 盘亏金额
        BigDecimal lossAmount = BigDecimal.ZERO;

        /**
         * 盘点金额
         */
        BigDecimal checkAmount = BigDecimal.ZERO;

        // 获取商品加权平均价
        List<Long> productIdList = checkDetailsList.stream().map(CheckDetails::getProductId).collect(Collectors.toList());
        Map<Long, BigDecimal> kv = stockService.getKV(Stock::getGoodsId, Stock::getWeightingAveragePrice,
                q -> q.eq(Stock::getWarehouseId, warehouseId).in(Stock::getGoodsId, productIdList));

        for (CheckDetails checkDetails : checkDetailsList) {
            Long productId = checkDetails.getProductId();
            BigDecimal checkQuantity = checkDetails.getCheckQuantity();
            BigDecimal inventoryQuantity = checkDetails.getInventoryQuantity();


            Assert.notEmpty(productId, "产品id不能为空");
            Assert.notEmpty(checkQuantity, "盘点数量不能为空");
            Assert.notEmpty(inventoryQuantity, "现有库存不能为空");

            checkDetails.setCheckInfoId(id);

            // 产品加权平均价
            BigDecimal weightingAveragePrice = ObjectUtil.defaultIfNull(kv.get(productId), BigDecimal.ZERO);

            checkAmount = checkAmount.add(weightingAveragePrice.multiply(checkQuantity));

            int flag = inventoryQuantity.compareTo(checkQuantity);
            if (flag > 0) {
                checkDetails.setResultType(2);
                checkResultType = 1;

                // 添加盘亏金额
                lossAmount = lossAmount.add(inventoryQuantity.subtract(checkQuantity).multiply(weightingAveragePrice));
            } else if (flag < 0) {
                checkDetails.setResultType(1);
                checkResultType = 1;

                // 添加盘盈金额
                overflowAmount = overflowAmount.add(checkQuantity.subtract(inventoryQuantity).multiply(weightingAveragePrice));
            } else {
                checkDetails.setResultType(0);
            }
        }

        // 添加盘点记录
        synchronized (this) {
            checkInfoVo.setId(id);
            checkInfoVo.setResultType(checkResultType);
            checkInfoVo.setCode(CodeEnum.CHECK_CODE.getCode());
            checkInfoVo.setAmount(checkAmount);
            save(checkInfoVo);
        }

        // 添加盘点明细
        checkDetailsService.saveBatch(checkDetailsList);

        // 添加溢损单
        if (overflowAmount.compareTo(BigDecimal.ZERO) > 0) {
            formOverflowLossService.addOverflow(1, id, warehouseId, overflowAmount, "");
        }
        if (lossAmount.compareTo(BigDecimal.ZERO) > 0) {
            formOverflowLossService.addLoss(1, id, warehouseId, lossAmount, "");
        }

    }

    @Override
    public void edit(CheckInfoVo checkInfoVo) {
        updateById(checkInfoVo);
    }

    @Override
    public void delete(CheckInfoVo checkInfoVo) {
        removeById(checkInfoVo.getId());
    }

}
