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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
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.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.constant.DelFlagEnum;
import com.bonus.core.common.page.PageVO;
import com.bonus.core.menu.dto.OrderEvaluaCountDto;
import com.bonus.core.menu.entity.MenuEvaluaOrder;
import com.bonus.core.menu.mapper.MenuEvaluaOrderMapper;
import com.bonus.core.menu.mapper.MenuEvaluaPictureMapper;
import com.bonus.core.allocation.api.AllocCanteenApi;
import com.bonus.core.common.page.PageVO;
import com.bonus.core.common.utils.SysUtil;
import com.bonus.core.menu.constant.MenuConstant;
import com.bonus.core.menu.constant.MenuEvaluaOrderTypeEnum;
import com.bonus.core.menu.dto.MenuEvaluaDetailAddDTO;
import com.bonus.core.menu.dto.MenuEvaluaOrderAddDTO;
import com.bonus.core.menu.dto.MenuEvaluaOrderPageDTO;
import com.bonus.core.menu.entity.*;
import com.bonus.core.menu.mapper.*;
import com.bonus.core.menu.service.MenuEvaluaOrderService;
import com.bonus.core.menu.vo.MenuEvaluaMealVO;
import com.bonus.core.menu.vo.MenuEvaluaOrderPageMealDTO;
import com.bonus.core.menu.vo.MenuEvaluaOrderPageMealVO;
import com.bonus.core.order.mobile.vo.OrderListMobileVO;
import com.bonus.core.menu.vo.*;
import com.bonus.core.order.api.OrderMenuApi;
import com.bonus.i18n.I18n;
import com.bonus.utils.id.Id;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MenuEvaluaOrderServiceImpl extends ServiceImpl<MenuEvaluaOrderMapper, MenuEvaluaOrder> implements MenuEvaluaOrderService {
   private static final Logger log = LoggerFactory.getLogger(MenuEvaluaOrderServiceImpl.class);
   @Lazy
   @Resource
   private MenuEvaluaPictureMapper menuEvaluaPictureMapper;
   @Lazy
   @Autowired
   private OrderMenuApi orderMenuApi;
   @Lazy
   @Autowired
   private MenuDishesMapper menuDishesMapper;
   @Lazy
   @Autowired
   private MenuEvaluaDetailMapper menuEvaluaDetailMapper;
   @Lazy
   @Autowired
   private MenuDishesSaleRecordMapper menuDishesSaleRecordMapper;
   @Autowired
   private AllocCanteenApi allocCanteenApi;

   @Override
   @Transactional(
           rollbackFor = {Exception.class}
   )
   public void addMenuEvaluaOrder(MenuEvaluaOrderAddDTO content) {
      Long ordId = content.getOrdId();
      LocalDateTime ordTime = this.orderMenuApi.getOrdTimeByOrdId(ordId);
      if (ObjectUtil.isNotNull(ordTime) && ordTime.until(LocalDateTime.now(), ChronoUnit.DAYS) >= (long) MenuConstant.ORDER_EVALUA_LOSE_DAY) {
         throw new ServiceException(I18n.getMessage("menu_order_over_three_day", new Object[0]));
      } else {
         MenuEvaluaOrder evaluaOrder = new MenuEvaluaOrder();
         BeanUtil.copyProperties(content, evaluaOrder, new String[0]);
         Long evaluaId = Id.next();
         evaluaOrder.setEvaluaId(evaluaId);
         evaluaOrder.setStarLevel(5);
         ((MenuEvaluaOrderMapper)this.baseMapper).insert(evaluaOrder);
         List<String> pictureList = content.getPictureList();
         if (CollUtil.isNotEmpty(pictureList)) {
            Iterator var7 = pictureList.iterator();

            while(var7.hasNext()) {
               String pictureUrl = (String)var7.next();
               MenuEvaluaPicture evaluaPicture = new MenuEvaluaPicture();
               evaluaPicture.setEvaluaId(evaluaId);
               evaluaPicture.setPictureUrl(SysUtil.getCutPath(pictureUrl));
               this.menuEvaluaPictureMapper.insert(evaluaPicture);
            }
         }

         List<MenuEvaluaDetailAddDTO> detailList = (List)content.getDetailList().stream().distinct().collect(Collectors.toList());
         List<MenuDishes> mealList = this.menuDishesMapper.selectList(((LambdaQueryWrapper<MenuDishes>) Wrappers
                 .lambdaQuery(MenuDishes.class).in(MenuDishes::getDishesId,
                         (Collection)detailList.stream().map(MenuEvaluaDetailAddDTO::getMealId)
                                 .collect(Collectors.toSet())))
                 .select(MenuDishes::getDishesId, MenuDishes::getMealType));
         Map<Long, Integer> mealTypeMap = Maps.newTreeMap();
         if (CollUtil.isNotEmpty(mealList)) {
            mealList.forEach((m) -> {
               mealTypeMap.put(m.getDishesId(), m.getMealType());
            });
         }

         Iterator var10 = detailList.iterator();

         while(var10.hasNext()) {
            MenuEvaluaDetailAddDTO detail = (MenuEvaluaDetailAddDTO)var10.next();
            MenuEvaluaDetail evaluaDetail = new MenuEvaluaDetail();
            BeanUtil.copyProperties(detail, evaluaDetail, new String[0]);
            Integer mealType = detail.getMealType();
            if (ObjectUtil.isNull(mealType)) {
               mealType = (Integer)Optional.ofNullable((Integer)mealTypeMap.get(detail.getMealId())).orElse(1);
               if (content.getOrderEvaluaType().equals(MenuEvaluaOrderTypeEnum.SUPERMARKET_ORDER.key())) {
                  mealType = 3;
               }
            }

            evaluaDetail.setDetailId(Id.next());
            evaluaDetail.setEvaluaId(evaluaId);
            evaluaDetail.setStarLevel(detail.getStarLevel());
            evaluaDetail.setDescription(content.getDescription());
            evaluaDetail.setMealType(mealType);
            this.menuEvaluaDetailMapper.insert(evaluaDetail);
            MenuDishesSaleRecord dishesEvaluate = this.menuDishesSaleRecordMapper
                    .selectEvaluate(Wrappers.lambdaQuery(MenuDishesSaleRecord.class)
                            .eq(MenuDishesSaleRecord::getDishesId, detail.getMealId())
                            .eq(MenuDishesSaleRecord::getStallId, content.getShopstallId()));
            if (ObjectUtil.isNull(dishesEvaluate)) {
               dishesEvaluate = new MenuDishesSaleRecord();
               dishesEvaluate.setDishesId(detail.getMealId());
               dishesEvaluate.setStallId(content.getShopstallId());
               dishesEvaluate.setSaleNum(0);
               dishesEvaluate.setSaleMonth(LocalDate.now().getMonthValue());
               dishesEvaluate.setMonthlySales(0);
               dishesEvaluate.setEvaluateNum(1);
               dishesEvaluate.setEvaluateLevel(BigDecimal.valueOf(5L));
               if (detail.getStarLevel() >= 4) {
                  dishesEvaluate.setGoodProbability(BigDecimal.ONE);
               } else {
                  dishesEvaluate.setGoodProbability(BigDecimal.ZERO);
               }

               dishesEvaluate.setUpdateTime(LocalDateTime.now());
               this.menuDishesSaleRecordMapper.insert(dishesEvaluate);
            } else {
               BigDecimal evaluateLevel = BigDecimal.valueOf((long)dishesEvaluate.getEvaluateNum()).multiply(dishesEvaluate.getEvaluateLevel()).add(BigDecimal.valueOf((long)detail.getStarLevel())).divide(BigDecimal.valueOf((long)dishesEvaluate.getEvaluateNum() + 1L), 2, RoundingMode.HALF_UP);
               int goodNum = 0;
               if (detail.getStarLevel() >= 4) {
                  goodNum = 1;
               }

               BigDecimal goodProbability = BigDecimal.valueOf((long)dishesEvaluate.getEvaluateNum()).multiply(dishesEvaluate.getGoodProbability()).add(BigDecimal.valueOf((long)goodNum)).divide(BigDecimal.valueOf((long)dishesEvaluate.getEvaluateNum() + 1L), 2, RoundingMode.HALF_UP);
               this.menuDishesSaleRecordMapper.update(null, Wrappers.lambdaUpdate(MenuDishesSaleRecord.class).eq(MenuDishesSaleRecord::getDishesId, detail.getMealId()).eq(MenuDishesSaleRecord::getStallId,
                       content.getShopstallId()).set(MenuDishesSaleRecord::getEvaluateNum, dishesEvaluate.getEvaluateNum() + 1)
                       .set(MenuDishesSaleRecord::getEvaluateLevel, evaluateLevel).set(MenuDishesSaleRecord::getGoodProbability, goodProbability));
            }
         }

         this.orderMenuApi.editOrdStateByOrdId(ordId);
      }
   }

   @Override
   public MenuEvaluaMealVO getMenuEvaluaOrderPageByMeal(MenuEvaluaOrderPageMealDTO content) {
      List<MenuEvaluaOrderPageMealVO> evaluaList =
              ((MenuEvaluaOrderMapper)this.baseMapper).selectAllListByMeal(content.getMealId(), content.getShopstallId(), content.getSearchType());
      if (CollUtil.isNotEmpty(evaluaList)) {
         Iterator var5 = evaluaList.iterator();

         while(var5.hasNext()) {
            MenuEvaluaOrderPageMealVO item = (MenuEvaluaOrderPageMealVO)var5.next();
            Long evaluaId = item.getEvaluaId();
            List<String> pictureList = this.menuEvaluaPictureMapper.selectPictureByEvaluaId(evaluaId);
            item.setPictureList(pictureList);
         }
      }

      MenuEvaluaMealVO result = ((MenuEvaluaOrderMapper)this.baseMapper).selectAvgByMealAndShop(content.getMealId(), content.getMealType(), content.getShopstallId(), DelFlagEnum.DEL_FALSE.key());
      if (result == null) {
         log.info("***[小程序_获取餐品的评价列表]_没有记录,直接返回空**************");
         return new MenuEvaluaMealVO();
      } else {
         if (result.getAvgStarLevel() != null) {
            result.setAvgStarLevel(result.getAvgStarLevel().setScale(1, RoundingMode.HALF_UP));
         }
         PageVO<MenuEvaluaOrderPageMealVO> orderPage = PageVO.of(evaluaList, evaluaList);
         result.setEvaluaListVo(orderPage);
         result.setEvaluaList(evaluaList);
         return result;
      }
   }

   @Override
   public PageVO<MenuEvaluateOrderPageVO> getMenuEvaluateOrderPagePc(MenuEvaluaOrderPageDTO content) {
      List menuEvaluateOrderPageVOS;
      if (CollUtil.isNotEmpty(content.getAreaIdList()) && ObjectUtil.isEmpty(content.getCanteenIdList())) {
         menuEvaluateOrderPageVOS = this.allocCanteenApi.getCanteenIdListByAreaIdList((List)content.getAreaIdList());
         if (ObjectUtil.isEmpty(menuEvaluateOrderPageVOS)) {
            return PageVO.of((List)(new ArrayList()));
         }

         content.setCanteenIdList(this.allocCanteenApi.getCanteenIdListByAreaIdList((List)content.getAreaIdList()));
      }

      PageHelper.startPage(content);
      menuEvaluateOrderPageVOS = ((MenuEvaluaOrderMapper)this.baseMapper).selectEvaluatePagePc(content);
      if (CollUtil.isEmpty(menuEvaluateOrderPageVOS)) {
         return PageVO.of(menuEvaluateOrderPageVOS);
      } else {
         Set<Long> evaluaIds = (Set)((List<MenuEvaluateOrderPageVO>)menuEvaluateOrderPageVOS).stream().map(MenuEvaluateOrderPageVO::getEvaluaId).collect(Collectors.toSet());
         List<MenuEvaluaPicture> menuEvaluaPictures = this.menuEvaluaPictureMapper.selectList((Wrapper)Wrappers.lambdaQuery(MenuEvaluaPicture.class).in(MenuEvaluaPicture::getEvaluaId, evaluaIds));
         Map<Long, List<String>> pictureMap = (Map)menuEvaluaPictures.stream().collect(Collectors.groupingBy(MenuEvaluaPicture::getEvaluaId, Collectors.mapping(MenuEvaluaPicture::getPictureUrl, Collectors.toList())));
         List<MenuEvaluateDishesVO> menuEvaluateDishesVOS = this.menuEvaluaDetailMapper.selectDishesDetailByEvaluaIds(evaluaIds);
         Map<Long, List<MenuEvaluateDishesVO>> dishesMap = (Map)menuEvaluateDishesVOS.stream().collect(Collectors.groupingBy(MenuEvaluateDishesVO::getEvaluaId));
         menuEvaluateOrderPageVOS.forEach((r) -> {

            Long evaluaId = ((MenuEvaluateOrderPageVO)r).getEvaluaId();
            ((MenuEvaluateOrderPageVO)r).setDishesList((List)dishesMap.get(evaluaId));
            ((MenuEvaluateOrderPageVO)r).setPictureList((List)pictureMap.get(evaluaId));
         });
         return PageVO.of(menuEvaluateOrderPageVOS);
      }
   }


   public OrderEvaluaCountDto getHaveImageCount(Long dishesId) {
      OrderEvaluaCountDto orderEvaluaCountDto = new OrderEvaluaCountDto();
      Integer haveImage = ((MenuEvaluaOrderMapper)this.baseMapper).selectHaveImageCount(dishesId);
      Integer allCount = ((MenuEvaluaOrderMapper)this.baseMapper).selectAllCount(dishesId);
      orderEvaluaCountDto.setImageCount(haveImage);
      orderEvaluaCountDto.setTotalCount(allCount);
      return orderEvaluaCountDto;
   }
}
