package com.foreverwin.mesnac.dispatch.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.foreverwin.mesnac.common.constant.Constants;
import com.foreverwin.mesnac.common.constant.DataImportConstant;
import com.foreverwin.mesnac.common.enums.HandleEnum;
import com.foreverwin.mesnac.common.util.ExceptionUtil;
import com.foreverwin.mesnac.common.util.StringUtil;
import com.foreverwin.mesnac.dispatch.dto.IssueItemDto;
import com.foreverwin.mesnac.dispatch.mapper.CallItemMapper;
import com.foreverwin.mesnac.dispatch.model.CallItem;
import com.foreverwin.mesnac.dispatch.model.IssueItem;
import com.foreverwin.mesnac.dispatch.mapper.IssueItemMapper;
import com.foreverwin.mesnac.dispatch.model.ItemBatch;
import com.foreverwin.mesnac.dispatch.model.SurplusInventory;
import com.foreverwin.mesnac.dispatch.service.CallItemService;
import com.foreverwin.mesnac.dispatch.service.IssueItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.foreverwin.mesnac.dispatch.service.ItemBatchService;
import com.foreverwin.mesnac.dispatch.service.SurplusInventoryService;
import com.foreverwin.mesnac.meapi.model.Inventory;
import com.foreverwin.mesnac.meapi.model.InventoryAssyData;
import com.foreverwin.mesnac.meapi.model.Item;
import com.foreverwin.mesnac.meapi.model.Sfc;
import com.foreverwin.mesnac.meapi.service.InventoryAssyDataService;
import com.foreverwin.mesnac.meapi.service.InventoryService;
import com.foreverwin.mesnac.meapi.service.ItemService;
import com.foreverwin.mesnac.meapi.service.SfcService;
import com.foreverwin.modular.core.exception.BusinessException;
import com.foreverwin.modular.core.meext.MEServices;
import com.sap.me.common.MaterialType;
import com.sap.me.common.ObjectReference;
import com.sap.me.inventory.*;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;


/**
 * <p>
 * 车间发料 服务实现类
 * </p>
 *
 * @author Leon.L
 * @since 2021-07-09
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class IssueItemServiceImpl extends ServiceImpl<IssueItemMapper, IssueItem> implements IssueItemService {

    @Autowired
    private SfcService sfcService;
    @Autowired
    private ItemService itemService;
    @Autowired
    private IssueItemMapper issueItemMapper;
    @Autowired
    private CallItemService callItemService;
    @Autowired
    private CallItemMapper callItemMapper;
    @Autowired
    private ItemBatchService itemBatchService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private SurplusInventoryService surplusInventoryService;


    @Override
    public BigDecimal getInvIssueQty(String site, String inventory) {
        BigDecimal qty = issueItemMapper.selectInvIssueQty(site, inventory);

        return (qty == null ? BigDecimal.ZERO : qty);
    }

    @Override
    public Map<String, Object> scanIssueInventory(String site, String item, String inventory, Boolean oddments) {
        Item itemModel = itemService.selectCurrent(site, item);
        if (itemModel == null) {
            throw BusinessException.build("物料【"  +item+"】的当前版本不存在！");
        }
        String itemBo = itemModel.getHandle();
        String materialType = itemModel.getMaterialType();

        //返回参数
        Map<String, Object> map = new HashMap<>();
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if (MaterialType.RAW.value().equals(materialType)){
            //原材料
            List<ItemBatch> itemBatchList = itemBatchService.findItemLabel(site, item, inventory);
            if (itemBatchList == null || itemBatchList.size() <= 0) {
                throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不存在！");
            }

        } else {
            //半成品|成品物料
            String inventoryBo = HandleEnum.INVENTORY.getHandle(site, inventory);
            Inventory inventoryModel = inventoryService.getById(inventoryBo);
            if (inventoryModel == null) {
                String sfcBo = HandleEnum.SFC.getHandle(site, inventory);
                Sfc sfcModel = sfcService.getById(sfcBo);
                if (sfcModel !=  null) {
                    if (!sfcModel.getItemBo().equals(itemBo)) {
                        throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不是物料【"+ item +"】的批次！");
                    }

                    map.put("qty", sfcModel.getQty());
                    return map;
                }

                throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不存在！");
            }

            if (!inventoryModel.getItemBo().equals(itemBo)) {
                throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不是物料【"+ item +"】的库存！");
            }
            map.put("qty", inventoryModel.getQtyOnHand());
        }

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //查询余料长宽
        if (oddments && StringUtil.notBlank(inventory)) {
            List<SurplusInventory> list = surplusInventoryService.selectSurplusLWList(site, inventory);
            if (list == null || list.size() <= 0) {
                throw BusinessException.build("物料条码【" +inventory+ "】没有可用余料");
            }
            map.put("wlList", list);
        }

        return map;
    }

    @Override
    public void issueItem(String site, String user, JSONObject jsonObject) {
        JSONArray jsonArray = jsonObject.getJSONArray("inventoryItems");
        if (jsonArray == null || jsonArray.size() <= 0) {
            throw BusinessException.build("发料清单不能为空！");
        }

        String item = jsonObject.getString("item");
        if (StringUtil.isBlank(item)) {
            throw BusinessException.build("物料编号不能为空！");
        }
        Item itemModel = itemService.selectCurrent(site, item);
        if (itemModel == null) {
            throw BusinessException.build("物料【" +item+"】没有维护当前版本！");
        }
        String itemBo = itemModel.getHandle();
        String materialType = itemModel.getMaterialType();
        Boolean oddments = jsonObject.getBoolean("oddments");
        String resource = jsonObject.getString("resource");
        String workCenter = jsonObject.getString("workCenter");
        String workOrder = jsonObject.getString("workOrder");
        String blankingSize = jsonObject.getString("blankingSize");


        LocalDateTime dateTime = LocalDateTime.now();
        List<CallItem> callItemList = new ArrayList<>();
        List<IssueItem> issueItemList = new ArrayList<>();
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if (!oddments) {
            //非余料发料 原材料-创建库存，计算发料数量; 半成品|成品-只计算发料数量
            InventoryServiceInterface meInventoryService;
            try {
                meInventoryService = MEServices.create("com.sap.me.inventory", "InventoryService", site);
            } catch (Exception e) {
                throw BusinessException.build("获取标准库存操作服务失败：" + e.getMessage());
            }

            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject _jsonObject = jsonArray.getJSONObject(i);

                String inventory = _jsonObject.getString("inventory");
                String inventoryBo = HandleEnum.INVENTORY.getHandle(site, inventory);
                String qty = _jsonObject.getString("qty");
                BigDecimal issueInvQty = new BigDecimal(qty);

                if (MaterialType.RAW.value().equals(materialType)) {
                    //原材料
                    List<ItemBatch> itemBatchList = itemBatchService.findItemLabel(site, item, inventory);
                    if (itemBatchList == null || itemBatchList.size() <= 0) {
                        throw BusinessException.build("扫描的物料条码【 " + inventory + " 】不存在！");
                    }
                    String batch = itemBatchList.get(0).getBatch();
                    String supplier = itemBatchList.get(0).getSupplier();

                    try {
                        //查询库存是否存在
                        ObjectReference objectReference = new ObjectReference();
                        objectReference.setRef(inventoryBo);
                        com.sap.me.inventory.Inventory inventoryModel = meInventoryService.findInventoryByRef(objectReference);

                        if (inventoryModel == null) {
                            //库存创建
                            InventoryValidateAndAddRequest request = new InventoryValidateAndAddRequest();
                            request.setItemRef(itemBo);
                            request.setInventoryId(inventory);
                            request.setQuantityOnHand(issueInvQty);

                            //库存自定义字段
                            List<InventoryDataField> inventoryDataFieldList = new ArrayList<>();
                            InventoryDataField dataField = new InventoryDataField();
                            dataField.setAttribute("BATCH_NUMBER");
                            dataField.setValue(batch);
                            inventoryDataFieldList.add(dataField);

                            dataField = new InventoryDataField();
                            dataField.setAttribute("VENDOR_NAME");
                            dataField.setValue(supplier);
                            inventoryDataFieldList.add(dataField);
                            request.setAssemblyDataList(inventoryDataFieldList);

                            meInventoryService.validateAndAdd(request);
                        } else {
                            String inventoryId = inventoryModel.getInventoryId();
                            BigDecimal handOnQty = issueItemMapper.selectLoadInventoryQty(site, inventoryId);
                            issueInvQty = issueInvQty.add(inventoryModel.getQtyOnHand()).add(handOnQty);

                            //库存修改
                            InventoryValidateAndUpdateWithReceiveQuantityOverrideRequest request = new InventoryValidateAndUpdateWithReceiveQuantityOverrideRequest();
                            request.setItemRef(itemBo);
                            request.setInventoryId(inventory);
                            request.setReceiveQty(issueInvQty);
                            request.setQuantityOnHand(issueInvQty);
                            request.setModifiedDateTime(inventoryModel.getModifiedDateTime());
                            meInventoryService.validateAndUpdateWithReceiveQtyOverride(request);
                        }
                    } catch (Exception e) {
                        ExceptionUtil.throwException(e);
                    }
                } else {
                    //半成品|成品
                    Inventory inventoryModel = inventoryService.getById(inventoryBo);
                    if (inventoryModel == null) {
                        String sfcBo = HandleEnum.SFC.getHandle(site, inventory);
                        Sfc sfcModel = sfcService.getById(sfcBo);
                        if (sfcModel == null) {
                            throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不存在！");
                        }
                        if (sfcModel !=  null && !sfcModel.getItemBo().equals(itemBo)) {
                            throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不是物料【"+ item +"】的批次！");
                        }
                        if (new BigDecimal(sfcModel.getQty()).compareTo(issueInvQty) <= 0) {
                            throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】的数量小于发料数量【" +issueInvQty+ "】！");
                        }
                    }

                    if (!inventoryModel.getItemBo().equals(itemBo)) {
                        throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不是物料【"+ item +"】的库存！");
                    }

                    BigDecimal issuedQty = this.getInvIssueQty(site, inventory);
                    BigDecimal qtyOnHand = inventoryModel.getQtyOnHand().subtract(issuedQty);
                    if (qtyOnHand.compareTo(issueInvQty) <= 0) {
                        throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】的库存数量小于发料数量【" +issueInvQty+ "】！");
                    }
                }

                //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                //查询匹配的叫料记录
//                List<CallItem> list = callItemService.findIssueMatchCallItemList(site, workOrder, blankingSize, resource, item);
                List<CallItem> list = callItemMapper.findIssueMatchCallItemListPda(site,workCenter,null,resource,item);
                if (list == null || list.size() <= 0) {
                    throw BusinessException.build("未找到当前物料对应的叫料记录！");
                }

                BigDecimal remainQty = new BigDecimal(qty);
                for (CallItem callItem: list) {
                    BigDecimal issueQty = callItem.getIssueQty();
                    BigDecimal requiredQty = callItem.getRequiredQty();
                    //还需发料数量
                    requiredQty = requiredQty.subtract(issueQty);
                    if (remainQty.compareTo(requiredQty) == 1) {
                        issueQty = issueQty.add(requiredQty);
                    } else {
                        issueQty = issueQty.add(remainQty);
                    }

                    //叫料数据修改
                    if (issueQty.compareTo(requiredQty) >= 0) {
                        callItem.setStatus(Constants.CALL_ITEM_STATUS_ISSUED);
                    }
                    callItem.setIssueQty(issueQty);
                    callItem.setModifyUser(user);
                    callItem.setModifiedDateTime(dateTime);
                    callItemList.add(callItem);

                    remainQty = remainQty.subtract(requiredQty);
                    if (remainQty.compareTo(BigDecimal.ZERO) <= 0) {
                        break;
                    }
                }

                //发料明细记录
                IssueItem issueItem = new IssueItem();
                issueItem.setHandle("IssueItemBO:" + site + "," + UUID.randomUUID().toString());
                issueItem.setSite(site);
                issueItem.setItem(item);
                issueItem.setInventory(inventory);
                issueItem.setQty(new BigDecimal(qty));
                issueItem.setCreateUser(user);
                issueItem.setCreatedDateTime(dateTime);
                issueItem.setModifyUser(user);
                issueItem.setModifiedDateTime(dateTime);
                issueItemList.add(issueItem);
            }//end for
        } else {
            //余料发料
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject _jsonObject = jsonArray.getJSONObject(i);

                String inventory = _jsonObject.getString("inventory");
                String qty = _jsonObject.getString("qty");
                String width = _jsonObject.getString("width");
                String length = _jsonObject.getString("length");
                BigDecimal issueInvQty = new BigDecimal(qty);
                if (StringUtil.isBlank(width) && StringUtil.isBlank(length)) {
                    throw BusinessException.build("请选择余料的长度和宽度！");
                }
                inventory = StringUtil.notBlank(length) ? inventory + "*" + length : inventory;
                inventory = StringUtil.notBlank(width) ? inventory + "*" + width : inventory;
                String inventoryBo = HandleEnum.INVENTORY.getHandle(site, inventory);

                //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                Inventory inventoryModel = inventoryService.getById(inventoryBo);
                if (inventoryModel == null) {
                    throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不存在！");
                }
                if (!inventoryModel.getItemBo().equals(itemBo)) {
                    throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】不是物料【"+ item +"】的库存！");
                }

                BigDecimal issuedQty = this.getInvIssueQty(site, inventory);
                BigDecimal qtyOnHand = inventoryModel.getQtyOnHand().subtract(issuedQty);
                if (qtyOnHand.compareTo(issueInvQty) <= 0) {
                    throw BusinessException.build("扫描的物料条码【 "+ inventory +" 】的库存数量小于发料数量【" +issueInvQty+ "】！");
                }

                //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                //查询匹配的叫料记录
                //  List<CallItem> list = callItemService.findIssueMatchCallItemList(site, workOrder, blankingSize, resource, item);
                List<CallItem> list = callItemMapper.findIssueMatchCallItemListPda(site, workCenter, null, resource, item);
                if (list == null || list.size() <= 0) {
                    throw BusinessException.build("根据发料数据未找到发料记录！");
                }

                BigDecimal remainQty = new BigDecimal(qty);
                for (CallItem callItem: list) {
                    BigDecimal issueQty = callItem.getIssueQty();
                    BigDecimal requiredQty = callItem.getRequiredQty();
                    //还需发料数量
                    requiredQty = requiredQty.subtract(issueQty);
                    if (remainQty.compareTo(requiredQty) == 1) {
                        issueQty = issueQty.add(requiredQty);
                    } else {
                        issueQty = issueQty.add(remainQty);
                    }

                    //叫料数据修改
                    if (issueQty.compareTo(requiredQty) >= 0) {
                        callItem.setStatus(Constants.CALL_ITEM_STATUS_ISSUED);
                    }
                    callItem.setIssueQty(issueQty);
                    callItem.setModifyUser(user);
                    callItem.setModifiedDateTime(dateTime);
                    callItemList.add(callItem);

                    remainQty = remainQty.subtract(requiredQty);
                    if (remainQty.compareTo(BigDecimal.ZERO) <= 0) {
                        break;
                    }
                }

                //发料明细记录
                IssueItem issueItem = new IssueItem();
                issueItem.setHandle("IssueItemBO:" + site + "," + UUID.randomUUID().toString());
                issueItem.setSite(site);
                issueItem.setItem(item);
                issueItem.setInventory(inventory);
                issueItem.setQty(new BigDecimal(qty));
                issueItem.setCreateUser(user);
                issueItem.setCreatedDateTime(dateTime);
                issueItem.setModifyUser(user);
                issueItem.setModifiedDateTime(dateTime);
                issueItemList.add(issueItem);
            }
        }

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //记录发料历史
        if (issueItemList != null && issueItemList.size() > 0) {
            this.saveBatch(issueItemList);
        }

        //修改叫料记录
        if (callItemList != null && callItemList.size() > 0) {
            callItemService.updateBatchById(callItemList);
        }
    }
}