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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foreverwin.mesnac.common.constant.Constants;
import com.foreverwin.mesnac.common.dto.SfcDispatchDto;
import com.foreverwin.mesnac.common.enums.HandleEnum;
import com.foreverwin.mesnac.common.util.StringUtil;
import com.foreverwin.mesnac.dispatch.dto.IssueItemDto;
import com.foreverwin.mesnac.meapi.mapper.NwaUserMapper;
import com.foreverwin.mesnac.meapi.mapper.UserGroupMapper;
import com.foreverwin.mesnac.meapi.model.NwaUser;
import com.foreverwin.mesnac.meapi.service.NwaUserService;
import com.foreverwin.mesnac.meapi.service.UserGroupService;
import com.foreverwin.modular.core.exception.BusinessException;
import com.foreverwin.modular.core.util.CommonMethods;
import com.foreverwin.modular.core.util.FrontPage;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.foreverwin.mesnac.dispatch.model.CallItem;
import com.foreverwin.mesnac.dispatch.mapper.CallItemMapper;
import com.foreverwin.mesnac.dispatch.service.CallItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.context.i18n.LocaleContextHolder;
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.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Leon.L
 * @since 2021-06-30
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CallItemServiceImpl extends ServiceImpl<CallItemMapper, CallItem> implements CallItemService {

    @Autowired
    private CallItemMapper callItemMapper;
    @Autowired
    private CallItemService callItemService;
    @Autowired
    private UserGroupMapper userGroupMapper;

    @Override
    public void sfcDispatchCallItem(String site, String user, List<SfcDispatchDto> sfcDispatchList) {
        LocalDateTime nowDate = LocalDateTime.now();
        if (sfcDispatchList == null || sfcDispatchList.size() <= 0) {
            return;
        }

        //删除原来的数据
        callItemMapper.deleteDispatchCallItem(sfcDispatchList);

        //查询叫料组件
        List<CallItem> callItemList = callItemMapper.selectDispatchCallItem(sfcDispatchList);
        if (callItemList == null || callItemList.size() <= 0) {
            return;
        }

        List<CallItem> list = new ArrayList<>();
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //工序叫料数据
        //Leon.L 2021/8/16 业务取消工序叫料
        /**for (SfcDispatchDto sfcDispatchDto : sfcDispatchList) {
            String prepositionStepId = sfcDispatchDto.getPrepositionStepId();
            if (StringUtil.isBlank(prepositionStepId)) {
                continue;
            }

            String callItemNo = sfcDispatchDto.getSfc() + sfcDispatchDto.getStepId();
            CallItem callItem = new CallItem();
            callItem.setCallItemNo(callItemNo);
            callItem.setHandle(HandleEnum.CALL_ITEM.getHandle(site, callItemNo));
            callItem.setSite(site);
            callItem.setShopOrder(sfcDispatchDto.getShopOrder());
            callItem.setSfc(sfcDispatchDto.getSfc());
            callItem.setSfcDispatchBo(sfcDispatchDto.getHandle());
            callItem.setOperation(sfcDispatchDto.getOperation());
            callItem.setStepId(sfcDispatchDto.getStepId());
            callItem.setResrce(sfcDispatchDto.getResrce());
            callItem.setCallType(Constants.CALL_TYPE_OPERATION);
            callItem.setComponentBo(sfcDispatchDto.getItemBo());
            callItem.setRequiredQty(sfcDispatchDto.getDispatchQty());
            callItem.setRequiredDateTime(sfcDispatchDto.getPlannedStartDate());
            callItem.setStatus(Constants.CALL_ITEM_STATUS_NEW);
            callItem.setCreateUser(user);
            callItem.setCreatedDateTime(nowDate);
            callItem.setModifyUser(user);
            callItem.setModifiedDateTime(nowDate);
            list.add(callItem);
        }**/


        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //组件叫料数据
        for (int i = 0; i< callItemList.size(); i++) {
            CallItem callItem = callItemList.get(i);
            String component = StringUtil.trimHandle(callItem.getComponentBo());
            String callItemNo = callItem.getSfc() + callItem.getStepId() + component;

            callItem.setCallItemNo(callItemNo);
            callItem.setHandle(HandleEnum.CALL_ITEM.getHandle(site, callItemNo));
            callItem.setCallType(Constants.CALL_TYPE_MATERIAL);
            callItem.setStatus(Constants.CALL_ITEM_STATUS_NEW);
            callItem.setIssueQty(BigDecimal.ZERO);
            callItem.setCreateUser(user);
            callItem.setCreatedDateTime(nowDate);
            callItem.setModifyUser(user);
            callItem.setModifiedDateTime(nowDate);
            list.add(callItem);
        }


        //数据保存
        if (list != null && list.size() > 0) {
            this.saveBatch(list);
        }
    }

    @Override
    public List<CallItem> getEffectedCallItemByDispatchBo(String sfcDispatchBo) {
        return callItemMapper.selectEffectedCallItemByDispatchBo(sfcDispatchBo);
    }

    @Override
    public List<CallItem> findCallItemList(Map paramMap) {
        return callItemMapper.findCallItemList(paramMap);
    }

    @Override
    public List<CallItem> findCallItemDetailList(CallItem callItem) {
        return callItemMapper.findCallItemDetailList(callItem);
    }

    @Override
    public List<CallItem> findCallItemDetailListByDispatchBo(String site, List<String> dispatchBoList) {
        return callItemMapper.findCallItemDetailListByDispatchBo(site, dispatchBoList);
    }

    @Override
    public List<CallItem> findCallItemListPda(CallItem callItem) {
        String site = CommonMethods.getSite();
        String user = CommonMethods.getUser();
        String language = LocaleContextHolder.getLocale().getLanguage();
        List<String> list = new ArrayList<>();
        list.add("CJZR");
        list.add("ADMINISTRATORS");
        list.add("CJDD");
        callItem.setCallType(Constants.CALL_TYPE_MATERIAL);
        Integer cnt = userGroupMapper.findUserGroupByUser(site, user, list);
        if (cnt > 0){
            return callItemMapper.findCallItemListPda(site,language,null,callItem);
        }
        return callItemMapper.findCallItemListPda(site,language,user,callItem);
    }

    @Override
    public void callItem(String site, String user, List<CallItem> callItemList) {
        if (callItemList == null || callItemList.size() <= 0) {
            return;
        }

        LocalDateTime nowDate = LocalDateTime.now();
        callItemMapper.updateCallItemStatusByHandle(Constants.CALL_ITEM_STATUS_CALLED, user, nowDate, callItemList);
    }

    @Override
    public void callOrConfirmItemPda(Map<String,Object> map) {
        String user = CommonMethods.getUser();
        String site = CommonMethods.getSite();
        String status = (String) map.get("status");
        List<CallItem> callItemList = (List<CallItem>) map.get("callItemList");
        String parse = JSON.toJSONString(callItemList);
        List<CallItem> callItems = JSONObject.parseArray(parse, CallItem.class);
        LocalDateTime dateTime = LocalDateTime.now();
        for (CallItem callItem : callItems) {
            callItemMapper.updateCallItemStatusByCallItem(site,status, user, dateTime, callItem);
        }

    }

    @Override
    public void confirmReceive(String site, String user, List<CallItem> callItemList) {
        if (callItemList == null || callItemList.size() <= 0) {
            return;
        }

        //派工单号集合
        List<String> dispatchBoList = new ArrayList<>();
        for (CallItem callItem : callItemList) {
            String sfcDispatchBo = callItem.getSfcDispatchBo();
            List<CallItem> list = callItemMapper.selectCallItemAndType(sfcDispatchBo);
            if (list == null || list.size() <= 0) {
                continue;
            }

            for (CallItem callItem1 : list) {
                String callType = callItem1.getCallType();
                String materialType = callItem1.getMaterialType();
                if (Constants.CALL_TYPE_MATERIAL.equals(callType) && "ROH".equals(materialType)) {
                    throw BusinessException.build("勾选的派工单包含原材料组件，不能触发确认到料");
                }
            }

            dispatchBoList.add(sfcDispatchBo);
        }

        this.updateCallItemStatusByDispatchBo(Constants.CALL_ITEM_STATUS_ISSUED, user, dispatchBoList);
    }

    @Override
    public void cancelCallItem(String site, String user, List<CallItem> callItemNoList) {
        if (callItemNoList == null || callItemNoList.size() <= 0) {
            return;
        }

        List<String> callItemList = new ArrayList<>();
        for (CallItem callItem: callItemNoList) {
            String status = callItem.getStatus();
            if (Constants.CALL_ITEM_STATUS_ISSUED.equals(status)) {
                throw BusinessException.build("领料单号【" +callItem.getCallItemNo()+ "】已发料，不允许取消！");
            }

            callItemList.add(callItem.getCallItemNo());
        }

        LocalDateTime dateTime = LocalDateTime.now();
        callItemMapper.updateCallItemStatusByCallItemNo(Constants.CALL_ITEM_STATUS_CANCELED, user, dateTime, callItemList);
    }

    @Override
    public void refreshCallItem(String site, String user, List<CallItem> callItemList) {
        LocalDateTime nowDate = LocalDateTime.now();
        if (callItemList == null || callItemList.size() <= 0) {
            return;
        }
        List<SfcDispatchDto> sfcDispatchList = new ArrayList<>();
        for (CallItem callItem: callItemList) {
            SfcDispatchDto sfcDispatchDto = new SfcDispatchDto();
            sfcDispatchDto.setHandle(callItem.getSfcDispatchBo());
            sfcDispatchList.add(sfcDispatchDto);
        }

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //删除原来的非发料状态数据
        callItemMapper.deleteCallItem(sfcDispatchList);

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        List<CallItem> list = callItemMapper.selectDispatchCallItem(sfcDispatchList);
        if (list == null || list.size() <= 0) {
            return;
        }
        List<CallItem> addList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            CallItem callItem = list.get(i);
            BigDecimal reqQty = callItem.getRequiredQty();
            if (reqQty.compareTo(BigDecimal.ZERO) == 1) {
                String component = StringUtil.trimHandle(callItem.getComponentBo());
                String callItemNo = callItem.getSfc() + callItem.getStepId() + component;

                callItem.setCallItemNo(callItemNo);
                callItem.setHandle(HandleEnum.CALL_ITEM.getHandle(site, UUID.randomUUID().toString()));
                callItem.setCallType(Constants.CALL_TYPE_MATERIAL);
                callItem.setStatus(Constants.CALL_ITEM_STATUS_NEW);
                callItem.setCreateUser(user);
                callItem.setCreatedDateTime(nowDate);
                callItem.setModifyUser(user);
                callItem.setModifiedDateTime(nowDate);
                addList.add(callItem);
            }
        }

        if (addList != null && addList.size() > 0) {
            this.saveBatch(addList);
        }
    }

    @Override
    public void refreshCallItemPda(List<CallItem> callItemList) {
        List<CallItem> callItems = new ArrayList<>();
        List<String> list = new ArrayList<>();
        for (CallItem callItem:callItemList) {
            String handle = callItem.getHandle();
            list.add(handle);
            CallItem call = new CallItem();
            call.setHandle(handle);
            callItems.add(call);
        }
        List<CallItem> itemList = callItemMapper.findRefreshCallItemPda(list);

        Boolean bl = false;
        for (int i = 0; i < callItemList.size(); i++) {
            BigDecimal oldQty = callItemList.get(i).getRequiredQty();
            BigDecimal newQty = itemList.get(i).getRequiredQty();
            if (oldQty.compareTo(newQty) == -1){
                callItems.get(i).setStatus(Constants.CALL_ITEM_STATUS_NEW);
                callItems.get(i).setRequiredQty(newQty);
                bl = true;
            }
        }
        if (bl){
            callItemService.updateBatchById(callItems);
        }
    }

    @Override
    public void refreshRequiredTime(String site, String user, List<String> callItemNoList) {
        if (callItemNoList == null || callItemNoList.size() <= 0) {
            return;
        }
        callItemNoList.stream().distinct().collect(Collectors.toList());

        LocalDateTime dateTime = LocalDateTime.now();
        callItemMapper.refreshRequiredTime(user, dateTime, callItemNoList);
    }

    @Override
    public void updateCallItemStatusByDispatchBo(String status, String user, List<String> list) {
        LocalDateTime dateTime = LocalDateTime.now();
        callItemMapper.updateCallItemStatusByDispatchBo(status, user, dateTime, list);
    }


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @Override
    public List<CallItem> findIssueMatchCallItemList(String site, String workOrder, String blankingSize, String resource, String item) {
        return callItemMapper.findIssueMatchCallItemList(site, workOrder, blankingSize, resource, item);
    }

    @Override
    public List<CallItem> findIssueItemList(IssueItemDto issueItemDto) {
        List<CallItem> list;
        if (issueItemDto.getMatchResource()) {
            list = callItemMapper.finsIssueItemListToResource(issueItemDto);
        } else {
            list = callItemMapper.finsIssueItemListNoResource(issueItemDto);
        }

        if (list == null || list.size() <= 0) {
            return list;
        }

        //计算合计(按下料尺寸)
        //物料组为GB(钢板)：合计=下料尺寸*号最后两位相乘*需求数量
        //其他物料: 合计：下料尺寸*号最后一位*需求数量
        Map<String, BigDecimal> compQtyMap = new HashMap<>();
        for (CallItem callItem: list) {
            String component = callItem.getItem();
            String itemGroup = callItem.getItemGroup();
            BigDecimal reqQty = callItem.getRequiredQty();
            String blankingSize =  callItem.getBlankingSize();

            //工序叫料不需要计算数量
            /**if (Constants.CALL_TYPE_OPERATION.equals(callItem.getCallType())) {
                callItem.setSizeReqQty(BigDecimal.ONE);
                compQtyMap.put(component, BigDecimal.ONE);
                continue;
            }**/

            if (StringUtil.isBlank(blankingSize)) {
                callItem.setSizeReqQty(callItem.getRequiredQty());
                compQtyMap.put(component, callItem.getRequiredQty());
                continue;
            }

            if (StringUtil.notBlank(itemGroup) && "GB".equals(itemGroup)) {
                if (!blankingSize.contains("×") || blankingSize.split("×").length < 2) {
                    callItem.setSizeReqQty(callItem.getRequiredQty());
                    compQtyMap.put(component, callItem.getRequiredQty());
                    continue;
                }

                String []size = blankingSize.split("×");
                if (size != null && size.length >= 2) {
                   int sizeLength = size.length;
                   BigDecimal length =  new BigDecimal(size[sizeLength-1]);
                   BigDecimal width =  new BigDecimal(size[sizeLength-2]);
                   BigDecimal sizeReqQty = length.multiply(width).multiply(reqQty);
                   callItem.setSizeReqQty(sizeReqQty);

                   //按物料汇总需求数量
                   compQtyMap.put(component, (compQtyMap.get(component) != null ? compQtyMap.get(component).add(sizeReqQty) : sizeReqQty));
                }
            } else {
                String[] size = new String[1];
                if (blankingSize.contains("×")) {
                    size = blankingSize.split("×");
                } else {
                    size[0] = blankingSize;
                }

                if (size != null && size.length >= 1) {
                    int sizeLength = size.length;
                    BigDecimal length =  new BigDecimal(size[sizeLength-1]);
                    BigDecimal sizeReqQty = length.multiply(reqQty);
                    callItem.setSizeReqQty(sizeReqQty);

                    //按物料汇总需求数量
                    compQtyMap.put(component, (compQtyMap.get(component) != null ? compQtyMap.get(component).add(sizeReqQty) : sizeReqQty));
                }
            }
        }

        //计算总数量(按数量汇总)
        for (CallItem callItem : list) {
            callItem.setCompReqQty(compQtyMap.get(callItem.getItem()));
        }
        return list;
    }


    @Override
    public List<CallItem> findIssueItemListPda(IssueItemDto issueItemDto) {
        List<CallItem> list;
        if (issueItemDto.getMatchResource()) {
            list = callItemMapper.finsIssueItemListToResourcePda(issueItemDto);
        } else {
            list = callItemMapper.finsIssueItemListNoResourcePda(issueItemDto);
        }

        if (list == null || list.size() < 1) {
            return list;
        }

        //计算合计(按下料尺寸)
        //物料组为GB(钢板)：合计=下料尺寸*号最后两位相乘*需求数量
        //其他物料: 合计：下料尺寸*号最后一位*需求数量
        Map<String, BigDecimal> compQtyMap = new HashMap<>();
        for (CallItem callItem: list) {
            String component = callItem.getItem();
            String itemGroup = callItem.getItemGroup();
            BigDecimal reqQty = callItem.getDispatchQty();
            // 需求件数
            callItem.setDispatchQty(reqQty);
            String blankingSize =  callItem.getBlankingSize();

            if (StringUtil.isBlank(blankingSize)) {
                callItem.setSizeReqQty(reqQty);
                compQtyMap.put(component, reqQty);
                continue;
            }

            if (StringUtil.notBlank(itemGroup) && "GB".equals(itemGroup)) {
                if (!blankingSize.contains("×") || blankingSize.split("×").length < 2) {
                    callItem.setSizeReqQty(reqQty);
                    compQtyMap.put(component, reqQty);
                    continue;
                }

                String []size = blankingSize.split("×");
                if (size != null && size.length >= 2) {
                    try {
                        int sizeLength = size.length;
                        BigDecimal length =  new BigDecimal(size[sizeLength-1]);
                        BigDecimal width =  new BigDecimal(size[sizeLength-2]);
                        BigDecimal sizeReqQty = length.multiply(width).multiply(reqQty).divide(new BigDecimal(1000000));
                        callItem.setSizeReqQty(sizeReqQty);

                        //按物料汇总需求数量
                        compQtyMap.put(component, (compQtyMap.get(component) != null ? compQtyMap.get(component).add(sizeReqQty) : sizeReqQty));
                    }catch (Exception e){
                        throw BusinessException.build("产品条码["+callItem.getSfc()+"]的下料尺寸不符合钢板的标准尺寸！");
                    }
                }
            } else {
                String[] size = new String[1];
                if (blankingSize.contains("×")) {
                    size = blankingSize.split("×");
                } else {
                    size[0] = blankingSize;
                }

                if (size != null && size.length >= 1) {
                    int sizeLength = size.length;
                    BigDecimal length =  new BigDecimal(size[sizeLength-1]);
                    BigDecimal sizeReqQty = length.multiply(reqQty).divide(new BigDecimal(1000));
                    callItem.setSizeReqQty(sizeReqQty);

                    //按物料汇总需求数量
                    compQtyMap.put(component, (compQtyMap.get(component) != null ? compQtyMap.get(component).add(sizeReqQty) : sizeReqQty));
                }
            }
        }

        //计算总数量(按数量汇总)
        for (CallItem callItem : list) {
            callItem.setCompReqQty(compQtyMap.get(callItem.getItem()));
        }
        return list;
    }

}