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

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.fastjson2.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.bonus.canteen.core.alloc.domain.AllocArea;
import com.bonus.canteen.core.alloc.domain.AllocCanteen;
import com.bonus.canteen.core.alloc.domain.AllocStall;
import com.bonus.canteen.core.alloc.service.IAllocAreaService;
import com.bonus.canteen.core.alloc.service.IAllocCanteenService;
import com.bonus.canteen.core.alloc.service.IAllocStallService;
import com.bonus.canteen.core.common.utils.LogUtil;
import com.bonus.canteen.core.common.utils.MqUtil;
import com.bonus.canteen.core.menu.dto.MenuDishesImportDTO;
import com.bonus.canteen.core.menu.domain.MenuAppRecipe;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.canteen.core.common.utils.RedisUtil;
import com.bonus.canteen.core.common.utils.TenantContextHolder;
import com.bonus.canteen.core.menu.domain.*;
import com.bonus.canteen.core.menu.dto.*;
import com.bonus.canteen.core.menu.enums.*;
import com.bonus.canteen.core.menu.enums.MenuRecipeSortEnum;
import com.bonus.canteen.core.menu.mapper.*;
import com.bonus.canteen.core.menu.model.*;
import com.bonus.canteen.core.menu.service.IMenuRecipeDetailService;
import com.bonus.canteen.core.menu.service.IMenuRecipeService;
import com.bonus.canteen.core.menu.service.MenuDishesBaseService;
import com.bonus.canteen.core.menu.service.MenuDishesSizeService;
import com.bonus.canteen.core.menu.vo.*;
import com.bonus.canteen.core.utils.*;
import com.bonus.canteen.core.user.domain.DeviceMqPersonalUpdateMessageDTO;
import com.bonus.canteen.core.utils.BnsConstants;
import com.bonus.canteen.core.utils.CurrentToNextSunday;
import com.bonus.canteen.core.utils.DeviceMqMessage;
import com.bonus.canteen.core.menu.vo.MenuRecipeDataVO;
import com.bonus.canteen.core.menu.vo.MenuRecipeDetailDateVO;
import com.bonus.canteen.core.menu.vo.MenuRecipeV2VO;
import com.bonus.canteen.core.utils.excel.EasyExcelUtil;
import com.bonus.canteen.core.utils.excel.MenuRecipeImportListener;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.houqin.constant.DelFlagEnum;
import com.bonus.common.houqin.i18n.I18n;
import com.bonus.common.houqin.mq.constant.LeMqConstant;
import com.bonus.common.houqin.utils.LeBeanUtil;
import com.bonus.common.houqin.utils.id.Id;
import com.bonus.common.security.utils.SecurityUtils;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * 菜品计划信息Service业务层处理
 *
 * @author xsheng
 * @date 2025-04-03
 */
@Service
public class MenuRecipeServiceImpl extends ServiceImpl<MenuRecipeMapper, MenuRecipe> implements IMenuRecipeService {
    @Autowired
    private MenuRecipeMapper menuRecipeMapper;


    /**
     * 查询菜品计划信息
     *
     * @param id 菜品计划信息主键
     * @return 菜品计划信息
     */
    @Override
    public MenuRecipe selectMenuRecipeById(Long id) {
        return menuRecipeMapper.selectMenuRecipeById(id);
    }

    /**
     * 查询菜品计划信息列表
     *
     * @param menuRecipe 菜品计划信息
     * @return 菜品计划信息
     */
    @Override
    public List<MenuRecipeVO> selectMenuRecipeList(MenuRecipe menuRecipe) {
        Map<Integer, MenuRecipeSortEnum> bindTypeMap = MenuRecipeSortEnum.getKeyMap();
        MenuRecipeSortEnum sortEnum = bindTypeMap.get(Integer.parseInt(menuRecipe.getKey()));
        menuRecipe.setDeviceTypeList(sortEnum.getDeviceType());
        menuRecipe.setBindType(sortEnum.getBindType());
        List<MenuRecipeVO> menuRecipeList = menuRecipeMapper.selectMenuRecipeList(menuRecipe);
        for (MenuRecipeVO menuRecipeVO : menuRecipeList) {
           String recipeId = menuRecipeVO.getRecipeId();
            List<MenuRecipeDetailsVO> menuRecipeDetailsVOList = new ArrayList<>();
            MenuRecipeDetailsVO menuRecipeDetailsVO = new MenuRecipeDetailsVO();
            menuRecipeDetailsVO.setRecipeId(recipeId);
            //获取早/中等餐次信息
           List<MenuRecipeMealtimeTypeVO> menuRecipeMealtimeTypeVOList = menuRecipeMapper.getDishesListByRecipeId(recipeId,menuRecipe.getApplyDate());
           int dishesCount = 0;
           for (MenuRecipeMealtimeTypeVO dishesId : menuRecipeMealtimeTypeVOList) {
               //获取最底层用餐信息
               List<MenuRecipeDishesVO> dishesListByDetailId = menuRecipeMapper.getDishesListByDetailId(dishesId.getDetailId());
               dishesId.setDishesList(dishesListByDetailId);
               dishesCount = dishesCount+dishesListByDetailId.size();
           }
            menuRecipeDetailsVO.setDetails(menuRecipeMealtimeTypeVOList);
            menuRecipeDetailsVOList.add(menuRecipeDetailsVO);
            menuRecipeVO.setDetail(menuRecipeDetailsVOList);
            menuRecipeVO.setDishesCount(dishesCount);

        }
        return menuRecipeList;
    }

    @Override
    public List<AllocRecipeStallVO> selectMenuRecipeListV2(AllocRecipeStallDTO content) {
        Map<Integer, MenuRecipeSortEnum> bindTypeMap = MenuRecipeSortEnum.getKeyMap();
        MenuRecipeSortEnum sortEnum = bindTypeMap.get(content.getKey());
        List<AllocRecipeStallVO> records = new ArrayList<>();
        if (ObjectUtil.isEmpty(sortEnum)) {
            throw new ServiceException("参数错误");
        }else{
            content.setDeviceTypeList(sortEnum.getDeviceType());
            content.setBindType(sortEnum.getBindType());
            content.setRecipeName(LeBeanUtil.fieldLikeHandle(content.getRecipeName()));
            records = menuRecipeMapper.selectMenuRecipeListV2(content);
            if (ObjectUtil.isNotEmpty(records)) {
                List<Long> recipeIds;
                Map<Long ,Long> maping;
                List<Long> menuRecipeDateVOS;
                menuRecipeDateVOS = records.stream().map(AllocRecipeStallVO::getStallId).collect(Collectors.toList());
                List<StallAndRecipeBindDto> stallAndRecipeBindDtos = this.menuRecipeMapper.selectRecipeByStallIdsAndBindType(menuRecipeDateVOS, content.getBindType());
                maping = stallAndRecipeBindDtos.stream().collect(Collectors.toMap(StallAndRecipeBindDto::getStallId, StallAndRecipeBindDto::getRecipeId));
                recipeIds = stallAndRecipeBindDtos.stream().map(StallAndRecipeBindDto::getRecipeId).distinct().collect(Collectors.toList());

                this.generateRecipe(recipeIds, content.getApplyDate());
                List<MenuRecipeDateVO> menuRecipeDateVOS1 = this.menuRecipeMapper.selectTmpBetweenDateDetailList(recipeIds, content.getApplyDate(), content.getApplyDate());
                Map<Long, MenuRecipe> recipeMap = (recipeIds == null || recipeIds.isEmpty())
                        ? new HashMap<>()
                        : this.list(Wrappers.lambdaQuery(MenuRecipe.class)
                                .in(MenuRecipe::getRecipeId, recipeIds))
                        .stream()
                        .collect(Collectors.toMap(MenuRecipe::getRecipeId, Function.identity()));
                Map<Long, MenuRecipeDateVO> detailMap = menuRecipeDateVOS1.stream().collect(Collectors.toMap(MenuRecipeDateVO::getRecipeId, Function.identity(), (t1, t2) -> {
                    return t1;
                }));
                System.err.println("records = " + records.size());
                AllocRecipeStallVO item;
                long count;
                for(Iterator<AllocRecipeStallVO> var12 = records.iterator(); var12.hasNext(); item.setDishesCount(count)) {
                    item = var12.next();
                    Long recipeId;
                    recipeId = maping.get(item.getStallId());

                    item.setRecipeId(recipeId);
                    item.setDetail(detailMap.get(recipeId));
                    item.setRecipeName(Optional.ofNullable(recipeMap.get(recipeId)).map(MenuRecipe::getRecipeName).orElse(null));
                   // item.setUptime(Optional.ofNullable(recipeMap.get(recipeId)).map(MenuRecipe::getUptime).orElse(null));
                    count = 0L;
                    if (ObjectUtil.isNotEmpty(item.getDetail()) && ObjectUtil.isNotEmpty(item.getDetail().getDetails())) {
                        count = item.getDetail().getDetails().stream().filter((x) -> {
                            return ObjectUtil.isNotEmpty(x.getDishesList());
                        }).flatMap((x) -> {
                            return x.getDishesList().stream();
                        }).map(MenuRecipeDetailDishesVO::getDishesId).distinct().count();
                    }
                }

            }
        }
        return records;
    }


    @Override
    public void bindAppRecipe(MenuRecipeBindDTO content) {
        MenuRecipe menuRecipe = this.menuRecipeMapper.selectMenuRecipe(content.getRecipeId());
        List<Integer> deviceInfoList = new ArrayList<>();
        if(content.getStallId() !=null){
            deviceInfoList = this.menuRecipeMapper.getDeviceIdByDevivce(null, String.valueOf(content.getStallId()));
            if(deviceInfoList == null || deviceInfoList.isEmpty() || deviceInfoList.size() == 0){
                throw new ServiceException("该食堂档口下没有设备信息");
            }
        }
        List<String> deviceSnList = this.menuRecipeMapper.getDeviceSnByIds(deviceInfoList);
        MenuRecipeSortEnum sortEnum = MenuRecipeSortEnum.getBindTypeMap().get(content.getBindType());
        MenuAppRecipe mar = new MenuAppRecipe();
        mar.setRecipeId(content.getRecipeId());
        mar.setMealLineId(content.getMealLineId());
        mar.setBindType(content.getBindType());
        List<Integer> deviceTypeList = menuRecipeMapper.getDeviceIdByDevivce(null, String.valueOf(menuRecipe.getStallId()));
        if (ObjectUtil.isEmpty(sortEnum)) {
            throw new ServiceException("bingType值异常");
        } else {
            List<Integer> deviceTypes = sortEnum.getDeviceType();
            if (content.getHandleType().equals(1)) {
                boolean exists;
                if (MenuBindTypeEnum.RESERVE.key().equals(content.getBindType())) {
                    exists = this.checkCanteenIfReserve(menuRecipe.getCanteenId(), menuRecipe.getStallId());
                    if (!exists) {
                        throw new ServiceException("不支持预订餐");
                    }
                }
                exists = this.menuRecipeMapper.exists(mar);
                if (exists) {
                    throw new ServiceException("菜谱已被使用，请勿重复绑定");
                }
                List<Long> sourceRecipeList = this.menuRecipeMapper.selectRecipeInSameShop(menuRecipe.getStallId(), null, content.getBindType(), content.getMealLineId());
                if (ObjectUtil.isNotEmpty(sourceRecipeList)) {
                    mar.setRecipeIds(sourceRecipeList);
                    this.menuRecipeMapper.delete(mar);
                }

                MenuAppRecipe appRecipe = new MenuAppRecipe();
                appRecipe.setRecipeId(content.getRecipeId());
                appRecipe.setBindType(content.getBindType());
                appRecipe.setMealLineId(content.getMealLineId());
                appRecipe.setBindTime(LocalDateTime.now());
                this.menuRecipeMapper.insert(appRecipe);
                if (ObjectUtil.isNotEmpty(deviceTypes) && deviceTypeList!= null && !deviceTypeList.isEmpty()) {
                    this.menuRecipeMapper.updateRecipeByCanteeStallMeal(String.valueOf(content.getRecipeId()), String.valueOf(menuRecipe.getCanteenId()), String.valueOf(menuRecipe.getStallId()),deviceTypeList);
                }
                MqUtil.sendDataChange(menuRecipe, LeMqConstant.DataChangeType.ADD, LeMqConstant.Topic.DATA_CHANGE_RECIPE_RELEASE);
            } else {
                mar.setRecipeIds(Collections.singletonList(mar.getRecipeId()));
                this.menuRecipeMapper.delete(mar);
                if (ObjectUtil.isNotEmpty(deviceTypes) && deviceTypeList!= null && !deviceTypeList.isEmpty()) {
                    this.menuRecipeMapper.updateRecipeByCanteeStallMeal("-1",  String.valueOf(menuRecipe.getCanteenId()), String.valueOf(menuRecipe.getStallId()), deviceTypeList);
                }
            }
            //发送消息
            //发送mq
            for (String deviceSn : deviceSnList){
                DeviceMqPersonalUpdateMessageDTO bean = new DeviceMqPersonalUpdateMessageDTO().setUpdatePerson(0,content.getHandleType().equals(1) ? "update" : "del");
                MqUtil.pushToSingleDevice(bean, LeMqConstant.Topic.DEVICE_UPDATE_MENU_CONFIG_V4, deviceSn);
            }

        }

    }

//    public void updateRecipeByCanteeStallMeal(Long recipeId, Long canteenId, Long stallId, Long mealLineId, List<Integer> deviceTypeList) {
//        String currentTraceId = LogUtil.getCurrentTraceId();
//        this.asyncTaskExecutor.execute(() -> {
//            LogUtil.putLogTraceId(currentTraceId);
//            if (!ObjectUtil.isEmpty(deviceTypeList)) {
//                DeviceSearchDTO deviceSearchDTO = new DeviceSearchDTO();
//                deviceSearchDTO.setCanteenId(canteenId);
//                deviceSearchDTO.setStallId(stallId);
//                deviceSearchDTO.setMealLineId(mealLineId);
//                deviceSearchDTO.setDeviceTypeList(deviceTypeList);
//                List<DeviceInfo> deviceInfoList = this.deviceInfoService.list(deviceSearchDTO);
//                List<DeviceFullInfoVO> deviceFullInfoVOList = this.deviceInfoService.fillFullVo(deviceInfoList);
//                MenuRecipeMachineChangeDTO dto = new MenuRecipeMachineChangeDTO();
//                dto.setCanteenId(canteenId);
//                dto.setShopstallId(stallId);
//                dto.setRecipeId(recipeId);
//                dto.setMealLineId(mealLineId);
//                dto.setMachineIdList(deviceFullInfoVOList.stream().map(DeviceFullInfoVO::getDeviceId).collect(Collectors.toList()));
//                this.deviceInfoService.editMacRecipeBydevice(dto);
//                deviceInfoList.forEach((s) -> {
//                    DeviceMqMessage.deviceUpdateMenuConfigV4(s.getDeviceSn());
//                });
//                if (deviceTypeList.contains(SourceTypeEnum.AUTONOMOUS_WEIGHING.getKey()) || deviceTypeList.contains(SourceTypeEnum.PRODUCTION.getKey())) {
//                    IssueRecipeListDTO issueRecipeListDTO = new IssueRecipeListDTO();
//                    issueRecipeListDTO.setRecipeId(recipeId);
//                    issueRecipeListDTO.setMachineNumList(deviceInfoList.stream().map(MenuSendMacListDto::of).collect(Collectors.toList()));
//                    this.macMenuRecipeService.issueRecipeList(issueRecipeListDTO);
//                }
//
//            }
//        });
//    }

//    public List<DeviceFullInfoVO> fillFullVo(List<DeviceInfo> deviceInfoList) {
//        if (CollUtil.isEmpty(deviceInfoList)) {
//            return CollUtil.toList(new DeviceFullInfoVO[0]);
//        } else {
//            List<Long> deviceIds = deviceInfoList.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toList());
//            Map<Long, List<DeviceBindVO>> deviceBindGroupByDeviceId = this.deviceBindService.listVoByDeviceIds(deviceIds).stream().collect(Collectors.groupingBy(DeviceBindVO::getDeviceId));
//            Map<Long, List<DeviceRecipeVO>> deviceRecipeGroupByDeviceId = this.deviceRecipeService.listVoByDeviceIds(deviceIds)
//                    .stream().collect(Collectors.groupingBy(DeviceRecipeVO::getDeviceId));
//            Map<Long, List<DeviceDishesVO>> deviceDishesGroupByDeviceId = this.deviceDishesService.listVoByDeviceIds(deviceIds)
//                    .stream().collect(Collectors.groupingBy(DeviceDishesVO::getDeviceId));
//            Map<Long, List<DeviceLockerCabinetVO>> cabinetListGroupByDeviceId = this.deviceLockerCabinetService
//                    .listVoByDeviceIds(deviceIds).stream().collect(Collectors.groupingBy(DeviceLockerCabinetVO::getDeviceId));
//            Map<Long, List<DeviceControlRelationVO>> relationGroupByDeviceId = this.deviceControlRelationService
//                    .listVoByDeviceIds(deviceIds).stream().collect(Collectors.groupingBy(DeviceControlRelationVO::getControlDeviceId));
//            Map<Long, Map> deviceMetadataByDeviceId = this.deviceMetadataService.listDeviceMetadataBYDeviceIdList(deviceIds);
//            return deviceInfoList.stream().map((s) -> {
//                DeviceFullInfoVO vo = DeviceFullInfoVO.of(s, deviceBindGroupByDeviceId.get(s.getDeviceId()),
//                        deviceRecipeGroupByDeviceId.get(s.getDeviceId()), deviceDishesGroupByDeviceId.get(s.getDeviceId()),
//                        cabinetListGroupByDeviceId.get(s.getDeviceId()), relationGroupByDeviceId.get(s.getDeviceId()),
//                        deviceMetadataByDeviceId.get(s.getDeviceId()));
//                return vo;
//            }).collect(Collectors.toList());
//        }
//    }


    public boolean checkCanteenIfReserve(Long canteenId, Long stallId) {
        AllocCanteen allocCanteen = menuRecipeMapper.getCanNum(canteenId);
        AllocStall allocStall = menuRecipeMapper.getStallNum(stallId);
        return BnsConstants.COMMON_YES.equals(allocCanteen.getIfReserve())
                && BnsConstants.COMMON_YES.equals(allocStall.getIfReserve());
    }

    /**
     * 新增菜品计划信息
     *
     * @param menuRecipe 菜品计划信息
     * @return 结果
     */
    @Override
    public int insertMenuRecipe(MenuRecipe menuRecipe) {
        menuRecipe.setCreateTime(LocalDateTime.now());
        try {
            return menuRecipeMapper.insertMenuRecipe(menuRecipe);
        } catch (Exception e) {
            throw new ServiceException("错误信息描述");
        }
    }

    @Override
    public int updateMenuRecipe(MenuRecipe menuRecipe) {
        return 0;
    }

    @Override
    public int deleteMenuRecipeByIds(Long[] ids) {
        return 0;
    }

    /**
     * 修改菜品计划信息
     *
     * @param dto 菜品计划信息
     * @return 结果
     * 菜谱列表-获取菜品列表
     *
     * @param dto
     * @return
     */
    @Override
    public AjaxResult getDishesList(MenuRecipeParamDTO dto) {
        List<MenuRecipeV2VO> list = menuRecipeMapper.getDishesList(dto);
        List<LocalDate> last = this.getLastWeekDate();
        List<Long> recipeIds = list.stream().map(MenuRecipeV2VO::getRecipeId).collect(Collectors.toList());
        List<RecipeDishesCountDTO> dishesCountByRecipeIdsList = menuRecipeMapper.getDishesCountByRecipeIds(recipeIds);
        Map<Long, Integer> dishesCountByRecipeIds = dishesCountByRecipeIdsList.stream().collect(Collectors.toMap(RecipeDishesCountDTO::getRecipeId, RecipeDishesCountDTO::getNum));
        List<MenuRecipeDataVO> recipeDatesList = this.menuRecipeMapper.selectApplyDateListByRecipeId(LocalDate.now(), recipeIds);
        Map<Long, TreeSet<LocalDate>> recipeDates = recipeDatesList.stream().collect(Collectors.groupingBy(MenuRecipeDataVO::getRecipeId, Collectors.mapping(MenuRecipeDataVO::getApplyData, Collectors.toCollection(TreeSet::new))));
        if (list.isEmpty()) {
            return AjaxResult.success(new ArrayList<>());
        }
        list.forEach(r -> {
            Long recipeId = r.getRecipeId();
            r.setDishesCount(dishesCountByRecipeIds.getOrDefault(recipeId, 0));
            Set<LocalDate> applyDateList = recipeDates.getOrDefault(recipeId, new TreeSet<>());
            Object finalDate;
            if (ObjectUtil.equal(r.getRecipeType(), 3)) {
                Stream<LocalDate> var10000 = last.stream();
                Objects.requireNonNull(applyDateList);
                finalDate = var10000.filter(applyDateList::contains).collect(Collectors.toList());
            } else if (ObjectUtil.equal(r.getRecipeType(), 2)) {
                finalDate = this.getLastWeek();
            } else {
                finalDate = new ArrayList<>(applyDateList);
            }
            List<String> applyDateStringList = Lists.newArrayList();
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM-dd");
            ((List) finalDate).forEach(d -> {
                applyDateStringList.add(dateTimeFormatter.format((TemporalAccessor) d));
            });
            r.setApplyDateList((List) finalDate);
            r.setApplyDateStringList(applyDateStringList);
        });
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult getDishesListV2(MenuRecipeV2PageDTO dto) {

        List<MenuRecipeV2PageVO> list = menuRecipeMapper.getMenuRecipeList(dto);


        return null;
    }

    /**
     * 批量删除菜品计划信息
     *
     * @param dto 需要删除的菜品计划信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Long add(MenuRecipeAddDTO dto) {
        this.changeBaseDishesIdTo(dto);
        Long recipeId = dto.getRecipeId();
        String userName = SecurityUtils.getUsername();
        Integer recipeType = dto.getRecipeType();
        MenuRecipe recipe;
        Boolean add;
        if (ObjectUtil.isNull(recipeId)) {
            Long count = menuRecipeMapper.selectCount(dto);
            if (ObjectUtil.isNotNull(count) && count > 0L) {
                throw new ServiceException("菜单菜谱名称重复");
            }
            recipeId = Id.next();
            recipe = new MenuRecipe();
            recipe.setRecipeId(recipeId);
            recipe.setRecipeType(dto.getRecipeType());
            recipe.setRecipeName(dto.getRecipeName());
            recipe.setCanteenId(ObjectUtil.isNull(dto.getCanteenId()) ? -1L : dto.getCanteenId());
            recipe.setStallId(ObjectUtil.isNull(dto.getStallId()) ? -1L : dto.getStallId());
            recipe.setCreateBy(userName);
            recipe.setUpdateTime(LocalDateTime.now());
            menuRecipeMapper.insertData(recipe);
            add = true;
        } else {
            recipe = menuRecipeMapper.getOneById(recipeId);
            recipe.setRecipeName(dto.getRecipeName());
            recipeType = Math.toIntExact(recipe.getRecipeType());
            add = false;
        }

        if (ObjectUtil.isEmpty(dto.getRecipeDateList())) {
            return recipeId;
        } else {
            RecipeProcessResult result;
            if (ObjectUtil.equal(recipeType, 3)) {
                result = this.processWeek(dto, recipeId);
            } else if (ObjectUtil.equal(recipeType, 2)) {
                result = this.processDay(dto, recipeId);
            } else {
                result = this.processDefault(dto, recipeId);
            }

            result.setRecipeId(recipeId);
            result.setMenuRecipe(recipe);
            result.setAdd(add);
            this.processResult(result);
            if (!add){
                List<Integer> deviceInfoList = this.menuRecipeMapper.getDeviceIdByDevivce(String.valueOf(dto.getCanteenId()), String.valueOf(dto.getStallId()));
                if(deviceInfoList !=null && deviceInfoList.size() >0){
                    List<String> deviceSnList = this.menuRecipeMapper.getDeviceSnByIds(deviceInfoList);
                    for (String deviceSn : deviceSnList){
                        DeviceMqPersonalUpdateMessageDTO bean = new DeviceMqPersonalUpdateMessageDTO().setUpdatePerson(0,"update");
                        MqUtil.pushToSingleDevice(bean, LeMqConstant.Topic.DEVICE_UPDATE_MENU_CONFIG_V4, deviceSn);
                    }
                }
            }
            return recipeId;
        }
    }


    public void  addReplaceDishes( Long recipeId) {

        //获取当前日期后的日期
        Map<DayOfWeek, CurrentToNextSunday.DateInfo> dateMap = CurrentToNextSunday.getDatesFromTodayToNextSunday(LocalDate.now());

        List<MenuRecipeDetail> menuRecipeDetailList =  menuRecipeMapper.MenuRecipeDetailList(recipeId);




    }

    @Override
    public List<MenuRecipeDetailDateVO> getDetail(MenuRecipeParamDTO dto) {
        return this.menuRecipeMapper.getDetail(dto);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void deleteRecipeById(Long recipeId) {
        Integer recipeMacBindNumber = this.menuRecipeMapper.getRecipeBindCount(recipeId);
        int appCount = this.menuRecipeMapper.selectMenuAppRecipeCount(recipeId);
        if (recipeMacBindNumber > 0) {
            throw new ServiceException("菜谱已绑定设备");
        } else if (appCount > 0) {
            throw new ServiceException("菜谱已绑定设备");
        } else {
//            this.baseMapper.delete( Wrappers.lambdaUpdate(MenuRecipe.class)
//                    .in(MenuRecipe::getRecipeId, recipeId));

            menuRecipeMapper.deleteRecipeByrecipeId(recipeId);

            List<Long> detailIdList = this.menuRecipeMapper.getDetailIdList(recipeId);
            if (ObjectUtil.isNotEmpty(detailIdList)) {
                this.menuRecipeMapper.deleteMenuRecipeDetailByIds(detailIdList);
                this.menuRecipeMapper.deleteMenuRecipeDishesByIds(detailIdList);
            }
            String redisKey = String.format("yst:%s:recipe:%s:detail:%s", TenantContextHolder.getTenantId(), recipeId, "*");
            RedisUtil.deleteByPattern(redisKey);
            MqUtil.sendDataChange(recipeId, LeMqConstant.DataChangeType.REMOVE, LeMqConstant.Topic.DATA_CHANGE_RECIPE);

        }
    }

    @Override
    public AjaxResult getDishesCategoryList(MenuTypeDishesDTO dto) {
        List<MenuAllTypeDishesVO> resultList = this.baseMapper.selectTypeDishesList(dto);
        if (CollUtil.isEmpty(resultList)) {
            return AjaxResult.success(new ArrayList<>());
        } else {
            List<MenuDishesCostModel> costList = this.baseMapper.selectMaterialCostList(new QueryWrapper<MenuDishes>()
                    .in("base_dishes_id", resultList.stream()
                            .map(MenuAllTypeDishesVO::getDishesId)
                            .collect(Collectors.toList()))
                    .eq("size_json", "{\"sizeType\":\"小份\"}"));
            if (CollUtil.isNotEmpty(costList)) {
                Map<Long, Integer> mostMap = costList.stream().collect(Collectors.toMap(MenuDishesCostModel::getBaseDishesId, MenuDishesCostModel::getMaterialCost));
                resultList.forEach((x) -> x.setLittleMaterialCost((Integer) mostMap.get(x.getDishesId())));
            }

            return AjaxResult.success(resultList);
        }
    }

    @Override
    public List<MenuDishesTypeAllVO> getAllDishCategories() {
        return this.baseMapper.getAllDishCategories(Wrappers.lambdaQuery(MenuDishesType.class)
                .eq(MenuDishesType::getDelFlag, DelFlagEnum.DEL_FALSE.key())
                .orderByAsc(MenuDishesType::getDefaultFlag)
                .orderByDesc(MenuDishesType::getCreateTime));
    }

    @Override
    public List<MenuRecipeDetailDateVO> getDetailByDate(MenuRecipeParamDTO dto) {
        this.generateRecipe(dto.getRecipeId(), dto.getApplyDate());
        List<MenuRecipeDetailDateVO> menuRecipeDetailDateVOS = this.menuRecipeMapper.selectDateDetailList(dto.getRecipeId(), dto.getApplyDate());
        return menuRecipeDetailDateVOS.stream().sorted(Comparator.comparing(MenuRecipeDetailDateVO::getMealtimeType)).collect(Collectors.toList());
    }
    @Override
    public void generateRecipe(Long recipeId, LocalDate applyDate) {
        if (!ObjectUtil.isEmpty(recipeId) && !ObjectUtil.isEmpty(applyDate)) {
            this.generateRecipe(Collections.singletonList(recipeId), applyDate);
        }
    }

    @Override
    public void generateRecipe() {
//        List<Long> recipeIds = (List)this.list((Wrapper)((LambdaQueryWrapper)Wrappers.lambdaQuery(MenuRecipe.class).eq(MenuRecipe::getDelFlag, DelFlagEnum.DEL_FALSE.key())).in(MenuRecipe::getRecipeType, new Object[]{2, 3})).stream().map(MenuRecipe::getRecipeId).collect(Collectors.toList());
        List<Long> recipeIds = this.menuRecipeMapper.selectRecipeIdList(new QueryWrapper<MenuRecipe>()
                .in("recipe_type", 2, 3));
        for(int i = 0; i < 7; ++i) {
            this.generateRecipe(recipeIds, LocalDate.now().plusDays((long)i));
        }
    }

@Resource
private IMenuRecipeDetailService menuRecipeDetailService;
    @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 = this.menuRecipeMapper.selectMenuRecipeDetailList(new QueryWrapper<MenuRecipeDetail>()
//                    .eq("apply_date", applyDate)
//                    .in("recipe_id", recipeIdList))
//                    .stream().collect(Collectors.groupingBy(MenuRecipeDetail::getRecipeId, Collectors.counting()));
            Map<Long, Long> recipeDetailContMap = (Map) 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(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 = menuRecipes.stream().collect(Collectors.toMap(MenuRecipe::getRecipeId, Function.identity()));
                    List<MenuRecipeDetail> menuRecipeDetails = this.menuRecipeMapper.selectMenuRecipeDetailList(
                            new QueryWrapper<MenuRecipeDetail>().eq("detail_type", 1)
                                    .apply(CollUtil.isNotEmpty(recipeIdList), "recipe_id IN (" + recipeIdList.stream().map(String::valueOf).collect(Collectors.joining(", ")) + ")"));
                    Map<Long, Integer> recipeTypeMap = menuRecipes.stream().collect(Collectors.toMap(MenuRecipe::getRecipeId, MenuRecipe::getRecipeType));
                    menuRecipeDetails = this.filterMenuRecipeDetails(recipeTypeMap, menuRecipeDetails, applyDate);
                    if (!ObjectUtil.isEmpty(menuRecipeDetails)) {
                        Map<Long, List<MenuRecipeDetail>> detailMap = menuRecipeDetails.stream().collect(Collectors.groupingBy(MenuRecipeDetail::getRecipeId));
                        List<Long> detailIds = menuRecipeDetails.stream().map(MenuRecipeDetail::getDetailId).collect(Collectors.toList());
                        Map<Long, List<MenuRecipeDishes>> recipeDishes = this.menuRecipeMapper.selectMenuRecipeDishList(new QueryWrapper<MenuRecipeDishes>()
                                .in("detail_id", 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.menuRecipeMapper.insertMenuDetails(recipeDetailV2List);
                                    if (ObjectUtil.isNotEmpty(recipeDishesV2List)) {
                                        this.menuRecipeMapper.insertMenuDishes(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.setCreateBy("");
                                    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());
    }
    public void processResult(RecipeProcessResult result) {
        List<Long> detailIds = result.getTemplateDetailIds();
        MenuRecipe menuRecipe = result.getMenuRecipe();
        if (ObjectUtil.isNotEmpty(detailIds)) {
            menuRecipeMapper.deleteMenuRecipeDetailByIds(detailIds);
            menuRecipeMapper.deleteMenuRecipeDishesByIds(detailIds);
        }

        List<Long> haveDetailIds = result.getHaveDetailIds();
        if (ObjectUtil.isNotEmpty(haveDetailIds)) {
            menuRecipeMapper.deleteMenuRecipeDishesByIds(haveDetailIds);
        }


        LeMqConstant.DataChangeType type;
        String redisKey;
        if (result.getAdd()) {
            type = LeMqConstant.DataChangeType.ADD;
        } else {
            type = LeMqConstant.DataChangeType.UPDATE;
            redisKey = Optional.ofNullable(menuRecipe).map(MenuRecipe::getRecipeName).orElse(null);
            this.update(Wrappers.lambdaUpdate(MenuRecipe.class).eq(MenuRecipe::getRecipeId, result.getRecipeId())
                    .set(ObjectUtil.isNotEmpty(redisKey), MenuRecipe::getRecipeName, redisKey)
                    .set(MenuRecipe::getUpdateTime, LocalDateTime.now()));
            this.menuRecipeMapper.updateMenuRecipeDetail(result.getRecipeId(), LocalDateTime.now());
            List<MenuAppRecipe> menuAppRecipes = this.menuRecipeMapper.selectAppRecipeList(result.getRecipeId());
            if (ObjectUtil.isNotEmpty(menuAppRecipes)) {
                Map<Integer, MenuRecipeSortEnum> bindTypeMap = MenuRecipeSortEnum.getBindTypeMap();
                List<Integer> deviceBindTypes = MenuRecipeSortEnum.getDeviceBindTypes();
                List<MenuSendByDTO> menuSendByDTOS = menuAppRecipes.stream()
                        .filter((x) -> deviceBindTypes.contains(x.getBindType())).map((item) -> {
                            MenuSendByDTO menuSendByDTO = new MenuSendByDTO();
                            menuSendByDTO.setStallId(menuRecipe.getStallId());
                            menuSendByDTO.setCanteenId(menuRecipe.getCanteenId());
                            menuSendByDTO.setMealLineId(item.getMealLineId());
                            menuSendByDTO.setDeviceTypeList((bindTypeMap.get(item.getBindType())).getDeviceType());
                            return menuSendByDTO;
                        }).collect(Collectors.toList());
                //TODO 发送mq
             //   this.deviceApi.sendMenuByCanteen(result.getRecipeId(), menuSendByDTOS);
              //  MqUtil.pushToSingleTxDevice((new DeviceMqSendUpdateConfigDto()).setNeedupdate(LeConstants.COMMON_YES), LeMqConstant.Topic.DEVICE_UPDATE_MENU_CONFIG_V4, machineSn);
            }
        }

        List<MenuRecipeDetail> recipeDetailV2List = result.getRecipeDetails();
        if (ObjectUtil.isNotEmpty(recipeDetailV2List)) {
            menuRecipeMapper.insertMenuDetails(recipeDetailV2List);
        }

        List<MenuRecipeDishes> recipeDishesV2List = result.getRecipeDishes();
        if (ObjectUtil.isNotEmpty(recipeDishesV2List)) {
            recipeDishesV2List.forEach((r) -> {
                r.setId((Long) null);
                Integer surplusNum = r.getSurplusNum();
                if (ObjectUtil.isNull(surplusNum) || surplusNum <= 0) {
                    r.setSurplusNum(0);
                }

            });
            menuRecipeMapper.insertMenuDishes(recipeDishesV2List);
        }

        MqUtil.sendDataChange(menuRecipe, type, LeMqConstant.Topic.DATA_CHANGE_RECIPE);
        redisKey = String.format("yst:%s:recipe:%s:detail:%s", TenantContextHolder.getTenantId(), result.getRecipeId(), "*");
        RedisUtil.deleteByPattern(redisKey);
        //sendMq(menuRecipe);
    }

    private void sendMq(MenuRecipe menuRecipe) {
       List<String> deviceInfos = menuRecipeMapper.getSnByCanteenId(menuRecipe.getCanteenId());
        if (ObjectUtil.isNotEmpty(deviceInfos)) {
            deviceInfos.forEach((s) -> {
                DeviceMqMessage.deviceUpdateMenuConfigV4(s);
            });
        }
    }

    public RecipeProcessResult processDefault(MenuRecipeAddDTO content, Long recipeId) {
        return this.processDefault(content, recipeId, true);
    }

    public RecipeProcessResult processDefault(MenuRecipeAddDTO content, Long recipeId, Boolean isComplete) {
        RecipeProcessResult result = new RecipeProcessResult();
        String username = SecurityUtils.getUsername();
        List<MenuRecipeDateAddDTO> recipeDateList = content.getRecipeDateList();
        List<MenuRecipeDetail> recipeDetailV2List = Lists.newArrayList();
        List<MenuRecipeDishes> recipeDishesV2List = Lists.newArrayList();
        List<Long> ids = recipeDateList.stream()
                .filter((x) -> ObjectUtil.isNotNull(x.getDetailList()))
                .flatMap((x) -> x.getDetailList().stream())
                .filter((x) -> ObjectUtil.isNotNull(x.getDishesList()))
                .flatMap((x) -> x.getDishesList().stream())
                .map(MenuRecipeDishesAddDTO::getId)
                .filter(ObjectUtil::isNotNull).collect(Collectors.toList());
        Map<Long, Integer> idAndSalesMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(ids)) {
            List<MenuRecipeDishes> menuRecipeDishes = this.menuRecipeMapper.selectBatchIds(ids);
            idAndSalesMap = menuRecipeDishes.stream().collect(Collectors.groupingBy(MenuRecipeDishes::getId,
                    Collectors.collectingAndThen(Collectors.toList(), (x) -> (x.get(0)).getSaleNum())));
        }

        Map<Long, Integer> finalIdAndSalesMap = idAndSalesMap;
        Iterator<MenuRecipeDateAddDTO> var12 = recipeDateList.iterator();

        List<MenuRecipeDetailAddDTO> detailIdList;
        while (var12.hasNext()) {
            MenuRecipeDateAddDTO rd = var12.next();
            detailIdList = rd.getDetailList();
            detailIdList = detailIdList.stream().filter((d) -> {
                return ObjectUtil.isNotEmpty(d.getDishesList());
            }).collect(Collectors.toList());
            if (!ObjectUtil.isEmpty(detailIdList)) {
                detailIdList.forEach((in) -> {
                    List<MenuRecipeDishesAddDTO> dishesList = in.getDishesList();
                    if (ObjectUtil.isNotEmpty(dishesList)) {
                        this.checkDishesList(dishesList);
                    }

                });
                detailIdList.forEach((in) -> {
                    List<MenuRecipeDishesAddDTO> dishesList = in.getDishesList();
                    MenuRecipeDetail detailItem = new MenuRecipeDetail();
                    Long detailId = Id.next();
                    detailItem.setDetailId(detailId);
                    detailItem.setRecipeId(recipeId);
                    detailItem.setApplyDate(rd.getApplyDate());
                    detailItem.setMealtimeType(in.getMealtimeType());
                    detailItem.setCreateBy(username);
                    recipeDetailV2List.add(detailItem);
                    dishesList.forEach((di) -> {
                        MenuRecipeDishes dishesItem = new MenuRecipeDishes();
                        Integer salesSum = Optional.ofNullable(finalIdAndSalesMap.get(di.getId())).orElse(0);
                        dishesItem.setDetailId(detailId);
                        dishesItem.setDishesId(di.getDishesId());
                        dishesItem.setPrice(di.getPrice());
                        dishesItem.setSizeType(di.getSizeType());
                        dishesItem.setSaleNum(salesSum);
                        dishesItem.setSupplyNum(di.getSupplyNum());
                        int surplusNum = di.getSupplyNum() - salesSum;
                        if (surplusNum <= 0) {
                            surplusNum = 0;
                        }

                        dishesItem.setSurplusNum(surplusNum);
                        dishesItem.setRestrictNum(di.getRestrictNum());
                        dishesItem.setSalePrice(Optional.ofNullable(di.getSalePrice()).orElse(di.getPrice()));
                        dishesItem.setRecommendFlag(di.getRecommendFlag());
                        dishesItem.setSortNum(di.getSortNum());
                        recipeDishesV2List.add(dishesItem);
                    });
                });
            }
        }

        List<LocalDate> applyDateList = recipeDateList.stream().map(MenuRecipeDateAddDTO::getApplyDate).collect(Collectors.toList());
        List<Long> detailIdLists = this.menuRecipeMapper.selectDetailIdListByWrapper(recipeId, applyDateList, isComplete, recipeDateList);
        result.setTemplateDetailIds(detailIdLists);
        result.setRecipeDetails(recipeDetailV2List);
        result.setRecipeDishes(recipeDishesV2List);
        return result;
    }

    public List<LocalDate> getLastWeekDate() {
        List<LocalDate> objects = new ArrayList<>();
        LocalDate sunday = LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        LocalDate now = LocalDate.now();
        for (LocalDate date = now; date.isBefore(sunday) || date.isEqual(sunday); date = date.plusDays(1L)) {
            objects.add(date);
        }
        return objects;
    }

    public List<LocalDate> getLastWeek() {
        List<LocalDate> dates = new ArrayList<>();
        LocalDate now = LocalDate.now();
        for (int i = 0; i < 7; ++i) {
            dates.add(now.plusDays(i));
        }
        return dates;
    }

    public void changeBaseDishesIdTo(MenuRecipeAddDTO content) {
        List<MenuRecipeDateAddDTO> recipeDateList = content.getRecipeDateList();
        if (!ObjectUtil.isEmpty(recipeDateList)) {
            List<MenuRecipeDishesAddDTO> bean = recipeDateList.stream()
                    .filter((x) -> ObjectUtil.isNotEmpty(x.getDetailList()))
                    .flatMap((x) -> x.getDetailList().stream())
                    .filter((x) -> ObjectUtil.isNotEmpty(x.getDishesList()))
                    .flatMap((x) -> x.getDishesList().stream()).collect(Collectors.toList());
            this.changeBaseDishesId(bean);
        }
    }

    /**
     * 删除菜品计划信息信息
     *
     * @param id 菜品计划信息主键
     * @return 结果
     */
    @Override
    public int deleteMenuRecipeById(Long id) {
        return menuRecipeMapper.deleteMenuRecipeById(id);
    }

    public void changeBaseDishesId(List<MenuRecipeDishesAddDTO> bean) {
        if (!ObjectUtil.isEmpty(bean)) {
            List<Long> baseDishesIdList = bean.stream().map(MenuRecipeDishesAddDTO::getDishesId).distinct().collect(Collectors.toList());
            List<MenuBaseModel> baseList = this.menuRecipeMapper.selectBaseSizeDishesId(baseDishesIdList);
            Map<Long, List<MenuBaseDishesModel>> baseMap = baseList.stream().collect(Collectors.toMap(MenuBaseModel::getBaseDishesId, MenuBaseModel::getDishesList));
            bean.forEach((dishes) -> {
                Long sizeType = dishes.getSizeType();
                List baseDishesList;
                MenuBaseDishesModel tempDishes;
                if (sizeType == 2L) {
                    baseDishesList = baseMap.get(dishes.getDishesId());
                    if (ObjectUtil.isEmpty(baseDishesList)) {
                        return;
                    }
                    tempDishes = (MenuBaseDishesModel) baseDishesList.get(0);
                    if (CharSequenceUtil.contains(tempDishes.getSizeJson(), "大份")) {
                        dishes.setDishesId(tempDishes.getDishesId());
                    } else {
                        dishes.setDishesId(((MenuBaseDishesModel) baseDishesList.get(1)).getDishesId());
                    }
                } else if (sizeType == 3L) {
                    baseDishesList = baseMap.get(dishes.getDishesId());
                    if (ObjectUtil.isEmpty(baseDishesList)) {
                        return;
                    }
                    tempDishes = (MenuBaseDishesModel) baseDishesList.get(0);
                    if (CharSequenceUtil.contains(tempDishes.getSizeJson(), "小份")) {
                        dishes.setDishesId(tempDishes.getDishesId());
                    } else {
                        dishes.setDishesId(((MenuBaseDishesModel) baseDishesList.get(1)).getDishesId());
                    }
                } else {
                    baseDishesList = baseMap.get(dishes.getDishesId());
                    if (ObjectUtil.isEmpty(baseDishesList)) {
                        return;
                    }
                    tempDishes = (MenuBaseDishesModel) baseDishesList.get(0);
                    dishes.setDishesId(tempDishes.getDishesId());
                }

            });
        }
    }

    public RecipeProcessResult processDay(MenuRecipeAddDTO content, Long recipeId) {
        return this.processDay(content, recipeId, true);
    }

    public RecipeProcessResult processDay(MenuRecipeAddDTO content, Long recipeId, Boolean isComplete) {
        RecipeProcessResult result = new RecipeProcessResult();
        List<MenuRecipeDateAddDTO> recipeDateList = content.getRecipeDateList();
        GetRecipeDTO getRecipeDto = new GetRecipeDTO();
        getRecipeDto.setRecipeId(recipeId).setRecipeType(2).setIsComplete(isComplete).setMenuRecipeV2Add(content);
        List<Long> detailIds = this.getTemplateDetailIds(getRecipeDto);
        MenuRecipeDateAddDTO menuRecipeDateV2AddDTO = recipeDateList.get(0);
        List<MenuRecipeDetailAddDTO> detailList = menuRecipeDateV2AddDTO.getDetailList();
        List<MenuRecipeDetail> recipeDetailV2List = Lists.newArrayList();
        List<MenuRecipeDishes> recipeDishesV2List = Lists.newArrayList();
        if (ObjectUtil.isNotEmpty(detailList)) {
            String username = SecurityUtils.getUsername();

            for (MenuRecipeDetailAddDTO menuRecipeDetailV2AddDTO : detailList) {
                Integer mealtimeType = menuRecipeDetailV2AddDTO.getMealtimeType();
                MenuRecipeDetail detailItem = new MenuRecipeDetail();
                Long detailId = Id.next();
                detailItem.setDetailId(detailId);
                detailItem.setRecipeId(recipeId);
                detailItem.setMealtimeType(mealtimeType);
                detailItem.setCreateBy(username);
                detailItem.setDetailType(1);
                recipeDetailV2List.add(detailItem);
                List<MenuRecipeDishesAddDTO> dishesList = menuRecipeDetailV2AddDTO.getDishesList();
                if (ObjectUtil.isNotEmpty(dishesList)) {
                    this.checkDishesList(dishesList);
                    this.addMenuDishesToList(recipeDishesV2List, detailId, dishesList);
                }
            }
        }

        List<MenuRecipeDetail> menuRecipeDetails = this.getGeNowMenuRecipeDetail(getRecipeDto);
        List<Long> haveDetailIds = menuRecipeDetails.stream().map(MenuRecipeDetail::getDetailId)
                .collect(Collectors.toList());
        this.getDayActiveMenuRecipeDetailDishes(menuRecipeDetails, detailList, recipeDishesV2List, haveDetailIds);
        this.creatLastWeekRecipe(menuRecipeDateV2AddDTO, recipeDishesV2List, recipeDetailV2List, recipeId);
        result.setTemplateDetailIds(detailIds);
        result.setHaveDetailIds(haveDetailIds);
        result.setRecipeDetails(recipeDetailV2List);
        result.setRecipeDishes(recipeDishesV2List);
        return result;
    }

    public RecipeProcessResult processWeek(MenuRecipeAddDTO content, Long recipeId) {
        return this.processWeek(content, recipeId, true);
    }

    public RecipeProcessResult processWeek(MenuRecipeAddDTO content, Long recipeId, Boolean isComplete) {
        RecipeProcessResult result = new RecipeProcessResult();
        List<MenuRecipeDateAddDTO> recipeDateList = content.getRecipeDateList();
        List<MenuRecipeDetail> recipeDetailV2List = Lists.newArrayList();
        List<MenuRecipeDishes> recipeDishesV2List = Lists.newArrayList();
        String username = SecurityUtils.getUsername();
        List<Integer> weeks = recipeDateList.stream().map(MenuRecipeDateAddDTO::getApplyWeek).collect(Collectors.toList());
        GetRecipeDTO getRecipeDto = new GetRecipeDTO();
        getRecipeDto.setRecipeId(recipeId).setRecipeType(3).setMenuRecipeV2Add(content).setWeeks(weeks).setIsComplete(isComplete);
        List<Long> detailIds = this.getTemplateDetailIds(getRecipeDto);
        Iterator var12 = recipeDateList.iterator();

        while (true) {
            Integer applyWeek;
            List detailList;
            do {
                if (!var12.hasNext()) {
                    List<MenuRecipeDetail> menuRecipeDetails = this.getGeNowMenuRecipeDetail(getRecipeDto);
                    List<Long> haveDetailIds = menuRecipeDetails.stream().map(MenuRecipeDetail::getDetailId).collect(Collectors.toList());
                    this.getActiveMenuRecipeDetailDisnes(menuRecipeDetails, recipeDateList, recipeDishesV2List, haveDetailIds);
                    this.creatLastWeekRecipe(recipeDateList, recipeDishesV2List, recipeDetailV2List, recipeId, weeks);
                    result.setTemplateDetailIds(detailIds);
                    result.setHaveDetailIds(haveDetailIds);
                    result.setRecipeDetails(recipeDetailV2List);
                    result.setRecipeDishes(recipeDishesV2List);
                    return result;
                }

                MenuRecipeDateAddDTO menuRecipeDateV2AddDTO = (MenuRecipeDateAddDTO) var12.next();
                applyWeek = menuRecipeDateV2AddDTO.getApplyWeek();
                detailList = menuRecipeDateV2AddDTO.getDetailList();
            } while (ObjectUtil.isEmpty(detailList));

            Iterator var16 = detailList.iterator();

            while (var16.hasNext()) {
                MenuRecipeDetailAddDTO menuRecipeDetailV2AddDTO = (MenuRecipeDetailAddDTO) var16.next();
                Integer mealtimeType = menuRecipeDetailV2AddDTO.getMealtimeType();
                MenuRecipeDetail detailItem = new MenuRecipeDetail();
                Long detailId = Id.next();
                detailItem.setDetailId(detailId);
                detailItem.setRecipeId(recipeId);
                detailItem.setApplyWeek(applyWeek);
                detailItem.setMealtimeType(mealtimeType);
                detailItem.setCreateBy(username);
                detailItem.setDetailType(1);
                recipeDetailV2List.add(detailItem);
                List<MenuRecipeDishesAddDTO> dishesList = menuRecipeDetailV2AddDTO.getDishesList();
                if (ObjectUtil.isNotEmpty(dishesList)) {
                    this.checkDishesList(dishesList);
                    this.addMenuDishesToList(recipeDishesV2List, detailId, dishesList);
                }
            }
        }
    }

    public List<Long> getTemplateDetailIds(GetRecipeDTO getRecipeDto) {
        // 计算mealType参数
        Integer mealType = null;
        if (!getRecipeDto.getIsComplete() && getRecipeDto.getRecipeType() != 3) {
            mealType = Optional.ofNullable(getRecipeDto)
                    .map(GetRecipeDTO::getMenuRecipeV2Add)
                    .map(MenuRecipeAddDTO::getRecipeDateList)
                    .map(list -> list.get(0))
                    .map(MenuRecipeDateAddDTO::getDetailList)
                    .map(list -> list.get(0))
                    .map(MenuRecipeDetailAddDTO::getMealtimeType)
                    .orElseThrow(() -> new ServiceException("详情id为空"));
        }
        return menuRecipeMapper.selectDetailIds(getRecipeDto, mealType);
    }

    public List<MenuRecipeDetail> getGeNowMenuRecipeDetail(GetRecipeDTO getRecipeDto) {
        // 计算mealType参数
        Integer mealType = null;
        if (!getRecipeDto.getIsComplete() && getRecipeDto.getRecipeType() != 3) {
            mealType = Optional.ofNullable(getRecipeDto)
                    .map(GetRecipeDTO::getMenuRecipeV2Add)
                    .map(MenuRecipeAddDTO::getRecipeDateList)
                    .map(list -> list.get(0))
                    .map(MenuRecipeDateAddDTO::getDetailList)
                    .map(list -> list.get(0))
                    .map(MenuRecipeDetailAddDTO::getMealtimeType)
                    .orElseThrow(() -> new ServiceException("详情id为空"));
        }
        return this.menuRecipeMapper.selectDetailsList(getRecipeDto, LocalDate.now(), mealType);
    }

    public void getActiveMenuRecipeDetailDisnes(List<MenuRecipeDetail> menuRecipeDetails, List<MenuRecipeDateAddDTO> recipeDateList, List<MenuRecipeDishes> recipeDishesV2List, List<Long> haveDetailIds) {
        if (!ObjectUtil.isEmpty(menuRecipeDetails)) {
            List<MenuRecipeDishes> menuRecipeDishes = this.menuRecipeMapper.getMenuRecipeDishesList(haveDetailIds);
            menuRecipeDishes.forEach((dishes) -> {
                dishes.setSizeType(Optional.ofNullable(dishes.getSizeType()).orElse(1L));
            });
            Map<Long, Map<String, MenuRecipeDishes>> dishesMap = menuRecipeDishes.stream()
                    .collect(Collectors.groupingBy(MenuRecipeDishes::getDetailId,
                            Collectors.toMap(this.getDishesUniKeyFunction(), Function.identity())));
            Map<Integer, Map<Integer, Map<Long, MenuRecipeDetail>>> weekAndMealTimeMap = menuRecipeDetails.stream()
                    .collect(Collectors.groupingBy(MenuRecipeDetail::getApplyWeek, Collectors.groupingBy(MenuRecipeDetail::getMealtimeType, Collectors.toMap(MenuRecipeDetail::getDetailId, Function.identity()))));

            for (MenuRecipeDateAddDTO menuRecipeDateV2AddDTO : recipeDateList) {
                Integer applyWeek = menuRecipeDateV2AddDTO.getApplyWeek();
                List<MenuRecipeDetailAddDTO> detailList = menuRecipeDateV2AddDTO.getDetailList();
                Map<Integer, Map<Long, MenuRecipeDetail>> byApplyWeekMap = Optional.ofNullable(weekAndMealTimeMap.get(applyWeek)).orElse(new HashMap());

                for (MenuRecipeDetailAddDTO detailV2AddDTO : detailList) {
                    Integer mealtimeType = detailV2AddDTO.getMealtimeType();
                    List<MenuRecipeDishesAddDTO> dishesList = detailV2AddDTO.getDishesList();
                    Map<String, MenuRecipeDishesAddDTO> editDishesMap = dishesList.stream().collect(Collectors.toMap(this.getUniKeyFunction(), Function.identity()));
                    Map<Long, MenuRecipeDetail> detailMap = Optional.ofNullable(byApplyWeekMap.get(mealtimeType)).orElse(new HashMap());

                    for (Long detailId : detailMap.keySet()) {
                        Map<String, MenuRecipeDishes> haveDishesMap = Optional.ofNullable(dishesMap.get(detailId)).orElse(new HashMap());
                        for (String dishesFlag : editDishesMap.keySet()) {
                            MenuRecipeDishesAddDTO addDishes = editDishesMap.get(dishesFlag);
                            MenuRecipeDishes haveDishes = haveDishesMap.get(dishesFlag);
                            MenuRecipeDishes dishesItem = this.getEditMenuDishes(dishesFlag, addDishes, haveDishes, detailId);
                            recipeDishesV2List.add(dishesItem);
                        }
                    }
                }
            }
        }
    }

    public Function<MenuRecipeDishes, String> getDishesUniKeyFunction() {
        return (item) -> {
            Long var10000 = item.getDishesId();
            return "" + var10000 + "_" + item.getSizeType();
        };
    }

    public Function<MenuRecipeDishesAddDTO, String> getUniKeyFunction() {
        return (item) -> {
            Long var10000 = item.getDishesId();
            return "" + var10000 + "_" + item.getSizeType();
        };
    }

    public MenuRecipeDishes getEditMenuDishes(String dishesFlag, MenuRecipeDishesAddDTO addDishes, MenuRecipeDishes haveDishes, Long detailId) {
        Integer salesSum = Math.toIntExact(Optional.ofNullable(haveDishes).map(MenuRecipeDishes::getSaleNum).orElse(0));
        MenuRecipeDishes dishesItem = new MenuRecipeDishes();
        dishesItem.setDetailId(detailId);
        dishesItem.setDishesId(Long.parseLong(CharSequenceUtil.subBefore(dishesFlag, "_", true)));
        dishesItem.setPrice(addDishes.getPrice());
        dishesItem.setSaleNum(salesSum);
        dishesItem.setSupplyNum(addDishes.getSupplyNum());
        dishesItem.setSurplusNum(addDishes.getSupplyNum() - salesSum);
        dishesItem.setRestrictNum(addDishes.getRestrictNum());
        dishesItem.setSalePrice(Optional.ofNullable(addDishes.getSalePrice()).orElse(addDishes.getPrice()));
        dishesItem.setRecommendFlag(addDishes.getRecommendFlag());
        dishesItem.setSizeType(addDishes.getSizeType());
        dishesItem.setSortNum(addDishes.getSortNum());
        return dishesItem;
    }

    public void creatLastWeekRecipe(MenuRecipeDateAddDTO recipeDate, List<MenuRecipeDishes> recipeDishesV2List, List<MenuRecipeDetail> recipeDetailV2List, Long recipeId) {
        if (!ObjectUtil.isEmpty(recipeDate)) {
            String username = SecurityUtils.getUsername();
            LocalDate now = LocalDate.now();
            List<LocalDate> dates = this.getLastWeek();
            MenuRecipeDetail menuRecipeDetailBean = new MenuRecipeDetail();
            menuRecipeDetailBean.setRecipeId(recipeId);
            menuRecipeDetailBean.setApplyDate(now);
            menuRecipeDetailBean.setEndDate(now.plusDays(6L));
            menuRecipeDetailBean.setDetailType(2);
            List<MenuRecipeDetail> menuRecipeDetails = menuRecipeMapper.selectMenuRecipeDetail(menuRecipeDetailBean, null);
            Map<LocalDate, Map<Integer, MenuRecipeDetail>> haveDetail = menuRecipeDetails.stream()
                    .collect(Collectors.groupingBy(MenuRecipeDetail::getApplyDate, Collectors.toMap(MenuRecipeDetail::getMealtimeType, Function.identity())));
            Iterator<LocalDate> var10 = dates.iterator();

            label35:
            while (var10.hasNext()) {
                LocalDate date = var10.next();
                Map<Integer, MenuRecipeDetail> haveDayDetail = Optional.ofNullable(haveDetail.get(date)).orElse(new HashMap());
                List<MenuRecipeDetailAddDTO> detailList = recipeDate.getDetailList();
                Iterator<MenuRecipeDetailAddDTO> var14 = detailList.iterator();

                while (true) {
                    MenuRecipeDetailAddDTO addDetail;
                    Integer mealtimeType;
                    MenuRecipeDetail menuRecipeDetail;
                    do {
                        if (!var14.hasNext()) {
                            continue label35;
                        }
                        addDetail = var14.next();
                        mealtimeType = addDetail.getMealtimeType();
                        menuRecipeDetail = haveDayDetail.get(mealtimeType);
                    } while (!ObjectUtil.isEmpty(menuRecipeDetail));

                    MenuRecipeDetail detailItem = new MenuRecipeDetail();
                    Long detailId = Id.next();
                    detailItem.setDetailId(detailId);
                    detailItem.setRecipeId(recipeId);
                    detailItem.setApplyDate(date);
                    detailItem.setMealtimeType(mealtimeType);
                    detailItem.setCreateBy(username);
                    recipeDetailV2List.add(detailItem);
                    List<MenuRecipeDishesAddDTO> dishesList = addDetail.getDishesList();

                    for (MenuRecipeDishesAddDTO menuRecipeDishesAddDTO : dishesList) {
                        MenuRecipeDishes dishesItem = BeanUtil.copyProperties(menuRecipeDishesAddDTO, MenuRecipeDishes.class, new String[0]);
                        dishesItem.setDetailId(detailId);
                        dishesItem.setSaleNum(0);
                        dishesItem.setSurplusNum(menuRecipeDishesAddDTO.getSupplyNum());
                        dishesItem.setSalePrice(Optional.ofNullable(menuRecipeDishesAddDTO.getSalePrice()).orElse(menuRecipeDishesAddDTO.getPrice()));
                        recipeDishesV2List.add(dishesItem);
                    }
                }
            }

        }
    }

    public void creatLastWeekRecipe(List<MenuRecipeDateAddDTO> recipeDateList, List<MenuRecipeDishes> recipeDishesV2List, List<MenuRecipeDetail> recipeDetailV2List, Long recipeId, List<Integer> weeks) {
        if (!ObjectUtil.isEmpty(recipeDateList)) {
            String username = SecurityUtils.getUsername();
            LocalDate now = LocalDate.now();
            HashMap<Integer, LocalDate> dateHashMap = new HashMap<>();

            for (int i = 0; i < 7; ++i) {
                LocalDate applyWeek = now.plusDays((long) i);
                dateHashMap.put(applyWeek.getDayOfWeek().getValue(), applyWeek);
            }
            MenuRecipeDetail menuRecipeDetailBean = new MenuRecipeDetail();
            menuRecipeDetailBean.setRecipeId(recipeId);
            menuRecipeDetailBean.setApplyDate(now);
            menuRecipeDetailBean.setEndDate(now.plusDays(6L));
            menuRecipeDetailBean.setDetailType(2);
            List<MenuRecipeDetail> menuRecipeDetails = menuRecipeMapper.selectMenuRecipeDetail(menuRecipeDetailBean, weeks);
            Map<Integer, Map<Integer, MenuRecipeDetail>> haveDetail = menuRecipeDetails.stream()
                    .collect(Collectors.groupingBy(MenuRecipeDetail::getApplyWeek,
                            Collectors.toMap(MenuRecipeDetail::getMealtimeType, Function.identity())));
            Iterator<MenuRecipeDateAddDTO> var11 = recipeDateList.iterator();

            label38:
            while (var11.hasNext()) {
                MenuRecipeDateAddDTO menuRecipeDateV2AddDTO = var11.next();
                Integer applyWeek = menuRecipeDateV2AddDTO.getApplyWeek();
                Map<Integer, MenuRecipeDetail> haveWeekDetail = Optional.ofNullable(haveDetail.get(applyWeek)).orElse(new HashMap());
                List<MenuRecipeDetailAddDTO> detailList = menuRecipeDateV2AddDTO.getDetailList();
                Iterator<MenuRecipeDetailAddDTO> var16 = detailList.iterator();
                while (true) {
                    MenuRecipeDetailAddDTO addDetail;
                    Integer mealtimeType;
                    MenuRecipeDetail menuRecipeDetail;
                    do {
                        if (!var16.hasNext()) {
                            continue label38;
                        }
                        addDetail = var16.next();
                        mealtimeType = addDetail.getMealtimeType();
                        menuRecipeDetail = haveWeekDetail.get(mealtimeType);
                    } while (!ObjectUtil.isEmpty(menuRecipeDetail));

                    MenuRecipeDetail detailItem = new MenuRecipeDetail();
                    Long detailId = Id.next();
                    detailItem.setDetailId(detailId);
                    detailItem.setRecipeId(recipeId);
                    detailItem.setApplyWeek(applyWeek);
                    detailItem.setApplyDate(dateHashMap.get(applyWeek));
                    detailItem.setMealtimeType(mealtimeType);
                    detailItem.setCreateBy(username);
                    recipeDetailV2List.add(detailItem);
                    List<MenuRecipeDishesAddDTO> dishesList = addDetail.getDishesList();

                    for (MenuRecipeDishesAddDTO menuRecipeDishesV2AddDTO : dishesList) {
                        MenuRecipeDishes dishesItem = BeanUtil.copyProperties(menuRecipeDishesV2AddDTO, MenuRecipeDishes.class, new String[0]);
                        dishesItem.setDetailId(detailId);
                        dishesItem.setSaleNum(0);
                        dishesItem.setSurplusNum(menuRecipeDishesV2AddDTO.getSupplyNum());
                        dishesItem.setSalePrice(Optional.ofNullable(menuRecipeDishesV2AddDTO.getSalePrice()).orElse(menuRecipeDishesV2AddDTO.getPrice()));
                        recipeDishesV2List.add(dishesItem);
                    }
                }
            }
        }
    }

    public void checkDishesList(List<MenuRecipeDishesAddDTO> dishesList) {
        long count = dishesList.stream().filter((x) -> {
            return x.getSizeType() != 3L;
        }).count();
        if (count > 99L) {
            throw new ServiceException("菜谱信息达到上限");
        } else {
            dishesList.stream().filter((x) -> {
                return x.getSizeType() == 3L;
            }).forEach((dishes) -> {
                dishes.setRecommendFlag(2);
            });
            long dishesCount = dishesList.stream().filter((d) -> {
                return Integer.valueOf(1).equals(d.getRecommendFlag());
            }).count();
            if (dishesCount > 3L) {
                throw new ServiceException("无推荐菜谱");
            }
        }
    }

    public void addMenuDishesToList(List<MenuRecipeDishes> recipeDishesV2List, Long detailId, List<MenuRecipeDishesAddDTO> dishesList) {
        for (MenuRecipeDishesAddDTO dishesV2AddDTO : dishesList) {
            MenuRecipeDishes dishesItem = BeanUtil.copyProperties(dishesV2AddDTO, MenuRecipeDishes.class, new String[0]);
            dishesItem.setSalePrice(Optional.ofNullable(dishesItem.getSalePrice()).orElse(dishesItem.getPrice()));
            dishesItem.setDetailId(detailId);
            dishesItem.setSurplusNum(dishesV2AddDTO.getSupplyNum());
            recipeDishesV2List.add(dishesItem);
        }
    }

    public void getDayActiveMenuRecipeDetailDishes(List<MenuRecipeDetail> menuRecipeDetails, List<MenuRecipeDetailAddDTO> recipeDetailV2AddDTOS, List<MenuRecipeDishes> recipeDishesV2List, List<Long> haveDetailIds) {
        if (!ObjectUtil.isEmpty(menuRecipeDetails)) {
            List<MenuRecipeDishes> menuRecipeDishes = menuRecipeMapper.getMenuRecipeDishesList(haveDetailIds);
            menuRecipeDishes.forEach((dishes) -> {
                dishes.setSizeType(Optional.ofNullable(dishes.getSizeType()).orElse(1L));
            });
            Map<Long, Map<String, MenuRecipeDishes>> dishesMap =
                    menuRecipeDishes.stream().collect(Collectors.groupingBy(MenuRecipeDishes::getDetailId,
                            Collectors.toMap(this.getDishesUniKeyFunction(), Function.identity())));
            Map<Integer, Map<Long, MenuRecipeDetail>> dayAndMealTimeMap = menuRecipeDetails.stream()
                    .collect(Collectors.groupingBy(MenuRecipeDetail::getMealtimeType,
                            Collectors.toMap(MenuRecipeDetail::getDetailId, Function.identity())));

            for (MenuRecipeDetailAddDTO detailV2AddDTO : recipeDetailV2AddDTOS) {
                Integer mealtimeType = detailV2AddDTO.getMealtimeType();
                List<MenuRecipeDishesAddDTO> dishesList = detailV2AddDTO.getDishesList();
                Map<String, MenuRecipeDishesAddDTO> editDishesMap = dishesList.stream().collect(Collectors.toMap(this.getUniKeyFunction(), Function.identity()));
                Map<Long, MenuRecipeDetail> detailMap = Optional.ofNullable(dayAndMealTimeMap.get(mealtimeType)).orElse(new HashMap());

                for (Long detailId : detailMap.keySet()) {
                    Map<String, MenuRecipeDishes> haveDishesMap = Optional.ofNullable(dishesMap.get(detailId)).orElse(new HashMap());

                    for (String dishesFlag : editDishesMap.keySet()) {
                        MenuRecipeDishesAddDTO addDishes = editDishesMap.get(dishesFlag);
                        MenuRecipeDishes haveDishes = haveDishesMap.get(dishesFlag);
                        MenuRecipeDishes dishesItem = this.getEditMenuDishes(dishesFlag, addDishes, haveDishes, detailId);
                        recipeDishesV2List.add(dishesItem);
                    }
                }
            }

        }
    }

    /**
     * 根据sn获取菜谱菜品信息
     *
     * @param machineSn
     * @return
     */
    @Override
    public IssueRecipeCompressVO getMenuInfoBySn(String machineSn) {
        IssueRecipeCompressVO issueRecipe = new IssueRecipeCompressVO();
        //判断当前设备是否存在菜谱
        Long recipeId = menuRecipeMapper.getRecipeIdBySn(machineSn);
        if (recipeId == 0){
            return issueRecipe;
        }
        //查询菜谱信息
        MenuRecipe menuRecipe = menuRecipeMapper.getOneById(recipeId);
        //查询所有的detailsId
        List<MenuAndroidRecipeDetailVO> menuRecipeDetailList = menuRecipeMapper.selectMenuRecipeDetailLists(recipeId);
        List<Long> detailIds = menuRecipeDetailList.stream().map(MenuAndroidRecipeDetailVO::getDetailId).collect(Collectors.toList());
        if (ObjectUtil.isEmpty(detailIds)){
            return issueRecipe;
        }
        //查询所有的dishesId
        List<IssueRecipeDetailCompressVO> recipeDishList = menuRecipeMapper.selectRecipeDishList(detailIds);
        List<Long> dishesIds = recipeDishList.stream().map(IssueRecipeDetailCompressVO::getDishesId).collect(Collectors.toList());
        //查询菜品
        List<IssueRecipeMealCompressVO> menuList = menuRecipeMapper.getMenuRecipeListByDishesIds(dishesIds);
        List<LocalDate> applyDateList = menuRecipeDetailList.stream().map(MenuAndroidRecipeDetailVO::getApplyData).collect(Collectors.toList());
        applyDateList = applyDateList.stream().distinct().collect(Collectors.toList());
        //查询所有的餐次
        List<MealTimeVO> mealTimeList = menuRecipeMapper.getMealTimeList(menuRecipe.getStallId());
        List<IssueRecipeDateCompressVO> dateList = new ArrayList<>();
        for (LocalDate date : applyDateList){
            IssueRecipeDateCompressVO dateCompressVO = new IssueRecipeDateCompressVO();
            List<IssueRecipeIntervalCompressVO> intervalList = new ArrayList<>();
            for (MealTimeVO mealTimeVO : mealTimeList){
                IssueRecipeIntervalCompressVO intervalCompressVO = new IssueRecipeIntervalCompressVO();
                intervalCompressVO.setIntervalId(Long.valueOf(mealTimeVO.getMealTimeType()));
                intervalCompressVO.setIntervalName(mealTimeVO.getMealTimeName());
                intervalCompressVO.setStartTime(LocalTime.parse(mealTimeVO.getStartTime()));
                intervalCompressVO.setEndTime(LocalTime.parse(mealTimeVO.getEndTime()));
                for (MenuAndroidRecipeDetailVO menuAndroidRecipeDetailVO : menuRecipeDetailList){
                    if (mealTimeVO.getMealTimeType().equals(menuAndroidRecipeDetailVO.getMealTimeType())){
                        List<IssueRecipeDetailCompressVO> recipeDetailList = recipeDishList.stream().filter(x -> x.getDetailId().equals(menuAndroidRecipeDetailVO.getDetailId())).collect(Collectors.toList());
                        intervalCompressVO.setProductList(recipeDetailList);
                        break;
                    }
                }
                intervalList.add(intervalCompressVO);
            }
            dateCompressVO.setApplyDate(date);
            dateCompressVO.setIntervalList(intervalList);
            dateList.add(dateCompressVO);
        }
        System.out.println("menuRecipe = " + menuRecipe);

        issueRecipe.setRecipeType(menuRecipe.getRecipeType());
        issueRecipe.setRecipeId(menuRecipe.getRecipeId());
        issueRecipe.setUptime(menuRecipe.getUpdateTime());
        issueRecipe.setDateList(dateList);
        issueRecipe.setMealList(menuList);
        return issueRecipe;
    }

    @Override
    public DviceTimeIntervalVO intervalConfig(String machineSn) {
        DviceTimeIntervalVO dviceTimeIntervalVO = new DviceTimeIntervalVO();
        dviceTimeIntervalVO.setLevel(2);
        Long recipeId = menuRecipeMapper.getRecipeIdBySn(machineSn);
        if (recipeId == 0){
            return new DviceTimeIntervalVO();
        }
        //查询菜谱信息
        MenuRecipe menuRecipe = menuRecipeMapper.getOneById(recipeId);
        if (menuRecipe == null){
            return new DviceTimeIntervalVO();
        }
        List<DeviceMealtimeVO> basicsTimeIntervals = menuRecipeMapper.getBasicsTimeIntervals(menuRecipe.getStallId());
        if (basicsTimeIntervals == null || basicsTimeIntervals.isEmpty()){
            basicsTimeIntervals = new ArrayList<>();
        }
        dviceTimeIntervalVO.setBasicsTimeIntervals(basicsTimeIntervals);
        return dviceTimeIntervalVO;
    }




    @Override
    public Set<String> recipeImportDishes(MultipartFile excel, Long recipeId) {
        ExcelReader excelReader = null;
        try {
        Set<String> notImportDishesNames = new HashSet();
        List<MenuRecipeImportListener> listeners = new ArrayList();

            excelReader = EasyExcel.read(excel.getInputStream()).build();
            List<ReadSheet> readSheets = excelReader.excelExecutor().sheetList();
            for (ReadSheet readSheet : readSheets) {
                String sheetName = readSheet.getSheetName();
                Integer mealtimeType = AllocMealtimeTypeEnum.getKeyByDesc(sheetName);
                if (!Objects.isNull(mealtimeType)) {
                    MenuRecipeImportListener menuRecipeImportListener = new MenuRecipeImportListener(sheetName, recipeId, mealtimeType);
                    listeners.add(menuRecipeImportListener);
                    readSheet.getCustomReadListenerList().add(menuRecipeImportListener);
                }
            }
            excelReader.read(readSheets);
            notImportDishesNames.addAll(
                    listeners.stream()
                            .flatMap(listener -> listener.getNotImportDishesNames().stream())
                            .collect(Collectors.toList())
            );

        return notImportDishesNames;
        }catch (Exception e) {
            // log.error("导入菜品失败", e);
            throw new ServiceException(e.toString());
        } finally {
            if (excelReader != null) {
                excelReader.finish();
            }

        }
    }
}
