package cn.iocoder.yudao.module.system.service.restaurant;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.FoodCategoryDO;
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.FoodCategoryMapper;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.starter.annotation.LogRecord;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.HAS_CHILDREN_NODE;
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;


/**
 * 菜品分类 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class FoodCategoryServiceImpl implements FoodCategoryService {

    @Resource
    private FoodCategoryMapper foodCategoryMapper;


    @Override
    @LogRecord(type = FOOD_CATEGORY, subType = FOOD_CATEGORY_CREATE_SUB_TYPE, bizNo = "{{#id}}",
            success = FOOD_CATEGORY_CREATE_SUCCESS)
    public void createFoodCategory(FoodCategoryDO createReqVO) {
        createReqVO.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
        createReqVO.setCreatedTime(new Date());
        if (createReqVO.getParentId() == null) {
            createReqVO.setParentId(0L); //父级分类
        }
        foodCategoryMapper.insert(createReqVO);

        LogRecordContext.putVariable("name", createReqVO.getCategoryName());
        LogRecordContext.putVariable("id", createReqVO.getId());
    }

    @Override
    @LogRecord(type = FOOD_CATEGORY, subType = FOOD_CATEGORY_UPDATE_SUB_TYPE, bizNo = "{{#id}}",
            success = FOOD_CATEGORY_UPDATE_SUCCESS)
    public void updateFoodCategory(FoodCategoryDO updateReqVO) {
        foodCategoryMapper.updateById(updateReqVO);

        LogRecordContext.putVariable("name", updateReqVO.getCategoryName());
        LogRecordContext.putVariable("id", updateReqVO.getId());
    }

    @Override
    public void deleteFoodCategory(Long id) {
        List<FoodCategoryDO> foodCategoryList = foodCategoryMapper.selectList(new LambdaQueryWrapperX<FoodCategoryDO>()
                .eq(FoodCategoryDO::getParentId, id));

        if (CollectionUtil.isNotEmpty(foodCategoryList)) {
            throw exception(HAS_CHILDREN_NODE);
        }
        foodCategoryMapper.deleteById(id);
    }

    @Override
    public FoodCategoryDO getFoodCategory(Long id) {
        return foodCategoryMapper.selectById(id);
    }

    @Override
    public List<FoodCategoryDO> getTree(Long restaurantId) {
        List<FoodCategoryDO> parentList = foodCategoryMapper.selectList(new LambdaQueryWrapperX<FoodCategoryDO>()
                .eq(FoodCategoryDO::getRestaurantId, restaurantId)
                .eq(FoodCategoryDO::getParentId, 0L));
        return parentList.stream().map(item -> this.getTreeById(item.getId())).collect(Collectors.toList());
    }


    public FoodCategoryDO getTreeById(Long id) {
        FoodCategoryDO category = foodCategoryMapper.selectById(id);
        List<FoodCategoryDO> list = foodCategoryMapper.selectList(null);
        category.setChildrenList(getAllSubNodes(category, list));
        return category;
    }


    private List<FoodCategoryDO> getAllSubNodes(FoodCategoryDO rootNode, List<FoodCategoryDO> list) {
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        return list.stream().filter(item -> item.getParentId().equals(rootNode.getId()))
                .peek(menu -> menu.setChildrenList(getAllSubNodes(menu, list)))
                .collect(Collectors.toList());
    }

}