package com.prolog.cs.biz.inbound.service.impl.processor.Helper;

import com.alibaba.fastjson.JSON;
import com.prolog.cs.basic.warehouse.model.BaseWmsWarehouseLocator;
import com.prolog.cs.biz.inbound.constant.BizConstant;
import com.prolog.cs.biz.inbound.dao.task.TaskHostedDetailMapper;
import com.prolog.cs.biz.inbound.dto.rcv.RcvLinesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcLinesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcReLinesDTO;
import com.prolog.cs.biz.inbound.model.task.TaskHostedDetail;
import com.prolog.cs.biz.inbound.remote.BaseInventoryRemoteCaller;
import com.prolog.cs.biz.inbound.remote.BaseWmsWarehouseCaller;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.beans.BeanUtils;
import com.prolog.framework.bz.core.collection.ValidList;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.utils.JsonUtils;
import com.prolog.framework.utils.ObjectUtils;
import com.prolog.upcloud.base.inventory.vo.InvStockIn;
import com.prolog.upcloud.base.inventory.vo.InvStockInDetail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: upcloud-base-wh-inbound
 * @description: 代管流程帮助类
 * @author: Huanglh
 * @create: 2021-12-24 09:46
 **/
@Service
public class HostedHelper {
    @Resource
    private BaseInventoryRemoteCaller baseInventoryRemoteCaller;

    @Resource
    private TaskHostedDetailMapper taskHostedDetailMapper;

    @Resource
    private BaseWmsWarehouseCaller baseWmsWarehouseCaller;

    private static Logger logger = LoggerFactory.getLogger(HostedHelper.class);

    /**
     * 入库明细数据做代管入库操作
     *
     * @param list
     * @param inType
     * @param status
     */
    public void rcvLinesInHosted(List<RcvLinesDTO> list, String inType, String status, UserDTO userDTO, Date dateNow, String warehouserId) {
        // 构建入库参数
        ValidList<InvStockIn> invStock = new ValidList<>();
        List<TaskHostedDetail> hostedDetails = new ArrayList<>();
        String locatorId = this.getLocatorId(warehouserId, BizConstant.DGK);
        for (RcvLinesDTO rcvLinesDTO : list) {
            InvStockIn invStockIn = new InvStockIn();
            InvStockInDetail detail = new InvStockInDetail();
            List<InvStockInDetail> details = new ArrayList<>();
            detail.setQuantity(rcvLinesDTO.getPieceQty());
            detail.setContainerCode(rcvLinesDTO.getContainerCode());
            detail.setGoodsCaseCode(rcvLinesDTO.getGoodsCaseCode());
            detail.setLocatorId(locatorId);
            detail.setComments(rcvLinesDTO.getComments());
            detail.setStatus(status);
            detail.setInType(inType);
            detail.setBatchId(rcvLinesDTO.getBatchId());

            details.add(detail);
            invStockIn.setDetails(details);

            invStockIn.setAsnLineId(rcvLinesDTO.getAsnLineId());
            invStockIn.setAsnId(rcvLinesDTO.getAsnHeaderId());
            invStockIn.setRcvId(rcvLinesDTO.getRcvHeaderId());
            invStockIn.setWarehouseId(warehouserId);
            invStockIn.setRcvLineId(rcvLinesDTO.getRcvLineId());
            invStockIn.setTaskId(rcvLinesDTO.getTaskRecheckId());
            invStockIn.setEnterpriseId(userDTO.getEnterpriseId());

            invStock.add(invStockIn);

            // 代管任务记录
            TaskHostedDetail taskHostedDetail = new TaskHostedDetail();
            BeanUtils.copyProperties(rcvLinesDTO, taskHostedDetail);

            taskHostedDetail.setLocatorId(locatorId);
            taskHostedDetail.setTaskRecheckId(rcvLinesDTO.getTaskRecheckId());
            taskHostedDetail.setWarehouseId(warehouserId);
            taskHostedDetail.setGmtCreate(dateNow);
            taskHostedDetail.setCreator(userDTO.getId());
            taskHostedDetail.setGmtModified(dateNow);
            taskHostedDetail.setModifier(userDTO.getId());
            taskHostedDetail.setEnterpriseId(userDTO.getEnterpriseId());
            taskHostedDetail.setComments("收货待处理代管入库");
            // 记录用，不允许作业
            taskHostedDetail.setActiveFlag("0");
            // 状态 10-收货代管入库
            taskHostedDetail.setStatus("10");

            hostedDetails.add(taskHostedDetail);
        }

        this.inHostedAndRecord(invStock, hostedDetails);
    }

    /**
     * 质检明细数据做代管入库操作
     *
     * @param list
     * @param inType
     * @param status
     */
    public void rqcLinesInHosted(List<RqcLinesDTO> list, String inType, String status, UserDTO userDTO, Date dateNow, String warehouserId) {
        // 构建入库参数
        ValidList<InvStockIn> invStock = new ValidList<>();
        List<TaskHostedDetail> hostedDetails = new ArrayList<>();
        String locatorId = this.getLocatorId(warehouserId, BizConstant.DGK);
        for (RqcLinesDTO rqcLinesDTO : list) {
            InvStockIn invStockIn = new InvStockIn();
            InvStockInDetail detail = new InvStockInDetail();
            List<InvStockInDetail> details = new ArrayList<>();
            detail.setQuantity(rqcLinesDTO.getPieceQty());
            detail.setContainerCode(rqcLinesDTO.getContainerCode());
            detail.setGoodsCaseCode(rqcLinesDTO.getGoodsCaseCode());
            detail.setLocatorId(locatorId);
            detail.setStatus(status);
            detail.setInType(inType);
            detail.setBatchId(rqcLinesDTO.getBatchId());

            details.add(detail);
            invStockIn.setDetails(details);

            invStockIn.setAsnLineId(rqcLinesDTO.getAsnLineId());
            invStockIn.setAsnId(rqcLinesDTO.getAsnHeaderId());
            invStockIn.setRcvId(rqcLinesDTO.getRcvHeaderId());
            invStockIn.setWarehouseId(warehouserId);
            invStockIn.setRcvLineId(rqcLinesDTO.getRcvLineId());
            invStockIn.setTaskId(rqcLinesDTO.getTaskRecheckId());
            invStockIn.setEnterpriseId(userDTO.getEnterpriseId());

            invStock.add(invStockIn);

            // 代管任务记录
            TaskHostedDetail taskHostedDetail = new TaskHostedDetail();
            BeanUtils.copyProperties(rqcLinesDTO, taskHostedDetail);

            taskHostedDetail.setLocatorId(locatorId);
            taskHostedDetail.setTaskRecheckId(rqcLinesDTO.getTaskRecheckId());
            taskHostedDetail.setWarehouseId(warehouserId);
            taskHostedDetail.setGmtCreate(dateNow);
            taskHostedDetail.setCreator(userDTO.getId());
            taskHostedDetail.setGmtModified(dateNow);
            taskHostedDetail.setModifier(userDTO.getId());
            taskHostedDetail.setEnterpriseId(userDTO.getEnterpriseId());
            taskHostedDetail.setComments("验收待处理代管入库");
            // 记录用，不允许作业
            taskHostedDetail.setActiveFlag("0");
            // 状态 12-验收代管入库
            taskHostedDetail.setStatus("12");

            hostedDetails.add(taskHostedDetail);
        }

        this.inHostedAndRecord(invStock, hostedDetails);
    }

    /**
     * 质检单明细数据做代管出库操作
     *
     * @param list
     * @param inType
     * @param status
     */
    public void rqcReLinesOutHosted(List<RqcReLinesDTO> list, String inType, String status, UserDTO userDTO, Date dateNow, String warehouserId) {
        // 构建入库参数
        ValidList<InvStockIn> invStock = new ValidList<>();
        List<TaskHostedDetail> hostedDetails = new ArrayList<>();

        // 复检任务id
        List<String> taskReRqcIds = list.stream().map(RqcReLinesDTO::getTaskReRqcId).collect(Collectors.toList());
        Criteria criteria = Criteria.forClass(TaskHostedDetail.class);
        // 只找入库代管状态
        String[] inStatus = {"10", "12"};
        Restriction r1 = criteria.restrictionBuilder()
          .in("taskRecheckId", taskReRqcIds.toArray(new String[taskReRqcIds.size()]))
          .in("status", inStatus)
          .build();
        criteria.setRestriction(r1);
        List<TaskHostedDetail> taskHostedDetails = taskHostedDetailMapper.findByCriteria(criteria);
        Map<String, String> locatorIdMap = taskHostedDetails.stream()
          .collect(Collectors.toMap(TaskHostedDetail::getTaskRecheckId, TaskHostedDetail::getLocatorId));

        for (RqcReLinesDTO rqcReLinesDTO : list) {
            String locatorId;
            if (!locatorIdMap.containsKey(rqcReLinesDTO.getTaskReRqcId())) {
                throw new BizException("未查询到入库代管记录!");
            }
            locatorId = locatorIdMap.get(rqcReLinesDTO.getTaskReRqcId());

            InvStockIn invStockIn = new InvStockIn();
            InvStockInDetail detail = new InvStockInDetail();
            List<InvStockInDetail> details = new ArrayList<>();
            detail.setQuantity(rqcReLinesDTO.getPieceQty());
            detail.setContainerCode(rqcReLinesDTO.getContainerCode());
            detail.setGoodsCaseCode(rqcReLinesDTO.getGoodsCaseCode());
            detail.setLocatorId(locatorId);
            //            detail.setComments(rqcReLinesDTO.getComments());
            detail.setStatus(status);
            detail.setInType(inType);
            detail.setBatchId(rqcReLinesDTO.getBatchId());

            details.add(detail);
            invStockIn.setDetails(details);

            invStockIn.setAsnLineId(rqcReLinesDTO.getAsnLineId());
            invStockIn.setAsnId(rqcReLinesDTO.getAsnHeaderId());
            invStockIn.setRcvId(rqcReLinesDTO.getRcvHeaderId());
            invStockIn.setWarehouseId(warehouserId);
            invStockIn.setRcvLineId(rqcReLinesDTO.getRcvLineId());
            invStockIn.setTaskId(rqcReLinesDTO.getTaskReRqcId());
            invStockIn.setEnterpriseId(userDTO.getEnterpriseId());

            invStock.add(invStockIn);

            // 代管任务记录
            TaskHostedDetail taskHostedDetail = new TaskHostedDetail();
            BeanUtils.copyProperties(rqcReLinesDTO, taskHostedDetail);

            taskHostedDetail.setLocatorId(locatorId);
            taskHostedDetail.setTaskRecheckId(rqcReLinesDTO.getTaskReRqcId());
            taskHostedDetail.setWarehouseId(warehouserId);
            taskHostedDetail.setGmtCreate(dateNow);
            taskHostedDetail.setCreator(userDTO.getId());
            taskHostedDetail.setGmtModified(dateNow);
            taskHostedDetail.setModifier(userDTO.getId());
            taskHostedDetail.setEnterpriseId(userDTO.getEnterpriseId());
            // 记录用，不允许作业
            taskHostedDetail.setActiveFlag("0");
            if ("1".equals(rqcReLinesDTO.getHostedStatus())) {
                // 收货代管出库
                taskHostedDetail.setComments("收货待处理代管出库");

                // 状态 11-收货代管出库
                taskHostedDetail.setStatus("11");
            }
            if ("2".equals(rqcReLinesDTO.getHostedStatus())) {
                // 验收代管出库
                taskHostedDetail.setComments("验收待处理代管出库");

                // 状态 13-验收代管出库
                taskHostedDetail.setStatus("13");
            }

            hostedDetails.add(taskHostedDetail);
        }

        this.outHostedAndRecord(invStock, hostedDetails);
    }

    /**
     * 代管入库及添加记录操作
     *
     * @param invStock
     * @param hostedDetails
     */
    public void inHostedAndRecord(ValidList<InvStockIn> invStock, List<TaskHostedDetail> hostedDetails) {
        this.callHostedAndRecord(invStock, hostedDetails, "代管上架");
    }

    /**
     * 代管出库及添加记录操作
     *
     * @param invStock
     * @param hostedDetails
     */
    public void outHostedAndRecord(ValidList<InvStockIn> invStock, List<TaskHostedDetail> hostedDetails) {
        this.callHostedAndRecord(invStock, hostedDetails, "代管下架");
    }

    /**
     * 远程调用库存接口服务,添加代管记录
     *
     * @param invStock
     * @param hostedDetails
     * @param prefix
     */
    private void callHostedAndRecord(ValidList<InvStockIn> invStock, List<TaskHostedDetail> hostedDetails, String prefix) {
        // 远程调用库存接口服务
        RestMessage inStockBatchCheck = null;
        try {

            inStockBatchCheck = baseInventoryRemoteCaller.inStockBatchCheck(invStock);
            logger.info("调用库存接口inStockBatchCheck，入参：" + JsonUtils.toString(invStock) + "，返回："
              + JsonUtils.toString(inStockBatchCheck));
        } catch (Exception e) {
            logger.error(prefix + "调用远程库存服务失败!原因->{}", e);
            throw new BizException(prefix + "调用远程库存服务失败!");
        }
        if (inStockBatchCheck == null) {
            logger.error(prefix + "调用远程库存服务失败!");
            throw new BizException(prefix + "调用远程库存服务失败!");
        }
        if (!inStockBatchCheck.isSuccess()) {
            Object data = inStockBatchCheck.getData();
            String dataMsg = "";
            if (data != null) {
                dataMsg = data.toString();
            }
            throw new BizException(String.format(prefix + "调用远程库存服务失败!原因->%s", inStockBatchCheck.getMessage()) + dataMsg);
        }

        // 代管任务添加代管入库记录
        taskHostedDetailMapper.saveBatch(hostedDetails);
    }

    /**
     * 获取一个代管库位
     *
     * @param warehouserId
     * @param warehouseCategoryCode
     * @return
     */
    private String getLocatorId(String warehouserId, String warehouseCategoryCode) {
        Map<String, Object> param = new HashMap<>();
        param.put("warehouserId", warehouserId);
        param.put("warehouseCategoryCode", warehouseCategoryCode);

        RestMessage<Map<String, BaseWmsWarehouseLocator>> resMap = baseWmsWarehouseCaller.getLocations2Map(param);

        logger.info("调用库位接口getLocations2Map，入参：" + JSON.toJSONString(param) + "，返回："
          + JSON.toJSONString(resMap));

        String res;
        if (ObjectUtils.isNotNull(resMap) && resMap.isSuccess()) {
            Map<String, BaseWmsWarehouseLocator> data = resMap.getData();
            if (ObjectUtils.isNotNull(data) && data.size() > 0) {
                List<String> list = data.values().stream().map(BaseWmsWarehouseLocator::getWarehouseLocatorId)
                  .collect(Collectors.toList());
                res = list.get(0);
            } else {
                logger.error("获取货位信息为空!");
                throw new BizException("获取货位信息为空!");
            }
        } else {
            logger.error("调用远程库存服务获取货位信息失败!");
            throw new BizException("调用远程库存服务获取货位信息失败!");
        }

        return res;
    }
}
