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.common.utils.StringUtils;
import com.yunfeiyun.agmp.common.utils.serialno.NoGenerator;
import com.yunfeiyun.agmp.fms.domain.*;
import com.yunfeiyun.agmp.fms.domain.resvo.*;
import com.yunfeiyun.agmp.fms.mapper.*;
import com.yunfeiyun.agmp.fms.domain.reqvo.SelectCountOfScreenReqVo;
import com.yunfeiyun.agmp.fms.domain.reqvo.SelectOfTssStatReqVo;
import com.yunfeiyun.agmp.fms.domain.reqvo.SpmOrderLogisticsInfoReqVo;
import com.yunfeiyun.agmp.fms.domain.reqvo.SpmOrderMatchTraceCodeReqVo;
import com.yunfeiyun.agmp.fms.service.ISpmOrderService;
import com.yunfeiyun.agmp.fms.service.ISysWarnService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 农产品出库登记单Service业务层处理
 * 
 * @author 杨晓辉
 * @date 2023-07-06
 */
@Service
public class SpmOrderServiceImpl implements ISpmOrderService
{
    @Autowired
    private SpmOrderMapper spmOrderMapper;

    @Resource
    private WmsStockMapper wmsStockMapper;

    @Resource
    private SysCustomerMapper sysCustomerMapper;

    @Resource
    private WmsChangeMapper wmsChangeMapper;
    @Resource
    private WmsChangeapplyMapper wmsChangeapplyMapper;
    @Resource
    private WmsChangeapplyitemMapper wmsChangeapplyitemMapper;
    @Resource
    private WmsFinishgoodsMapper wmsFinishgoodsMapper;
    @Resource
    private NoGenerator noGenerator;
    @Resource
    private TssTracecodeapplyMapper tssTracecodeapplyMapper;
    @Resource
    private ISysWarnService sysWarnService;
    /**
     * 查询农产品出库登记单
     * 
     * @param orderId 农产品出库登记单主键
     * @return 农产品出库登记单
     */
    @Override
    public SpmOrder selectSpmOrderByOrderId(String orderId)
    {
        return spmOrderMapper.selectSpmOrderByOrderId(orderId);
    }

    /**
     * 查询农产品出库登记单列表
     * 
     * @param spmOrder 农产品出库登记单
     * @return 农产品出库登记单
     */
    @Override
    public List<SpmOrder> selectSpmOrderList(SpmOrder spmOrder)
    {
        return spmOrderMapper.selectSpmOrderList(spmOrder);
    }

    @Override
    public List<SpmOrderResVo> selectSpmOrderResVoList(SpmOrder spmOrder) {
        return spmOrderMapper.selectSpmOrderResVoList(spmOrder);
    }

    @Override
    public List<SpmOrderOfScreenResVo> selectSpmOrderOfScreenList(SpmOrder spmOrder) {
        return spmOrderMapper.selectSpmOrderOfScreenList(spmOrder);
    }

    @Override
    public Map<String, Object> selectSpmOrderStat(SelectCountOfScreenReqVo reqVo) {
        return spmOrderMapper.selectSpmOrderStat(reqVo);
    }

    @Override
    public List<SpmOrderStatResVo> selectSpmOrderByGoodsStat(SelectCountOfScreenReqVo reqVo) {
        return spmOrderMapper.selectSpmOrderByGoodsStat(reqVo);
    }
    
    @Override
    public List<SpmOrderStatResVo> selectSpmOrderMoneyByGoodsStat(SelectCountOfScreenReqVo reqVo) {
    	return spmOrderMapper.selectSpmOrderMoneyByGoodsStat(reqVo);
    }

    @Override
    public List<SpmOrderStatResVo> selectCountGroupByProvince(SelectCountOfScreenReqVo reqVo) {
        return spmOrderMapper.selectCountGroupByProvince(reqVo);
    }

    @Override
    public List<SpmOrderStatResVo> selectCountGroupByCity(SelectCountOfScreenReqVo reqVo) {
        return spmOrderMapper.selectCountGroupByCity(reqVo);
    }

    @Override
    public List<SpmOrderLogisticsInfoResVo> selectSpmOrderLogisticsInfoReqVo(SpmOrderLogisticsInfoReqVo spmOrderLogisticsInfoReqVo) {
        return spmOrderMapper.selectSpmOrderLogisticsInfoReqVo(spmOrderLogisticsInfoReqVo);
    }

    @Override
    public  List<SpmOrderLogisticsSumInfoResVo> selectSpmOrderLogisticsSumInfo(SpmOrderLogisticsInfoReqVo spmOrderLogisticsInfoReqVo) {
        return spmOrderMapper.selectSpmOrderLogisticsSumInfo(spmOrderLogisticsInfoReqVo);
    }

    /**
     * 新增农产品出库登记单
     * 
     * @param spmOrder 农产品出库登记单
     * @return 结果
     */
    @Override
    public int insertSpmOrder(SpmOrder spmOrder)
    {
        return spmOrderMapper.insertSpmOrder(spmOrder);
    }

    /**
     * 修改农产品出库登记单
     * 
     * @param spmOrder 农产品出库登记单
     * @return 结果
     */
    @Override
    public int updateSpmOrder(SpmOrder spmOrder)
    {
        return spmOrderMapper.updateSpmOrder(spmOrder);
    }

    @Override
    public int updateSpmOrderByIds(SpmOrder spmOrder, String[] ids) {
        return spmOrderMapper.updateSpmOrderByIds(spmOrder, ids);
    }

    /**
     * 批量删除农产品出库登记单
     * 
     * @param orderIds 需要删除的农产品出库登记单主键
     * @return 结果
     */
    @Override
    public int deleteSpmOrderByOrderIds(String[] orderIds)
    {
        return spmOrderMapper.deleteSpmOrderByOrderIds(orderIds);
    }

    /**
     * 删除农产品出库登记单信息
     * 
     * @param orderId 农产品出库登记单主键
     * @return 结果
     */
    @Override
    public int deleteSpmOrderByOrderId(String orderId)
    {
        return spmOrderMapper.deleteSpmOrderByOrderId(orderId);
    }

    @Override
    public void sale(SpmOrder spmOrder) {
        // 检测库存标识是否存在
        if(StringUtils.isEmpty(spmOrder.getStockId())){
            throw new BizException(ErrorCode.SPM_ORDER_SALE_STOCK_ID_IS_BLOCK);
        }
        // 检测客户信息是否存在
        if(StringUtils.isEmpty(spmOrder.getCustomerId())){
            throw new BizException(ErrorCode.SPM_ORDER_SALE_CUSTOMER_ID_IS_BLOCK);
        }
        // 查询已下单，未发货的订单
        BigDecimal sealNumber = spmOrderMapper.selectSpmOrderTotalSealNumber(spmOrder.getStockId());
        if(null == sealNumber){
            sealNumber = new BigDecimal(0);
        }
        // 检测库存是否足够
        WmsStock wmsStock = wmsStockMapper.selectWmsStockByStockId(spmOrder.getStockId());
        if(wmsStock.getStockAmount().compareTo(new BigDecimal(spmOrder.getOrderGoodscount()).add(sealNumber)) < 0){
            throw new BizException(ErrorCode.WMS_STOCK_NOT_ENOUGH);
        }
        // 保存库存单
        spmOrder.setOrderId(spmOrder.getId());
        spmOrder.setOrderNo(noGenerator.getSpmOrderNo());
        spmOrder.setOrderCreateddate(DateUtils.getDate());
        spmOrder.setOrderStatus(SpmOrderStatus.NO_SEND.getCode());
        spmOrderMapper.insertSpmOrder(spmOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @RedisLock(key = RedisLockKey.STOCK_CHANGE_BIZ_LOCK)
    public void deliver(SpmOrder spmOrder) {
        SpmOrder order = spmOrderMapper.selectSpmOrderByOrderId(spmOrder.getOrderId());
        if(!SpmOrderStatus.NO_SEND.getCode().equals(order.getOrderStatus())){
            throw new BizException(ErrorCode.SPM_ORDER_SALE_SEND_STATUS_ERROR);
        }
        /* 出库预警删除 TssTracecodeapply tssTracecodeapply = new TssTracecodeapply();
        tssTracecodeapply.setOrderId(order.getOrderId());
        List<TssTracecodeapply> tssTracecodeapplies = tssTracecodeapplyMapper.selectTssTracecodeapplyList(tssTracecodeapply);
        if(tssTracecodeapplies.isEmpty()){
            WmsFinishgoodsStockResVo wmsFinishgoodsStockResVo = wmsFinishgoodsMapper.selectWmsFinishgoodsStockResVoByStockId(order.getStockId());
            String warnRemark = "订单编号:" +
                    order.getOrderNo() +
                    "中的产品 " +
                    wmsFinishgoodsStockResVo.getFinishgoodNo() +
                    " " +
                    wmsFinishgoodsStockResVo.getGoodsName() +
                    " 未经赋码进行了销售，此销售产品将不能进行溯源";
            sysWarnService.genWarn("", warnRemark, SysWarnEnum.SysWarnType.UNASSIGNED_CODE, SysWarnEnum.SysWarnClass.SALES_PROCESS);
        }*/
        // 检测库存是否足够
        WmsStock wmsStock = wmsStockMapper.selectWmsStockByStockId(order.getStockId());
        if(wmsStock.getStockAmount().compareTo(new BigDecimal(order.getOrderGoodscount())) < 0){
            throw new BizException(ErrorCode.WMS_STOCK_NOT_ENOUGH);
        }
        // 保存变动申请
        WmsChangeapply wmsChangeapply = generateWmsChangeApply(order);
        wmsChangeapplyMapper.insertWmsChangeapply(wmsChangeapply);
        WmsFinishgoodsStockResVo wmsFinishgoodsStockResVo = wmsFinishgoodsMapper.selectWmsFinishgoodsStockResVoByStockId(order.getStockId());
        // 保存变动申请物件
        WmsChangeapplyitem wmsChangeapplyitem = generateWmsChangeApplyItem(wmsChangeapply,wmsStock,wmsFinishgoodsStockResVo,order );
        wmsChangeapplyitemMapper.insertWmsChangeapplyitem(wmsChangeapplyitem);
        // 保存变动记录
        WmsChange wmsChange = generateWmsChange(wmsChangeapplyitem, wmsStock, order);
        wmsChangeMapper.insertWmsChange(wmsChange);
        wmsStockMapper.updateWmsStock(wmsStock);
        spmOrder.setOrderSenddate(DateUtils.getDate());
        spmOrder.setOrderStatus(SpmOrderStatus.SENDING.getCode());
        spmOrderMapper.updateSpmOrder(spmOrder);
    }

    @Override
    public boolean traceCodeMatch(SpmOrderMatchTraceCodeReqVo spmOrderMatchTraceCodeReqVo) {
        SpmOrder spmOrder = spmOrderMapper.selectSpmOrderByOrderId(spmOrderMatchTraceCodeReqVo.getSpmOrderId());
        TssTracecodeapply tssTracecodeapplyQuery = new TssTracecodeapply();
        tssTracecodeapplyQuery.setTarcecodeapplyno(spmOrderMatchTraceCodeReqVo.getTarcecodeapplyno());
        List<TssTracecodeapply> tssTracecodeapplys = tssTracecodeapplyMapper.selectTssTracecodeapplyList(tssTracecodeapplyQuery);
        if(CollectionUtils.isEmpty(tssTracecodeapplys)){
            throw new BizException(ErrorCode.TSS_TRACE_APPLY_NOT_EXIST);
        }
        for(TssTracecodeapply tssTracecodeapply: tssTracecodeapplys){
            if(!tssTracecodeapply.getStockId().equals(spmOrder.getStockId())){
                throw new BizException(ErrorCode.TSS_TRACE_CODE_NO_MATCH_GOODS);
            }
        }
        return tssTracecodeapplyMapper.matchSpmOrder(spmOrderMatchTraceCodeReqVo.getSpmOrderId(), spmOrderMatchTraceCodeReqVo.getTarcecodeapplyno()) == 1;
    }

    @Override
    public boolean traceCodeUnbind(String tarcecodeapplyno) {
        return tssTracecodeapplyMapper.unMatchSpmOrder(tarcecodeapplyno) == 1;
    }

    /**
     * 生成变动申请
     *
     * @param spmOrder 库存单
     * @return 变动申请
     */
    public static WmsChangeapply generateWmsChangeApply(SpmOrder spmOrder) {
        WmsChangeapply wmsChangeapply = new WmsChangeapply();
        wmsChangeapply.setChangeapplyId(wmsChangeapply.getId());
        wmsChangeapply.setChangeapplyWay(ChangeApplyWay.SINGLE.getCode());
        wmsChangeapply.setChangeapplyBiztype(ChangeBizType.SALE.getCode());
        wmsChangeapply.setChangeapplyPricetotal(new BigDecimal(spmOrder.getOrderGoodscount()));
        wmsChangeapply.setChangeapplyApplyer(SecurityUtils.getUserId());
        wmsChangeapply.setChangeapplyApplydate(DateUtils.dateTimeNow());
        wmsChangeapply.setChangeapplyAuditstatus(ChangeApplyAuditStatus.PASS.getCode());
        wmsChangeapply.setChangeapplyAuditdate(wmsChangeapply.getChangeapplyApplydate());
        wmsChangeapply.setChangeapplyAuditor(wmsChangeapply.getChangeapplyApplyer());
        wmsChangeapply.setChangeapplyRemark(spmOrder.getOrderRemark());
        wmsChangeapply.setChangeapplyInoutdate(spmOrder.getOrderCreateddate());
        return wmsChangeapply;
    }

    /**
     * 生成变动申请物件
     *
     * @param wmsChangeapply               变动申请
     * @param wmsStock                     库存
     * @param spmOrder 农产品销售单
     * @return 变动申请物件
     */
    public static WmsChangeapplyitem generateWmsChangeApplyItem(WmsChangeapply wmsChangeapply, WmsStock wmsStock, WmsFinishgoodsStockResVo wmsFinishgoodsStockResVo,SpmOrder spmOrder) {
        WmsChangeapplyitem wmsChangeapplyitem = new WmsChangeapplyitem();
        wmsChangeapplyitem.setChangeapplyitemId(wmsChangeapplyitem.getId());
        wmsChangeapplyitem.setChangeapplyId(wmsChangeapply.getChangeapplyId());
        wmsChangeapplyitem.setWarehouseId(wmsStock.getWarehouseId());
        wmsChangeapplyitem.setGoodsId(wmsFinishgoodsStockResVo.getGoodsId());
        wmsChangeapplyitem.setChangeapplyitemName(wmsFinishgoodsStockResVo.getGoodsName());
        wmsChangeapplyitem.setChangeapplyitemType(wmsFinishgoodsStockResVo.getFinishgoodsType());
        wmsChangeapplyitem.setChangeapplyitemUnit(wmsFinishgoodsStockResVo.getGoodsUnit());
        wmsChangeapplyitem.setChangeapplyitemSpec(wmsFinishgoodsStockResVo.getGoodsSpec());
        if (spmOrder.getOrderGoodscount() == 0) {
            throw new BizException(ErrorCode.WMS_STOCK_CANNOT_CHANGE_ZERO);
        }
        wmsChangeapplyitem.setChangeapplyitemNum(new BigDecimal(spmOrder.getOrderGoodscount()));
        return wmsChangeapplyitem;
    }

    public static WmsChange generateWmsChange(WmsChangeapplyitem wmsChangeapplyitem, WmsStock wmsStock, SpmOrder spmOrder) {
        WmsChange wmsChange = new WmsChange();
        wmsChange.setChangeapplyId(wmsChangeapplyitem.getChangeapplyId());
        wmsChange.setChangeId(wmsChange.getId());
        wmsChange.setStockId(wmsStock.getStockId());
        wmsChange.setChangeId(wmsChange.getId());
        wmsChange.setChangeBiztype(ChangeBizType.SALE.getCode());
        wmsChange.setChangeNum(new BigDecimal(spmOrder.getOrderGoodscount()));
        wmsChange.setChangeOldnum(wmsStock.getStockAmount());
        wmsChange.setChangeWay(ChangeWay.OUT.getCode());
        wmsChange.setChangeNewnum(wmsStock.getStockAmount().subtract(wmsChangeapplyitem.getChangeapplyitemNum()));
        wmsStock.setStockAmount(wmsChange.getChangeNewnum());
        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(spmOrder.getOrderRemark());
        return wmsChange;
    }

    @Override
    public List<SpmOrderOfTssStatResVo> selectSpmOrderOfTssStatList(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectSpmOrderOfTssStatList(reqVo);
    }

    @Override
    public List<SpmPayOfTssStatResVo> selectSpmOrderPayOfTssStatList(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectSpmOrderPayOfTssStatList(reqVo);
    }
    
    @Override
    public Map<String, Object> selectMoneyOfTssTrace(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectMoneyOfTssTrace(reqVo);
    }
    
    @Override
    public List<Map<String, Object>> selectMoneyByMonthOfTssTrace(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectMoneyByMonthOfTssTrace(reqVo);
    }

    @Override
    public Map<String, Map<String, Object>> selectPayMonthByType(SelectOfTssStatReqVo reqVo) {
    	List<Map<String, Object>> gooodsCsList = spmOrderMapper.selectPayMonthByType(reqVo);
		Map<String, Map<String, Object>> gooodsCsMap = null;
		if (gooodsCsList != null) {
			gooodsCsMap = gooodsCsList.stream().collect(Collectors.toMap(e -> e.get("month").toString(), e -> e));
		}
		if (gooodsCsMap == null) {
			gooodsCsMap = new HashMap<String, Map<String, Object>>();
		}
    	return gooodsCsMap;
    }
    
    @Override
    public List<Map<String, Object>> selectFinishgoodsMoneyOfTssTrace(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectFinishgoodsMoneyOfTssTrace(reqVo);
    }
    
    @Override
    public List<SpmPayOfTssStatResVo> selectPayByCs(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectPayByCs(reqVo);
    }
    @Override
    public List<SpmPayOfTssStatResVo> selectPayByBz(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectPayByBz(reqVo);
    }
    
    @Override
    public List<SpmPayOfTssStatResVo> selectPayByJg(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectPayByJg(reqVo);
    }
    
    @Override
    public List<SpmOrderStatResVo> selectSpmOrderMoneyByTssStat(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectSpmOrderMoneyByTssStat(reqVo);
    }

    @Override
    public Integer selectDkCountOfTssTrace(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectDkCountOfTssTrace(reqVo);
    }

    @Override
    public Integer selectGoodsTypeCountOfTssTrace(SelectOfTssStatReqVo reqVo) {
    	return spmOrderMapper.selectGoodsTypeCountOfTssTrace(reqVo);
    }

	@Override
	public List<SpmOrderStatResVo> selectMoneyGroupByCity(SelectOfTssStatReqVo reqVo) {
		return spmOrderMapper.selectMoneyGroupByCity(reqVo);
	}

}
