package com.yhy.module.core.service.workbench.impl;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*;
import static com.yhy.module.core.enums.ErrorCodeConstants.*;

import cn.hutool.core.collection.CollUtil;
import com.yhy.module.core.controller.admin.workbench.vo.WbCompileTreeRespVO;
import com.yhy.module.core.controller.admin.workbench.vo.WbCompileTreeSaveReqVO;
import com.yhy.module.core.controller.admin.workbench.vo.WbCompileTreeSwapSortReqVO;
import com.yhy.module.core.convert.workbench.WbCompileTreeConvert;
import com.yhy.module.core.dal.dataobject.workbench.WbCompileTreeDO;
import com.yhy.module.core.dal.mysql.workbench.WbCompileTreeMapper;
import com.yhy.module.core.service.workbench.WbCompileTreeService;
import com.yhy.module.core.service.workbench.WbItemInfoService;
import com.yhy.module.core.service.workbench.WbUnitInfoService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

/**
 * 编制模式树 Service 实现类
 *
 * @author yhy
 */
@Service
@Validated
@Slf4j
public class WbCompileTreeServiceImpl implements WbCompileTreeService {

    @Resource
    private WbCompileTreeMapper wbCompileTreeMapper;

    @Resource
    @Lazy
    private WbItemInfoService wbItemInfoService;

    @Resource
    @Lazy
    private WbUnitInfoService wbUnitInfoService;

    @Resource
    @Lazy
    private com.yhy.module.core.service.workbench.WbBoqDivisionService wbBoqDivisionService;

    @Resource
    private com.yhy.module.core.dal.mysql.workbench.WbProjectTreeMapper wbProjectTreeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long initCompileTree(Long projectId, String projectName) {
        // 检查是否已存在根节点
        WbCompileTreeDO existRoot = wbCompileTreeMapper.selectRootByProjectId(projectId);
        if (existRoot != null) {
            throw exception(WB_COMPILE_TREE_ROOT_EXISTS);
        }

        // 创建根节点
        WbCompileTreeDO root = WbCompileTreeDO.builder()
                .projectId(projectId)
                .parentId(null)
                .nodeType(WbCompileTreeDO.NODE_TYPE_ROOT)
                .name(projectName)
                .sortOrder(0)
                .build();

        wbCompileTreeMapper.insert(root);

        // 更新路径
        root.setPath(new String[]{String.valueOf(root.getId())});
        wbCompileTreeMapper.updateById(root);

        return root.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createNode(WbCompileTreeSaveReqVO createReqVO) {
        // 1. 校验节点类型
        validateNodeType(createReqVO.getNodeType());

        // 2. 校验父节点
        WbCompileTreeDO parent = validateParentExists(createReqVO.getParentId());

        // 3. 校验层级关系
        validateHierarchy(createReqVO.getNodeType(), parent);

        // 4. 构建DO
        WbCompileTreeDO node = WbCompileTreeConvert.INSTANCE.convert(createReqVO);

        // 5. 设置排序号
        Integer maxSortOrder = wbCompileTreeMapper.selectMaxSortOrderByParentId(createReqVO.getParentId());
        node.setSortOrder(maxSortOrder + 1);

        // 6. 设置路径
        node.setPath(buildPath(parent));

        // 7. 插入数据库
        wbCompileTreeMapper.insert(node);

        // 8. 更新路径（包含自身ID）
        updatePathWithSelfId(node);

        // 9. 如果是单项节点，创建单项基本信息并复制配置快照
        if (WbCompileTreeDO.NODE_TYPE_ITEM.equals(createReqVO.getNodeType())) {
            wbItemInfoService.refreshConfigSnapshot(node.getId());
        }

        // 10. 如果是单位工程节点，自动创建分部分项根目录
        if (WbCompileTreeDO.NODE_TYPE_UNIT.equals(createReqVO.getNodeType())) {
            wbBoqDivisionService.createRootNode(node.getId(), createReqVO.getName());
        }

        return node.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateNode(WbCompileTreeSaveReqVO updateReqVO) {
        // 1. 校验存在
        WbCompileTreeDO existNode = validateNodeExists(updateReqVO.getId());

        // 2. 不允许修改节点类型
        if (!existNode.getNodeType().equals(updateReqVO.getNodeType())) {
            throw exception(WB_COMPILE_TREE_NODE_TYPE_CANNOT_CHANGE);
        }

        // 3. 不允许修改根节点
        if (WbCompileTreeDO.NODE_TYPE_ROOT.equals(existNode.getNodeType())) {
            // 根节点只能修改名称
            existNode.setName(updateReqVO.getName());
            wbCompileTreeMapper.updateById(existNode);
            return;
        }

        // 4. 更新
        WbCompileTreeDO updateObj = WbCompileTreeConvert.INSTANCE.convert(updateReqVO);
        updateObj.setId(existNode.getId());
        wbCompileTreeMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNode(Long id) {
        // 1. 校验存在
        WbCompileTreeDO node = validateNodeExists(id);

        // 2. 不允许删除根节点
        if (WbCompileTreeDO.NODE_TYPE_ROOT.equals(node.getNodeType())) {
            throw exception(WB_COMPILE_TREE_HAS_CHILDREN);
        }

        // 3. 校验是否有子节点
        List<WbCompileTreeDO> children = wbCompileTreeMapper.selectListByParentId(id);
        if (CollUtil.isNotEmpty(children)) {
            throw exception(WB_COMPILE_TREE_HAS_CHILDREN);
        }

        // 4. 删除关联数据
        if (WbCompileTreeDO.NODE_TYPE_ITEM.equals(node.getNodeType())) {
            wbItemInfoService.deleteByCompileTreeId(id);
        } else if (WbCompileTreeDO.NODE_TYPE_UNIT.equals(node.getNodeType())) {
            wbUnitInfoService.deleteByCompileTreeId(id);
        }

        // 5. 删除节点
        wbCompileTreeMapper.deleteById(id);
    }

    @Override
    public WbCompileTreeRespVO getNode(Long id) {
        WbCompileTreeDO node = wbCompileTreeMapper.selectById(id);
        if (node == null) {
            return null;
        }
        return WbCompileTreeConvert.INSTANCE.convert(node);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<WbCompileTreeRespVO> getTree(Long projectId) {
        List<WbCompileTreeDO> list = wbCompileTreeMapper.selectListByProjectId(projectId);
        
        // 如果没有根节点，自动创建
        if (CollUtil.isEmpty(list)) {
            // 获取项目名称
            String projectName = getProjectName(projectId);
            // 创建根节点
            WbCompileTreeDO root = WbCompileTreeDO.builder()
                    .projectId(projectId)
                    .parentId(null)
                    .nodeType(WbCompileTreeDO.NODE_TYPE_ROOT)
                    .name(projectName)
                    .sortOrder(0)
                    .build();
            wbCompileTreeMapper.insert(root);
            // 更新路径
            root.setPath(new String[]{String.valueOf(root.getId())});
            wbCompileTreeMapper.updateById(root);
            list = wbCompileTreeMapper.selectListByProjectId(projectId);
        }
        
        return buildTree(list);
    }
    
    /**
     * 获取项目名称
     */
    private String getProjectName(Long projectId) {
        // 从项目管理树获取项目名称
        com.yhy.module.core.dal.dataobject.workbench.WbProjectTreeDO project = 
                wbProjectTreeMapper.selectById(projectId);
        return project != null ? project.getName() : "新建项目";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void swapSort(WbCompileTreeSwapSortReqVO swapReqVO) {
        // 1. 校验两个节点存在
        WbCompileTreeDO node1 = validateNodeExists(swapReqVO.getNodeId1());
        WbCompileTreeDO node2 = validateNodeExists(swapReqVO.getNodeId2());

        // 2. 校验是否同级
        if (!Objects.equals(node1.getParentId(), node2.getParentId())) {
            throw exception(WB_COMPILE_TREE_NOT_SAME_LEVEL);
        }

        // 3. 交换排序号
        Integer tempSortOrder = node1.getSortOrder();
        node1.setSortOrder(node2.getSortOrder());
        node2.setSortOrder(tempSortOrder);

        wbCompileTreeMapper.updateById(node1);
        wbCompileTreeMapper.updateById(node2);
    }

    /**
     * 校验节点类型
     */
    private void validateNodeType(String nodeType) {
        if (!WbCompileTreeDO.NODE_TYPE_ITEM.equals(nodeType)
                && !WbCompileTreeDO.NODE_TYPE_UNIT.equals(nodeType)) {
            throw exception(WB_COMPILE_TREE_NODE_TYPE_INVALID);
        }
    }

    /**
     * 校验父节点存在
     */
    private WbCompileTreeDO validateParentExists(Long parentId) {
        if (parentId == null) {
            throw exception(WB_COMPILE_TREE_PARENT_NOT_EXISTS);
        }
        WbCompileTreeDO parent = wbCompileTreeMapper.selectById(parentId);
        if (parent == null) {
            throw exception(WB_COMPILE_TREE_PARENT_NOT_EXISTS);
        }
        return parent;
    }

    /**
     * 校验层级关系
     */
    private void validateHierarchy(String nodeType, WbCompileTreeDO parent) {
        if (WbCompileTreeDO.NODE_TYPE_ITEM.equals(nodeType)) {
            // 单项只能在根节点下创建
            if (!WbCompileTreeDO.NODE_TYPE_ROOT.equals(parent.getNodeType())) {
                throw exception(WB_COMPILE_TREE_ITEM_PARENT_MUST_ROOT);
            }
        } else if (WbCompileTreeDO.NODE_TYPE_UNIT.equals(nodeType)) {
            // 单位工程只能在单项下创建
            if (!WbCompileTreeDO.NODE_TYPE_ITEM.equals(parent.getNodeType())) {
                throw exception(WB_COMPILE_TREE_UNIT_PARENT_MUST_ITEM);
            }
        }
    }

    /**
     * 校验节点存在
     */
    private WbCompileTreeDO validateNodeExists(Long id) {
        WbCompileTreeDO node = wbCompileTreeMapper.selectById(id);
        if (node == null) {
            throw exception(WB_COMPILE_TREE_NOT_EXISTS);
        }
        return node;
    }

    /**
     * 构建路径
     */
    private String[] buildPath(WbCompileTreeDO parent) {
        if (parent == null || parent.getPath() == null) {
            return new String[]{};
        }
        return parent.getPath();
    }

    /**
     * 更新路径（包含自身ID）
     */
    private void updatePathWithSelfId(WbCompileTreeDO node) {
        List<String> pathList = node.getPath() != null
                ? new ArrayList<>(Arrays.asList(node.getPath()))
                : new ArrayList<>();
        pathList.add(String.valueOf(node.getId()));
        node.setPath(pathList.toArray(new String[0]));
        wbCompileTreeMapper.updateById(node);
    }

    /**
     * 构建树形结构
     */
    private List<WbCompileTreeRespVO> buildTree(List<WbCompileTreeDO> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }

        // 转换为VO
        List<WbCompileTreeRespVO> voList = list.stream()
                .map(WbCompileTreeConvert.INSTANCE::convert)
                .collect(Collectors.toList());

        // 构建父子关系
        Map<Long, List<WbCompileTreeRespVO>> parentIdMap = voList.stream()
                .filter(vo -> vo.getParentId() != null)
                .collect(Collectors.groupingBy(WbCompileTreeRespVO::getParentId));

        voList.forEach(vo -> vo.setChildren(parentIdMap.get(vo.getId())));

        // 返回根节点
        return voList.stream()
                .filter(vo -> vo.getParentId() == null)
                .collect(Collectors.toList());
    }
}
