package com.bonus.canteen.core.menu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.canteen.core.menu.model.AllocMealtimeModel;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.houqin.constant.DelFlagEnum;
import com.bonus.canteen.core.allocation.api.AllocCanteenApi;
import com.bonus.canteen.core.allocation.api.AllocDeliveryApi;
import com.bonus.canteen.core.allocation.api.AllocMealtimeApi;
import com.bonus.canteen.core.allocation.canteen.model.AllocDeliveryCostModel;
import com.bonus.canteen.core.customer.model.CustInfo;
import com.bonus.canteen.core.marketing.constants.MktEffTypeEnum;
import com.bonus.canteen.core.marketing.constants.MktUserTypeEnum;
import com.bonus.canteen.core.marketing.vo.MktEffectiveUserVO;
import com.bonus.canteen.core.menu.dto.*;
import com.bonus.canteen.core.menu.entity.MenuDishesSaleRecord;
import com.bonus.canteen.core.menu.entity.MenuRecipe;
import com.bonus.canteen.core.menu.entity.MenuRecipeDetail;
import com.bonus.canteen.core.menu.entity.MenuRecipeDishes;
import com.bonus.canteen.core.menu.mapper.*;
import com.bonus.canteen.core.menu.model.AllocMealtimeStateModel;
import com.bonus.canteen.core.menu.model.MenuStallSaleModel;
import com.bonus.canteen.core.menu.service.MenuRecipeDetailService;
import com.bonus.canteen.core.menu.service.MenuRecipeDishesService;
import com.bonus.canteen.core.menu.service.MenuRecipeService;
import com.bonus.canteen.core.menu.vo.*;
import com.bonus.canteen.core.nutrition.api.NutritionApi;
import com.bonus.canteen.core.nutrition.common.po.DishNutritionParam;
import com.bonus.canteen.core.nutrition.common.vo.HealthDishRecommendScoreVO;
import com.bonus.canteen.core.order.api.OrderMenuApi;
import com.bonus.canteen.core.order.common.vo.OrderGoodsNumVO;
import com.bonus.common.houqin.i18n.I18n;
import com.bonus.common.houqin.utils.id.Id;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class MenuRecipeServiceImpl extends ServiceImpl<MenuRecipeMapper, MenuRecipe> implements MenuRecipeService {
    private static final Logger log = LoggerFactory.getLogger(MenuRecipeServiceImpl.class);

    @Autowired
    private MenuRecipeDetailService menuRecipeDetailService;

    @Autowired
    private MenuRecipeDishesService menuRecipeDishesService;

    @Autowired
    private MenuAppRecipeMapper menuAppRecipeMapper;

    @Autowired
    private MenuDishesSaleRecordMapper menuDishesSaleRecordMapper;

    @Autowired
    private MenuRecipeMapper menuRecipeMapper;

    @Autowired
    private AllocDeliveryApi allocDeliveryApi;

    @Autowired
    private AllocMealtimeApi allocMealtimeApi;

    @Autowired
    private MenuDishesMapper menuDishesMapper;

    @Autowired
    private NutritionApi nutritionApi;

    @Autowired
    private MenuRecipeDetailMapper menuRecipeDetailMapper;

    @Autowired
    private OrderMenuApi orderMenuApi;

    @Autowired
    private MenuRecipeDishesMapper menuRecipeDishesMapper;

    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

    @Autowired
    private AllocCanteenApi allocCanteenApi;

    @Override
    public List<AppletWeekCanteenVO> getWeekMealList(AppletWeekCanteenDTO content) {
        Set<Long> effIdSet = this.getShopstallIdListByCustId(content.getCustId(), false);
        if (ObjectUtil.isEmpty(effIdSet)) {
            effIdSet = Sets.newTreeSet();
            ((Set) effIdSet).add(-1L);
        }

        return this.menuAppRecipeMapper.selectWeekCanteenList((Set) effIdSet);
    }

    public Set<Long> getShopstallIdListByCustId(Long custId, boolean checkCustInfo) {
        Set<Long> effIdSet = Sets.newTreeSet();
        CustInfo custInfoQuery = new CustInfo();
        custInfoQuery.setCustId(custId);
        custInfoQuery.setCustState(1);
        CustInfo custInfo = menuRecipeMapper.selectOrgAndPsnByCustLimitId(custInfoQuery);
        if (ObjectUtil.isNull(custInfo)) {
            if (checkCustInfo) {
                throw new ServiceException("菜单绑定错误");
            } else {
                log.info("***[获取全档口菜谱信息]_未查询到人员信息,直接返回********************");
                return (Set) effIdSet;
            }
        } else {
            List<MktEffectiveUserVO> effectiveUserVOList = menuRecipeMapper.selectAllUserEff(MktEffTypeEnum.USER_SORT.key(), DelFlagEnum.DEL_FALSE.key());
            Long orgId = custInfo.getOrgId();
            Integer psnType = custInfo.getPsnType();
            if (ObjectUtil.isNotEmpty(effectiveUserVOList)) {
                List<MktEffectiveUserVO> collect = (List) effectiveUserVOList.stream().filter((u) -> {
                    boolean containsOrg = ObjectUtil.isNotEmpty(u.getOrgIdList()) && u.getOrgIdList().contains(orgId);
                    boolean containsPsn = ObjectUtil.isNotEmpty(u.getPsnTypeList()) && u.getPsnTypeList().contains(psnType);
                    return MktUserTypeEnum.INTERSECTION.key().equals(u.getUserType()) && containsOrg && containsPsn || MktUserTypeEnum.UNION_SET.key().equals(u.getUserType()) && (containsOrg || containsPsn);
                }).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(collect)) {
                    effIdSet = (Set) collect.stream().map(MktEffectiveUserVO::getEffId).collect(Collectors.toSet());
                    ((Set) effIdSet).add(-1L);
                }
            }

            log.info("***[获取指定人员折扣比例]_指定人员的生效范围effIdSet: {}", effIdSet);
            return (Set) effIdSet;
        }
    }

    @Override
    public List<AppletWeekRecipeVO> getWeekRecipeDetailList(AppletWeekRecipeDTO content) {
        Set<Long> effIdSet = this.getShopstallIdListByCustId(content.getCustId(), false);
        System.err.println("档口id集合: " + effIdSet.size());
        List<Long> recipeIdList = Lists.newArrayList();
        if (ObjectUtil.isNull(content.getRecipeId())) {
            if (ObjectUtil.isEmpty(effIdSet)) {
                effIdSet = Sets.newTreeSet();
                ((Set) effIdSet).add(-1L);
            }

            recipeIdList = this.menuAppRecipeMapper.selectWeekRecipeId(content.getRecipeId(), (Set) effIdSet);
            if (ObjectUtil.isEmpty(recipeIdList)) {
                return Lists.newArrayList();
            }
        } else {
            LocalDate applyDate = LocalDate.parse(content.getDate());
            LocalDate now = LocalDate.now();

            if (applyDate.isBefore(now)) {
                System.out.println("applyDate 早于当前日期");
                //获取当前菜谱绑定的日期
                String bindTime = this.menuAppRecipeMapper.getBingTimeByRecipeId(content.getRecipeId());
                if(bindTime !=null){
                    bindTime =  bindTime.substring(0,10);
                    LocalDate bindDate = LocalDate.parse(bindTime);
                    System.out.println("Parsed date and time: " + bindDate);
                    if(bindDate.isBefore(applyDate)){
                        System.out.println("绑定日期早于查询历史信息日期");
                        recipeIdList = this.menuAppRecipeMapper.selectWeekRecipeId(content.getRecipeId(), effIdSet);
                    }else{
                        System.out.println("绑定日期迟于查询历史信息日期");
                        List<Long> repeIdList = this.menuAppRecipeMapper.getRecipeIdListByRecipeId(content.getRecipeId());
                        recipeIdList = this.menuAppRecipeMapper.selectWeekRecipeIdHistory(repeIdList, null,applyDate);
                        if(recipeIdList == null || recipeIdList.size() == 0){
                            ((List) recipeIdList).add(content.getRecipeId());
                        }
                    }
                }
            } else if (applyDate.isAfter(now)) {
                System.out.println("applyDate 晚于当前日期");
                recipeIdList = this.menuAppRecipeMapper.selectWeekRecipeId(content.getRecipeId(), effIdSet);
            } else {
                System.out.println("applyDate 等于当前日期");
                recipeIdList = this.menuAppRecipeMapper.selectWeekRecipeId(content.getRecipeId(), effIdSet);
            }
            if(recipeIdList == null || recipeIdList.size() == 0){
                throw new ServiceException("本档口没有更早的历史菜谱记录");
                // recipeIdList.add(content.getRecipeId());
            }
         //   ((List) recipeIdList).add(content.getRecipeId());
        }

        this.generateRecipe((List) recipeIdList, content.getApplyDate());
        List<AppletWeekRecipeVO> resultList = menuRecipeMapper.selectWeekRecipe(content.getApplyDate(), content.getRecipeId(), (List) recipeIdList);
        resultList.sort(Collections.reverseOrder((s1, s2) -> {
            return s2.getMealtimeType() - s1.getMealtimeType();
        }));
        return resultList;
    }

    @Override
    public List<AppletReserveCanteenVO> getReserveMealCanteenList(AppletReserveCanteenDTO content) {
        Set<Long> effIdSet = this.getShopstallIdListByCustId(content.getCustId(), false);
        if (ObjectUtil.isEmpty(effIdSet)) {
            effIdSet = Sets.newTreeSet();
            ((Set)effIdSet).add(-1L);
        }

        List<AppletReserveCanteenVO> resultList = this.menuAppRecipeMapper.selectReserveMealCanteenList((Set)effIdSet);
        if (ObjectUtil.isEmpty(resultList)) {
            return resultList;
        } else {
            this.allocCanteenApi.checkAndDelReserveCanteen(resultList);
            List<Long> stallIdList = (List)resultList.stream().flatMap((canteen) -> {
                return canteen.getStallList().stream().map(AppletReserveStallVO::getStallId);
            }).collect(Collectors.toList());
            if (ObjectUtil.isNotEmpty(stallIdList)) {
                List<MenuStallSaleModel> stallMonthSalesList = this.menuDishesSaleRecordMapper.selectMonthSalesStall(stallIdList);
                Map<Long, Integer> stallSaleMap = (Map)stallMonthSalesList.stream().collect(Collectors.toMap(MenuStallSaleModel::getStallId, MenuStallSaleModel::getMonthlySales));
                resultList.forEach((canteen) -> {
                    List<AppletReserveStallVO> stallList = canteen.getStallList();
                    if (ObjectUtil.isNotEmpty(stallList)) {
                        stallList.forEach((stall) -> {
                            stall.setMonthlySales((Integer)stallSaleMap.get(stall.getStallId()));
                        });
                    }

                });
            }

            resultList.forEach((c) -> {
                List<AppletReserveStallVO> stallList = c.getStallList();
                if (ObjectUtil.isNotEmpty(stallList)) {
                    stallList.forEach((s) -> {
                        List<Long> topDishesIdList = this.menuDishesSaleRecordMapper.selectTopDishesIdList(Collections.singletonList(s.getStallId()));
                        List<AppletRecommendDishesVO> recommendList = Lists.newArrayList();
                        List<AppletRecommendDishesVO> allRecipeDishesList = ((MenuRecipeMapper)this.baseMapper).selectAllRecipeDishesList(s.getRecipeId(), (Integer)null);
                        if (ObjectUtil.isNotEmpty(allRecipeDishesList) && ObjectUtil.isNotEmpty(topDishesIdList)) {
                            Iterator var5 = topDishesIdList.iterator();

                            while(var5.hasNext()) {
                                Long dishesId = (Long)var5.next();
                                if (allRecipeDishesList.stream().map(AppletRecommendDishesVO::getDishesId).collect(Collectors.toList()).contains(dishesId)) {
                                    AppletRecommendDishesVO recommendDishes = (AppletRecommendDishesVO)allRecipeDishesList.stream().filter((a) -> {
                                        return a.getDishesId().equals(dishesId);
                                    }).collect(Collectors.toList()).get(0);
                                    if (!recommendList.contains(recommendDishes)) {
                                        recommendList.add(recommendDishes);
                                    }

                                    if (recommendList.size() >= 3) {
                                        s.setRecommendList(recommendList);
                                        return;
                                    }
                                }
                            }
                        }

                        s.setRecommendList(recommendList);
                    });
                }

            });
            return resultList;
        }
    }

    @Override
    public List<AppletReserveRecipeVO> getReserveRecipeDetailList(AppletReserveRecipeDTO content) {
        this.generateRecipe(content.getRecipeId(), content.getApplyDate());
        List<AppletReserveRecipeVO> resultList = ((MenuRecipeMapper)this.baseMapper).selectReserveRecipe(content.getApplyDate(), content.getRecipeId());
        if (ObjectUtil.isEmpty(resultList)) {
            return resultList;
        } else {
            for(AppletReserveRecipeVO vo:resultList){
                List<AppletReserveRecipeTypeVO> typeList=vo.getTypeList();
                if (ObjectUtil.isNotEmpty(typeList)) {
                    for(AppletReserveRecipeTypeVO vo1:typeList){
                        List<AppletReserveRecipeDishesVO> dishesList=vo1.getDishesList();
                        if (ObjectUtil.isNotEmpty(dishesList)) {
                            for(AppletReserveRecipeDishesVO vo2:dishesList){
                                String mealtime=vo2.getMealTime();
                                if(mealtime!=null&&mealtime.contains("\"endTime\":")){
                                    ObjectMapper mapper = new ObjectMapper();
                                    AllocMealtimeModel person =new AllocMealtimeModel();
                                    try{
                                        person = (AllocMealtimeModel) JSONObject.parseObject(mealtime, AllocMealtimeModel.class);
                                    }catch (Exception e){e.printStackTrace();}
                                    if(person!=null){
                                        vo2.setStartTime(person.getReserveStartTime());
                                    }
                                    if(person!=null){
                                        vo2.setEndTime(person.getReserveEndTime());
                                    }

                                }
                            }
                        }
                    }
                }
            }
            resultList.sort(Collections.reverseOrder((s1, s2) -> {
                return s2.getMealtimeType() - s1.getMealtimeType();
            }));
            Long stallId = ((MenuRecipeMapper)this.baseMapper).selectStallIdByWrappers(Wrappers.lambdaQuery(MenuRecipe.class).eq(MenuRecipe::getRecipeId, content.getRecipeId()).eq(MenuRecipe::getDelFlag, DelFlagEnum.DEL_FALSE.key()));
            List<AllocDeliveryCostModel> costModelList = this.allocDeliveryApi.queryDeliveryCostModel(stallId);
            log.info("配置api查询的档口配送,档口id: {}, 配置: {}", stallId, JSON.toJSONString(costModelList));
            List<AllocMealtimeStateModel> mealTimeList = this.allocMealtimeApi.getAllocMealtimeMenuModel(stallId).getMealtimeStateModelList();
            if (ObjectUtil.isNotEmpty(mealTimeList)) {
                mealTimeList = (List)mealTimeList.stream().filter((mealtimex) -> {
                    return mealtimex.getIfUse() == 1;
                }).collect(Collectors.toList());
            }

            log.info("配置api查询的档口餐次,档口id: {}, 配置: {}", stallId, JSON.toJSONString(mealTimeList));
            if (ObjectUtil.isEmpty(mealTimeList)) {
                log.info("未获取到开启餐次");
                return Lists.newArrayList();
            } else {
                if (LocalDate.now().isEqual(content.getApplyDate())) {
                    mealTimeList = (List)mealTimeList.stream().filter((time) -> {
                        return LocalTime.now().isBefore(time.getStartTime());
                    }).collect(Collectors.toList());
                }

                if (ObjectUtil.isEmpty(mealTimeList)) {
                    log.info("未获取到餐次");
                    return Lists.newArrayList();
                } else {
                    List<AllocMealtimeStateModel> finalMealTimeList = mealTimeList;
                    resultList = (List)resultList.stream().filter((time) -> {
                        return finalMealTimeList.stream().map(AllocMealtimeStateModel::getMealtimeType).collect(Collectors.toList()).contains(time.getMealtimeType());
                    }).collect(Collectors.toList());
                    resultList.forEach((time) -> {
                        List<AppletReserveRecipeTypeVO> typeList = time.getTypeList();
                        if (ObjectUtil.isNotEmpty(typeList)) {
                            typeList.forEach((type) -> {
                                List<AppletReserveRecipeDishesVO> dishesList = type.getDishesList();
                                if (ObjectUtil.isNotEmpty(dishesList)) {
                                    dishesList.forEach((dishes) -> {
                                        dishes.setCostModelList(costModelList);
                                    });
                                }

                            });
                        }

                    });
                    Set<Long> dishesIdSet = (Set)resultList.stream().flatMap((time) -> {
                        return time.getTypeList().stream().flatMap((type) -> {
                            return type.getDishesList().stream().map((item) -> {
                                return ((AppletCurrentDishesDetailVO)item.getDishesDetailList().get(0)).getDishesId();
                            });
                        });
                    }).collect(Collectors.toSet());
                    if (ObjectUtil.isEmpty(dishesIdSet)) {
                        return resultList;
                    } else {
                        List<DishNutritionParam> dishNutritionParamList = this.menuDishesMapper.selectNutrition(dishesIdSet);
                        HealthDishRecommendScoreVO dishesRecommendScore = this.nutritionApi.getDishesRecommendScore(content.getCustId(), dishNutritionParamList);
                        if (dishesRecommendScore.getRecommendFlag()) {
                            resultList.forEach((time) -> {
                                List<AppletReserveRecipeTypeVO> typeList = time.getTypeList();
                                if (ObjectUtil.isNotEmpty(typeList)) {
                                    typeList.forEach((type) -> {
                                        List<AppletReserveRecipeDishesVO> dishesList = type.getDishesList();
                                        if (ObjectUtil.isNotEmpty(dishesList)) {
                                            dishesList.forEach((dishes) -> {
                                                Integer initialScore = (Integer)dishesRecommendScore.getDishRecommendMap().get(((AppletCurrentDishesDetailVO)dishes.getDishesDetailList().get(0)).getDishesId());
                                                if (ObjectUtil.isNotNull(initialScore)) {
                                                    dishes.setInitialScore(initialScore);
                                                }

                                            });
                                        }

                                    });
                                }

                            });
                        }

                        Iterator var10 = resultList.iterator();

                        while(true) {
                            List typeList;
                            do {
                                if (!var10.hasNext()) {
                                    return resultList;
                                }

                                AppletReserveRecipeVO mealtime = (AppletReserveRecipeVO)var10.next();
                                typeList = mealtime.getTypeList();
                            } while(!ObjectUtil.isNotEmpty(typeList));

                            List<AppletReserveRecipeDishesVO> recommendList = Lists.newArrayList();
                            Iterator var14 = typeList.iterator();

                            while(var14.hasNext()) {
                                AppletReserveRecipeTypeVO type = (AppletReserveRecipeTypeVO)var14.next();
                                List<AppletReserveRecipeDishesVO> dishesList = type.getDishesList();
                                if (ObjectUtil.isNotEmpty(dishesList)) {
                                    List<AppletReserveRecipeDishesVO> tempList = (List)dishesList.stream().filter((d) -> {
                                        return d.getRecommendFlag() == 1;
                                    }).collect(Collectors.toList());
                                    if (ObjectUtil.isNotEmpty(tempList)) {
                                        recommendList.addAll(tempList);
                                    }
                                }
                            }

                            if (ObjectUtil.isNotEmpty(recommendList)) {
                                AppletReserveRecipeTypeVO recommend = new AppletReserveRecipeTypeVO();
                                recommend.setTypeId(999L);
                                recommend.setTypeName("推荐");
                                recommend.setDishesList(recommendList);
                                typeList.add(0, recommend);
                            }
                        }
                    }
                }
            }
        }
    }

    public void generateRecipe(Long recipeId, LocalDate applyDate) {
        if (!ObjectUtil.isEmpty(recipeId) && !ObjectUtil.isEmpty(applyDate)) {
            this.generateRecipe(Collections.singletonList(recipeId), applyDate);
        }
    }
    @Transactional(rollbackFor = {Exception.class})
    public synchronized void generateRecipe(List<Long> recipeIdList, LocalDate applyDate) {
        if (!ObjectUtil.isEmpty(recipeIdList) && !ObjectUtil.isEmpty(applyDate)) {
            recipeIdList = new ArrayList(recipeIdList);
            Map<Long, Long> recipeDetailContMap = (Map)this.menuRecipeDetailService.list((Wrapper<MenuRecipeDetail>)((LambdaQueryWrapper<MenuRecipeDetail>)Wrappers.lambdaQuery(MenuRecipeDetail.class).select(MenuRecipeDetail::getRecipeId).eq(MenuRecipeDetail::getApplyDate, applyDate)).in(MenuRecipeDetail::getRecipeId, recipeIdList)).stream().collect(Collectors.groupingBy(MenuRecipeDetail::getRecipeId, Collectors.counting()));
            recipeIdList.removeAll(recipeDetailContMap.keySet());
            if (!ObjectUtil.isEmpty(recipeIdList)) {
                List<MenuRecipe> menuRecipes = this.list((Wrapper)((LambdaQueryWrapper)Wrappers.lambdaQuery(MenuRecipe.class).in(MenuRecipe::getRecipeType, new Object[]{2, 3})).apply(CollUtil.isNotEmpty(recipeIdList),"recipe_id IN (" + recipeIdList.stream().map(String::valueOf).collect(Collectors.joining(", ")) + ")"));
                if (!ObjectUtil.isEmpty(menuRecipes)) {
                    Map<Long, MenuRecipe> recipeMap = (Map)menuRecipes.stream().collect(Collectors.toMap(MenuRecipe::getRecipeId, Function.identity()));
                    List<MenuRecipeDetail> menuRecipeDetails = this.menuRecipeDetailService.list((Wrapper)((LambdaQueryWrapper)Wrappers.lambdaQuery(MenuRecipeDetail.class).eq(MenuRecipeDetail::getDetailType, 1)).apply(CollUtil.isNotEmpty(recipeIdList),"recipe_id IN (" + recipeIdList.stream().map(String::valueOf).collect(Collectors.joining(", ")) + ")"));
                    Map<Long, Integer> recipeTypeMap = (Map)menuRecipes.stream().collect(Collectors.toMap(MenuRecipe::getRecipeId, MenuRecipe::getRecipeType));
                    menuRecipeDetails = this.filterMenuRecipeDetails(recipeTypeMap, menuRecipeDetails, applyDate);
                    if (!ObjectUtil.isEmpty(menuRecipeDetails)) {
                        Map<Long, List<MenuRecipeDetail>> detailMap = (Map)menuRecipeDetails.stream().collect(Collectors.groupingBy(MenuRecipeDetail::getRecipeId));
                        List<Long> detailIds = (List)menuRecipeDetails.stream().map(MenuRecipeDetail::getDetailId).collect(Collectors.toList());
                        Map<Long, List<MenuRecipeDishes>> recipeDishes = (Map)this.menuRecipeDishesService.list((Wrapper)Wrappers.lambdaQuery(MenuRecipeDishes.class).in(MenuRecipeDishes::getDetailId, detailIds)).stream().collect(Collectors.groupingBy(MenuRecipeDishes::getDetailId));
                        List<MenuRecipeDetail> recipeDetailV2List = Lists.newArrayList();
                        List<MenuRecipeDishes> recipeDishesV2List = Lists.newArrayList();
                        Iterator var13 = recipeMap.keySet().iterator();

                        label59:
                        while(true) {
                            Long recipeId;
                            Integer type;
                            List menuRecipeDetail;
                            do {
                                if (!var13.hasNext()) {
                                    this.menuRecipeDetailService.saveBatch(recipeDetailV2List);
                                    if (ObjectUtil.isNotEmpty(recipeDishesV2List)) {
                                        this.menuRecipeDishesService.saveBatch(recipeDishesV2List);
                                    }
                                    return;
                                }
                                recipeId = (Long)var13.next();
                                type = (Integer)recipeTypeMap.get(recipeId);
                                menuRecipeDetail = (List)detailMap.get(recipeId);
                            } while(!ObjectUtil.isNotEmpty(menuRecipeDetail));
                            Iterator var17 = menuRecipeDetail.iterator();
                            while(true) {
                                Long detailId;
                                List dishes;
                                do {
                                    if (!var17.hasNext()) {
                                        continue label59;
                                    }
                                    MenuRecipeDetail recipeDetail = (MenuRecipeDetail)var17.next();
                                    MenuRecipeDetail detailItem = new MenuRecipeDetail();
                                    detailId = Id.next();
                                    detailItem.setDetailId(detailId);
                                    detailItem.setRecipeId(recipeId);
                                    if (ObjectUtil.equal(type, 3)) {
                                        detailItem.setApplyWeek(applyDate.getDayOfWeek().getValue());
                                    }
                                    detailItem.setApplyDate(applyDate);
                                    detailItem.setMealtimeType(recipeDetail.getMealtimeType());
                                    detailItem.setCrby("");
                                    detailItem.setDetailType(2);
                                    recipeDetailV2List.add(detailItem);
                                    dishes = (List)recipeDishes.get(recipeDetail.getDetailId());
                                } while(!ObjectUtil.isNotEmpty(dishes));
                                Iterator var22 = dishes.iterator();
                                while(var22.hasNext()) {
                                    MenuRecipeDishes dish = (MenuRecipeDishes)var22.next();
                                    MenuRecipeDishes dishesItem = (MenuRecipeDishes)BeanUtil.copyProperties(dish, MenuRecipeDishes.class, new String[0]);
                                    dishesItem.setDetailId(detailId);
                                    dishesItem.setId((Long)null);
                                    recipeDishesV2List.add(dishesItem);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    public List<MenuRecipeDetail> filterMenuRecipeDetails(Map<Long, Integer> recipeTypeMap, List<MenuRecipeDetail> menuRecipeDetails, LocalDate applyDate) {
        return menuRecipeDetails.stream().filter((item) -> {
            Long recipeId = item.getRecipeId();
            Integer type = (Integer)recipeTypeMap.get(recipeId);
            if (type == 3) {
                return ObjectUtil.equal(item.getApplyWeek(), applyDate.getDayOfWeek().getValue());
            } else {
                return type == 2;
            }
        }).collect(Collectors.toList());
    }

    @Override
    public Set<Long> changeSurplusNum(List<MenuRecipeChangeSurplusNum> changeSurplusNumList, Long custId, Integer mealtimeType,
                                      LocalDate ordGoodsDate) {
        this.checkChangeSurplusNum(changeSurplusNumList, ordGoodsDate, mealtimeType);
        Set<Long> goodIdSet = new HashSet();
        log.info("[扣减库存]_custId:{}, mealtimeType: {}, ordGoodsDate: {}", new Object[]{custId, mealtimeType, ordGoodsDate});
        List<OrderGoodsNumVO> custQuantityList = Lists.newArrayList();
        if (ObjectUtil.isNotNull(custId) && ObjectUtil.isNotNull(mealtimeType) && ObjectUtil.isNotNull(ordGoodsDate)) {
            custQuantityList = this.orderMenuApi.getQuantityByCustId(custId, mealtimeType, ordGoodsDate);
        }

        List<MenuRecipeChangeDetail> updateDetailList = Lists.newArrayList();
        Iterator var8 = changeSurplusNumList.iterator();

        while(var8.hasNext()) {
            MenuRecipeChangeSurplusNum changeSurplusNum = (MenuRecipeChangeSurplusNum)var8.next();
            Integer saleNum = changeSurplusNum.getSaleNum();
            Long detailId = changeSurplusNum.getDetailId();
            Long productId = changeSurplusNum.getProductId();
            log.info("***接收到的变更库存数量参数详情changeSurplusNum : {}*******************", changeSurplusNum);
            log.info("***下单请求售出菜品 : {} 份", saleNum);
            MenuRecipeDishes recipeDishes = this.menuRecipeDishesMapper.selectOne(Wrappers
                    .lambdaQuery(MenuRecipeDishes.class).eq(MenuRecipeDishes::getDetailId, detailId)
                    .eq(MenuRecipeDishes::getDishesId, productId));
            Integer originalSaleNum = recipeDishes.getSaleNum();
            Integer surplusNum = recipeDishes.getSurplusNum();
            log.info("***扣减库存当前detailId: {},productId: {},剩余库存数量surplusNum: {}", new Object[]{detailId, productId, surplusNum});
            Integer restrictNum = recipeDishes.getRestrictNum();
            int historySaleNum = 0;
            if (ObjectUtil.isNotEmpty(custQuantityList)) {
                List<OrderGoodsNumVO> historyList = (custQuantityList).stream().filter((o) -> {
                    return productId.equals(o.getGoodsDishesId());
                }).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(historyList)) {
                    historySaleNum = (historyList.get(0)).getQuantity();
                }
            }

            if (restrictNum < saleNum + historySaleNum) {
                log.info("***下单数量 {} 超出个人限购数量 {}", saleNum, restrictNum);
                goodIdSet.add(productId);
            } else if (surplusNum < saleNum) {
                log.info("***下单数量 {} 超出库存 {}", saleNum, surplusNum);
                goodIdSet.add(productId);
            } else {
                Integer newSaleNum = originalSaleNum + saleNum;
                Integer newSurplusNum = surplusNum - saleNum;
                MenuRecipeDishes newRecipeDishes = new MenuRecipeDishes();
                newRecipeDishes.setId(recipeDishes.getId());
                newRecipeDishes.setSaleNum(newSaleNum);
                newRecipeDishes.setSurplusNum(newSurplusNum);
                MenuRecipeChangeDetail recipeChangeDetail = new MenuRecipeChangeDetail();
                recipeChangeDetail.setId(recipeDishes.getId());
                recipeChangeDetail.setSaleNum(saleNum);
                recipeChangeDetail.setProductId(productId);
                recipeChangeDetail.setShopstallId(((MenuRecipeMapper)this.baseMapper).selectShopstallIdByDetailId(detailId));
                updateDetailList.add(recipeChangeDetail);
            }
        }

        if (ObjectUtil.isEmpty(goodIdSet) && ObjectUtil.isNotEmpty(updateDetailList)) {
            TransactionStatus transaction = this.dataSourceTransactionManager.getTransaction(this.transactionDefinition);
            Iterator var24 = updateDetailList.iterator();

            while(var24.hasNext()) {
                MenuRecipeChangeDetail updateDetail = (MenuRecipeChangeDetail)var24.next();

                try {
                    this.menuRecipeDishesMapper.updateNumById(updateDetail.getId(), updateDetail.getSaleNum());
                    MenuDishesSaleRecord sourceRecord = this.menuDishesSaleRecordMapper
                            .selectOne(Wrappers.lambdaQuery(MenuDishesSaleRecord.class)
                                    .eq(MenuDishesSaleRecord::getDishesId, updateDetail.getProductId())
                                    .eq(MenuDishesSaleRecord::getStallId, updateDetail.getShopstallId()));
                    if (!ObjectUtil.isNotNull(sourceRecord)) {
                        MenuDishesSaleRecord item = new MenuDishesSaleRecord();
                        item.setDishesId(updateDetail.getProductId());
                        item.setStallId(updateDetail.getShopstallId());
                        item.setSaleNum(updateDetail.getSaleNum());
                        item.setMonthlySales(updateDetail.getSaleNum());
                        item.setSaleMonth(LocalDate.now().getMonthValue());
                        item.setEvaluateNum(0);
                        item.setEvaluateLevel(BigDecimal.ZERO);
                        item.setGoodProbability(BigDecimal.ZERO);
                        item.setUpdateTime(LocalDateTime.now());
                        this.menuDishesSaleRecordMapper.insert(item);
                    } else {
                        int monthValue = LocalDate.now().getMonthValue();
                        if (ObjectUtil.isNull(sourceRecord.getSaleMonth()) || sourceRecord.getSaleMonth() != monthValue) {
                            MenuDishesSaleRecord updateMonth = new MenuDishesSaleRecord();
                            updateMonth.setId(sourceRecord.getId());
                            updateMonth.setSaleMonth(monthValue);
                            updateMonth.setMonthlySales(0);
                            this.menuDishesSaleRecordMapper.updateById(updateMonth);
                        }

                        this.menuDishesSaleRecordMapper.updateSaleNum(updateDetail.getProductId(), updateDetail.getShopstallId(), updateDetail.getSaleNum());
                    }
                } catch (Exception var22) {
                    this.dataSourceTransactionManager.rollback(transaction);
                    goodIdSet.add(updateDetail.getProductId());
                    return goodIdSet;
                }
            }

            this.dataSourceTransactionManager.commit(transaction);
        }

        return goodIdSet;
    }

    public void checkChangeSurplusNum(List<MenuRecipeChangeSurplusNum> changeSurplusNumList, LocalDate applyDate, Integer mealtimeType) {
        log.info("扣减库存传入参数: {}, 日期: {}, 餐次: {}", new Object[]{JSON.toJSONString(changeSurplusNumList), applyDate, mealtimeType});
        if (ObjectUtil.isEmpty(changeSurplusNumList)) {
            throw new ServiceException(I18n.getMessage("menu_param_null_continue", new Object[0]));
        } else {
            Iterator var4 = changeSurplusNumList.iterator();

            while(var4.hasNext()) {
                MenuRecipeChangeSurplusNum changeSurplusNum = (MenuRecipeChangeSurplusNum)var4.next();
                Long detailId = changeSurplusNum.getDetailId();
                Long productId = changeSurplusNum.getProductId();
                Integer saleNum = changeSurplusNum.getSaleNum();
                if (ObjectUtil.hasNull(new Object[]{detailId, productId, saleNum})) {
                    throw new ServiceException(I18n.getMessage("menu_type_num_detail_product_null", new Object[0]));
                }

                if (saleNum == 0) {
                    throw new ServiceException(I18n.getMessage("menu_order_num_not_zero", new Object[0]));
                }

                if (ObjectUtil.isNotNull(applyDate)) {
                    Integer dishesCount = this.menuRecipeDetailMapper.selectDishesCount(detailId, productId, applyDate, mealtimeType);
                    if (ObjectUtil.isNull(dishesCount) || dishesCount <= 0) {
                        throw new ServiceException(I18n.getMessage("menu_not_select_dishes_detail", new Object[0]));
                    }
                }
            }

        }
    }

}
