package com.yunfeiyun.agmp.fms.service.impl;

import com.yunfeiyun.agmp.common.annotation.RedisLock;
import com.yunfeiyun.agmp.common.constant.ErrorCode;
import com.yunfeiyun.agmp.common.enums.*;
import com.yunfeiyun.agmp.common.exception.BizException;
import com.yunfeiyun.agmp.common.utils.DateUtils;
import com.yunfeiyun.agmp.common.utils.SecurityUtils;
import com.yunfeiyun.agmp.fms.domain.*;
import com.yunfeiyun.agmp.fms.mapper.*;
import com.yunfeiyun.agmp.fms.domain.reqvo.WmsStockAddReqVo;
import com.yunfeiyun.agmp.fms.domain.reqvo.WmsStockBatchChangeReqVo;
import com.yunfeiyun.agmp.fms.domain.reqvo.WmsStockBatchChangeReqVoItem;
import com.yunfeiyun.agmp.fms.domain.reqvo.WmsStockListReqVo;
import com.yunfeiyun.agmp.fms.domain.resvo.WmsStockAppMapResVo;
import com.yunfeiyun.agmp.fms.domain.resvo.WmsStockAppMapResVoItem;
import com.yunfeiyun.agmp.fms.domain.resvo.WmsStockListResVo;
import com.yunfeiyun.agmp.fms.service.IWmsStockService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 库存Service业务层处理
 *
 * @author 杨晓辉
 * @date 2023-05-25
 */
@Service
public class WmsStockServiceImpl implements IWmsStockService {
    @Autowired
    private WmsStockMapper wmsStockMapper;
    @Resource
    private WmsGoodsMapper wmsGoodsMapper;
    @Resource
    private WmsChangeMapper wmsChangeMapper;
    @Resource
    private WmsChangeapplyMapper wmsChangeapplyMapper;
    @Resource
    private WmsChangeapplyitemMapper wmsChangeapplyitemMapper;
    @Resource
    private WmsAssetgoodsMapper wmsAssetgoodsMapper;

    /**
     * 查询库存
     *
     * @param stockId 库存主键
     * @return 库存
     */
    @Override
    public WmsStock selectWmsStockByStockId(String stockId) {
        return wmsStockMapper.selectWmsStockByStockId(stockId);
    }

    @Override
    public List<WmsStock> selectWmsStockByGoodsIdAndWarehouseId(WmsStock wmsStock) {
        return wmsStockMapper.selectWmsStock(wmsStock);
    }

    /**
     * 查询库存列表
     *
     * @param wmsStockListReqVo 库存
     * @return 库存
     */
    @Override
    public List<WmsStockListResVo> selectWmsStockList(WmsStockListReqVo wmsStockListReqVo) {
        return wmsStockMapper.selectWmsStockList(wmsStockListReqVo);
    }

    /**
     * app查询库存农资信息列表
     *
     * @return 库存集合
     */
    @Override
    public List<WmsStockAppMapResVo> selectWmsStockAppMapResVoList() {
        WmsStockListReqVo wmsStockListReqVo = new WmsStockListReqVo();
        wmsStockListReqVo.setMinStockAmount(0);
        List<WmsStockListResVo> list = wmsStockMapper.selectWmsStockList(wmsStockListReqVo);
        Map<String, WmsStockAppMapResVo> map = new HashMap<>();
        for (WmsStockListResVo wmsStockListResVo : list) {
            WmsStockAppMapResVo wmsStockAppMapResVo = map.get(wmsStockListResVo.getWarehouseId());
            if (null == wmsStockAppMapResVo) {
                wmsStockAppMapResVo = new WmsStockAppMapResVo();
                wmsStockAppMapResVo.setWarehouseId(wmsStockListResVo.getWarehouseId());
                wmsStockAppMapResVo.setWarehouseName(wmsStockListResVo.getWarehouseName());
                map.put(wmsStockAppMapResVo.getWarehouseId(), wmsStockAppMapResVo);
            }
            Map<String, WmsStockAppMapResVoItem> wmsStockAppMapResVoItemList = wmsStockAppMapResVo.getStockAppMapResVoItemMap();
            WmsStockAppMapResVoItem wmsStockAppMapResVoItem = wmsStockAppMapResVoItemList.get(wmsStockListResVo.getGoodsType());
            if (null == wmsStockAppMapResVoItem) {
                wmsStockAppMapResVoItem = new WmsStockAppMapResVoItem();
                wmsStockAppMapResVoItem.setGoodsType(wmsStockListResVo.getGoodsType());
                wmsStockAppMapResVoItem.setGoodsTypeName(wmsStockListResVo.getGoodsTypeContent());
                wmsStockAppMapResVoItemList.put(wmsStockAppMapResVoItem.getGoodsType(), wmsStockAppMapResVoItem);
            }
            wmsStockAppMapResVoItem.getGoodsList().add(wmsStockListResVo);
        }
        return new ArrayList<>(map.values());
    }

    /**
     * 新增农资
     *
     * @param wmsStockAddReqVo 新农资入库单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @RedisLock(key = RedisLockKey.STOCK_CHANGE_BIZ_LOCK)
    public int add(WmsStockAddReqVo wmsStockAddReqVo) {
        WmsStockListReqVo wmsStockListReqVo = new WmsStockListReqVo();
        wmsStockListReqVo.setGoodsName(wmsStockAddReqVo.getGoodsName());
        wmsStockListReqVo.setGoodsType(wmsStockAddReqVo.getGoodsType());
        wmsStockListReqVo.setWarehouseId(wmsStockAddReqVo.getWarehouseId());
        List<WmsStockListResVo> wmsStockListResVos = wmsStockMapper.selectWmsStockList(wmsStockListReqVo);
        if(!wmsStockListResVos.isEmpty()){
            throw new BizException(ErrorCode.WMS_GOODS_EXIST);
        }

        // 生成货物
        WmsGoods wmsGoods = new WmsGoods();
        BeanUtils.copyProperties(wmsStockAddReqVo, wmsGoods);
        wmsGoods.setGoodsId(wmsGoods.getId());
        // 保存
        wmsGoodsMapper.insertWmsGoods(wmsGoods);
        // 生成农资
        WmsAssetgoods wmsAssetgoods = new WmsAssetgoods();
        wmsAssetgoods.setAssetgoodsId(wmsAssetgoods.getId());
        wmsAssetgoods.setGoodsId(wmsGoods.getGoodsId());
        wmsAssetgoods.setAssetgoodsType(wmsStockAddReqVo.getGoodsType());
        wmsAssetgoods.setAssetgoodsManufactor(wmsStockAddReqVo.getGoodsManufactor());
        wmsAssetgoods.setSupplierId(wmsStockAddReqVo.getSupplierId());
        // 保存
        wmsAssetgoodsMapper.insertWmsAssetgoods(wmsAssetgoods);

        // 生成库存
        WmsStock wmsStock = new WmsStock();
        BeanUtils.copyProperties(wmsStockAddReqVo, wmsStock);
        wmsStock.setStockId(wmsStock.getId());
        wmsStock.setGoodsId(wmsGoods.getGoodsId());
        // 保存
        wmsStockMapper.insertWmsStock(wmsStock);
        // 保存变动申请
        WmsChangeapply wmsChangeapply = generateWmsChangeApply(wmsStockAddReqVo);
        wmsChangeapplyMapper.insertWmsChangeapply(wmsChangeapply);
        // 保存变动申请物件
        WmsChangeapplyitem wmsChangeapplyitem = generateWmsChangeApplyItem(wmsGoods, wmsChangeapply, wmsStockAddReqVo);
        wmsChangeapplyitemMapper.insertWmsChangeapplyitem(wmsChangeapplyitem);
        // 保存变动记录
        WmsChange wmsChange = generateWmsChange(wmsStock, wmsChangeapply, wmsStockAddReqVo);
        wmsChangeMapper.insertWmsChange(wmsChange);
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @RedisLock(key = RedisLockKey.STOCK_CHANGE_BIZ_LOCK)
    public int batchChange(WmsStockBatchChangeReqVo wmsStockBatchChangeReqVo) {
        // 获取库存标识
        List<String> stockIds = wmsStockBatchChangeReqVo.getWmsStockBatchChangeReqVoItemList().stream().map(WmsStockBatchChangeReqVoItem::getStockId).collect(Collectors.toList());
        // 查询改动的库存
        List<WmsStock> wmsStockList = wmsStockMapper.slectWmsStockListByStockIds(stockIds);
        // 转化为库存map
        Map<String, WmsStock> wmsStockMap = wmsStockList.stream().collect(Collectors.toMap(WmsStock::getStockId, wmsStock -> wmsStock));
        // 生成变动申请
        WmsChangeapply wmsChangeapply = generateWmsChangeApply(wmsStockBatchChangeReqVo);
        List<WmsChangeapplyitem> wmsChangeapplyitems = new ArrayList<>();
        List<WmsChange> wmsChanges = new ArrayList<>();
        // 遍历接口入参
        for (WmsStockBatchChangeReqVoItem wmsStockBatchChangeReqVoItem : wmsStockBatchChangeReqVo.getWmsStockBatchChangeReqVoItemList()) {
            // 获取库存
            WmsStock wmsStock = wmsStockMap.get(wmsStockBatchChangeReqVoItem.getStockId());
            // 生成变动申请物件信息
            WmsChangeapplyitem wmsChangeapplyitem = generateWmsChangeApplyItem(wmsChangeapply, wmsStock, wmsStockBatchChangeReqVoItem);
            // 生成变动记录
            WmsChange wmsChange = generateWmsChange(wmsChangeapplyitem, wmsStock, wmsStockBatchChangeReqVo);
            // 更改库存
            wmsStock.setStockAmount(wmsChange.getChangeNewnum());
            // 写入变动物件信息列表
            wmsChangeapplyitems.add(wmsChangeapplyitem);
            // 写入变动列表
            wmsChanges.add(wmsChange);
        }
        // 保存变动申请
        wmsChangeapplyMapper.insertWmsChangeapply(wmsChangeapply);
        // 保存变动申请物件信息列表
        wmsChangeapplyitemMapper.insertWmsChangeapplyitemList(wmsChangeapplyitems);
        // 保存变动记录
        wmsChangeMapper.insertWmsChangeList(wmsChanges);
        // 更新库存信息
        wmsStockMapper.updateWmsStockByBatch(new ArrayList<>(wmsStockMap.values()));
        return 1;
    }

    /**
     * 生成变动申请
     *
     * @param wmsStockAddReqVo 库存新增Vo
     * @return 变动申请
     */
    public static WmsChangeapply generateWmsChangeApply(WmsStockAddReqVo wmsStockAddReqVo) {
        WmsChangeapply wmsChangeapply = new WmsChangeapply();
        wmsChangeapply.setChangeapplyId(wmsChangeapply.getId());
        wmsChangeapply.setChangeapplyWay(ChangeApplyWay.SINGLE.getCode());
        wmsChangeapply.setChangeapplyBiztype(ChangeBizType.RECEIPTS_APPLY.getCode());
        wmsChangeapply.setChangeapplyPricetotal(wmsStockAddReqVo.getChangeapplyitemUnitTotal());
        wmsChangeapply.setChangeapplyApplyer(SecurityUtils.getUserId());
        wmsChangeapply.setChangeapplyApplydate(DateUtils.dateTimeNow());
        wmsChangeapply.setChangeapplyAuditstatus(ChangeApplyAuditStatus.PASS.getCode());
        wmsChangeapply.setChangeapplyAuditdate(wmsChangeapply.getChangeapplyApplydate());
        wmsChangeapply.setChangeapplyAuditor(wmsChangeapply.getChangeapplyApplyer());
        wmsChangeapply.setChangeapplyRemark(wmsStockAddReqVo.getChangeapplyRemark());
        wmsChangeapply.setChangeapplyInoutdate(wmsStockAddReqVo.getChangeapplyInoutdate());
        return wmsChangeapply;
    }

    /**
     * 生成变动申请
     *
     * @param wmsStockBatchChangeReqVo 库存批量新增Vo
     * @return 变动申请
     */
    public static WmsChangeapply generateWmsChangeApply(WmsStockBatchChangeReqVo wmsStockBatchChangeReqVo) {
        BigDecimal total = wmsStockBatchChangeReqVo.getWmsStockBatchChangeReqVoItemList().stream().map(WmsStockBatchChangeReqVoItem::getChangeapplyitemPricetotal).reduce(new BigDecimal("0"), BigDecimal::add);
        WmsChangeapply wmsChangeapply = new WmsChangeapply();
        wmsChangeapply.setChangeapplyId(wmsChangeapply.getId());
        wmsChangeapply.setChangeapplyWay(ChangeApplyWay.BATCH.getCode());
        wmsChangeapply.setChangeapplyBiztype(wmsStockBatchChangeReqVo.getChangeBiztype());
        wmsChangeapply.setChangeapplyPricetotal(total);
        wmsChangeapply.setChangeapplyApplyer(SecurityUtils.getUserId());
        wmsChangeapply.setChangeapplyApplydate(DateUtils.dateTimeNow());
        wmsChangeapply.setChangeapplyAuditstatus(ChangeApplyAuditStatus.PASS.getCode());
        wmsChangeapply.setChangeapplyAuditdate(wmsChangeapply.getChangeapplyApplydate());
        wmsChangeapply.setChangeapplyAuditor(wmsChangeapply.getChangeapplyApplyer());
        wmsChangeapply.setChangeapplyRemark(wmsStockBatchChangeReqVo.getChangeapplyRemark());
        wmsChangeapply.setChangeapplyInoutdate(wmsStockBatchChangeReqVo.getChangeapplyInoutdate());
        return wmsChangeapply;

    }

    /**
     * 生成变动申请物件
     *
     * @param wmsGoods         农资
     * @param wmsChangeapply   变动申请
     * @param wmsStockAddReqVo 库存新增Vo
     * @return 变动申请物件
     */
    public static WmsChangeapplyitem generateWmsChangeApplyItem(WmsGoods wmsGoods, WmsChangeapply wmsChangeapply, WmsStockAddReqVo wmsStockAddReqVo) {
        WmsChangeapplyitem wmsChangeapplyitem = new WmsChangeapplyitem();
        wmsChangeapplyitem.setChangeapplyitemId(wmsChangeapplyitem.getId());
        wmsChangeapplyitem.setChangeapplyId(wmsChangeapply.getChangeapplyId());
        wmsChangeapplyitem.setGoodsId(wmsGoods.getGoodsId());
        wmsChangeapplyitem.setWarehouseId(wmsStockAddReqVo.getWarehouseId());
        wmsChangeapplyitem.setChangeapplyitemName(wmsStockAddReqVo.getGoodsName());
        wmsChangeapplyitem.setChangeapplyitemType(wmsStockAddReqVo.getGoodsType());
        wmsChangeapplyitem.setChangeapplyitemUnit(wmsStockAddReqVo.getGoodsUnit());
        wmsChangeapplyitem.setChangeapplyitemSpec(wmsStockAddReqVo.getGoodsSpec());
        if (wmsStockAddReqVo.getStockAmount().compareTo(new BigDecimal("0")) == 0) {
            throw new BizException(ErrorCode.WMS_STOCK_CANNOT_CHANGE_ZERO);
        }
        wmsChangeapplyitem.setChangeapplyitemNum(wmsStockAddReqVo.getStockAmount());
        wmsChangeapplyitem.setChangeapplyitemPriceunit(wmsStockAddReqVo.getChangeapplyitemUnit());
        wmsChangeapplyitem.setChangeapplyitemPricetotal(wmsChangeapply.getChangeapplyPricetotal());
        return wmsChangeapplyitem;
    }

    /**
     * 生成变动申请物件
     *
     * @param wmsChangeapply               变动申请
     * @param wmsStock                     库存
     * @param wmsStockBatchChangeReqVoItem 库存新增子项Vo
     * @return 变动申请物件
     */
    public static WmsChangeapplyitem generateWmsChangeApplyItem(WmsChangeapply wmsChangeapply, WmsStock wmsStock, WmsStockBatchChangeReqVoItem wmsStockBatchChangeReqVoItem) {
        WmsChangeapplyitem wmsChangeapplyitem = new WmsChangeapplyitem();
        wmsChangeapplyitem.setChangeapplyitemId(wmsChangeapplyitem.getId());
        wmsChangeapplyitem.setChangeapplyId(wmsChangeapply.getChangeapplyId());
        wmsChangeapplyitem.setWarehouseId(wmsStock.getWarehouseId());
        wmsChangeapplyitem.setGoodsId(wmsStockBatchChangeReqVoItem.getGoodsId());
        wmsChangeapplyitem.setChangeapplyitemName(wmsStockBatchChangeReqVoItem.getGoodsName());
        wmsChangeapplyitem.setChangeapplyitemType(wmsStockBatchChangeReqVoItem.getGoodsType());
        wmsChangeapplyitem.setChangeapplyitemUnit(wmsStockBatchChangeReqVoItem.getGoodsUnit());
        wmsChangeapplyitem.setChangeapplyitemSpec(wmsStockBatchChangeReqVoItem.getGoodsSpec());
        if (wmsStockBatchChangeReqVoItem.getStockAmount().compareTo(new BigDecimal("0")) == 0) {
            throw new BizException(ErrorCode.WMS_STOCK_CANNOT_CHANGE_ZERO);
        }
        wmsChangeapplyitem.setChangeapplyitemNum(wmsStockBatchChangeReqVoItem.getStockAmount());
        wmsChangeapplyitem.setChangeapplyitemPriceunit(wmsStockBatchChangeReqVoItem.getChangeapplyitemPriceunit());
        wmsChangeapplyitem.setChangeapplyitemPricetotal(wmsStockBatchChangeReqVoItem.getChangeapplyitemPricetotal());
        return wmsChangeapplyitem;
    }

    /**
     * 生产变动记录
     *
     * @param wmsStock         库存
     * @param wmsChangeapply   变动申请
     * @param wmsStockAddReqVo 库存新增Vo
     */
    public static WmsChange generateWmsChange(WmsStock wmsStock, WmsChangeapply wmsChangeapply, WmsStockAddReqVo wmsStockAddReqVo) {
        WmsChange wmsChange = new WmsChange();
        wmsChange.setChangeapplyId(wmsChangeapply.getChangeapplyId());
        wmsChange.setChangeId(wmsChange.getId());
        wmsChange.setStockId(wmsStock.getStockId());
        wmsChange.setChangeId(wmsChange.getId());
        wmsChange.setChangeBiztype(ChangeBizType.RECEIPTS_APPLY.getCode());
        wmsChange.setChangeWay(ChangeWay.IN.getCode());
        wmsChange.setChangeNum(wmsStock.getStockAmount());
        wmsChange.setChangeOldnum(new BigDecimal("0"));
        if (wmsStock.getStockAmount().compareTo(new BigDecimal("0")) == 0) {
            throw new BizException(ErrorCode.WMS_STOCK_CANNOT_CHANGE_ZERO);
        }
        wmsChange.setChangeNewnum(wmsStock.getStockAmount());
        wmsChange.setChangeAuditor(SecurityUtils.getUserId());
        wmsChange.setChangeAuditeddate(DateUtils.dateTimeNow());
        wmsChange.setChangeRemark(wmsStockAddReqVo.getChangeapplyRemark());
        return wmsChange;
    }

    public static WmsChange generateWmsChange(WmsChangeapplyitem wmsChangeapplyitem, WmsStock wmsStock, WmsStockBatchChangeReqVo wmsStockBatchChangeReqVo) {
        WmsChange wmsChange = new WmsChange();
        wmsChange.setChangeapplyId(wmsChangeapplyitem.getChangeapplyId());
        wmsChange.setChangeId(wmsChange.getId());
        wmsChange.setStockId(wmsStock.getStockId());
        wmsChange.setChangeId(wmsChange.getId());
        wmsChange.setChangeBiztype(wmsStockBatchChangeReqVo.getChangeBiztype());
        wmsChange.setChangeNum(wmsChangeapplyitem.getChangeapplyitemNum());
        wmsChange.setChangeOldnum(wmsStock.getStockAmount());
        if (ChangeBizType.RECEIPTS_APPLY.equal(wmsStockBatchChangeReqVo.getChangeBiztype())) {
            wmsChange.setChangeWay(ChangeWay.IN.getCode());
            wmsChange.setChangeNewnum(wmsStock.getStockAmount().add(wmsChangeapplyitem.getChangeapplyitemNum()));
        } else {
            wmsChange.setChangeWay(ChangeWay.OUT.getCode());
            wmsChange.setChangeNewnum(wmsStock.getStockAmount().subtract(wmsChangeapplyitem.getChangeapplyitemNum()));
            if (wmsChange.getChangeNewnum().compareTo(new BigDecimal("0")) < 0) {
                throw new BizException(ErrorCode.WMS_STOCK_NOT_ENOUGH);
            }
        }
        if (wmsChangeapplyitem.getChangeapplyitemNum().compareTo(new BigDecimal("0")) == 0) {
            throw new BizException(ErrorCode.WMS_STOCK_CANNOT_CHANGE_ZERO);
        }

        wmsChange.setChangeAuditor(SecurityUtils.getUserId());
        wmsChange.setChangeAuditeddate(DateUtils.dateTimeNow());
        wmsChange.setChangeRemark(wmsStockBatchChangeReqVo.getChangeapplyRemark());
        return wmsChange;
    }

    /**
     * 修改库存
     *
     * @param wmsStock 库存
     * @return 结果
     */
    @Override
    public int updateWmsStock(WmsStock wmsStock) {
        return wmsStockMapper.updateWmsStock(wmsStock);
    }

    /**
     * 批量删除库存
     *
     * @param stockIds 需要删除的库存主键
     * @return 结果
     */
    @Override
    public int deleteWmsStockByStockIds(String[] stockIds) {
        return wmsStockMapper.deleteWmsStockByStockIds(stockIds);
    }

    /**
     * 删除库存信息
     *
     * @param stockId 库存主键
     * @return 结果
     */
    @Override
    public int deleteWmsStockByStockId(String stockId) {
        return wmsStockMapper.deleteWmsStockByStockId(stockId);
    }
}
