package com.sunda.spmswms.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunda.spmscommon.Constans;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmswms.entity.SapDeliveryNote;
import com.sunda.spmswms.entity.SapDeliveryNoteDtl;
import com.sunda.spmswms.entity.WhsStorageInventory;
import com.sunda.spmswms.mapper.SapDeliveryNoteDtlMapper;
import com.sunda.spmswms.mapper.SapDeliveryNoteMapper;
import com.sunda.spmswms.mapper.WhsStorageInventoryMapper;
import com.sunda.spmswms.service.ISapDeliveryNoteWithdrawMService;
import com.sunda.spmswms.service.IWhsOperateLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;

@Service
public class ISapDeliveryNoteWithdrawMServiceImpl extends ServiceImpl<SapDeliveryNoteMapper, SapDeliveryNote> implements ISapDeliveryNoteWithdrawMService {

    @Autowired
    WhsStorageInventoryMapper whsStorageInventoryMapper;
    @Autowired
    WhsStorageInventoryServiceImpl whsStorageInventoryService;
    @Autowired
    SapDeliveryNoteMapper sapDeliveryNoteMapper;
    @Autowired
    SapDeliveryNoteDtlMapper sapDeliveryNoteDtlMapper;
    @Autowired
    WithdrawTaskServiceImpl withdrawTaskService;
    @Autowired
    IWhsOperateLogService iWhsOperateLogService;

    /**
     * 检查是否可以冲销
     */
    @Override
    public ResponseResult isWithdrawableM(String deliveryNoteSap, String userId, String createDate) {
        SapDeliveryNote sapDeliveryNote = getSapDeliveryNote(deliveryNoteSap);
        List<SapDeliveryNoteDtl> sapDeliveryNoteDtls = sapDeliveryNoteDtlMapper.selectList(new QueryWrapper<SapDeliveryNoteDtl>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap));
        if (null == sapDeliveryNote || null == sapDeliveryNoteDtls || sapDeliveryNoteDtls.size() <= 0) {
            // 无效的 sapDN号
            return ResponseResult.error("deliveryNoteSap: " + deliveryNoteSap + " is not validate, please double check");
        }
        String packageNote = sapDeliveryNote.getPackageNote();
        if (StringUtils.isNotEmpty(packageNote)) {
            // 非贸易货
            return ResponseResult.error("Only Trade goods allowed");
        }
        SapDeliveryNoteDtl sapDeliveryNoteDtl = sapDeliveryNoteDtls.get(0);
        String werks = sapDeliveryNoteDtl.getWerks();
        String whsLocationCode = sapDeliveryNoteDtl.getWhsLocationCode();
        String spmsStatus = sapDeliveryNote.getSpmsStatus();
        spmsStatus = StringUtils.isEmpty(spmsStatus) ? "0" : spmsStatus;

         /*
         * 货收货路径
         * null/0(待到货） --> 3 确认到货 --> 6 待上传SAP --> 7 上传SAP失败 --> 8 收货完成 -->11 关闭---> 0 已冲销
         * */

        switch (spmsStatus) {
            case "0":
                //  还没有开始的任务
                return ResponseResult.error("The given deliveryNoteSap:" + deliveryNoteSap + " not start yet");
            case "3":
            case "6":
            case "7":
            case "8":
            case "11":
                return checkStorageInventory(werks, whsLocationCode, sapDeliveryNoteDtls)
                        .add("spmsStatus", spmsStatus)
                        .add("sapVoucherNumber", sapDeliveryNote.getSapVoucherNumber())
                        .add("sapVoucherYear", sapDeliveryNote.getSapVoucherYear());
            default:
                return ResponseResult.error("SpmsStatus incorrect for sapDeliveryNote: " + deliveryNoteSap);
        }
    }

    /**
     * 执行库内数据冲销
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult withdrawSapDeliveryNote(String deliveryNoteSap, String userId, String createDate, String newSapVoucherNumber, String mobileType)throws Exception  {
//        try {
            SapDeliveryNote sapDeliveryNote = getSapDeliveryNote(deliveryNoteSap);
            List<SapDeliveryNoteDtl> sapDeliveryNoteDtls = sapDeliveryNoteDtlMapper.selectList(new QueryWrapper<SapDeliveryNoteDtl>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap));
            if (null == sapDeliveryNote || null == sapDeliveryNoteDtls || sapDeliveryNoteDtls.size() <= 0) {
                // 无效的 sapDN号
                throw new Exception("deliveryNoteSap: " + deliveryNoteSap + " is not validate, please double check");
            }
            String packageNote = sapDeliveryNote.getPackageNote();
            if (StringUtils.isNotEmpty(packageNote)) {
                // 非贸易货
                throw new Exception("Only Trade goods allowed");
            }
            SapDeliveryNoteDtl sapDeliveryNoteDtl = sapDeliveryNoteDtls.get(0);
            String werks = sapDeliveryNoteDtl.getWerks();
            String whsLocationCode = sapDeliveryNoteDtl.getWhsLocationCode();
            String spmsStatus = sapDeliveryNote.getSpmsStatus();
            spmsStatus = StringUtils.isEmpty(spmsStatus) ? "0" : spmsStatus;

            /*
             * 贸易货收货路径
             * null/0(待到货） --> 3 确认到货 --> 6 待上传SAP --> 7 上传SAP失败 --> 8 收货完成 -->11--->关闭---> 0 已冲销
            * */

            switch (spmsStatus) {
                case "3":
                case "6":
                case "7":
                case "8":
                case "11":
                    ResponseResult resetDtlRes = resetSapDeliveryNoteDtl(sapDeliveryNoteDtls, userId,werks,whsLocationCode);
                    if (resetDtlRes.getCode() != 200) {
                        // 更新行项目失败
                        throw new Exception(resetDtlRes.getMsg());
                    }
                    // 完成更新SapDN，返回
                    ResponseResult resetSapDNRes = resetSapDeliveryNote(deliveryNoteSap);
                    if (resetSapDNRes.getCode() != 200) {
                        // 冲销失败
                        throw new Exception(resetSapDNRes.getMsg());
                    }
                    return ResponseResult.success();
                default:
                    throw new Exception("SpmsStatus incorrect for sapDeliveryNote: " + deliveryNoteSap);
            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error(e.getMessage());
//        }

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult withdrawSapDeliveryNoteNotUpdate(String deliveryNoteSap, String userId, String createDate, String newSapVoucherNumber, String mobileType) throws Exception {
//        try {
            SapDeliveryNote sapDeliveryNote = getSapDeliveryNote(deliveryNoteSap);
            List<SapDeliveryNoteDtl> sapDeliveryNoteDtls = sapDeliveryNoteDtlMapper.selectList(new QueryWrapper<SapDeliveryNoteDtl>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap));
            if (null == sapDeliveryNote || null == sapDeliveryNoteDtls || sapDeliveryNoteDtls.size() <= 0) {
                // 无效的 sapDN号
                throw new Exception("deliveryNoteSap: " + deliveryNoteSap + " is not validate, please double check");
            }
            String packageNote = sapDeliveryNote.getPackageNote();
            if (StringUtils.isNotEmpty(packageNote)) {
                // 非贸易货
                throw new Exception("Only Trade goods allowed");
            }
            SapDeliveryNoteDtl sapDeliveryNoteDtl = sapDeliveryNoteDtls.get(0);
            String werks = sapDeliveryNoteDtl.getWerks();
            String whsLocationCode = sapDeliveryNoteDtl.getWhsLocationCode();
            String spmsStatus = sapDeliveryNote.getSpmsStatus();
            spmsStatus = StringUtils.isEmpty(spmsStatus) ? "0" : spmsStatus;

            /*
             * 贸易货收货路径
             * null/0(待到货） --> 3 确认到货 --> 6 待上传SAP --> 7 上传SAP失败 --> 8 收货完成 -->11--->关闭---> 0 已冲销
             * */

            switch (spmsStatus) {
                case "3":
                case "6":
                case "7":
                case "8":
                case "11":
                    ResponseResult resetDtlRes = resetSapDeliveryNoteDtlNotUpdate(sapDeliveryNoteDtls, userId,werks,whsLocationCode);
                    if (resetDtlRes.getCode() != 200) {
                        // 更新行项目失败
                        throw new Exception(resetDtlRes.getMsg());
                    }
                    return ResponseResult.success();
                default:
                    throw new Exception("SpmsStatus incorrect for sapDeliveryNote: " + deliveryNoteSap);
            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error(e.getMessage());
//        }

    }

    /* 根据deliveryNoteSap获取入库任务，取得入库任备状态 */
    @Override
    public SapDeliveryNote getSapDeliveryNote(String deliveryNoteSap) {
        return sapDeliveryNoteMapper.selectOne(new QueryWrapper<SapDeliveryNote>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap));
    }

    /* 检查储位库存 */
    @Override
    public ResponseResult checkStorageInventory(String werks, String whsLocationCode,
            List<SapDeliveryNoteDtl> sapDeliveryNoteDtls) {
        try {
            for (int i = 0; i < sapDeliveryNoteDtls.size(); i++) {
                SapDeliveryNoteDtl sapDeliveryNoteDtl = sapDeliveryNoteDtls.get(i);
                String tempStorage = sapDeliveryNoteDtl.getTempStorage();
                String materialNo = sapDeliveryNoteDtl.getMaterialNo();
                if (StringUtils.isEmpty(materialNo)) {
                    return ResponseResult.error("material No is empty for row :" + i);
                }
                double receivedQty = sapDeliveryNoteDtl.getReceivedQty() == null
                        || "".equals(sapDeliveryNoteDtl.getReceivedQty().toString())
                                ? 0
                                : sapDeliveryNoteDtl.getReceivedQty();
                /** 只有实收数量大于 0 的行才需要校验库存是否足够 */
                if (receivedQty > 0) {
                    if (StringUtils.isEmpty(tempStorage)) {
                        return ResponseResult.error(
                                "Can not find storage Info for materialNo: " + sapDeliveryNoteDtl.getMaterialNo());
                    }
                    JSONArray storageList = JSONArray.parseArray(sapDeliveryNoteDtl.getTempStorage());
                    if (null == storageList || storageList.size() <= 0) {
                        return ResponseResult.error(
                                "Can not find storage Info for materialNo: " + sapDeliveryNoteDtl.getMaterialNo());
                    }
                    /**
                     * 2022-04-19 优化库存检查的逻辑，有可能实在同一个物料在同一个位位存在多行的问题
                     * 我们以物料编码+储位uuid来合并数量，之后再进行库存检查
                     */
                    JSONArray storageArray = new JSONArray();
                    for (int k = 0; k < storageList.size(); k++) {
                        JSONObject storageObj = storageList.getJSONObject(k);
                        String storageUuid = storageObj.getString("storageUuid");
                        int qty = storageObj.containsKey("qty") ? storageObj.getInteger("qty") : 0;
                        if (StringUtils.isEmpty(storageUuid) || qty <= 0) {
                            return ResponseResult.error(
                                    "Can not find storage Info for materialNo: " + sapDeliveryNoteDtl.getMaterialNo());
                        }
                        boolean isExist = false;
                        for (int m = 0; m < storageArray.size(); m++) {
                            JSONObject mObj = storageArray.getJSONObject(m);
                            if (mObj.getString("materialNo").equals(materialNo)
                                    && mObj.getString("storageUuid").equals(storageUuid)) {
                                mObj.put("qty", mObj.getInteger("qty") + qty);
                                isExist = true;
                            }
                        }
                        if (!isExist) {
                            JSONObject mObj = new JSONObject();
                            mObj.put("materialNo", materialNo);
                            mObj.put("qty", qty);
                            mObj.put("storageUuid", storageUuid);
                            storageArray.add(mObj);
                        }
                    }
                    for (int k = 0; k < storageArray.size(); k++) {
                        JSONObject storageObj = storageArray.getJSONObject(k);
                        String storageUuid = storageObj.getString("storageUuid");
                        int qty = storageObj.getInteger("qty");
                        if (StringUtils.isEmpty(storageUuid) || qty <= 0) {
                            return ResponseResult.error(
                                    "Can not find storage Info for materialNo: " + sapDeliveryNoteDtl.getMaterialNo());
                        }
                        WhsStorageInventory whsStorageInventory = whsStorageInventoryMapper
                                .selectOne(new QueryWrapper<WhsStorageInventory>()
                                        .eq("UUID", storageUuid)
                                        .eq("MATERIAL_NO", materialNo));
                        if (whsStorageInventory == null || whsStorageInventory.getQuantity() < qty) {
                            return ResponseResult.error("Storage Inventory check failed for materialNo: "
                                    + sapDeliveryNoteDtl.getMaterialNo());
                        }
                    }
                }
            }
            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Error when checking storage inventory");
        }
    }

     /* 重置 SAP_DELIVERY_NOTE
     *  SPMS_STATUS 0,
     *  DOCUMENT_DATE,
     *  POSTING_DATE,
     *  MOBILE_TYPE,
     *  USER_ID,
     *  PDA_SN,
     *  SAP_VOUCHER_NUMBER,
     *  SAP_VOUCHER_YEAR
     *  设为空
     *  */
    @Override
    public ResponseResult resetSapDeliveryNote(String deliveryNoteSap) throws Exception {
        try {
            UpdateWrapper updateWrapper = new UpdateWrapper<SapDeliveryNote>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap);
            SapDeliveryNote sapDeliveryNote = new SapDeliveryNote();
            sapDeliveryNote.setSpmsStatus("0");
            // Aug 3, kpzhang@cn.ibm.com, 近用户要求,在撤销采购入库时,不清空行上的实收数量
            // sapDeliveryNote.setDocumentDate("");
            // sapDeliveryNote.setPostingDate("");
            // sapDeliveryNote.setMobileType("");
            // sapDeliveryNote.setUserId("");
            // sapDeliveryNote.setSapVoucherNumber("");
            // sapDeliveryNote.setSapVoucherYear("");
            sapDeliveryNoteMapper.update(sapDeliveryNote, updateWrapper);
            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(
                    "重置SAP_DELIVERY_NOTE DOCUMENT_DATE,POSTING_DATE,MOBILE_TYPE,USER_ID, PDA_SN,SAP_VOUCHER_NUMBER,SAP_VOUCHER_YEAR设为空存,失败");
            // return ResponseResult.error("重置SAP_DELIVERY_NOTE
            // DOCUMENT_DATE,POSTING_DATE,MOBILE_TYPE,USER_ID,
            // PDA_SN,SAP_VOUCHER_NUMBER,SAP_VOUCHER_YEAR设为空存,失败");
        }
    }

    /* 重置 SAP_DELIVERY_NOTE_DTL RECEIVED_QTY,ITEM_STATUS, TEMP_STORAGE */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult resetSapDeliveryNoteDtl(List<SapDeliveryNoteDtl> sapDeliveryNoteDtls, String userId, String werks, String whsLocationCode) throws Exception {
//        try {
            JSONArray objList = new JSONArray();
            for (int i = 0; i < sapDeliveryNoteDtls.size(); i++) {
                // 更新行项目
                String tempStorage = sapDeliveryNoteDtls.get(i).getTempStorage();
                // Aug 3, kpzhang@cn.ibm.com, 近用户要求,在撤销采购入库时,不清空行上的实收数量
                // SapDeliveryNoteDtl sapDeliveryNoteDtl = new SapDeliveryNoteDtl();
                // sapDeliveryNoteDtl.setTempStorage("[]");
                // sapDeliveryNoteDtl.setReceivedQty(0.0);
                // sapDeliveryNoteDtl.setItemStatus("0");
                String deliveryNoteSap = sapDeliveryNoteDtls.get(i).getDeliveryNoteSap();
                String materialNo = sapDeliveryNoteDtls.get(i).getMaterialNo();

                // 扣减储位库存
                JSONArray storageList = JSONArray.parseArray(tempStorage);
                if (storageList != null && storageList.size() > 0) {
                    for (int k = 0; k < storageList.size(); k++) {
                        JSONObject storageObj = storageList.getJSONObject(k);
                        String storageUuid = storageObj.getString("storageUuid");
                        Double qty = storageObj.getDouble("qty");

                        // 扣减储位库存
                        if (whsStorageInventoryService.updateWhsStorage(storageUuid, materialNo, qty) < 0) {
                            throw new Exception(
                                    "Update Storage Inventory failed for " + materialNo + " on storage storageUuid: " +
                                            storageUuid + ", qty: " + qty);
                        }
                        iWhsOperateLogService.insertOperateLog(
                                Constans.WhsOperateLog_DocumentType_NanShaStorageLog,
                                storageUuid,
                                materialNo,
                                "",
                                qty,
                                Constans.WhsOperateLog_OperationType_ShelfOff,
                                deliveryNoteSap,
                                Constans.WHS_WhsIn_Withdraw_ShelfOffM,
                                userId,
                                Constans.WHS_WhsIn_WithdrawM,
                                werks,
                                whsLocationCode,
                                deliveryNoteSap);

                        // 将数据返回，用于创建冲销任务明细
                        storageObj.put("materialNo", materialNo);
                        objList.add(storageObj);
                    }
                }
                // Aug 3, kpzhang@cn.ibm.com, 近用户要求,在撤销采购入库时,不清空行上的实收数量
                // int res = sapDeliveryNoteDtlMapper.update(sapDeliveryNoteDtl, new
                // UpdateWrapper<SapDeliveryNoteDtl>()
                // .eq("DELIVERY_NOTE_SAP", deliveryNoteSap).eq("MATERIAL_NO", materialNo));
                // if (res <= 0) {
                // throw new Exception("Error when update DeliverNoteDtl + materialNo: " +
                // materialNo + " , deliveryNoteSap: " + deliveryNoteSap);
                // }
            }
            return ResponseResult.success().add("storageList", objList.toArray());
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw e;
//            // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            // return ResponseResult.error("Error when reset SapDeliveryNoteDtl");
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult resetSapDeliveryNoteDtlNotUpdate(List<SapDeliveryNoteDtl> sapDeliveryNoteDtls, String userId, String werks, String whsLocationCode) throws Exception {
//        try {
            JSONArray objList = new JSONArray();
            for (int i = 0; i < sapDeliveryNoteDtls.size(); i++) {
                // 更新行项目
                String tempStorage = sapDeliveryNoteDtls.get(i).getTempStorage();
                String deliveryNoteSap = sapDeliveryNoteDtls.get(i).getDeliveryNoteSap();
                String materialNo = sapDeliveryNoteDtls.get(i).getMaterialNo();

                // 扣减储位库存
                JSONArray storageList = JSONArray.parseArray(tempStorage);
                if (storageList != null && storageList.size() > 0) {
                    for (int k = 0; k < storageList.size(); k++) {
                        JSONObject storageObj = storageList.getJSONObject(k);
                        String storageUuid = storageObj.getString("storageUuid");
                        Double qty = storageObj.getDouble("qty");

                        // 扣减储位库存
                        if (whsStorageInventoryService.updateWhsStorageNotUpdate(storageUuid, materialNo, qty) < 0) {
                            throw new Exception(
                                    "Update Storage Inventory failed for " + materialNo + " on storage storageUuid: " +
                                            storageUuid + ", qty: " + qty);
                        }
                        // 将数据返回，用于创建冲销任务明细
                        storageObj.put("materialNo", materialNo);
                        objList.add(storageObj);
                    }
                }
            }
            return ResponseResult.success().add("storageList", objList.toArray());
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw e;
//            // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            // return ResponseResult.error("Error when reset SapDeliveryNoteDtl");
//        }
    }


}
