package com.shkj.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shkj.common.core.domain.Result;
import com.shkj.wms.bo.AdjustLocationBo;
import com.shkj.wms.bo.BusinStockMoveSQueryBo;
import com.shkj.wms.bo.LocationMoveBo;
import com.shkj.wms.domain.BaseLocation;
import com.shkj.wms.domain.BusinOutInPlan;
import com.shkj.wms.domain.BusinStockMoveD;
import com.shkj.wms.domain.SysStockDetail;
import com.shkj.wms.enums.MoveDStatusEnum;
import com.shkj.wms.enums.PlanStatusEnum;
import com.shkj.wms.enums.PlanTypeEnum;
import com.shkj.wms.mapper.BusinStockMoveDMapper;
import com.shkj.wms.service.*;
import com.shkj.wms.utils.IntIdUtil;
import com.shkj.wms.utils.SnowflakeIdWorker;
import com.shkj.wms.utils.WmsCallWcsUtil;
import com.shkj.wms.vo.BaseLocationVo;
import com.shkj.wms.vo.BusinStockMoveDVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
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.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 货位移动明细Service业务层处理
 *
 * @author lch
 * @date 2022-06-10
 */
@Slf4j
@Service
public class BusinStockMoveDServiceImpl extends ServiceImpl<BusinStockMoveDMapper, BusinStockMoveD> implements IBusinStockMoveDService {

    @Autowired
    private IBaseLocationService iBaseLocationService;

    @Autowired
    private ISysStockDetailService sysStockDetailService;

    @Autowired
    @Lazy
    private IBusinOutInPlanService businOutInPlanService;

    @Autowired
    private ISysSeqManaService iSysSeqManaService;

    @Autowired
    private IBasRuleService basRuleService;

    @Autowired
    private WmsCallWcsUtil wmsCallWcsUtil;

    @Autowired
    private ISysStockDetailQrcodeService iSysStockDetailQrcodeService;

    /**
     * 货位调整
     *
     * @param bo 薄
     * @return {@code Result<Boolean>}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> adjustLocation(AdjustLocationBo bo) {
        BaseLocationVo location = iBaseLocationService.queryLocationByCode(bo.getTargetLocationCode());
        if (location == null) {
            return Result.err().msg("目的货位不存在");
        }
        BaseLocation formLocation = iBaseLocationService.getByLocationCode(bo.getLocationCode());
        if (formLocation == null) {
            return Result.err().msg("移出货位不存在");
        }


        //选择货位为空的货位作为入库货位
        LambdaQueryWrapper<SysStockDetail> wrapper = new LambdaQueryWrapper<SysStockDetail>()
                .eq(SysStockDetail::getLocationCode, bo.getTargetLocationCode());

        List<SysStockDetail> list = sysStockDetailService.list(wrapper);
        // 这里三个数量都必须为0才可以/如果有一个不为0都不行 所以全部累加 大于0就不行
        if (CollectionUtils.isNotEmpty(list)) {
            return Result.err().msg("目的货位存在库存或者任务数据");
        }

        LambdaQueryWrapper<SysStockDetail> wrapperOld = new LambdaQueryWrapper<SysStockDetail>()
                .eq(SysStockDetail::getLocationCode, bo.getLocationCode());
        List<SysStockDetail> oldList = sysStockDetailService.list(wrapperOld);
        // 相同的货位上不可能有2条记录记录着相同的条码商品
        if (CollectionUtils.isEmpty(oldList)) {
            return Result.err().msg("原货位不存在");
        }

        Long code = IntIdUtil.generateIntId();
        List<BusinStockMoveD> businStockMoveDS = addMoveRecords(code.toString(), oldList, location);

        //todo 回调是否需要处理
        LocationMoveBo moveBo = new LocationMoveBo();
        moveBo.setBranchId(location.getBranchId());
        moveBo.setFromLocationCode(formLocation.getLocationCode());
        moveBo.setToLocationCode(location.getLocationCode());
        moveBo.setTaskId(code);
        moveBo.setFromRow(formLocation.getLocationRow());
        moveBo.setFromColumn(formLocation.getLocationColumn());
        moveBo.setFromLayer(formLocation.getLayer());
        moveBo.setToRow(location.getLocationRow());
        moveBo.setToColumn(location.getLocationColumn());
        moveBo.setToLayer(location.getLayer());
        Result result = wmsCallWcsUtil.locationAdjustment(moveBo);
        if (Result.isOk(result)) {
            // 成功就修改为执行中
            businStockMoveDS.forEach(x -> x.setMoveStatus(MoveDStatusEnum.DOING.getValue()));
        }
        this.saveBatch(businStockMoveDS);

        //添加计划
        addPlan(businStockMoveDS.get(0), oldList.get(0).getContainerId(), oldList.get(0).getContainerCode());
        return Result.ok();
    }

    public void addPlan(BusinStockMoveD moveD, Long containerId, String containerCode){
        BusinOutInPlan inPlan = new BusinOutInPlan();
        inPlan.setOrderNo(Long.parseLong(moveD.getOrderNo()));
        inPlan.setContainerId(containerId);
        //随机定义一个磨具即可
        inPlan.setContainerCode(containerCode);
        inPlan.setType(PlanTypeEnum.MOVE.getValue());
        inPlan.setPlanStatus(PlanStatusEnum.DOING.getValue());
        inPlan.setQty(moveD.getMoveQty());
        inPlan.setBranchId(moveD.getBranchId());
        inPlan.setMoldBarcode(moveD.getMoldBarcode())
                .setMoldId(moveD.getMoldId())
                .setMoldNo(moveD.getMoldNo());
        inPlan.setLocationId(moveD.getInLocationId());
        businOutInPlanService.save(inPlan);
    }

    /**
     * 把任务完成
     *
     * @param orderNo 订单没有
     * @return {@link Result}
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result moveTaskFinish(Long orderNo) {
        LambdaQueryWrapper<BusinStockMoveD> wrapper = new LambdaQueryWrapper<BusinStockMoveD>()
                .eq(BusinStockMoveD::getOrderNo, orderNo)
                .ne(BusinStockMoveD::getMoveStatus, MoveDStatusEnum.END.getValue());
        List<BusinStockMoveD> list = list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return Result.err().msg("不存在");
        }
        BaseLocationVo location = iBaseLocationService.queryLocationById(list.get(0).getInLocationId());
        if (location == null) {
            return Result.err().msg("货位不存在");
        }
        LambdaQueryWrapper<SysStockDetail> wrapperOld = new LambdaQueryWrapper<SysStockDetail>()
                .eq(SysStockDetail::getContainerCode, list.get(0).getOutContainerCode());
        List<SysStockDetail> oldList = sysStockDetailService.list(wrapperOld);
        Date date = new Date();
        oldList.forEach(detail -> {
            detail.setLocationCode(location.getLocationCode())
                    .setLocationId(location.getId())
                    .setAreaId(location.getAreaId())
                    .setStorageId(location.getStorageId())
                    .setInTime(date);
        });
        sysStockDetailService.updateBatchById(oldList);

        list.forEach(x -> x.setMoveStatus(MoveDStatusEnum.END.getValue()));
        this.updateBatchById(list);
        return Result.ok();
    }

    /**
     * 查询列表
     *
     * @param bo 薄
     * @return {@code List<BusinStockMoveDVo>}
     */
    @Override
    public List<BusinStockMoveDVo> queryList(BusinStockMoveSQueryBo bo) {
        List<BusinStockMoveDVo> list = this.baseMapper.queryList(bo);
        return list;
    }

    @Override
    public void updateMoveStatusByAgain(String orderNo) {
        LambdaQueryWrapper<BusinStockMoveD> wrapper = new LambdaQueryWrapper<BusinStockMoveD>().eq(BusinStockMoveD::getOrderNo, orderNo)
                .eq(BusinStockMoveD::getMoveStatus, MoveDStatusEnum.CREATE.getValue());
        BusinStockMoveD moveD = new BusinStockMoveD();
        moveD.setMoveStatus(MoveDStatusEnum.END.getValue());
        this.update(moveD, wrapper);
    }

    /**
     * 添加移动记录
     *
     * @param code     代码
     * @param oldList  旧列表
     * @param location 位置
     */
    private List<BusinStockMoveD> addMoveRecords(String code, List<SysStockDetail> oldList, BaseLocation location) {
        List<BusinStockMoveD> list = new ArrayList<>();
        for (SysStockDetail detail : oldList) {
            BusinStockMoveD moveD = new BusinStockMoveD();
            moveD.setOrderNo(code);
            moveD.setOutLocationId(detail.getLocationId());
            moveD.setOutLocationCode(detail.getLocationCode());
            moveD.setOutContainerCode(detail.getContainerCode());
            moveD.setInLocationId(location.getId());
            moveD.setInLocationCode(location.getLocationCode());
            moveD.setMoldId(detail.getMoldId());
            moveD.setMoldBarcode(detail.getBarcode());
            moveD.setMoldNo(detail.getMoldNo());
            moveD.setMoveStatus(MoveDStatusEnum.CREATE.getValue());
            moveD.setMoveQty(detail.getQty());
            moveD.setBranchId(detail.getBranchId());
            list.add(moveD);
        }
        return list;
    }

}
