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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.canteen.core.auth.api.MgrAuthApi;
import com.bonus.canteen.core.auth.po.MgrUserAuthPO;
import com.bonus.canteen.core.common.page.QueryParseHelper;
import com.bonus.canteen.core.data.dataset.Executors;
import com.bonus.canteen.core.menu.constant.MenuDishesTypeDefaultFlagEnum;
import com.bonus.canteen.core.menu.dto.MenuDishesTypeAddDTO;
import com.bonus.canteen.core.menu.dto.MenuDishesTypeEditDTO;
import com.bonus.canteen.core.menu.dto.MenuDishesTypePageDTO;
import com.bonus.canteen.core.menu.dto.MenuTypeDishesDTO;
import com.bonus.canteen.core.menu.entity.MenuDishes;
import com.bonus.canteen.core.menu.entity.MenuDishesType;
import com.bonus.canteen.core.menu.mapper.MenuDishesMapper;
import com.bonus.canteen.core.menu.mapper.MenuDishesTypeMapper;
import com.bonus.canteen.core.menu.service.MenuDishesTypeService;
import com.bonus.canteen.core.menu.vo.MenuDishesTypeAllVO;
import com.bonus.canteen.core.menu.vo.MenuDishesTypePageVO;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.houqin.constant.DelFlagEnum;
import com.bonus.common.houqin.i18n.I18n;
import com.bonus.common.houqin.utils.id.Id;
import com.bonus.common.security.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Service
public class MenuDishesTypeServiceImpl extends ServiceImpl<MenuDishesTypeMapper, MenuDishesType> implements MenuDishesTypeService {
   private static final Logger log = LoggerFactory.getLogger(MenuDishesTypeServiceImpl.class);
   @Resource
   @Lazy
   private MenuDishesMapper menuDishesMapper;
   @Resource
   private MgrAuthApi mgrAuthApi;

   @Override
   public void addMenuDishesType(MenuDishesTypeAddDTO content) {
      List<MenuDishesType> cookList = this.baseMapper.selectList(Wrappers.lambdaQuery(MenuDishesType.class)
              .eq(MenuDishesType::getTypeName, content.getTypeName())
              .eq(MenuDishesType::getDelFlag, DelFlagEnum.DEL_FALSE.key()));
      if (CollUtil.isNotEmpty(cookList)) {
         throw new ServiceException(I18n.getMessage("menu_type_name_repeat", new Object[0]));
      } else {
         String username = SecurityUtils.getUsername();
         MenuDishesType dishesType = new MenuDishesType();
         BeanUtil.copyProperties(content, dishesType, new String[0]);
         dishesType.setCrby(username);
         dishesType.setTypeId(Id.next());
         this.baseMapper.insert(dishesType);
      }
   }

   @Override
   public Page<MenuDishesTypePageVO> getMenuDishesTypePage(String content) {
      Map<String, JSONObject> contentMap = JSON.parseObject(content, Map.class);
      Page<MenuDishesType> page = QueryParseHelper.getPageFromContent(content, MenuDishesType.class);
      MenuDishesTypePageDTO dishesTypePageDTO = contentMap.get("object")
              .toJavaObject(MenuDishesTypePageDTO.class);
      return this.baseMapper.selectAllList(page, dishesTypePageDTO, DelFlagEnum.DEL_FALSE.key());
   }

   @Override
   public void editMenuDishesType(MenuDishesTypeEditDTO content) {
      Long typeId = content.getTypeId();
      String typeName = content.getTypeName();
      Integer defaultFlag = this.baseMapper.selectDefaultFlagByTypeId(typeId);
      if (MenuDishesTypeDefaultFlagEnum.DEFAULT.key().equals(defaultFlag)) {
         throw new ServiceException(I18n.getMessage("menu_dishes_type_default", new Object[0]));
      } else {
         if (StringUtils.isNotBlank(typeName)) {
            List<MenuDishesType> cookList = this.baseMapper.selectList(Wrappers.lambdaQuery(MenuDishesType.class)
                    .eq(MenuDishesType::getTypeName, typeName)
                    .eq(MenuDishesType::getDelFlag, DelFlagEnum.DEL_FALSE.key())
                    .ne(MenuDishesType::getTypeId, typeId));
            if (CollUtil.isNotEmpty(cookList)) {
               throw new ServiceException(I18n.getMessage("menu_type_name_repeat", new Object[0]));
            }
         }

         String username = SecurityUtils.getUsername();
         MenuDishesType dishesType = new MenuDishesType();
         BeanUtil.copyProperties(content, dishesType, new String[0]);
         dishesType.setUpby(username);
         this.baseMapper.update(dishesType,Wrappers.lambdaQuery(MenuDishesType.class)
                 .eq(MenuDishesType::getTypeId, typeId));
      }
   }

   @Override
   public void removeByTypeId(Long typeId) {
      Long typeCount = this.menuDishesMapper.selectCount(Wrappers.lambdaQuery(MenuDishes.class)
              .eq(MenuDishes::getTypeId, typeId).eq(MenuDishes::getDelFlag, DelFlagEnum.DEL_FALSE.key()));
      if (ObjectUtil.isNotNull(typeCount) && typeCount > 0L) {
         throw new ServiceException(I18n.getMessage("menu_type_use_del", new Object[0]));
      } else {
         Integer defaultFlag = this.baseMapper.selectDefaultFlagByTypeId(typeId);
         if (MenuDishesTypeDefaultFlagEnum.DEFAULT.key().equals(defaultFlag)) {
            throw new ServiceException(I18n.getMessage("menu_type_default_del", new Object[0]));
         } else {
            ((MenuDishesTypeMapper)this.baseMapper).update(null, Wrappers.lambdaUpdate(MenuDishesType.class)
                    .eq(MenuDishesType::getTypeId, typeId)
                    .set(MenuDishesType::getDelFlag, DelFlagEnum.DEL_TRUE.key()));
         }
      }
   }

   @Override
   @Transactional(rollbackFor = {Exception.class})
   public void dateRecoveryMenuDishesType() {
      Executors.doInAllTenant((merchantId) -> {
         Long count = this.baseMapper.selectCount(Wrappers.lambdaQuery(MenuDishesType.class)
                 .eq(MenuDishesType::getDefaultFlag, MenuDishesTypeDefaultFlagEnum.DEFAULT.key()));
         if (!ObjectUtil.isNotNull(count) || count <= 0L) {
            Long typeId = Id.next();
            MenuDishesType dishesType = new MenuDishesType();
            dishesType.setTypeId(typeId);
            dishesType.setTypeName("默认");
            dishesType.setAliasName("default");
            dishesType.setDefaultFlag(MenuDishesTypeDefaultFlagEnum.DEFAULT.key());
            dishesType.setCrby("");
            this.baseMapper.insert(dishesType);
            this.menuDishesMapper.update(null, Wrappers.lambdaUpdate(MenuDishes.class)
                    .eq(MenuDishes::getTypeId, -1)
                    .set(MenuDishes::getTypeId, typeId));
         }
      });
   }

   @Override
   public Long getDefaultTypeId() {
      Long typeId = this.baseMapper.selectDefaultTypeId(MenuDishesTypeDefaultFlagEnum.DEFAULT.key());
      if (ObjectUtil.isNull(typeId)) {
         MenuDishesType dishesType = new MenuDishesType();
         typeId = Id.next();
         dishesType.setTypeId(typeId);
         dishesType.setTypeName("默认");
         dishesType.setAliasName("default");
         dishesType.setDefaultFlag(MenuDishesTypeDefaultFlagEnum.DEFAULT.key());
         dishesType.setCrby("");
         this.baseMapper.insert(dishesType);
      }

      return typeId;
   }

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

   @Override
   public List<MenuDishesTypeAllVO> getAllUseMenuDishesTypeList(MenuTypeDishesDTO content) {
      MgrUserAuthPO authPo = this.mgrAuthApi.getUserAuthPO();
      List<Long> typeIds = this.menuDishesMapper.selectUseTypeDishesList(content, authPo);
      if (ObjectUtil.isEmpty(typeIds)) {
         return CollUtil.newArrayList(new MenuDishesTypeAllVO[0]);
      } else {
         List<MenuDishesType> menuDishesTypes = this.baseMapper.selectList(Wrappers.lambdaQuery(MenuDishesType.class)
                 .eq(MenuDishesType::getDelFlag, DelFlagEnum.DEL_FALSE.key())
                 .in(MenuDishesType::getTypeId, typeIds));
         return BeanUtil.copyToList(menuDishesTypes, MenuDishesTypeAllVO.class);
      }
   }
}
