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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.yhy.module.core.controller.admin.boq.vo.BoqItemTreeRespVO;
import com.yhy.module.core.controller.admin.boq.vo.BoqItemTreeSaveReqVO;
import com.yhy.module.core.controller.admin.boq.vo.BoqItemTreeSwapSortReqVO;
import com.yhy.module.core.dal.dataobject.boq.BoqItemTreeDO;
import com.yhy.module.core.dal.mysql.boq.BoqItemTreeMapper;
import com.yhy.module.core.service.boq.BoqItemTreeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

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

/**
 * 清单项树 Service 实现类
 *
 * @author yhy
 */
@Service
@Validated
@Slf4j
public class BoqItemTreeServiceImpl implements BoqItemTreeService {

    @Resource
    private BoqItemTreeMapper boqItemTreeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createBoqItemTree(BoqItemTreeSaveReqVO createReqVO) {
        // 1. 校验编码唯一性
        validateCodeUnique(null, createReqVO.getCode());

        // 2. 构建DO对象
        BoqItemTreeDO boqItemTree = buildBoqItemTreeDO(createReqVO);

        // 3. 计算路径和层级
        calculatePathAndLevel(boqItemTree, createReqVO.getParentId(), createReqVO.getBoqCatalogItemId());

        // 4. 设置排序
        if (boqItemTree.getSortOrder() == null) {
            boqItemTree.setSortOrder(getNextSortOrder(createReqVO.getParentId(), createReqVO.getBoqCatalogItemId()));
        }

        // 5. 插入数据库
        boqItemTreeMapper.insert(boqItemTree);

        return boqItemTree.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBoqItemTree(BoqItemTreeSaveReqVO updateReqVO) {
        // 1. 校验节点存在
        validateBoqItemTreeExists(updateReqVO.getId());

        // 2. 校验编码唯一性
        validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());

        // 3. 构建更新对象
        BoqItemTreeDO updateObj = BoqItemTreeDO.builder()
                .id(updateReqVO.getId())
                .code(updateReqVO.getCode())
                .name(updateReqVO.getName())
                .unit(updateReqVO.getUnit())
                .sortOrder(updateReqVO.getSortOrder())
                .attributes(updateReqVO.getAttributes())
                .build();

        // 4. 更新数据库
        boqItemTreeMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBoqItemTree(Long id) {
        // 1. 校验节点存在
        validateBoqItemTreeExists(id);

        // 2. 校验是否有子节点
        List<BoqItemTreeDO> children = boqItemTreeMapper.selectListByParentId(id);
        if (CollUtil.isNotEmpty(children)) {
            throw exception(BOQ_ITEM_TREE_HAS_CHILDREN);
        }

        // 3. 删除节点
        boqItemTreeMapper.deleteById(id);
    }

    @Override
    public BoqItemTreeRespVO getBoqItemTree(Long id) {
        BoqItemTreeDO item = boqItemTreeMapper.selectById(id);
        if (item == null) {
            return null;
        }
        return convertToRespVO(item);
    }

    @Override
    public List<BoqItemTreeRespVO> getBoqItemTreeTree(Long boqCatalogItemId) {
        // 1. 查询所有节点
        List<BoqItemTreeDO> allItems = boqItemTreeMapper.selectListByBoqCatalogItemId(boqCatalogItemId);

        // 2. 转换为VO
        List<BoqItemTreeRespVO> allVOs = allItems.stream()
                .map(this::convertToRespVO)
                .collect(Collectors.toList());

        // 3. 构建树形结构
        return buildTree(allVOs, null);
    }

    @Override
    public List<BoqItemTreeRespVO> getBoqItemTreeList(Long boqCatalogItemId) {
        // 查询所有节点并转换为VO
        List<BoqItemTreeDO> items = boqItemTreeMapper.selectListByBoqCatalogItemId(boqCatalogItemId);
        return items.stream()
                .map(this::convertToRespVO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void swapSort(BoqItemTreeSwapSortReqVO swapReqVO) {
        // 1. 查询两个节点（加锁）
        BoqItemTreeDO node1 = boqItemTreeMapper.selectById(swapReqVO.getNodeId1());
        BoqItemTreeDO node2 = boqItemTreeMapper.selectById(swapReqVO.getNodeId2());

        if (node1 == null || node2 == null) {
            throw exception(BOQ_ITEM_TREE_NOT_EXISTS);
        }

        // 2. 校验是否同级
        if (!isSameLevel(node1, node2)) {
            throw exception(BOQ_ITEM_TREE_NOT_SAME_LEVEL);
        }

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

        // 4. 更新数据库
        boqItemTreeMapper.updateById(node1);
        boqItemTreeMapper.updateById(node2);

        log.info("[swapSort] 交换节点[{}]和节点[{}]的排序成功", swapReqVO.getNodeId1(), swapReqVO.getNodeId2());
    }

    // ==================== 私有方法 ====================

    /**
     * 校验编码唯一性
     */
    private void validateCodeUnique(Long id, String code) {
        BoqItemTreeDO existing = boqItemTreeMapper.selectByCode(code);
        if (existing != null && !existing.getId().equals(id)) {
            throw exception(BOQ_ITEM_TREE_CODE_DUPLICATE, code);
        }
    }

    /**
     * 校验节点存在
     */
    private BoqItemTreeDO validateBoqItemTreeExists(Long id) {
        BoqItemTreeDO item = boqItemTreeMapper.selectById(id);
        if (item == null) {
            throw exception(BOQ_ITEM_TREE_NOT_EXISTS);
        }
        return item;
    }

    /**
     * 构建DO对象
     */
    private BoqItemTreeDO buildBoqItemTreeDO(BoqItemTreeSaveReqVO reqVO) {
        return BoqItemTreeDO.builder()
                .id(reqVO.getId())
                .boqCatalogItemId(reqVO.getBoqCatalogItemId())
                .parentId(reqVO.getParentId())
                .code(reqVO.getCode())
                .name(reqVO.getName())
                .unit(reqVO.getUnit())
                .sortOrder(reqVO.getSortOrder())
                .attributes(reqVO.getAttributes())
                .build();
    }

    /**
     * 计算路径和层级
     */
    private void calculatePathAndLevel(BoqItemTreeDO item, Long parentId, Long boqCatalogItemId) {
        if (parentId == null) {
            // 根节点
            item.setPath(new String[]{item.getId().toString()});
            item.setLevel(1);
        } else {
            // 子节点
            BoqItemTreeDO parent = boqItemTreeMapper.selectById(parentId);
            if (parent == null) {
                throw exception(BOQ_ITEM_TREE_PARENT_NOT_EXISTS);
            }

            // 拼接路径
            String[] parentPath = parent.getPath();
            String[] newPath = ArrayUtil.append(parentPath, item.getId().toString());
            item.setPath(newPath);
            item.setLevel(parent.getLevel() + 1);
        }
    }

    /**
     * 获取下一个排序值
     */
    private Integer getNextSortOrder(Long parentId, Long boqCatalogItemId) {
        List<BoqItemTreeDO> siblings = boqItemTreeMapper.selectSiblings(parentId, boqCatalogItemId);
        if (CollUtil.isEmpty(siblings)) {
            return 1;
        }
        return siblings.stream()
                .mapToInt(BoqItemTreeDO::getSortOrder)
                .max()
                .orElse(0) + 1;
    }

    /**
     * 转换为RespVO
     */
    private BoqItemTreeRespVO convertToRespVO(BoqItemTreeDO item) {
        BoqItemTreeRespVO vo = new BoqItemTreeRespVO();
        vo.setId(item.getId());
        vo.setBoqCatalogItemId(item.getBoqCatalogItemId());
        vo.setParentId(item.getParentId());
        vo.setCode(item.getCode());
        vo.setName(item.getName());
        vo.setUnit(item.getUnit());
        vo.setSortOrder(item.getSortOrder());
        vo.setPath(item.getPath());
        vo.setLevel(item.getLevel());
        vo.setAttributes(item.getAttributes());
        vo.setCreateTime(item.getCreateTime());
        vo.setUpdateTime(item.getUpdateTime());
        return vo;
    }

    /**
     * 构建树形结构
     */
    private List<BoqItemTreeRespVO> buildTree(List<BoqItemTreeRespVO> allNodes, Long parentId) {
        List<BoqItemTreeRespVO> result = new ArrayList<>();
        for (BoqItemTreeRespVO node : allNodes) {
            if ((parentId == null && node.getParentId() == null)
                    || (parentId != null && parentId.equals(node.getParentId()))) {
                node.setChildren(buildTree(allNodes, node.getId()));
                result.add(node);
            }
        }
        return result;
    }

    /**
     * 判断是否同级
     */
    private boolean isSameLevel(BoqItemTreeDO node1, BoqItemTreeDO node2) {
        // 父节点相同且清单专业相同即为同级
        if (!node1.getBoqCatalogItemId().equals(node2.getBoqCatalogItemId())) {
            return false;
        }
        if (node1.getParentId() == null && node2.getParentId() == null) {
            return true;
        }
        if (node1.getParentId() == null || node2.getParentId() == null) {
            return false;
        }
        return node1.getParentId().equals(node2.getParentId());
    }
}
