package org.dromara.mall.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.mall.product.domain.MallCategory;
import org.dromara.mall.product.domain.bo.MallCategoryBo;
import org.dromara.mall.product.domain.vo.MallCategoryVo;
import org.dromara.mall.product.mapper.MallCategoryMapper;
import org.dromara.mall.product.service.MallCategoryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品分类Service业务层处理
 *
 * @author pengles
 */
@RequiredArgsConstructor
@Service
public class MallCategoryServiceImpl implements MallCategoryService {

    private final MallCategoryMapper baseMapper;

    /**
     * 查询商品分类
     */
    @Override
    public MallCategoryVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询商品分类列表
     */
    @Override
    public TableDataInfo<MallCategoryVo> queryPageList(MallCategoryBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<MallCategory> lqw = buildQueryWrapper(bo);
        Page<MallCategoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询商品分类列表
     */
    @Override
    public List<MallCategoryVo> queryList(MallCategoryBo bo) {
        LambdaQueryWrapper<MallCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 查询商品分类树形列表
     */
    @Override
    public List<MallCategoryVo> queryTreeList() {
        MallCategoryBo bo = new MallCategoryBo();
        bo.setStatus(0); // 只查询启用的分类
        List<MallCategoryVo> list = queryList(bo);
        return buildTree(list);
    }

    private LambdaQueryWrapper<MallCategory> buildQueryWrapper(MallCategoryBo bo) {
        LambdaQueryWrapper<MallCategory> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(bo.getName()), MallCategory::getName, bo.getName());
        lqw.eq(bo.getParentId() != null, MallCategory::getParentId, bo.getParentId());
        lqw.eq(bo.getLevel() != null, MallCategory::getLevel, bo.getLevel());
        lqw.eq(bo.getStatus() != null, MallCategory::getStatus, bo.getStatus());
        lqw.orderByAsc(MallCategory::getSort);
        lqw.orderByAsc(MallCategory::getId);
        return lqw;
    }

    /**
     * 构建树形结构
     */
    private List<MallCategoryVo> buildTree(List<MallCategoryVo> list) {
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        // 按父ID分组
        Map<Long, List<MallCategoryVo>> childrenMap = list.stream()
                .filter(item -> item.getParentId() != null && item.getParentId() != 0)
                .collect(Collectors.groupingBy(MallCategoryVo::getParentId));

        // 设置子节点
        list.forEach(item -> {
            List<MallCategoryVo> children = childrenMap.get(item.getId());
            item.setChildren(children != null ? children : new ArrayList<>());
        });

        // 返回顶级节点
        return list.stream()
                .filter(item -> item.getParentId() == null || item.getParentId() == 0)
                .sorted(Comparator.comparing(MallCategoryVo::getSort, Comparator.nullsLast(Comparator.naturalOrder())))
                .collect(Collectors.toList());
    }

    /**
     * 新增商品分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(MallCategoryBo bo) {
        MallCategory add = MapstructUtils.convert(bo, MallCategory.class);
        validEntityBeforeSave(add);

        // 设置父级ID和级别
        if (add.getParentId() == null || add.getParentId() == 0) {
            add.setParentId(0L);
            add.setLevel(1);
        } else {
            // 查询父分类
            MallCategory parent = baseMapper.selectById(add.getParentId());
            if (parent == null) {
                throw new ServiceException("父分类不存在");
            }
            if (parent.getStatus() != 0) {
                throw new ServiceException("父分类已禁用，不能添加子分类");
            }
            if (parent.getLevel() >= 3) {
                throw new ServiceException("分类级别不能超过3级");
            }
            add.setLevel(parent.getLevel() + 1);
        }

        // 设置默认值
        if (add.getSort() == null) {
            add.setSort(0);
        }
        if (add.getStatus() == null) {
            add.setStatus(0);
        }

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改商品分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(MallCategoryBo bo) {
        MallCategory update = MapstructUtils.convert(bo, MallCategory.class);
        validEntityBeforeSave(update);

        // 不能将父分类设置为自己的子分类
        if (update.getParentId() != null && update.getParentId() != 0) {
            if (update.getId().equals(update.getParentId())) {
                throw new ServiceException("不能将分类设置为自己的父分类");
            }
            // 检查是否会形成循环
            if (hasCircularReference(update.getId(), update.getParentId())) {
                throw new ServiceException("不能将分类设置为自己的子分类的子分类");
            }

            // 查询父分类
            MallCategory parent = baseMapper.selectById(update.getParentId());
            if (parent == null) {
                throw new ServiceException("父分类不存在");
            }
            if (parent.getLevel() >= 3) {
                throw new ServiceException("分类级别不能超过3级");
            }
            update.setLevel(parent.getLevel() + 1);
        } else {
            update.setParentId(0L);
            update.setLevel(1);
        }

        return baseMapper.updateById(update) > 0;
    }

    /**
     * 检查是否存在循环引用
     */
    private boolean hasCircularReference(Long id, Long parentId) {
        Long currentParentId = parentId;
        Set<Long> visited = new HashSet<>();
        visited.add(id);

        while (currentParentId != null && currentParentId != 0) {
            if (visited.contains(currentParentId)) {
                return true;
            }
            visited.add(currentParentId);
            MallCategory parent = baseMapper.selectById(currentParentId);
            if (parent == null) {
                break;
            }
            currentParentId = parent.getParentId();
        }
        return false;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(MallCategory entity) {
        if (StringUtils.isBlank(entity.getName())) {
            throw new ServiceException("分类名称不能为空");
        }
        // 检查同级分类名称是否重复
        LambdaQueryWrapper<MallCategory> lqw = new LambdaQueryWrapper<>();
        lqw.eq(MallCategory::getName, entity.getName());
        lqw.eq(entity.getParentId() != null, MallCategory::getParentId, entity.getParentId());
        if (entity.getId() != null) {
            lqw.ne(MallCategory::getId, entity.getId());
        }
        Long count = baseMapper.selectCount(lqw);
        if (count > 0) {
            throw new ServiceException("同级分类名称不能重复");
        }
    }

    /**
     * 批量删除商品分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // 检查是否存在子分类
            for (Long id : ids) {
                LambdaQueryWrapper<MallCategory> lqw = new LambdaQueryWrapper<>();
                lqw.eq(MallCategory::getParentId, id);
                Long count = baseMapper.selectCount(lqw);
                if (count > 0) {
                    throw new ServiceException("存在子分类，不能删除");
                }
                // 检查是否有关联的商品（这里需要关联商品表查询，暂时跳过）
                // 可以后续添加商品表关联查询
            }
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
