package org.dromara.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.dromara.system.domain.bo.SysFoodCategoryBo;
import org.dromara.system.domain.vo.SysFoodCategoryVo;
import org.dromara.system.domain.SysFoodCategory;
import org.dromara.system.mapper.SysFoodCategoryMapper;
import org.dromara.system.service.ISysFoodCategoryService;

import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 食材分类Service业务层处理
 *
 * @author Lion Li
 * @date 2025-06-27
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SysFoodCategoryServiceImpl implements ISysFoodCategoryService {

    private final SysFoodCategoryMapper baseMapper;

    @Override
    public TableDataInfo<SysFoodCategoryVo> listTree(SysFoodCategoryBo bo) {
        List<SysFoodCategory> foodCategoryList = null;
        if (StrUtil.isNotBlank(bo.getName())) {
            foodCategoryList = baseMapper.selectList(Wrappers.lambdaQuery(SysFoodCategory.class)
                .like(SysFoodCategory::getName, bo.getName()));
            if (CollUtil.isEmpty(foodCategoryList)) {
                return TableDataInfo.build();
            }

            Set<Long> parentIdSet = foodCategoryList.stream()
                .filter(v -> ObjUtil.isNotNull(v.getParentId()) && v.getParentId() > 0)
                .map(SysFoodCategory::getParentId).collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(parentIdSet)) {
                Map<Long, SysFoodCategory> parentMap = baseMapper
                    .selectList(Wrappers.lambdaQuery(SysFoodCategory.class)
                        .in(SysFoodCategory::getFoodCategoryId, parentIdSet))
                    .stream().collect(Collectors.toMap(k1 -> k1.getFoodCategoryId(), k2 -> k2, (k1, k2) -> k1));

                foodCategoryList.forEach(v -> {
                    parentMap.remove(v.getFoodCategoryId());
                });
                foodCategoryList.addAll(parentMap.values());
            }
        } else {
            foodCategoryList = baseMapper.selectList();
        }

        foodCategoryList.sort((o1, o2) -> o1.getParentId().compareTo(o2.getParentId()));
        List<SysFoodCategoryVo> treeList = CollUtil.newArrayList();
        Map<Long, SysFoodCategoryVo> foodMap = MapUtil.newHashMap(foodCategoryList.size());
        foodCategoryList.forEach(v -> {
            SysFoodCategoryVo vo = MapstructUtils.convert(v, SysFoodCategoryVo.class);
            if (ObjUtil.isNull(v.getParentId()) || v.getParentId() == 0) {
                treeList.add(vo);
            } else {
                SysFoodCategoryVo pVo = foodMap.get(v.getParentId());
                if (CollUtil.isEmpty(pVo.getChildren())) {
                    pVo.setChildren(CollUtil.newArrayList());
                }
                pVo.getChildren().add(vo);
            }
            foodMap.put(v.getFoodCategoryId(), vo);
        });

        return TableDataInfo.build(treeList);
    }

    /**
     * 查询食材分类
     *
     * @param foodCategoryId 主键
     * @return 食材分类
     */
    @Override
    public SysFoodCategoryVo queryById(Long foodCategoryId) {
        return baseMapper.selectVoById(foodCategoryId);
    }

    /**
     * 分页查询食材分类列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 食材分类分页列表
     */
    @Override
    public TableDataInfo<SysFoodCategoryVo> queryPageList(SysFoodCategoryBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysFoodCategory> lqw = buildQueryWrapper(bo);
        Page<SysFoodCategoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的食材分类列表
     *
     * @param bo 查询条件
     * @return 食材分类列表
     */
    @Override
    public List<SysFoodCategoryVo> queryList(SysFoodCategoryBo bo) {
        LambdaQueryWrapper<SysFoodCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SysFoodCategory> buildQueryWrapper(SysFoodCategoryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysFoodCategory> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(SysFoodCategory::getFoodCategoryId);
        lqw.like(StringUtils.isNotBlank(bo.getName()), SysFoodCategory::getName, bo.getName());
        lqw.eq(bo.getParentId() != null, SysFoodCategory::getParentId, bo.getParentId());
        lqw.eq(bo.getSort() != null, SysFoodCategory::getSort, bo.getSort());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysFoodCategory::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增食材分类
     *
     * @param bo 食材分类
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(SysFoodCategoryBo bo) {
        SysFoodCategory add = MapstructUtils.convert(bo, SysFoodCategory.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setFoodCategoryId(add.getFoodCategoryId());
        }
        return flag;
    }

    /**
     * 修改食材分类
     *
     * @param bo 食材分类
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(SysFoodCategoryBo bo) {
        SysFoodCategory update = MapstructUtils.convert(bo, SysFoodCategory.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysFoodCategory entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除食材分类信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
