package com.agent.management.service.impl;

import com.agent.management.common.exception.BusinessException;
import com.agent.management.model.entity.WfCategory;
import com.agent.management.model.entity.Workflow;
import com.agent.management.model.vo.CategoryVO;
import com.agent.management.repository.WfCategoryRepository;
import com.agent.management.repository.WorkflowRepository;
import com.agent.management.service.WfCategoryService;
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 WfCategoryServiceImpl implements WfCategoryService {

    private final WfCategoryRepository categoryRepository;
    private final WorkflowRepository workflowRepository;

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

        // 统计每个分类下的工作流数量
        List<Workflow> allWorkflows = workflowRepository.findAll();
        Map<Long, Long> countMap = allWorkflows.stream()
                .filter(wf -> wf.getCategoryId() != null)
                .collect(Collectors.groupingBy(Workflow::getCategoryId, Collectors.counting()));

        // 转为 VO
        Map<Long, CategoryVO> voMap = new LinkedHashMap<>();
        for (WfCategory 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(vo.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) {
            accumulateCount(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, "父分类不存在");
        }

        List<WfCategory> siblings = parentId == null
                ? categoryRepository.findByParentIdOrderBySortOrderAsc(null)
                : categoryRepository.findByParentIdOrderBySortOrderAsc(parentId);
        int maxSort = siblings.stream()
                .map(WfCategory::getSortOrder)
                .filter(Objects::nonNull)
                .max(Integer::compareTo)
                .orElse(0);

        WfCategory category = new WfCategory();
        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(0L);
        return vo;
    }

    @Override
    public CategoryVO updateCategory(Long id, String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new BusinessException("分类名称不能为空");
        }
        WfCategory 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<WfCategory> children = categoryRepository.findByParentIdOrderBySortOrderAsc(id);
        if (!children.isEmpty()) {
            throw new BusinessException("该分类下有子分类，不能删除");
        }

        // 将分类下的工作流设为未分类
        List<Workflow> workflows = workflowRepository.findAll().stream()
                .filter(wf -> id.equals(wf.getCategoryId()))
                .toList();
        for (Workflow wf : workflows) {
            wf.setCategoryId(null);
            wf.onUpdate();
        }
        workflowRepository.saveAll(workflows);

        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("不能移动到自身的子分类下");
            }
        }

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

    @Override
    public List<Long> getDescendantCategoryIds(Long categoryId) {
        List<WfCategory> all = categoryRepository.findAllByOrderBySortOrderAsc();
        Map<Long, List<Long>> parentChildMap = new HashMap<>();
        for (WfCategory 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 accumulateCount(CategoryVO node) {
        long total = node.getSkillCount();
        if (node.getChildren() != null) {
            for (CategoryVO child : node.getChildren()) {
                total += accumulateCount(child);
            }
        }
        node.setSkillCount(total);
        return total;
    }
}
