package com.hw.wms.service.impl;

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

import com.hw.common.core.constant.MesConstants;
import com.hw.common.core.constant.SecurityConstants;
import com.hw.common.core.constant.WmsConstants;
import com.hw.common.core.domain.R;
import com.hw.common.core.exception.ServiceException;
import com.hw.common.core.utils.uuid.Seq;
import com.hw.common.security.utils.SecurityUtils;
import com.hw.mes.api.RemoteMesService;
import com.hw.mes.api.domain.MesBaseBarcodeInfo;
import com.hw.wms.domain.WmsBaseLocation;
import com.hw.wms.domain.WmsRawStock;
import com.hw.wms.domain.vo.WmsRawBackVo;
import com.hw.wms.domain.vo.WmsRawInstockVo;
import com.hw.wms.mapper.WmsBaseLocationMapper;
import com.hw.wms.mapper.WmsRawStockMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;
import com.hw.wms.mapper.WmsRawInstockMapper;
import com.hw.wms.domain.WmsRawInstock;
import com.hw.wms.service.IWmsRawInstockService;

import javax.annotation.Resource;

/**
 * 原材料入库记录Service业务层处理
 *
 * @author xs
 * @date 2023-12-20
 */
@Service
public class WmsRawInstockServiceImpl implements IWmsRawInstockService {
    @Autowired
    private WmsRawInstockMapper wmsRawInstockMapper;

    @Autowired
    private WmsBaseLocationMapper wmsBaseLocationMapper;

    @Autowired
    private WmsRawStockMapper wmsRawStockMapper;

    @Resource
    private RemoteMesService remoteMesService;


    /**
     * 查询原材料入库记录
     *
     * @param rawInstockId 原材料入库记录主键
     * @return 原材料入库记录
     */
    @Override
    public WmsRawInstock selectWmsRawInstockByRawInstockId(Long rawInstockId) {
        return wmsRawInstockMapper.selectWmsRawInstockByRawInstockId(rawInstockId);
    }

    /**
     * 查询原材料入库记录列表
     *
     * @param wmsRawInstock 原材料入库记录
     * @return 原材料入库记录
     */
    @Override
    public List<WmsRawInstock> selectWmsRawInstockList(WmsRawInstock wmsRawInstock) {
        return wmsRawInstockMapper.selectWmsRawInstockList(wmsRawInstock);
    }


    /**
     * 新增原材料入库记录(适用于移动手持端)
     *
     * @param wmsRawInstock 原材料入库记录
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertWmsRawInstock(WmsRawInstock wmsRawInstock) {
        int rows = wmsRawInstockMapper.insertWmsRawInstock(wmsRawInstock);
        return rows;
    }

    /**
     * 修改原材料入库记录
     *
     * @param wmsRawInstock 原材料入库记录
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateWmsRawInstock(WmsRawInstock wmsRawInstock) {
        return wmsRawInstockMapper.updateWmsRawInstock(wmsRawInstock);
    }

    /**
     * 批量删除原材料入库记录
     *
     * @param rawInstockIds 需要删除的原材料入库记录主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteWmsRawInstockByRawInstockIds(Long[] rawInstockIds) {
        return wmsRawInstockMapper.deleteWmsRawInstockByRawInstockIds(rawInstockIds);
    }

    /**
     * 删除原材料入库记录信息
     *
     * @param rawInstockId 原材料入库记录主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteWmsRawInstockByRawInstockId(Long rawInstockId) {
        return wmsRawInstockMapper.deleteWmsRawInstockByRawInstockId(rawInstockId);
    }


    /**
     * 新增原材料入库记录(适用于移动手持端)
     *
     * @param wmsRawInstockVo 原材料入库记录
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertWmsRawInstock(WmsRawInstockVo wmsRawInstockVo) {
        String materialBarcode = wmsRawInstockVo.getMaterialBarcode();
        R<MesBaseBarcodeInfo> baseBarcodeInfoR = remoteMesService.getBarcode(materialBarcode, SecurityConstants.INNER);
        if (baseBarcodeInfoR == null) {
            throw new ServiceException("物料编码有误");
        }
        MesBaseBarcodeInfo baseBarcodeInfo = baseBarcodeInfoR.getData();
        if (baseBarcodeInfo == null) {
            throw new ServiceException("物料编码有误");
        }

        String locationCode = wmsRawInstockVo.getLocationCode();
        WmsBaseLocation baseLocation = wmsBaseLocationMapper.selectWmsBaseLocationByLocationCode(locationCode);
        if (baseLocation == null) {
            throw new ServiceException("库位编码有误");
        }
        //todo 可入物料（wms_warehouse_material）判断是否可以入此库位

        BigDecimal instockAmount = wmsRawInstockVo.getInstockAmount();
        if (baseBarcodeInfo.getBatchFlag().equals(MesConstants.IS_BATCH)) {
            if (instockAmount.compareTo(BigDecimal.ONE) < 0) {
                throw new ServiceException("入库数量需大于等于1");
            }
        } else {
            if (instockAmount.compareTo(BigDecimal.ONE) > 0) {
                throw new ServiceException("入库数量需等于1");
            }
        }

        WmsRawInstock existedRawInstock = wmsRawInstockMapper.selectWmsRawInstockByBarcode(wmsRawInstockVo.getMaterialBarcode());
        if (existedRawInstock != null) {
            throw new ServiceException("此物料已经入库，不需重复入库");
        }

        Date currentDate = new Date();
        String userName = SecurityUtils.getUsername();
        WmsRawInstock wmsRawInstock = new WmsRawInstock();
        wmsRawInstock.setTaskCode(Seq.getId(Seq.rawInstockSeqType, Seq.rawInstockSeqCode));
        wmsRawInstock.setWarehouseId(baseLocation.getWarehouseId());
        wmsRawInstock.setLocationCode(locationCode);
        wmsRawInstock.setPoNo(baseBarcodeInfo.getPoNo());
        wmsRawInstock.setOperationType(WmsConstants.WMS_OPERATION_TYPE_MANUAL);
        wmsRawInstock.setInstockType(WmsConstants.RAW_INSTOCK_INSTOCK_TYPE_PURCHASE);
        wmsRawInstock.setExecuteStatus(WmsConstants.WMS_EXECUTE_STATUS_FINISH);
        wmsRawInstock.setApplyBy(userName);
        wmsRawInstock.setApplyDate(currentDate);
        wmsRawInstock.setMaterialBarcode(wmsRawInstockVo.getMaterialBarcode());
        wmsRawInstock.setMaterialBatchCode(baseBarcodeInfo.getBatchCode());
        wmsRawInstock.setMaterialId(baseBarcodeInfo.getMaterialId());
        wmsRawInstock.setInstockAmount(wmsRawInstockVo.getInstockAmount());

        //插入记录
        int rows = wmsRawInstockMapper.insertWmsRawInstock(wmsRawInstock);

        //更新库位库存
        updateRawStock(wmsRawInstock, wmsRawInstockVo, baseLocation, baseBarcodeInfo, userName, currentDate);

        return rows;
    }


    /**
     * 更新原材料库存
     *
     * @param wmsRawInstock
     * @param wmsRawInstockVo
     * @param baseLocation
     * @param userName
     * @param currentDate
     */
    public void updateRawStock(WmsRawInstock wmsRawInstock, WmsRawInstockVo wmsRawInstockVo, WmsBaseLocation baseLocation
            , MesBaseBarcodeInfo baseBarcodeInfo, String userName, Date currentDate) {
        String instockBatch = baseBarcodeInfo.getBatchCode();
        String locationCode = wmsRawInstock.getLocationCode();

        //判断此库位的数量限制，是否还能入库
        WmsRawStock queryRawStock = new WmsRawStock();
        queryRawStock.setLocationCode(locationCode);
        BigDecimal totalAmount = wmsRawStockMapper.getRawStockTotalAmount(queryRawStock);
        totalAmount = totalAmount == null ? BigDecimal.ZERO : totalAmount;
        BigDecimal qtyLimit = baseLocation.getQtyLimit() == null ? BigDecimal.ZERO : baseLocation.getQtyLimit();
        if (totalAmount.add(wmsRawInstockVo.getInstockAmount()).compareTo(qtyLimit) > 0) {
            throw new ServiceException("已超出库位数量限制，请重新选择库位");
        }

        //如果是同一库位入同一批次，则更新数量
        WmsRawStock wmsRawStock = wmsRawStockMapper.selectRawStockByLocationAndBatch(locationCode, instockBatch);
        if (wmsRawStock != null) {
//            wmsRawStock.setQualityStatus(wmsRawInstockVo.getQualityStatus());
            wmsRawStock.setTotalAmount(wmsRawStock.getTotalAmount().add(wmsRawInstockVo.getInstockAmount()));
            wmsRawStock.setUpdateBy(userName);
            wmsRawStock.setUpdateDate(currentDate);
            wmsRawStockMapper.updateWmsRawStock(wmsRawStock);
        } else {
            wmsRawStock = new WmsRawStock();
            wmsRawStock.setWarehouseId(wmsRawInstock.getWarehouseId());
            wmsRawStock.setLocationCode(locationCode);
            wmsRawStock.setStockType(WmsConstants.RWA_STOCK_STOCK_TYPE_RAW);
            wmsRawStock.setMaterialId(baseBarcodeInfo.getMaterialId());
            wmsRawStock.setInstockBatch(instockBatch);
            wmsRawStock.setWarehouseFloor(baseLocation.getWarehouseFloor());
//            wmsRawStock.setLastOutstockTime(baseBarcodeInfo.getLastOutstockDate());
//            wmsRawStock.setQualityStatus(wmsRawInstockVo.getQualityStatus());
            wmsRawStock.setTotalAmount(wmsRawInstockVo.getInstockAmount());
            wmsRawStock.setCreateBy(userName);
            wmsRawStock.setCreateDate(currentDate);
            wmsRawStockMapper.insertWmsRawStock(wmsRawStock);
        }
    }


    /**
     * 柜体拆分后返库
     *
     * @param wmsRawBackVo
     */
    @Override
    public int applyRawBack(WmsRawBackVo wmsRawBackVo) {
        String materialBarcode = wmsRawBackVo.getMaterialBarcode();
        R<MesBaseBarcodeInfo> baseBarcodeInfoR = remoteMesService.getBarcode(materialBarcode, SecurityConstants.INNER);
        if (baseBarcodeInfoR == null) {
            throw new ServiceException("物料编码有误");
        }
        MesBaseBarcodeInfo baseBarcodeInfo = baseBarcodeInfoR.getData();
        if (baseBarcodeInfo == null) {
            throw new ServiceException("物料编码有误");
        }

        //判断此柜体是否已跟拆分门板绑定，如果未绑定不允许返库
        R<MesBaseBarcodeInfo> bindBarcodeInfoR = remoteMesService.getBarcodeByBindBarcode(materialBarcode, SecurityConstants.INNER);
        if (bindBarcodeInfoR == null) {
            throw new ServiceException("没找到绑定信息，不能返库");
        }
        MesBaseBarcodeInfo bindBarcodeInfo = bindBarcodeInfoR.getData();
        if (bindBarcodeInfo == null) {
            throw new ServiceException("没找到绑定信息，不能返库");
        }

        //判断是否有返库记录，不能重复提交
        WmsRawInstock queryRawInstock = new WmsRawInstock();
        queryRawInstock.setMaterialBarcode(materialBarcode);//materialBarcode是索引，先不需要加别的条件，获取出来再过滤
        List<WmsRawInstock> wmsRawInstocks = wmsRawInstockMapper.selectWmsRawInstockList(queryRawInstock);
        if (wmsRawInstocks != null && !wmsRawInstocks.isEmpty()) {
            List<WmsRawInstock> returnRawInstocks = wmsRawInstocks.stream().filter
                            (wmsRawInstock -> wmsRawInstock.getInstockType().equals(WmsConstants.RAW_INSTOCK_INSTOCK_TYPE_RETURN))
                    .collect(Collectors.toList());
            if (returnRawInstocks != null && !returnRawInstocks.isEmpty()) {
                throw new ServiceException("已经有此物料返库记录，无需重复返库");
            }
        }


        WmsRawInstock wmsRawInstock = new WmsRawInstock();
        wmsRawInstock.setTaskCode(Seq.getId(Seq.rawInstockSeqType, Seq.rawInstockSeqCode));
        wmsRawInstock.setWarehouseId(wmsRawBackVo.getWarehouseId());
        wmsRawInstock.setPoNo(baseBarcodeInfo.getPoNo());
        wmsRawInstock.setOperationType(WmsConstants.WMS_OPERATION_TYPE_AUTO);
        wmsRawInstock.setInstockType(WmsConstants.RAW_INSTOCK_INSTOCK_TYPE_RETURN);
        wmsRawInstock.setMaterialId(baseBarcodeInfo.getMaterialId());
        wmsRawInstock.setMaterialBarcode(materialBarcode);
        wmsRawInstock.setMaterialBatchCode(baseBarcodeInfo.getBatchCode());
        wmsRawInstock.setPalletInfoCode(baseBarcodeInfo.getPalletInfoCode());
        wmsRawInstock.setInstockAmount(BigDecimal.ONE);
        wmsRawInstock.setExecuteStatus(WmsConstants.WMS_EXECUTE_STATUS_TOEXECUTE);
        wmsRawInstock.setApplyBy(SecurityUtils.getUsername());
        wmsRawInstock.setApplyDate(new Date());

        //wcs轮询后执行完成要更新库存
        return wmsRawInstockMapper.insertWmsRawInstock(wmsRawInstock);
    }

}
