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

import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yhy.module.core.controller.admin.resource.vo.ResourceCategorySimpleRespVO;
import com.yhy.module.core.controller.admin.resource.vo.ResourceCategoryTreeMappingSaveReqVO;
import com.yhy.module.core.controller.admin.resource.vo.ResourceCategoryTreeNodeVO;
import com.yhy.module.core.controller.admin.resource.vo.ResourceCategoryTreeSaveReqVO;
import com.yhy.module.core.dal.dataobject.resource.ResourceCategoryDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceCategoryTreeDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceCategoryTreeMappingDO;
import com.yhy.module.core.dal.mysql.resource.ResourceCategoryMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceCategoryTreeMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceCategoryTreeMappingMapper;
import com.yhy.module.core.service.resource.ResourceCategoryTreeService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;

/**
 * 工料机机类树 Service 实现
 *
 * @author yihuiyong
 */
@Service
public class ResourceCategoryTreeServiceImpl implements ResourceCategoryTreeService {

    @Resource
    private ResourceCategoryTreeMapper categoryTreeMapper;

    @Resource
    private ResourceCategoryTreeMappingMapper mappingMapper;

    @Resource
    private ResourceCategoryMapper categoryMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createNode(ResourceCategoryTreeSaveReqVO reqVO) {
        Long tenantId = TenantContextHolder.getTenantId();

        // 检查编码是否重复
        ResourceCategoryTreeDO exists = categoryTreeMapper.selectOne(new LambdaQueryWrapper<ResourceCategoryTreeDO>()
                .eq(ResourceCategoryTreeDO::getTenantId, tenantId)
                .eq(ResourceCategoryTreeDO::getCode, reqVO.getCode()));
        if (exists != null) {
            throw exception0(BAD_REQUEST.getCode(), "节点编码已存在");
        }

        ResourceCategoryTreeDO node = BeanUtils.toBean(reqVO, ResourceCategoryTreeDO.class);
        node.setTenantId(tenantId);

        // 构建路径
        if (reqVO.getParentId() != null) {
            ResourceCategoryTreeDO parent = categoryTreeMapper.selectById(reqVO.getParentId());
            if (parent == null) {
                throw exception0(BAD_REQUEST.getCode(), "父节点不存在");
            }
            List<String> pathList = new ArrayList<>(Arrays.asList(parent.getPath()));
            pathList.add(String.valueOf(node.getId()));
            node.setPath(pathList.toArray(new String[0]));
        } else {
            node.setPath(new String[]{String.valueOf(node.getId())});
        }

        categoryTreeMapper.insert(node);

        // 更新路径（因为插入后才有ID）
        if (reqVO.getParentId() != null) {
            ResourceCategoryTreeDO parent = categoryTreeMapper.selectById(reqVO.getParentId());
            List<String> pathList = new ArrayList<>(Arrays.asList(parent.getPath()));
            pathList.add(String.valueOf(node.getId()));
            node.setPath(pathList.toArray(new String[0]));
        } else {
            node.setPath(new String[]{String.valueOf(node.getId())});
        }
        categoryTreeMapper.updateById(node);

        return node.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateNode(ResourceCategoryTreeSaveReqVO reqVO) {
        ResourceCategoryTreeDO db = categoryTreeMapper.selectById(reqVO.getId());
        if (db == null) {
            throw exception0(BAD_REQUEST.getCode(), "节点不存在");
        }

        ResourceCategoryTreeDO node = BeanUtils.toBean(reqVO, ResourceCategoryTreeDO.class);
        node.setTenantId(TenantContextHolder.getTenantId());
        categoryTreeMapper.updateById(node);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNode(Long id) {
        // 检查是否有子节点
        Long count = categoryTreeMapper.selectCount(new LambdaQueryWrapper<ResourceCategoryTreeDO>()
                .eq(ResourceCategoryTreeDO::getParentId, id));
        if (count > 0) {
            throw exception0(BAD_REQUEST.getCode(), "存在子节点，无法删除");
        }

        // 删除关联关系
        mappingMapper.delete(new LambdaQueryWrapper<ResourceCategoryTreeMappingDO>()
                .eq(ResourceCategoryTreeMappingDO::getCategoryTreeId, id));

        categoryTreeMapper.deleteById(id);
    }

    @Override
    public List<ResourceCategoryTreeNodeVO> getTree() {
        Long tenantId = TenantContextHolder.getTenantId();
        List<ResourceCategoryTreeDO> allNodes = categoryTreeMapper.selectList(
                new LambdaQueryWrapper<ResourceCategoryTreeDO>()
                        .eq(ResourceCategoryTreeDO::getTenantId, tenantId)
                        .orderByAsc(ResourceCategoryTreeDO::getSortOrder)
        );

        return buildTree(allNodes, null);
    }

    @Override
    public List<ResourceCategorySimpleRespVO> getCategoriesByTreeNode(Long treeNodeId) {
        Long tenantId = TenantContextHolder.getTenantId();

        // 查询关联关系
        List<ResourceCategoryTreeMappingDO> mappings = mappingMapper.selectList(
                new LambdaQueryWrapper<ResourceCategoryTreeMappingDO>()
                        .eq(ResourceCategoryTreeMappingDO::getTenantId, tenantId)
                        .eq(ResourceCategoryTreeMappingDO::getCategoryTreeId, treeNodeId)
        );

        if (mappings.isEmpty()) {
            return new ArrayList<>();
        }

        List<Long> categoryIds = mappings.stream()
                .map(ResourceCategoryTreeMappingDO::getCategoryId)
                .collect(Collectors.toList());

        // 查询类别详情，直接按类别字典的 sort_order 排序
        List<ResourceCategoryDO> categories = categoryMapper.selectList(
                new LambdaQueryWrapper<ResourceCategoryDO>()
                        .in(ResourceCategoryDO::getId, categoryIds)
                        .orderByAsc(ResourceCategoryDO::getSortOrder)
        );

        // 转换为简化VO（使用类别字典的排序）
        return categories.stream()
                .map(category -> {
                    ResourceCategorySimpleRespVO vo = new ResourceCategorySimpleRespVO();
                    vo.setId(category.getId());
                    vo.setCode(category.getCode());
                    vo.setName(category.getName());
                    vo.setSortOrder(category.getSortOrder());
                    return vo;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCategoryMapping(ResourceCategoryTreeMappingSaveReqVO reqVO) {
        Long tenantId = TenantContextHolder.getTenantId();

        // 1. 验证节点类型
        ResourceCategoryTreeDO treeNode = categoryTreeMapper.selectById(reqVO.getCategoryTreeId());
        if (treeNode == null) {
            throw exception0(BAD_REQUEST.getCode(), "机类树节点不存在");
        }
        if (!"specialty".equals(treeNode.getNodeType())) {
            throw exception0(BAD_REQUEST.getCode(), "只有工料机专业类型的节点才能添加类别列表");
        }

        // 2. 检查是否已存在
        ResourceCategoryTreeMappingDO exists = mappingMapper.selectOne(
                new LambdaQueryWrapper<ResourceCategoryTreeMappingDO>()
                        .eq(ResourceCategoryTreeMappingDO::getTenantId, tenantId)
                        .eq(ResourceCategoryTreeMappingDO::getCategoryTreeId, reqVO.getCategoryTreeId())
                        .eq(ResourceCategoryTreeMappingDO::getCategoryId, reqVO.getCategoryId())
        );
        if (exists != null) {
            throw exception0(BAD_REQUEST.getCode(), "关联关系已存在");
        }

        // 3. 添加关联
        ResourceCategoryTreeMappingDO mapping = BeanUtils.toBean(reqVO, ResourceCategoryTreeMappingDO.class);
        mapping.setTenantId(tenantId);
        mappingMapper.insert(mapping);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeCategoryMapping(Long treeNodeId, Long categoryId) {
        mappingMapper.delete(new LambdaQueryWrapper<ResourceCategoryTreeMappingDO>()
                .eq(ResourceCategoryTreeMappingDO::getCategoryTreeId, treeNodeId)
                .eq(ResourceCategoryTreeMappingDO::getCategoryId, categoryId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void swapSortOrder(Long nodeId1, Long nodeId2) {
        Long tenantId = TenantContextHolder.getTenantId();
        
        // 1. 查询两个节点（使用行锁）
        ResourceCategoryTreeDO node1 = categoryTreeMapper.selectOne(
                new LambdaQueryWrapper<ResourceCategoryTreeDO>()
                        .eq(ResourceCategoryTreeDO::getId, nodeId1)
                        .eq(ResourceCategoryTreeDO::getTenantId, tenantId)
                        .last("FOR UPDATE")
        );
        ResourceCategoryTreeDO node2 = categoryTreeMapper.selectOne(
                new LambdaQueryWrapper<ResourceCategoryTreeDO>()
                        .eq(ResourceCategoryTreeDO::getId, nodeId2)
                        .eq(ResourceCategoryTreeDO::getTenantId, tenantId)
                        .last("FOR UPDATE")
        );
        
        if (node1 == null || node2 == null) {
            throw exception0(BAD_REQUEST.getCode(), "节点不存在");
        }
        
        // 2. 验证是否同级（parent_id 必须相同）
        if (!isSameParent(node1.getParentId(), node2.getParentId())) {
            throw exception0(BAD_REQUEST.getCode(), "只能在同级节点之间调整排序");
        }
        
        // 3. 交换 sort_order
        Integer tempSortOrder = node1.getSortOrder();
        node1.setSortOrder(node2.getSortOrder());
        node2.setSortOrder(tempSortOrder);
        
        // 4. 更新数据库
        categoryTreeMapper.updateById(node1);
        categoryTreeMapper.updateById(node2);
    }
    
    /**
     * 判断两个节点是否有相同的父节点
     */
    private boolean isSameParent(Long parentId1, Long parentId2) {
        if (parentId1 == null && parentId2 == null) {
            return true;
        }
        if (parentId1 == null || parentId2 == null) {
            return false;
        }
        return parentId1.equals(parentId2);
    }

    /**
     * 构建树形结构
     */
    private List<ResourceCategoryTreeNodeVO> buildTree(List<ResourceCategoryTreeDO> allNodes, Long parentId) {
        return allNodes.stream()
                .filter(node -> {
                    if (parentId == null) {
                        return node.getParentId() == null;
                    }
                    return parentId.equals(node.getParentId());
                })
                .map(node -> {
                    ResourceCategoryTreeNodeVO vo = BeanUtils.toBean(node, ResourceCategoryTreeNodeVO.class);
                    vo.setChildren(buildTree(allNodes, node.getId()));
                    return vo;
                })
                .collect(Collectors.toList());
    }
}
