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

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bonus.canteen.core.menu.dto.*;
import com.bonus.canteen.core.menu.mapper.MenuRecipeDishesMapper;
import com.bonus.canteen.core.menu.model.MenuBaseDishesModel;
import com.bonus.canteen.core.menu.model.MenuBaseModel;
import com.bonus.canteen.core.menu.service.IMenuRecipeService;
import com.bonus.canteen.core.menu.vo.MenuRecipeDataVO;
import com.bonus.canteen.core.menu.vo.MenuRecipeV2VO;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bonus.canteen.core.menu.mapper.MenuRecipeMapper;
import com.bonus.canteen.core.menu.domain.MenuRecipe;
import org.springframework.transaction.annotation.Transactional;

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

    /**
     * 菜谱列表-获取菜品列表
     *
     * @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
    @Transactional(rollbackFor = {Exception.class})
    public Long add(MenuRecipeAddDTO dto) {
        this.changeBaseDishesIdTo(dto);
        return 0L;
    }

    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);
        }
    }

    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());
                    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());
                    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());
                    tempDishes = (MenuBaseDishesModel)baseDishesList.get(0);
                    dishes.setDishesId(tempDishes.getDishesId());
                }

            });
        }
    }

}
