package com.ruoyi.web.modules.region.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.web.modules.region.domain.BizRegion;
import com.ruoyi.web.modules.region.mapper.BizRegionMapper;
import com.ruoyi.web.modules.region.service.IRegionService;
import com.ruoyi.web.modules.region.vo.RegionTreeVO;

@Service
public class RegionServiceImpl implements IRegionService
{
    private static final int ROOT_PID = 0;

    @Autowired
    private BizRegionMapper regionMapper;

    private volatile List<RegionTreeVO> cachedTree;

    @Override
    public List<RegionTreeVO> getRegionTree()
    {
        List<RegionTreeVO> tree = cachedTree;
        if (tree != null)
        {
            return tree;
        }
        synchronized (this)
        {
            if (cachedTree == null)
            {
                cachedTree = buildTree(regionMapper.selectAll());
            }
            return cachedTree;
        }
    }

    private List<RegionTreeVO> buildTree(List<BizRegion> rows)
    {
        Map<Integer, RegionTreeVO> nodeMap = new HashMap<>();
        Map<Integer, List<RegionTreeVO>> childrenMap = new HashMap<>();
        for (BizRegion row : rows)
        {
            RegionTreeVO node = toNode(row);
            nodeMap.put(node.getId(), node);
            childrenMap.computeIfAbsent(row.getPid(), key -> new ArrayList<>()).add(node);
        }
        for (RegionTreeVO node : nodeMap.values())
        {
            List<RegionTreeVO> children = childrenMap.get(node.getId());
            if (children != null)
            {
                node.setChildren(children);
            }
        }
        List<RegionTreeVO> roots = childrenMap.get(ROOT_PID);
        return roots != null ? roots : new ArrayList<>();
    }

    private RegionTreeVO toNode(BizRegion row)
    {
        RegionTreeVO vo = new RegionTreeVO();
        vo.setId(row.getId());
        vo.setPid(row.getPid());
        vo.setName(row.getName());
        vo.setType(row.getType());
        vo.setCode(row.getCode());
        return vo;
    }
}
