package com.cim.idm.service.Impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cim.idm.data.ErpMessageLog;
import com.cim.idm.exception.GlobalException;
import com.cim.idm.framework.IDMFrameServiceProxy;
import com.cim.idm.framework.data.EventInfo;
import com.cim.idm.framework.orm.SqlTemplate;
import com.cim.idm.framework.util.sys.SystemPropHelper;
import com.cim.idm.framework.util.time.TimeStampUtil;
import com.cim.idm.mwmsextend.materialpacking.service.MaterialPackingServiceImpl;
import com.cim.idm.service.Impl.ProductIntoServiceImpl;
import com.cim.idm.service.Impl.ReturnStockIntoServiceImpl;
import com.cim.idm.service.MESToWMSService;
import com.cim.idm.service.QMSService;
import com.cim.idm.service.impl.ToSAPServiceImpl;
import com.cim.idm.util.MessageLogUtil;
import com.cim.idm.utils.AjaxResult;
import com.cim.idm.utils.CommonUtils;
import com.cim.idm.utils.EventInfoUtil;
import com.cim.idm.wmsextend.generic.errorHandler.CustomException;
import com.cim.idm.wmspackage.materialpacking.management.data.MaterialPackingKey;
import com.cim.idm.wmspackage.name.NameServiceProxy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.text.ParseException;
import java.util.*;

@Service("MESToWMS")
@Slf4j
public class MESToWMSServiceImpl implements MESToWMSService {


    @Autowired
    private ToSAPServiceImpl toSAPService;

    @Autowired
    private SqlTemplate sqlTemplate;

    @Autowired
    private ProductIntoServiceImpl productIntoServiceImpl;
    @Autowired
    private ReturnStockIntoServiceImpl returnStockIntoServiceImpl;
    @Autowired
    private QMSService qmsService;

    @Override
    @Transactional
    public AjaxResult materialConsume_Request(JSONArray in) throws Exception {
        AjaxResult result = new AjaxResult();
        ErpMessageLog loginfo = new ErpMessageLog();
        loginfo.setServerName("MESToWms");
        loginfo.setMessageId("");

        loginfo.setEventUser("MES");
        loginfo.setId(TimeStampUtil.getCurrentEventTimeKey());
        loginfo.setInterfaceTime(TimeStampUtil.getCurrentTime(TimeStampUtil.FORMAT_DEFAULT));
        loginfo.setSendMsg(in.toJSONString());
        loginfo.setEventName("materialConsume_Request");
        String siteName = System.getProperty("company", "SDK");

        Map<String, Object> bindMap = new HashMap<>();
        List<String> boxIdList = new ArrayList<>();
        List<String> qtyList = new ArrayList<>();
        List<MaterialPackingKey> mpList = new ArrayList<>();
        int success = 0;
        String errorCode = "";
        String wo = "";
        for (int i = 0; i < in.size(); i++) {
            JSONObject jb = in.getJSONObject(i);

            String charge = jb.get("charge").toString(); // 批号
            String qty = jb.get("qty").toString(); // 消耗数量
            wo = jb.get("requestName") == null ? "" : jb.get("requestName").toString(); // 工单
            boxIdList.add(charge);
            qtyList.add(qty);
        }
        // 将工单的物料消耗数据传给SAP
        String undoId = toSAPService.mesMaterialConsume(boxIdList, qtyList, "MES", wo);

        // 更新MATERIALPACKINGMDC表库存
        for (int j = 0; j < boxIdList.size(); j++) {

            String sqlu = "update MATERIALPACKINGMDC m SET m.MATERIALQUANTITY =m.MATERIALQUANTITY-:QTY,m.EVENTTIME =SYSDATE ,\r\n" +
                    " m.EVENTNAME =:EVENTNAME\r\n" +
                    " WHERE m.CHARGE =:CHARGE";
            Map<String, Object> bp = new HashMap<>();
            bp.put("CHARGE", boxIdList.get(j));
            bp.put("QTY", qtyList.get(j));
            bp.put("EVENTNAME", "MESCONSUME");
            IDMFrameServiceProxy.getSqlTemplate().update(sqlu, bp);

        }
        result = AjaxResult.me().setSuccess(true).setErrorCode(200).setMessage("执行成功");
        loginfo.setResultCode("0");
        loginfo.setReturnMsg(JSONObject.toJSONString(result));
        // 消息保存日志，erp推送wms的数据写入表BS_ERPMESSAGELOG中
        MessageLogUtil.writeMessageLog(loginfo);
        return result;
    }

    @Override
    @Transactional
    public AjaxResult materialOutByMES(JSONArray in) throws Exception {
        AjaxResult result = new AjaxResult();
        ErpMessageLog loginfo = new ErpMessageLog();
        loginfo.setServerName("MESToWms");
        loginfo.setMessageId("");
        loginfo.setEventUser("MES");
        loginfo.setInterfaceTime(TimeStampUtil.getCurrentTime(TimeStampUtil.FORMAT_DEFAULT));
        loginfo.setSendMsg(in.toJSONString());
        loginfo.setEventName("MaterialOut_Request");

        List<String> boxIdList = new ArrayList<>();
        String shipRequestName = "";
        for (int i = 0; i < in.size(); i++) {
            JSONObject jb = in.getJSONObject(i);
            String charge = jb.get("charge").toString(); // 批号
            shipRequestName = jb.get("shipRequestName").toString(); // 领料单号
            boxIdList.add(charge);

        }

        String billCode = new ToSAPServiceImpl().ProductionStockOut_NEW(shipRequestName, "SDK", "MES", boxIdList);

        EventInfo makeEventInfo = new EventInfoUtil().makeEventInfo("CompleteShipRequest", "MES", "CompleteShipRequest:MES Receive");
        new CommonUtils().SaveUnDoInfo_ForSap(boxIdList, billCode, makeEventInfo);

        result = AjaxResult.me().setSuccess(true).setErrorCode(200).setMessage("执行成功");
        loginfo.setResultCode("S");
        loginfo.setReturnMsg(JSONObject.toJSONString(result));
        // 消息保存日志，erp推送wms的数据写入表BS_ERPMESSAGELOG中
        MessageLogUtil.writeMessageLog(loginfo);
        return result;
    }

    @Override
    @Transactional
    public AjaxResult cancelShipByMES(JSONArray in) {
        AjaxResult result = new AjaxResult();
        ErpMessageLog loginfo = new ErpMessageLog();
        loginfo.setServerName("MESToWms");
        loginfo.setMessageId("");
        loginfo.setEventUser("MES");
        loginfo.setInterfaceTime(TimeStampUtil.getCurrentTime(TimeStampUtil.FORMAT_DEFAULT));
        loginfo.setSendMsg(in.toJSONString());
        loginfo.setEventName("CancelShip_Request");

        List<String> boxIdList = new ArrayList<>();
        for (int i = 0; i < in.size(); i++) {
            JSONObject jb = in.getJSONObject(i);
            String charge = jb.get("charge").toString(); // 批号
            boxIdList.add(charge);

        }

        String sqld = "DELETE FROM BS_MES_SHIPPED  b WHERE b.CHARGE in(:BOXIDLIST) AND NVL(b.receive_flag,'N')<>'Y' ";
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("BOXIDLIST", boxIdList);
        IDMFrameServiceProxy.getSqlTemplate().update(sqld, hashMap);

        result = AjaxResult.me().setSuccess(true).setErrorCode(200).setMessage("执行成功");
        loginfo.setResultCode("S");
        loginfo.setReturnMsg(JSONObject.toJSONString(result));
        // 消息保存日志，erp推送wms的数据写入表BS_ERPMESSAGELOG中
        MessageLogUtil.writeMessageLog(loginfo);
        return result;
    }

    @Override
    @Transactional
    public AjaxResult shipByMES(JSONArray in) throws Exception {
        AjaxResult result = new AjaxResult();
        ErpMessageLog loginfo = new ErpMessageLog();
        loginfo.setServerName("MESToWms");
        loginfo.setMessageId("");
        loginfo.setEventUser("MES");
        loginfo.setInterfaceTime(TimeStampUtil.getCurrentTime(TimeStampUtil.FORMAT_DEFAULT));
        loginfo.setSendMsg(in.toJSONString());
        loginfo.setEventName("Ship_Request");

        List<String> boxIdList = new ArrayList<>();
        List<String> barCodeList = new ArrayList<>();
        String stockInType = ""; // 用于记录是产成品入库，还是生产退料入库  入库类型，成品FG，退料MAT
        String operationType = ""; // 用于记录是否是自动入库  手动入库0，自动入库1
        if (in != null && in.size() > 0) {
            for (int i = 0; i < in.size(); i++) {
                JSONObject jb = in.getJSONObject(i);
                String charge = jb.get("charge").toString(); // 批号
                boxIdList.add(charge);
                barCodeList.add(jb.get("lotName").toString());
            }
            String sqld = "SELECT b.charge FROM BS_MES_SHIPPED  b WHERE b.CHARGE in(:BOXIDLIST) ";
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("BOXIDLIST", boxIdList);
            List<Map<String, Object>> existShips = sqlTemplate.queryForList(sqld, hashMap);
            if (existShips != null && existShips.size() > 0) {
                List<String> lots = new ArrayList<>();
                for (Map<String, Object> existShip : existShips) {
                    String lot = (String) existShip.get("charge");
                    lots.add(lot);
                }

                result = AjaxResult.me().setSuccess(false).setErrorCode(500).setMessage("执行失败:" + lots + " 已经SHIP,请不要重复SHIP");
                return result;
            }
            String needIqcSql = SystemPropHelper.CR + "SELECT IQCFLAG "
                    + "  FROM BS_MATERIALFACTORY bm "
                    + " WHERE bm.MATERIALSPECNAME = :MATERIALSPECNAME "
                    + "   AND bm.ERPFACTORY = :ERPFACTORY";
            String insertSql = SystemPropHelper.CR + "INSERT INTO BS_MES_SHIPPED(LOTNAME,QTY, UNIT, REQUESTNAME, AREA, "
                    + "PRODUCTSPECNAME, PRODUCTNAME, SDK_ID, PHASE, RECEIVE_FLAG,  REMARK, SHIPTIME, "
                    + "SHIPUSER, SITENAME, MATERIALSPECTYPE,"
                    + "INVENTORYTYPE, SALENO, SALEDETAILNO, ERPLOCATION, CHARGE, LOCATIONNAME, "
                    + "OPERATIONTYPE, ERPFACTORY,GXID)" + SystemPropHelper.CR
                    + "                     VALUES(:LOTNAME,:QTY,:UNIT,:REQUESTNAME, :AREA, "
                    + ":PRODUCTSPECNAME, :PRODUCTNAME, :SDK_ID, :PHASE, 'N',  :REMARK, :SHIPTIME, "
                    + "'MES', 'SDK', :MATERIALSPECTYPE, "
                    + ":INVENTORYTYPE, :SALENO, :SALEDETAILNO, :ERPLOCATION, :CHARGE, :LOCATIONNAME, "
                    + ":OPERATIONTYPE, :ERPFACTORY,:GXID)";
            String receiveActNo = "";
            String productSpecName = "";
            String erpFactory = "";
            for (int i = 0; i < in.size(); i++) {
                JSONObject jo = in.getJSONObject(i);
                String charge = jo.get("charge").toString(); // 批号
                String lotname = jo.getString("lotName");
                double qty = StringUtils.isEmpty(jo.getString("qty")) ? 0 : Double.parseDouble(jo.getString("qty"));
                String unit = jo.getString("unit");
                String requestName = jo.getString("requestName");
                String area = jo.getString("area");
                productSpecName = jo.getString("productSpecName");
                String productName = jo.getString("productName");
                String sdkId = jo.getString("sdkId");
                String phase = jo.getString("phase");
                String remark = jo.getString("remark");
                String shipTimeStr = jo.getString("shipTime");
                Timestamp shipTime = StringUtils.isEmpty(shipTimeStr) ? TimeStampUtil.getCurrentTimestamp() : TimeStampUtil.getTimestamp(shipTimeStr);
                String shipUser = jo.getString("shipUser");
                String inventoryType = jo.getString("inventoryType");
                String saleNo = jo.getString("saleNo");
                String saleDetailNo = jo.getString("saleDetailNo");
                String erpLocation = jo.getString("erpLocation");
                String locationName = jo.getString("locationName");
                String gxId = jo.getString("gxId"); // 增加管芯字段
                erpFactory = jo.getString("erpFactory");
                if (i == 0) {
                    stockInType = jo.getString("stockInType");
                    operationType = jo.getString("operationType");
                    List<String> args = Arrays.asList(new String[]{"SH", "F", TimeStampUtil.getCurrentTime("yyyyMMdd")});
                    receiveActNo = NameServiceProxy.getNameRuleDefService().generateName("ReceiveActNo", args, 1).get(0);
                }
                Map<String, Object> bindMap = new HashMap<>();
                bindMap.put("LOTNAME", lotname);
                bindMap.put("QTY", qty);
                bindMap.put("UNIT", unit);
                bindMap.put("REQUESTNAME", requestName);
                bindMap.put("AREA", area);
                bindMap.put("PRODUCTSPECNAME", productSpecName);
                bindMap.put("PRODUCTNAME", productName);
                bindMap.put("SDK_ID", sdkId);
                bindMap.put("PHASE", phase);
                bindMap.put("REMARK", remark);
                bindMap.put("SHIPTIME", shipTime);
                bindMap.put("SHIPUSER", shipUser);
                bindMap.put("INVENTORYTYPE", inventoryType);
                bindMap.put("SALENO", saleNo);
                bindMap.put("SALEDETAILNO", saleDetailNo);
                bindMap.put("ERPLOCATION", erpLocation);
                bindMap.put("LOCATIONNAME", locationName);
                bindMap.put("OPERATIONTYPE", operationType);
                bindMap.put("ERPFACTORY", erpFactory);
                bindMap.put("MATERIALSPECTYPE", stockInType);
                bindMap.put("CHARGE", charge);
                bindMap.put("GXID", gxId);

                if ("1".equals(operationType)) { // 自动入库
                    if ("FG".equals(stockInType)) { // 产成品入库
                        sqlTemplate.update(insertSql, bindMap);
                        MaterialPackingServiceImpl.checkMaterialPackingExist(lotname);

                        EventInfo makeEventInfo = EventInfoUtil.makeEventInfo("createfgBoxInfo", "MES", "createfgBoxInfo", "", "");
                        productIntoServiceImpl.receiveMesShippInfo(makeEventInfo, "SDK", lotname, "", "MES",
                                lotname, receiveActNo, erpLocation, erpFactory, locationName, requestName, "", "");
                    } else if ("MAT".equals(stockInType)) { // 生产退料入库
                        Map<String, Object> iqcBind = new HashMap<>();
                        iqcBind.put("MATERIALSPECNAME", productSpecName);
                        iqcBind.put("ERPFACTORY", erpFactory);
                        List<Map<String, Object>> iqcFlags = sqlTemplate.queryForList(needIqcSql, iqcBind);
                        if (iqcFlags != null && iqcFlags.size() > 0) {
                            if ("Y".equals(iqcFlags.get(0).get("IQCFLAG"))) {
                                throw new GlobalException("物料[" + productSpecName + "]需要质检，不允许自动入库，请手动入库");
                            }
                        }
                        sqlTemplate.update(insertSql, bindMap);
                        MaterialPackingServiceImpl.checkMaterialPackingExist(lotname);

                        EventInfo makeEventInfo = EventInfoUtil.makeEventInfo("createBoxInfoReturn", "MES", "createBoxInfoReturn", "", "");
//                        returnStockIntoServiceImpl.CreateMaterialReceiveRequestAct
//                                (makeEventInfo, "SDK", requestName, productSpecName, shipTimeStr,
//                                        receiveActNo, "ProduceReturn", Double.toString(qty), productSpecName);
                        returnStockIntoServiceImpl.SHIPMesShippInfo(makeEventInfo, "SDK", lotname, "", "MES",
                                lotname, receiveActNo, erpLocation, erpFactory, locationName, requestName,
                                productSpecName);
                    }
                } else {
                    sqlTemplate.update(insertSql, bindMap);
                }

            }
            if ("1".equals(operationType)) { // 自动入库
                if ("FG".equals(stockInType)) { // 产成品入库
                    boolean fgStockIn = productIntoServiceImpl.fgStockIn(receiveActNo, "MES");
                    if (!fgStockIn) {
                        throw new GlobalException("报送ERP失败,请联系IT处理！");
                    }
                    String checkIqcSql = "SELECT DISTINCT MATERIALSPECNAME, ERPFACTORY FROM MATERIALPACKING m WHERE M.RECEIVEACTNO = :RECEIVEACTNO";
                    Map<String, Object> bindMap = new HashMap<>();
                    bindMap.put("RECEIVEACTNO", receiveActNo);
                    bindMap.put("MATERIALSPECNAME", productSpecName);
                    bindMap.put("ERPFACTORY", erpFactory);
                    List<Map<String, Object>> materialSpecs = sqlTemplate.queryForList(needIqcSql, bindMap);
                    if (materialSpecs != null && materialSpecs.size() > 0) {
                        for (Map<String, Object> materialSpec : materialSpecs) {
                            Map<String, Object> iqcBind = new HashMap<>();
                            iqcBind.put("MATERIALSPECNAME", materialSpec.get("MATERIALSPECNAME"));
                            iqcBind.put("ERPFACTORY", materialSpec.get("ERPFACTORY"));
                            List<Map<String, Object>> iqcFlags = sqlTemplate.queryForList(needIqcSql, iqcBind);
                            if (iqcFlags != null && iqcFlags.size() > 0) {
                                if ("Y".equals(iqcFlags.get(0).get("IQCFLAG"))) {
                                    qmsService.PreIQCInfoSend(receiveActNo, "SDK", "", "");
                                }
                            }
                        }
                    }

                } else if ("MAT".equals(stockInType)) { // 生产退料入库
                    boolean fgStockIn = returnStockIntoServiceImpl.ReturnStockIn(receiveActNo, "MES", "", "");
                    if (!fgStockIn) {
                        throw new GlobalException("报送ERP失败,请联系IT处理！");
                    }
                    return AjaxResult.me().setResultObj(null);
                }
            }
        }
        result = AjaxResult.me().setSuccess(true).setErrorCode(200).setMessage("执行成功");
        loginfo.setResultCode("S");
        loginfo.setReturnMsg(JSONObject.toJSONString(result));
        // 消息保存日志，erp推送wms的数据写入表BS_ERPMESSAGELOG中
        MessageLogUtil.writeMessageLog(loginfo);
        return result;
    }
}