package com.agent.management.service.impl;

import com.agent.management.common.exception.BusinessException;
import com.agent.management.model.entity.Category;
import com.agent.management.model.entity.SkillCategory;
import com.agent.management.model.vo.CategoryVO;
import com.agent.management.repository.CategoryRepository;
import com.agent.management.repository.SkillCategoryRepository;
import com.agent.management.service.CategoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class CategoryServiceImpl implements CategoryService {

    private final CategoryRepository categoryRepository;
    private final SkillCategoryRepository skillCategoryRepository;

    @Override
    public List<CategoryVO> getCategoryTree() {
        List<Category> all = categoryRepository.findAllByOrderBySortOrderAsc();

        // 统计每个分类下的技能数
        List<SkillCategory> allMappings = skillCategoryRepository.findAll();
        Map<Long, Long> countMap = allMappings.stream()
                .collect(Collectors.groupingBy(SkillCategory::getCategoryId, Collectors.counting()));

        // 转为 VO
        Map<Long, CategoryVO> voMap = new LinkedHashMap<>();
        for (Category cat : all) {
            CategoryVO vo = new CategoryVO();
            vo.setId(cat.getId());
            vo.setParentId(cat.getParentId());
            vo.setName(cat.getName());
            vo.setSortOrder(cat.getSortOrder());
            vo.setChildren(new ArrayList<>());
            vo.setSkillCount(countMap.getOrDefault(cat.getId(), 0L));
            voMap.put(cat.getId(), vo);
        }

        // 构建树
        List<CategoryVO> roots = new ArrayList<>();
        for (CategoryVO vo : voMap.values()) {
            if (vo.getParentId() == null) {
                roots.add(vo);
            } else {
                CategoryVO parent = voMap.get(vo.getParentId());
                if (parent != null) {
                    parent.getChildren().add(vo);
                } else {
                    // 父节点不存在，作为根节点处理
                    vo.setParentId(null);
                    roots.add(vo);
                }
            }
        }

        // 递归汇总子分类的技能数
        for (CategoryVO root : roots) {
            accumulateSkillCount(root);
        }

        return roots;
    }

    @Override
    public CategoryVO createCategory(Long parentId, String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new BusinessException("分类名称不能为空");
        }
        if (parentId != null && !categoryRepository.existsById(parentId)) {
            throw new BusinessException(404, "父分类不存在");
        }

        // 获取同级最大 sortOrder
        List<Category> siblings = parentId == null
                ? categoryRepository.findByParentIdOrderBySortOrderAsc(null)
                : categoryRepository.findByParentIdOrderBySortOrderAsc(parentId);
        int maxSort = siblings.stream()
                .map(Category::getSortOrder)
                .filter(Objects::nonNull)
                .max(Integer::compareTo)
                .orElse(0);

        Category category = new Category();
        category.setParentId(parentId);
        category.setName(name.trim());
        category.setSortOrder(maxSort + 1);
        category.onCreate();
        category = categoryRepository.save(category);

        CategoryVO vo = new CategoryVO();
        vo.setId(category.getId());
        vo.setParentId(category.getParentId());
        vo.setName(category.getName());
        vo.setSortOrder(category.getSortOrder());
        vo.setChildren(new ArrayList<>());
        vo.setSkillCount(0);
        return vo;
    }

    @Override
    public CategoryVO updateCategory(Long id, String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new BusinessException("分类名称不能为空");
        }
        Category category = categoryRepository.findById(id)
                .orElseThrow(() -> new BusinessException(404, "分类不存在"));
        category.setName(name.trim());
        category.onUpdate();
        category = categoryRepository.save(category);

        CategoryVO vo = new CategoryVO();
        vo.setId(category.getId());
        vo.setParentId(category.getParentId());
        vo.setName(category.getName());
        vo.setSortOrder(category.getSortOrder());
        vo.setChildren(new ArrayList<>());
        return vo;
    }

    @Override
    public void deleteCategory(Long id) {
        // 检查是否有子分类
        List<Category> children = categoryRepository.findByParentIdOrderBySortOrderAsc(id);
        if (!children.isEmpty()) {
            throw new BusinessException("该分类下有子分类，不能删除");
        }

        // 删除分类下技能的关联（技能变为未分类）
        List<SkillCategory> mappings = skillCategoryRepository.findByCategoryId(id);
        skillCategoryRepository.deleteAll(mappings);

        categoryRepository.deleteById(id);
        log.info("删除分类: {}", id);
    }

    @Override
    public void moveCategory(Long id, Long newParentId) {
        if (newParentId != null && !categoryRepository.existsById(newParentId)) {
            throw new BusinessException(404, "目标父分类不存在");
        }
        // 防止循环引用：不能移动到自己的子分类下
        if (newParentId != null) {
            Set<Long> descendants = new HashSet<>(getDescendantCategoryIds(id));
            if (descendants.contains(newParentId)) {
                throw new BusinessException("不能移动到自身的子分类下");
            }
        }

        Category category = categoryRepository.findById(id)
                .orElseThrow(() -> new BusinessException(404, "分类不存在"));
        category.setParentId(newParentId);
        category.onUpdate();
        categoryRepository.save(category);
    }

    @Override
    public List<Long> getDescendantCategoryIds(Long categoryId) {
        List<Category> all = categoryRepository.findAllByOrderBySortOrderAsc();
        Map<Long, List<Long>> parentChildMap = new HashMap<>();
        for (Category cat : all) {
            parentChildMap.computeIfAbsent(cat.getParentId(), k -> new ArrayList<>()).add(cat.getId());
        }

        List<Long> result = new ArrayList<>();
        collectDescendants(categoryId, parentChildMap, result);
        return result;
    }

    private void collectDescendants(Long parentId, Map<Long, List<Long>> map, List<Long> result) {
        List<Long> children = map.get(parentId);
        if (children != null) {
            result.addAll(children);
            for (Long childId : children) {
                collectDescendants(childId, map, result);
            }
        }
    }

    /**
     * 递归汇总子分类技能数到父节点
     */
    private long accumulateSkillCount(CategoryVO node) {
        long total = node.getSkillCount();
        if (node.getChildren() != null) {
            for (CategoryVO child : node.getChildren()) {
                total += accumulateSkillCount(child);
            }
        }
        node.setSkillCount(total);
        return total;
    }
}
