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.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmswms.entity.InventoryCheck;
import com.sunda.spmswms.entity.InventoryCheckAction;
import com.sunda.spmswms.mapper.InventoryCheckMapper;
import com.sunda.spmswms.service.IInventoryCheckActionService;
import com.sunda.spmswms.service.IInventoryCheckDtlService;
import com.sunda.spmswms.service.IInventoryCheckService;
import com.sunda.spmswms.service.ISapDeliveryNoteLogService;
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;
import java.util.Map;
import java.util.UUID;

import static com.sunda.spmscommon.Constans.*;

/**
 * <p>
 * 仓库盘点任务表 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2021-05-10
 */
@Service
public class InventoryCheckServiceImpl extends ServiceImpl<InventoryCheckMapper, InventoryCheck> implements IInventoryCheckService {

    @Autowired
    IInventoryCheckDtlService iInventoryCheckDtlService;
    @Autowired
    IInventoryCheckActionService iInventoryCheckActionService;

    @Autowired
    ISapDeliveryNoteLogService iSapDeliveryNoteLogService;


    /**当盘盈亏单据关闭时，查询关联的盘点单是否可以关闭*/
    @Override
    public ResponseResult checkAndCloseInvChk(String inventoryCheckId) {
        InventoryCheck inventoryCheck=this.baseMapper.selectOne(new QueryWrapper<InventoryCheck>().eq("INVENTORY_CHECK_ID",inventoryCheckId));
        if(null==inventoryCheck){
            return ResponseResult.error("The give invcheck id is not exist: " + inventoryCheckId);
        }
        List<InventoryCheckAction> inventoryCheckActions=iInventoryCheckActionService.getInvChkAcByInvChkId(inventoryCheckId);
        boolean isCoseable=true;
        if(null!=inventoryCheckActions && inventoryCheckActions.size()>0){
            for(int i=0;i<inventoryCheckActions.size();i++){
                if(!inventoryCheckActions.get(i).getSpmsStatus().equals("4")){
                    isCoseable=false;
                }
            }
        }

        if(isCoseable){
            inventoryCheck.setSpmsStatus("5");
            this.baseMapper.update(inventoryCheck,new QueryWrapper<InventoryCheck>().eq("INVENTORY_CHECK_ID",inventoryCheckId));
        }

        return ResponseResult.success().add("inventoryCheck",inventoryCheck);
    }

    /**保存存盘点结果，生成盘盈盘亏单
    * {
          "invChkSurplus": {
            "invCheckAc": {
              "uuid": "盘盈盘亏任务UUID",
              "spmsId": "盘盈盘亏单号",
              "inventoryActionType": "盘盈盘亏类别 1-盘盈 2-盘亏",
              "werks": "工厂",
              "whsLocationCode": "仓库",
              "inventoryCheckId": "盘点单号",
              "inventoryCheckResult": "盘点结果 1-账实相符 2-盘盈 3-盘亏 4-盘盈盘亏",
              "inventoryCheckType": "是否杂货 X-备件货 M-贸易货",
              "inventoryCheckCategory": "盘点类别 1-日常盘点 2-月度盘点 3-动态盘点 4-其它盘点",
              "inventoryCheckMold": "盘点类型 1-明盘 2-暗盘",
              "createDate": "创建日期",
              "spmsStatus": "任务状态：1-待盘点；2-盘点中；3-复盘中；4-处理中；5-关闭(完成)",
              "requester": "创建人工号",
              "operator": "盘点人",
              "reviewer": "复核人",
              "approver": "审批人",
              "createTime": "创建时间",
              "updateUsername": "更新人",
              "updateTime": "更新时间",
              "justification": "申请原因",
              "remarks": "备注"
            },
            "invCheckAcDtls": [
              {
                "uuid": "盘盈盘亏任务UUID",
                "taskRowId": "盘盈盘亏任务行号",
                "materialNo": "物料编号",
                "boxNote": "箱码",
                "inventoryQuantity": "库存数量",
                "checkQuantity": "实盘数量",
                "discrepancy": "差异数量",
                "basicUnit": "基本单位",
                "storageUuid": "储位UUID",
                "remarks": "备注"
              }
            ]
          },
          "invChkLoss": {
            "invCheckAc": {}, // 与盘盈单相同
            "invCheckAcDtls": [] // 与盘盈单相同
          },
          "inventoryCheck": {
            "uuid": "盘点单的唯一id",
            "inventoryCheckId": "盘点单号",
            "werks": "工厂",
            "whsLocationCode": "仓库",
            "inventoryCheckType": "是否杂货 X-备件货 M-贸易货",
            "inventoryCheckCategory": "盘点类别 1-日常盘点 2-月度盘点 3-动态盘点 4-其它盘点",
            "inventoryCheckMold": "盘点类型 1-明盘 2-暗盘",
            "inventoryCheckDate": "盘点日期",
            "inventoryCheckResult": "盘点结果 1-账实相符 2-盘盈 3-盘亏 4-盘盈盘亏",
            "isReview": "是否复盘 1-初盘 2-复盘",
            "inventoryReviewId": "复盘单据UUID",
            "inventoryCheckSurplus": "盘盈单据号",
            "inventoryCheckLoss": "盘亏单据号",
            "createDate": "创建日期",
            "spmsStatus": "任务状态：1-待盘点；2-盘点中；3-复盘中；4-处理中；5-关闭(完成)",
            "requester": "创建人工号",
            "operator": "盘点人",
            "reviewer": "复核人",
            "approver": "审批人",
            "createTime": "创建时间",
            "updateUsername": "更新人",
            "updateTime": "更新时间"
          },
          "inventoryCheckDtls": [
            {
              "uuid": "盘点任务UUID",
              "taskRowId": "盘点任务行号",
              "materialNo": "物料编号",
              "boxNote": "箱码",
              "inventoryQuantity": "库存数量",
              "checkQuantity": "实盘数量",
              "discrepancy": "差异数量",
              "basicUnit": "基本单位",
              "storageUuid": "储位UUID",
              "remarks": "备注",
            }
          ]
        }
    * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult saveInventoryCheckRes(JSONObject InvCheckRes, String userId)throws Exception {
//        try {
            ResponseResult invChkLossRes ;
            ResponseResult invChkSurplusRes ;
            ResponseResult updateRes;
            QueryWrapper<InventoryCheck> queryWrapper;

            JSONObject inventoryCheckObj = InvCheckRes.containsKey("inventoryCheck") ? InvCheckRes.getJSONObject("inventoryCheck") : null;
            JSONArray inventoryCheckDtls = InvCheckRes.containsKey("inventoryCheckDtls") ? InvCheckRes.getJSONArray("inventoryCheckDtls") : null;
            JSONObject invChkSurplus = InvCheckRes.containsKey("invChkSurplus") ? InvCheckRes.getJSONObject("invChkSurplus") : null;
            JSONObject invChkLoss = InvCheckRes.containsKey("invChkLoss") ? InvCheckRes.getJSONObject("invChkLoss") : null;

            if (null == inventoryCheckObj || null == inventoryCheckDtls) {
                throw new Exception("Error, inventoryCheck or inventoryCheckDtls missed from the parameters, please double check");
            }
            InventoryCheck inventoryCheck = inventoryCheckObj.toJavaObject(InventoryCheck.class);

            /*如果invChkSurplus不空空，创建新的盘盈单据*/
            if (null != invChkSurplus) {
                invChkSurplusRes = iInventoryCheckActionService.updateInvCheckAc(invChkSurplus, userId);
                if (invChkSurplusRes.getCode() != 200) {
                    throw new Exception(invChkSurplusRes.getMsg());
                }
                inventoryCheck.setInventoryCheckSurplus(invChkSurplusRes.getObject("invCheckAc", InventoryCheckAction.class).getSpmsId());
            }

            /*invChkLoss，创建新的盘亏单据*/
            if (null != invChkLoss) {
                invChkLossRes = iInventoryCheckActionService.updateInvCheckAc(invChkLoss, userId);
                if (invChkLossRes.getCode() != 200) {
                    throw new Exception(invChkLossRes.getMsg());
                }
                inventoryCheck.setInventoryCheckLoss(invChkLossRes.getObject("invCheckAc", InventoryCheckAction.class).getSpmsId());
            }
            if (StringUtils.isNotEmpty(inventoryCheck.getUuid())) {
                // 更新
                updateRes = iInventoryCheckDtlService.updateInventoryCheckDtl(inventoryCheck.getUuid(), inventoryCheckDtls);
                if (updateRes.getCode() != 200) {
                    throw new Exception(updateRes.getMsg());
                }
                queryWrapper = new QueryWrapper<InventoryCheck>().eq("UUID", inventoryCheck.getUuid());
                this.baseMapper.update(inventoryCheck, queryWrapper);
            } else {
                // 新建
                String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
                inventoryCheck.setUuid(uuid);
                updateRes = iInventoryCheckDtlService.updateInventoryCheckDtl(uuid, inventoryCheckDtls);
                if (updateRes.getCode() != 200) {
                    throw new Exception(updateRes.getMsg());
                }
                this.baseMapper.insert(inventoryCheck);
                queryWrapper = new QueryWrapper<InventoryCheck>().eq("UUID", uuid);
            }
            InventoryCheck inventoryCheck1=this.baseMapper.selectOne(queryWrapper);
            return updateRes.add("inventoryCheck", inventoryCheck1)
                    .add("invCheckAcList",iInventoryCheckActionService.getInvChkAcByInvChkId(inventoryCheck1.getInventoryCheckId()));
//                    .add("inventoryCheckDtls",iInventoryCheckDtlService.getInventoryCheckDtl(inventoryCheck1.getUuid()));
//        } catch (Exception e) {
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error(e.getMessage());
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult getInventoryCheckWithDtl(String uuid) throws Exception{
//        try {
            QueryWrapper<InventoryCheck> queryWrapper = new QueryWrapper<InventoryCheck>().eq("UUID", uuid);
            InventoryCheck inventoryCheck = this.baseMapper.selectOne(queryWrapper);
            if (null == inventoryCheck) {
                throw new Exception("Could not find Inventory Check for uuid: " + uuid);
            }

            ResponseResult res = iInventoryCheckDtlService.getInventoryCheckDtl(uuid);
            if (res.getCode() != 200) {
                throw new Exception(res.getMsg());
            }

            // 获取关联的盘赢、盘亏单数据

            return res.add("inventoryCheck", inventoryCheck)
                    .add("invCheckAcList",iInventoryCheckActionService.getInvChkAcByInvChkId(inventoryCheck.getInventoryCheckId()));

//        } catch (Exception e) {
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error(e.getMessage());
//        }
    }

    /*获取库存盘点任务列表
         *{
               "werks":["CN01","CM31"],
               "whsLocationCode":["1011","1061"],
               "inventoryCheckType":"X",  // X-备件货, M-贸易货
               "inventoryCheckCategory":"1", //盘点类别 1-日常盘点 2-月度盘点 3-动态盘点 4-其它盘点
               "inventoryCheckDate":["20210401","20210501"],
               "inventoryCheckResult":"1", //盘点结果 1-账实相符 2-盘盈 3-盘亏 4-盘盈盘亏
               "isReview":"1", //是否复盘 1-初盘 2-复盘
               "spmsStatus":"1", //任务状态：1-待盘点；2-盘点中；3-复盘中；4-处理中；5-关闭(完成)
           }
         **/
    @Override
    public ResponseResult getInventoryCheck(JSONObject InvCheckFilter) {
        List<String> werks = InvCheckFilter.containsKey("werks") ? (List) InvCheckFilter.getJSONArray("werks") : null;
        List<String> whsLocationCode = InvCheckFilter.containsKey("whsLocationCode") ? (List) InvCheckFilter.getJSONArray("whsLocationCode") : null;
        String inventoryCheckType = InvCheckFilter.containsKey("inventoryCheckType")&& StringUtils.isNotEmpty(InvCheckFilter.getString("inventoryCheckType")) ? InvCheckFilter.getString("inventoryCheckType") : null;
        String[] inventoryCheckCategory = InvCheckFilter.containsKey("inventoryCheckCategory") && StringUtils.isNotEmpty(InvCheckFilter.getString("inventoryCheckCategory")) ? InvCheckFilter.getString("inventoryCheckCategory").split(",") : null;
        String inventoryCheckResult = InvCheckFilter.containsKey("inventoryCheckResult") ? InvCheckFilter.getString("inventoryCheckResult") : null;
        String inventoryCheckId = InvCheckFilter.containsKey("inventoryCheckId") ? InvCheckFilter.getString("inventoryCheckId") : null;
        // String isReview = InvCheckFilter.containsKey("isReview") ? InvCheckFilter.getString("isReview") : null;
        String[] spmsStatus = InvCheckFilter.containsKey("spmsStatus") && StringUtils.isNotEmpty(InvCheckFilter.getString("spmsStatus")) ? InvCheckFilter.getString("spmsStatus").split(",") : null;
        String startDate = null, endDate = null;
        if (InvCheckFilter.containsKey("inventoryCheckDate")) {
            List<String> datePeriod = (List) InvCheckFilter.getJSONArray("inventoryCheckDate");
            if (datePeriod.size() == 2) {
                startDate = datePeriod.get(0);
                endDate = datePeriod.get(1);
            }
        }
        QueryWrapper<InventoryCheck> queryWrapper = new QueryWrapper<InventoryCheck>();
        if (null != werks) queryWrapper.in("WERKS", werks);
        if (null != whsLocationCode) queryWrapper.in("WHS_LOCATION_CODE", whsLocationCode);
        if (StringUtils.isNotEmpty(inventoryCheckType)) queryWrapper.eq("INVENTORY_CHECK_TYPE", inventoryCheckType);
        if(null!=inventoryCheckCategory && inventoryCheckCategory.length>0){
            queryWrapper.in("INVENTORY_CHECK_CATEGORY",inventoryCheckCategory);
        }
        if (StringUtils.isNotEmpty(inventoryCheckResult)) queryWrapper.eq("INVENTORY_CHECK_RESULT", inventoryCheckResult);
        if (StringUtils.isNotEmpty(inventoryCheckId)){
            queryWrapper.eq("INVENTORY_CHECK_ID", inventoryCheckId);
        }
        if(null!=spmsStatus && spmsStatus.length>0){
            queryWrapper.in("SPMS_STATUS",spmsStatus);
        }
        if (StringUtils.isNotEmpty(startDate)) queryWrapper.between("INVENTORY_CHECK_DATE", startDate, endDate);
        try {
            return ResponseResult.success().add("invCheckList", this.baseMapper.selectList(queryWrapper.orderByDesc("CREATE_TIME")));
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Failed when query Inventory Check");
        }

    }

    /*新建盘点单
     * 1. 有uuid 更新
     * 2. 无uuid 新建
     * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult updateInventoryCheck(JSONObject InvCheckDoc, String userId) throws Exception{
//        try {
            JSONObject inventoryCheckObj = InvCheckDoc.containsKey("inventoryCheck") ? InvCheckDoc.getJSONObject("inventoryCheck") : null;
            JSONArray inventoryCheckDtls = InvCheckDoc.containsKey("inventoryCheckDtls") ? InvCheckDoc.getJSONArray("inventoryCheckDtls") : null;
            if (null == inventoryCheckObj || null == inventoryCheckDtls) {
                throw new Exception("Error, inventoryCheck or inventoryCheckDtls missed from the parameters, please double check");
            }
            InventoryCheck inventoryCheck = inventoryCheckObj.toJavaObject(InventoryCheck.class);
            if (StringUtils.isNotEmpty(inventoryCheck.getUuid())) {
                // 更新
                QueryWrapper<InventoryCheck> queryWrapper = new QueryWrapper<InventoryCheck>().eq("UUID", inventoryCheck.getUuid());
                ResponseResult res = iInventoryCheckDtlService.updateInventoryCheckDtl(inventoryCheck.getUuid(), inventoryCheckDtls);
                if (res.getCode() == 200) {
                    this.baseMapper.update(inventoryCheck, queryWrapper);
                    if ("5".equals(inventoryCheck.getSpmsStatus())){
                        iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(inventoryCheck.getUuid(), userId, INV_CHECK_CLOSE);
                    }else {
                        iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(inventoryCheck.getUuid(), userId, INV_CHECK_UPDATE);
                    }
                    InventoryCheck inventoryCheck1=this.baseMapper.selectOne(queryWrapper);
                    return res.add("inventoryCheck", inventoryCheck1)
                            .add("invCheckAcList",iInventoryCheckActionService.getInvChkAcByInvChkId(inventoryCheck1.getInventoryCheckId()));
//                            .add("inventoryCheckDtls",iInventoryCheckDtlService.getInventoryCheckDtl(inventoryCheck1.getUuid()));
                }
                throw new Exception(res.getMsg());
            } else {
                // 新建
                String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
                inventoryCheck.setUuid(uuid);
                ResponseResult res = iInventoryCheckDtlService.updateInventoryCheckDtl(uuid, inventoryCheckDtls);
                if (res.getCode() == 200) {
                    this.baseMapper.insert(inventoryCheck);
                    iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(inventoryCheck.getUuid(), userId, INV_CHECK);
                    QueryWrapper<InventoryCheck> queryWrapper = new QueryWrapper<InventoryCheck>().eq("UUID", uuid);
                    InventoryCheck inventoryCheck1=this.baseMapper.selectOne(queryWrapper);
                    return res.add("inventoryCheck", inventoryCheck1)
                            .add("invCheckAcList",iInventoryCheckActionService.getInvChkAcByInvChkId(inventoryCheck1.getInventoryCheckId()));
//                            .add("inventoryCheckDtls",iInventoryCheckDtlService.getInventoryCheckDtl(inventoryCheck1.getUuid()));
                }
                throw new Exception(res.getMsg());
            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error(e.getMessage());
//        }
    }

    @Override
    public List<Map<String, Object>> getInventoryCheckLogs(String uuid) {
        return iSapDeliveryNoteLogService.getDocumentLogs(uuid);
    }
}
