package com.ruoyi.excel.wecom.service.impl;

import com.ruoyi.excel.wecom.domain.CorpDepartment;
import com.ruoyi.excel.wecom.dto.CorpDepartmentDTO;
import com.ruoyi.excel.wecom.mapper.CorpDepartmentMapper;
import com.ruoyi.excel.wecom.service.ICorpDepartmentService;
import com.ruoyi.excel.wecom.vo.CorpDepartmentVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CorpDepartmentServiceImpl implements ICorpDepartmentService {

    @Autowired
    private CorpDepartmentMapper corpDepartmentMapper;

    @Override
    public List<CorpDepartmentVO> selectCorpDepartmentTree(String corpId) {
        CorpDepartmentDTO query = new CorpDepartmentDTO();
        query.setCorpId(corpId);
        List<CorpDepartment> allDepartments = corpDepartmentMapper.selectCorpDepartmentList(query);
        
        Map<Long, CorpDepartment> deptMap = new HashMap<>();
        Map<Long, Long> parentMap = new HashMap<>();
        
        for (CorpDepartment dept : allDepartments) {
            deptMap.put(dept.getId(), dept);
            parentMap.put(dept.getId(), dept.getParentid());
        }
        
        Map<Long, String> ancestorsMap = new HashMap<>();
        for (CorpDepartment dept : allDepartments) {
            String fullPath = buildDepartmentPath(dept.getId(), deptMap, parentMap);
            ancestorsMap.put(dept.getId(), fullPath);
        }
        
        return buildTree(allDepartments, ancestorsMap);
    }

    private String buildDepartmentPath(Long deptId, Map<Long, CorpDepartment> deptMap, Map<Long, Long> parentMap) {
        if (deptId == null || !deptMap.containsKey(deptId)) {
            return "";
        }

        CorpDepartment dept = deptMap.get(deptId);
        String currentName = dept.getName();
        Long parentId = parentMap.get(deptId);

        if (parentId == null || parentId == 0L || !parentMap.containsKey(parentId)) {
            return currentName;
        }

        String parentPath = buildDepartmentPath(parentId, deptMap, parentMap);
        if (parentPath.isEmpty()) {
            return currentName;
        } else {
            return parentPath + "/" + currentName;
        }
    }

    private List<CorpDepartmentVO> buildTree(List<CorpDepartment> departments, Map<Long, String> ancestorsMap) {
        List<CorpDepartmentVO> result = new ArrayList<>();
        List<Long> ids = departments.stream().map(CorpDepartment::getId).collect(Collectors.toList());

        for (CorpDepartment dept : departments) {
            Long parentId = dept.getParentid();
            if (parentId == null || parentId == 0L || !ids.contains(parentId)) {
                CorpDepartmentVO vo = convertToVO(dept, ancestorsMap.get(dept.getId()));
                recursionFn(departments, vo, ancestorsMap);
                result.add(vo);
            }
        }

        if (result.isEmpty()) {
            for (CorpDepartment dept : departments) {
                result.add(convertToVO(dept, ancestorsMap.get(dept.getId())));
            }
        }
        return result;
    }

    private CorpDepartmentVO convertToVO(CorpDepartment dept, String ancestors) {
        CorpDepartmentVO vo = new CorpDepartmentVO();
        vo.setId(dept.getId());
        vo.setName(dept.getName());
        vo.setAncestors(ancestors);
        return vo;
    }

    private void recursionFn(List<CorpDepartment> list, CorpDepartmentVO parent, Map<Long, String> ancestorsMap) {
        List<CorpDepartmentVO> childList = getChildList(list, parent, ancestorsMap);
        parent.setChildren(childList);
        for (CorpDepartmentVO child : childList) {
            if (hasChild(list, child)) {
                recursionFn(list, child, ancestorsMap);
            }
        }
    }

    private List<CorpDepartmentVO> getChildList(List<CorpDepartment> list, CorpDepartmentVO parent, Map<Long, String> ancestorsMap) {
        List<CorpDepartmentVO> result = new ArrayList<>();
        for (CorpDepartment dept : list) {
            if (dept.getParentid() != null && dept.getParentid().longValue() == parent.getId().longValue()) {
                CorpDepartmentVO vo = convertToVO(dept, ancestorsMap.get(dept.getId()));
                result.add(vo);
            }
        }
        return result;
    }

    private boolean hasChild(List<CorpDepartment> list, CorpDepartmentVO t) {
        for (CorpDepartment dept : list) {
            if (dept.getParentid() != null && dept.getParentid().longValue() == t.getId().longValue()) {
                return true;
            }
        }
        return false;
    }
}
