package com.cim.idm.service.Impl;

import com.cim.idm.dao.MaterialPackingDao;
import com.cim.idm.framework.IDMFrameServiceProxy;
import com.cim.idm.framework.data.EventInfo;
import com.cim.idm.model.dto.packing.MaterialPackingListDto;
import com.cim.idm.service.IMaterialPackingService;
import com.cim.idm.utils.EventInfoUtil;
import com.cim.idm.wmspackage.materialpacking.MaterialPackingServiceProxy;
import com.cim.idm.wmspackage.materialpacking.management.data.MaterialPackingKey;
import com.cim.idm.wmspackage.materialpacking.management.info.RemoveInfo;
import com.cim.idm.wmspackage.materialpacking.management.info.SetEventInfo;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class MaterialPackingServiceServiceImpl implements IMaterialPackingService {

    @Resource
    private MaterialPackingDao materialPackingDao;


    @Override
    public List<Map<String, Object>> getMaterialPacking(MaterialPackingListDto dto) {
        return materialPackingDao.getMaterialPacking(dto);
    }

    @Override
    public void delMaterialPacking(Map<String, Object> hashMap, String materialPackingName, String siteName, EventInfo makeEventInfo) {
        MaterialPackingKey materialPackingKey = new MaterialPackingKey(siteName, materialPackingName);
        RemoveInfo removeInfo = new RemoveInfo();
        MaterialPackingServiceProxy.getMaterialPackingService().remove(materialPackingKey, makeEventInfo, removeInfo);
        // 找到条码明细表的数据，先更新订单在删除条码明细
        String selectSql = "SELECT * FROM MATERIALPACKINGSUB m WHERE m.MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
        hashMap.put("MATERIALPACKINGNAME", materialPackingName);
        List<Map<String, Object>> queryForList2 = IDMFrameServiceProxy.getSqlTemplate().queryForList(selectSql, hashMap);
        for (Map<String, Object> item : queryForList2) {
            hashMap.put("RECEIVEREQUESTNAME", item.get("RECEIVEREQUESTNAME").toString());
            hashMap.put("RECEIVEREQUESTDETAILNAME", item.get("RECEIVEREQUESTDETAILNAME").toString());
            hashMap.put("QTY", item.get("QTY").toString());
            // 去掉接收数量更新
            String updateSql = "UPDATE MATERIALRECEIVEREQUESTDETAIL T SET T.RECEIVEDQUANTITY = T.RECEIVEDQUANTITY  - :QTY "
                    + "WHERE T.RECEIVEREQUESTNAME = :RECEIVEREQUESTNAME AND T.RECEIVEREQUESTDETAILNAME  = :RECEIVEREQUESTDETAILNAME";
            IDMFrameServiceProxy.getSqlTemplate().update(updateSql, hashMap);

            String deleteSql = "DELETE FROM MATERIALPACKINGSUB m WHERE m.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND RECEIVEREQUESTNAME = :RECEIVEREQUESTNAME";
            IDMFrameServiceProxy.getSqlTemplate().update(deleteSql, hashMap);
        }
    }

    /**
     * SAP物料消耗(正向、反向)
     * 2025-05-08
     * @param dataList body报文
     * @param siteName 工厂
     * @param userName 用户名
     */
    @Override
    public void materialConsumeSapBwtar(ArrayList<Map<String,Object>> dataList, String siteName, String userName) throws Exception  {
        String checkBwart = "";// 移动类型
        EventInfo eventInfo = new EventInfoUtil().makeEventInfo("materialConsumeSapBwtar", userName, "materialConsumeSapBwtar", "", "");
        for (Map<String, Object> data : dataList) {
            //存储要更新的MaterialPacking信息
            ArrayList<SetEventInfo> setEventInfoList = new ArrayList<>();
            //存储要更新MaterialPacking信息的key
            ArrayList<MaterialPackingKey> materialPackingKeyList = new ArrayList<>();
            String aufnr = MapUtils.getString(data, "AUFNR"); //生产单号
            String werks = MapUtils.getString(data, "WERKS");  // 组织
            String matnr = MapUtils.getString(data, "MATNR");  // 物料编号
            String bwart = MapUtils.getString(data, "BWART");  // 移动类型
            String menge = MapUtils.getString(data, "MENGE"); // 订单数量
            String meins = MapUtils.getString(data, "MEINS");  // 单位
            String lgort = MapUtils.getString(data, "LGORT");  // ERP库存地点
            String budatMkpf = MapUtils.getString(data, "BUDAT_MKPF");  // 过账日期
            String mblnr = MapUtils.getString(data, "MBLNR");  // 物料凭证号
            String zeile = MapUtils.getString(data, "ZEILE");  // 物料凭证号行号
            if (StringUtils.isEmpty(aufnr) || StringUtils.isEmpty(werks) || StringUtils.isEmpty(matnr)
                    || StringUtils.isEmpty(bwart) || StringUtils.isEmpty(menge) || StringUtils.isEmpty(meins)
                    || StringUtils.isEmpty(lgort) || StringUtils.isEmpty(budatMkpf) || StringUtils.isEmpty(mblnr)) {
                throw new Exception("AUFNR、WERKS、MATNR、BWART、MENGE、MEINS、LGORT、BUDAT_MKPF、MBLNR是必填项");
            }
            //操作数量
            BigDecimal mengeBigDecimal = new BigDecimal(menge);
            if (StringUtils.isNotEmpty(checkBwart) && !bwart.equals(checkBwart)){
                throw new Exception("不能同时操作261、262多种移动类型，请确认");
            }
            if ("261".equals(bwart)){
                //正向 BWART=261发料，根据WERKS+LGORT+AUFNR+MATNR+MEINS根据先进先出逻辑扣减MENGE量的库存
                //根据先进先出查询库存
                String selcetMaterialpackingSql = " SELECT\n" +
                        "\tSITENAME, MATERIALPACKINGNAME, MATERIALQUANTITY, CREATETIME \n" +
                        "FROM\n" +
                        "\tMATERIALPACKING \n" +
                        "WHERE\n" +
                        "\tSITENAME =:SITENAME\n" +
                        "\tAND STOCKSTATE =:STOCKSTATE\n" +
                        "\tAND ERPFACTORY =:ERPFACTORY \n" +
                        "\tAND ERPLOCATION =:ERPLOCATION\n" +
                        "\tAND UNIT =:UNIT\n" +
                        "\tAND MATERIALSPECNAME =:MATERIALSPECNAME \n" +
                        "ORDER BY CREATETIME ASC ";
                Map<String, Object> selcetMaterialpackingMap = new HashMap<String, Object> ();
                selcetMaterialpackingMap.put("SITENAME", siteName);
                selcetMaterialpackingMap.put("STOCKSTATE", "Stocked");
                selcetMaterialpackingMap.put("ERPFACTORY", werks);
                selcetMaterialpackingMap.put("ERPLOCATION", lgort);
                selcetMaterialpackingMap.put("UNIT", meins);
                selcetMaterialpackingMap.put("MATERIALSPECNAME", matnr);
                selcetMaterialpackingMap.put("UNDOID", mblnr);
                List<Map<String, Object>> queryMaterialpackingList = IDMFrameServiceProxy.getSqlTemplate().queryForList(selcetMaterialpackingSql, selcetMaterialpackingMap);
                for (int i = 0; i < queryMaterialpackingList.size(); i++) {
                    Map<String, Object> hashMap2 = new HashMap<String,Object>();
                    SetEventInfo setEventInfo = new SetEventInfo();

                    String materialPackingName = queryMaterialpackingList.get(i).get("MATERIALPACKINGNAME").toString();
                    String materialQuantity = queryMaterialpackingList.get(i).get("MATERIALQUANTITY").toString();
                    BigDecimal materialQuantityDecimal = new BigDecimal(materialQuantity);
                    if (mengeBigDecimal.compareTo(materialQuantityDecimal) < 0){
                        //消耗数量小于当前条码库存数量
                        materialQuantityDecimal = materialQuantityDecimal.subtract(mengeBigDecimal);
                        mengeBigDecimal = new BigDecimal(BigInteger.ZERO);

                        //保存要更新的MaterialPacking信息
                        materialQuantity = materialQuantityDecimal.toString();
                        hashMap2.put("materialQuantity", materialQuantity);
                        hashMap2.put("materialCreateQuantity", materialQuantity);
                        hashMap2.put("unDoID", mblnr);
                        setEventInfo.setUserColumns(hashMap2);
                        setEventInfoList.add(setEventInfo);
                        MaterialPackingKey materialPackingKey = new MaterialPackingKey(siteName, materialPackingName);
                        materialPackingKeyList.add(materialPackingKey);
                        break;
                    } else if (mengeBigDecimal.compareTo(materialQuantityDecimal) == 0){
                        //消耗数量等于当前条码库存数量
                        mengeBigDecimal = new BigDecimal(BigInteger.ZERO);
                        materialQuantityDecimal = new BigDecimal(BigInteger.ZERO);

                        //保存要更新的MaterialPacking信息
                        materialQuantity = materialQuantityDecimal.toString();
                        hashMap2.put("materialQuantity", materialQuantity);
                        hashMap2.put("materialCreateQuantity", materialQuantity);
                        hashMap2.put("unDoID", mblnr);
                        setEventInfo.setUserColumns(hashMap2);
                        setEventInfoList.add(setEventInfo);
                        MaterialPackingKey materialPackingKey = new MaterialPackingKey(siteName, materialPackingName);
                        materialPackingKeyList.add(materialPackingKey);
                        break;
                    } else {
                        //消耗数量大于当前条码库存数量
                        mengeBigDecimal = mengeBigDecimal.subtract(materialQuantityDecimal);
                        materialQuantityDecimal = new BigDecimal(BigInteger.ZERO);
                        //如果扣减后当前条码库存数量等于0，将状态改为StockOut
                        hashMap2.put("stockState", "StockOut");
                        //保存要更新的MaterialPacking信息

                        materialQuantity = materialQuantityDecimal.toString();
                        hashMap2.put("materialQuantity", materialQuantity);
                        hashMap2.put("materialCreateQuantity", materialQuantity);
                        hashMap2.put("unDoID", mblnr);
                        setEventInfo.setUserColumns(hashMap2);
                        setEventInfoList.add(setEventInfo);
                        MaterialPackingKey materialPackingKey = new MaterialPackingKey(siteName, materialPackingName);
                        materialPackingKeyList.add(materialPackingKey);
                    }

                }
                if (mengeBigDecimal.compareTo(BigDecimal.ZERO) > 0){
                    throw new Exception("消耗失败，物料：" + matnr + " " + werks + " " + lgort + " " + meins + "库存短缺");
                }
                MaterialPackingServiceProxy.getMaterialPackingService().setEvent(materialPackingKeyList, eventInfo, setEventInfoList);
            } else if ("262".equals(bwart)) {
                String smbln = MapUtils.getString(data, "SMBLN");  // 原始物料凭证号
                String smblp = MapUtils.getString(data, "SMBLP");  // 原始物料凭证号行号
                //反向 BWART=262冲销，根据MBLNR增加对应的数量
                String selcetMaterialpackingSql = " SELECT\n" +
                        "\tSITENAME, MATERIALPACKINGNAME, STOCKSTATE, MATERIALQUANTITY \n" +
                        "FROM\n" +
                        "\tMATERIALPACKING \n" +
                        "WHERE\n" +
                        "\tSITENAME =:SITENAME\n" +
                        "\tAND STOCKSTATE IN ('Stocked','StockOut')\n" +
                        "\tAND ERPFACTORY =:ERPFACTORY \n" +
                        "\tAND ERPLOCATION =:ERPLOCATION\n" +
                        "\tAND UNIT =:UNIT\n" +
                        "\tAND MATERIALSPECNAME =:MATERIALSPECNAME \n" +
                        "\tAND UNDOID =:UNDOID \n";
                Map<String, Object> selcetMaterialpackingMap = new HashMap<String, Object> ();
                selcetMaterialpackingMap.put("SITENAME", siteName);
                selcetMaterialpackingMap.put("ERPFACTORY", werks);
                selcetMaterialpackingMap.put("ERPLOCATION", lgort);
                selcetMaterialpackingMap.put("UNIT", meins);
                selcetMaterialpackingMap.put("MATERIALSPECNAME", matnr);
                selcetMaterialpackingMap.put("UNDOID", smbln);
                List<Map<String, Object>> queryMaterialpackingList = IDMFrameServiceProxy.getSqlTemplate().queryForList(selcetMaterialpackingSql, selcetMaterialpackingMap);
                for (int i = 0; i < queryMaterialpackingList.size(); i++) {
                    Map<String, Object> hashMap2 = new HashMap<String,Object>();
                    SetEventInfo setEventInfo = new SetEventInfo();

                    String materialPackingName = queryMaterialpackingList.get(i).get("MATERIALPACKINGNAME").toString();
                    String materialQuantity = queryMaterialpackingList.get(i).get("MATERIALQUANTITY").toString();
                    String stockState = queryMaterialpackingList.get(i).get("STOCKSTATE").toString();
                    BigDecimal materialQuantityDecimal = new BigDecimal(materialQuantity);
                    if("Stocked".equals(stockState)){
                        materialQuantityDecimal = materialQuantityDecimal.add(mengeBigDecimal);
                    }else if ("StockOut".equals(stockState)){
                        materialQuantityDecimal = mengeBigDecimal;
                        hashMap2.put("STOCKSTATE", "Stocked");
                    }
                    //保存要更新的MaterialPacking信息
                    materialQuantity = materialQuantityDecimal.toString();
                    hashMap2.put("materialQuantity", materialQuantity);
                    hashMap2.put("materialCreateQuantity", materialQuantity);
                    hashMap2.put("unDoID", mblnr);
                    setEventInfo.setUserColumns(hashMap2);
                    setEventInfoList.add(setEventInfo);
                    MaterialPackingKey materialPackingKey = new MaterialPackingKey(siteName, materialPackingName);
                    materialPackingKeyList.add(materialPackingKey);
                    break;
                }
                if (queryMaterialpackingList.isEmpty()){
                    throw new Exception("冲销失败，没有匹配该物料凭证：" + smbln + "的消耗记录无法冲销");
                }else {
                    MaterialPackingServiceProxy.getMaterialPackingService().setEvent(materialPackingKeyList, eventInfo, setEventInfoList);
                }

            } else {
                throw new Exception("不属于物料消耗261、262的移动类型，请确认");
            }
            checkBwart = bwart;
        }
    }
}
