package com.zt.plat.module.base.service.tmpltp;

import cn.hutool.core.collection.CollUtil;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zt.plat.module.base.controller.admin.templtp.vo.*;

import com.zt.plat.module.base.dal.dataobject.tmpltp.TmplFldRelDO;
import com.zt.plat.module.base.dal.dataobject.tmpltp.TmplItmRelDO;
import com.zt.plat.module.base.dal.dataobject.tmpltp.TmplTpDO;
import com.zt.plat.module.base.dal.dataobject.tmpltp.TmplTpFldDO;
import com.zt.plat.module.base.dal.mysql.tmpltp.TmplFldRelMapper;
import com.zt.plat.module.base.dal.mysql.tmpltp.TmplItmRelMapper;
import com.zt.plat.module.base.dal.mysql.tmpltp.TmplTpMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import java.util.stream.Collectors;

import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;


import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.tmpltp.enums.ErrorCodeConstants.*;

/**
 * 模板分类 Service 实现类
 *
 * @author 后台管理
 */
@Service
@Validated
@RequiredArgsConstructor
@Slf4j
public class TmplTpServiceImpl extends ServiceImpl<TmplTpMapper, TmplTpDO> implements TmplTpService {
    private final TmplFldRelMapper tmplFldRelMapper;
    private final TmplItmRelMapper tmplItmRelMapper;


    @Override
    @Transactional
    public TmplTpRespVO createTmplTp(TmplTpSaveReqVO createReqVO) {
        //置空id
        createReqVO.setId(null);
        // 插入
        TmplTpDO tmplTp = BeanUtils.toBean(createReqVO, TmplTpDO.class);
        tmplTp.setSts("Y");
        baseMapper.insert(tmplTp);
        log.info("创建模板分类成功 【{}】", tmplTp);
        // 返回
        List<TmplFldRelDO> tmplFldRelDOS = new ArrayList<>();
        List<TmplItmRelDO> tmplItmRelDOS = new ArrayList<>();
        createReqVO.getTmplTpFldIds().forEach(tmplItmId -> {
            TmplFldRelDO tmplFldRelDO = new TmplFldRelDO();
            tmplFldRelDO.setTmplTpId(String.valueOf(tmplTp.getId()));
            tmplFldRelDO.setTpFldId(String.valueOf(tmplItmId));
            tmplFldRelDOS.add(tmplFldRelDO);
        });
        createReqVO.getTmplItmIds().forEach(tmplFldId -> {
            TmplItmRelDO tmplItmRelDO = new TmplItmRelDO();
            tmplItmRelDO.setTmplTpId(String.valueOf(tmplTp.getId()));
            tmplItmRelDO.setItmFldId(String.valueOf(tmplFldId));
            tmplItmRelDOS.add(tmplItmRelDO);
        });
        tmplFldRelMapper.insertBatch(tmplFldRelDOS);
        log.info("创建模板分类与字段关系成功 【{}】", tmplFldRelDOS);
        tmplItmRelMapper.insertBatch(tmplItmRelDOS);
        log.info("创建模板分类与条款关系成功 【{}】", tmplItmRelDOS);
        return BeanUtils.toBean(tmplTp, TmplTpRespVO.class);
    }

    @Override
    public void updateTmplTp(TmplTpSaveReqVO updateReqVO) {
        // 校验存在
        validateTmplTpExists(updateReqVO.getId());
        // 更新
        TmplTpDO updateObj = BeanUtils.toBean(updateReqVO, TmplTpDO.class);
        baseMapper.updateById(updateObj);
        log.info("更新模板分类成功 【{}】", updateObj);
    }

    @Override
    @Transactional
    public void deleteTmplTp(List<Long> ids) {
        // 校验存在
        validateTmplTpExists(ids);
        //校验能否进行删除
//        if (!validateStatusCanDelete(ids)){
//            throw exception(TMPL_TP_DEl_ERROR);
//        }
        // 删除
        baseMapper.deleteByIds(ids);
        log.info("删除模板分类成功 【{}】", ids);
        //删除对应的关联信息
        tmplFldRelMapper.delete(Wrappers.<TmplFldRelDO>lambdaQuery().in(TmplFldRelDO::getTmplTpId, ids));
        log.info("删除模板分类与字段关系成功 【{}】", ids);
        tmplItmRelMapper.delete(Wrappers.<TmplItmRelDO>lambdaQuery().in(TmplItmRelDO::getTmplTpId, ids));
        log.info("删除模板分类与条款关系成功 【{}】", ids);
    }

    @Override
    @Transactional
    public void deleteTmplTpListByIds(List<Long> ids) {
        // 校验存在
        validateTmplTpExists(ids);
        // 删除
        baseMapper.deleteByIds(ids);
        log.info("删除模板分类成功 【{}】", ids);
        tmplFldRelMapper.delete(Wrappers.<TmplFldRelDO>lambdaQuery().in(TmplFldRelDO::getTmplTpId, ids));
        log.info("删除模板分类与字段关系成功 【{}】", ids);
        tmplItmRelMapper.delete(Wrappers.<TmplItmRelDO>lambdaQuery().in(TmplItmRelDO::getTmplTpId, ids));
        log.info("删除模板分类与条款关系成功 【{}】", ids);
    }

    private void validateTmplTpExists(List<Long> ids) {
        List<TmplTpDO> list = baseMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(TMPL_TP_NOT_EXISTS);
        }
    }

    private void validateTmplTpExists(Long id) {
        if (baseMapper.selectById(id) == null) {
            throw exception(TMPL_TP_NOT_EXISTS);
        }
    }

    @Override
    public TmplTpDO getTmplTp(Long id) {
        return baseMapper.selectById(id);
    }

    @Override
    public PageResult<TmplTpDO> getTmplTpPage(TmplTpPageReqVO pageReqVO) {
        log.info("查询模板分类列表 【{}】", pageReqVO);
        return baseMapper.selectPage(pageReqVO);
    }

    @Override
    public List<TmplFldRespVO> getField(Long id) {
        return baseMapper.getField(id);
    }

    @Override
    public List<TmplItmRespVO> getClause(Long id) {
        return baseMapper.getClause(id);
    }


    @Override
    public void updateStatus(Long id, String status) {
        //验证当前的能否变更为之后的状态
//        if (!validateStatusUpdate(id, status)) {
//            throw exception(TMPL_TP_SATUS_ERROR);
//        }
        baseMapper.update(Wrappers.<TmplTpDO>lambdaUpdate().set(TmplTpDO::getSts, status).eq(TmplTpDO::getId, id));
        log.info("更新模板分类状态成功 【{}】,更新前的状态为【{}】", id, status);
    }


//    private boolean validateStatusUpdate(Long id, String status) {
//        TmplTpDO tmplTpDO = baseMapper.getTmplTpById(id);
//        String currentSts = tmplTpDO.getSts();
//
//        // 获取当前状态对应的枚举实例
//        PublishStatusEnum currentStatus = PublishStatusEnum.fromCode(currentSts);
//
//        // 如果当前状态不合法，直接返回false
//        if (currentStatus == null) {
//            return false;
//        }
//
//        // 校验状态转换是否合法
//        return currentStatus.isTransitionAllowed(status);
//    }

//    private boolean validateStatusCanDelete(List<Long> ids) {
//        Set<String> sts = listByIds(ids).stream().map(TmplTpDO::getSts).collect(Collectors.toSet());
//        List<Boolean> result = new ArrayList<>();
//        sts.forEach(status -> {
//            PublishStatusEnum currentStatus = PublishStatusEnum.fromCode(status);
//            boolean transitionAllowed = false;
//            if (currentStatus != null) {
//                transitionAllowed = currentStatus.isTransitionAllowed(status);
//            } else {
//                result.add(false);
//            }
//            result.add(transitionAllowed);
//        });
//        return !result.contains(false);
//    }

    @Override
    public void fieldEdit(TmplTpEditOrDeleteReqVO reqVO) {
        if ("create".equals(reqVO.getType())) {
            List<TmplFldRelDO> tmplFldRelDOS = new ArrayList<>();
            reqVO.getIds().forEach(id -> {
                TmplFldRelDO tmplFldRelDO = new TmplFldRelDO();
                tmplFldRelDO.setTmplTpId(reqVO.getTpId());
                tmplFldRelDO.setTpFldId(id);
                tmplFldRelDOS.add(tmplFldRelDO);
            });
            tmplFldRelMapper.insertBatch(tmplFldRelDOS);
            log.info("模板字段添加成功，模板字段：【{}】", reqVO.getIds());
        }else if ("delete".equals(reqVO.getType())) {
            tmplFldRelMapper.delete(Wrappers.<TmplFldRelDO>lambdaQuery()
                    .eq(TmplFldRelDO::getTmplTpId, reqVO.getTpId())
                    .in(TmplFldRelDO::getTpFldId, reqVO.getIds()));
            log.info("模板字段删除成功，模板字段：【{}】", reqVO.getIds());
        }else {
            throw exception(ILLEGAL_OPERATION_TYPE);
        }
    }

    @Override
    public void ltmEdit(TmplTpEditOrDeleteReqVO reqVO) {
        if ("create".equals(reqVO.getType())) {
            List<TmplItmRelDO> tmplItmRelDOS = new ArrayList<>();
            reqVO.getIds().forEach(id -> {
                TmplItmRelDO tmplItmRelDO = new TmplItmRelDO();
                tmplItmRelDO.setTmplTpId(reqVO.getTpId());
                tmplItmRelDO.setItmFldId(id);
                tmplItmRelDOS.add(tmplItmRelDO);
            });
            tmplItmRelMapper.insertBatch(tmplItmRelDOS);
            log.info("模板条目添加成功，模板条目：【{}】", reqVO.getIds());
        }else if ("delete".equals(reqVO.getType())) {
            tmplItmRelMapper.delete(Wrappers.<TmplItmRelDO>lambdaQuery()
                    .eq(TmplItmRelDO::getTmplTpId, reqVO.getTpId())
                    .in(TmplItmRelDO::getItmFldId, reqVO.getIds()));
            log.info("模板条目删除成功，模板条目：【{}】", reqVO.getIds());
        }else {
            throw exception(ILLEGAL_OPERATION_TYPE);
        }
    }

    @Override
    public List<TmplTpTreeVO> buildTree(String num, String name) {
        // 如果没有查询条件，返回完整树结构
        if ((num == null || num.isEmpty()) && (name == null || name.isEmpty())) {
            return buildFullTree();
        }

        // 1. 根据条件查询匹配的节点
        List<TmplTpDO> matchedNodes = baseMapper.selectList(new LambdaQueryWrapper<TmplTpDO>()
                .like(name != null && !name.isEmpty(), TmplTpDO::getName, name)
                .like(num != null && !num.isEmpty(), TmplTpDO::getNum, num));

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

        // 2. 获取匹配节点的ID集合
        Set<String> rootIds = matchedNodes.stream()
                .map(node -> node.getId().toString())
                .collect(Collectors.toSet());

        // 3. 一次性查询所有数据（用于后续过滤）
        List<TmplTpDO> allNodes = baseMapper.selectList(null);

        // 4. 转换为VO
        List<TmplTpTreeVO> allTreeNodes = allNodes.stream()
                .map(this::convertToTreeVO)
                .collect(Collectors.toList());

        // 5. 过滤出匹配节点及其所有子孙节点
        Set<String> validNodeIds = new HashSet<>(rootIds);
        findAllDescendantIds(allTreeNodes, rootIds, validNodeIds);

        // 6. 只保留有效节点
        List<TmplTpTreeVO> filteredNodes = allTreeNodes.stream()
                .filter(node -> validNodeIds.contains(node.getId().toString()))
                .collect(Collectors.toList());

        // 7. 构建树形结构
        return buildTreeStructure(filteredNodes, rootIds);
    }

    /**
     * 构建完整树结构（从真正的根节点开始）
     */
    private List<TmplTpTreeVO> buildFullTree() {
        // 1. 查询所有数据
        List<TmplTpDO> allNodes = baseMapper.selectList(null);

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

        // 2. 转换为树节点VO
        List<TmplTpTreeVO> treeNodes = allNodes.stream()
                .map(this::convertToTreeVO)
                .collect(Collectors.toList());

        // 3. 创建ID到节点的映射
        Map<String, TmplTpTreeVO> nodeMap = treeNodes.stream()
                .collect(Collectors.toMap(
                        node -> node.getId().toString(),
                        node -> node
                ));

        // 4. 收集所有节点ID，用于判断哪些是根节点
        Set<String> allNodeIds = nodeMap.keySet();
        List<TmplTpTreeVO> roots = new ArrayList<>();

        // 5. 构建父子关系，并识别根节点
        for (TmplTpTreeVO node : treeNodes) {
            String parentId = node.getPrnId() != null ? node.getPrnId().toString() : null;

            if (parentId != null && nodeMap.containsKey(parentId)) {
                // 有父节点，建立父子关系
                TmplTpTreeVO parent = nodeMap.get(parentId);
                if (parent.getChildren() == null) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(node);
            } else {
                // 没有父节点或父节点不存在，视为根节点
                roots.add(node);
            }
        }

        // 6. 对所有节点的子节点进行排序
        nodeMap.values().forEach(node -> {
            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                node.getChildren().sort(Comparator.comparing(TmplTpTreeVO::getSrt));
            }
        });

        // 7. 对根节点排序
        if (!roots.isEmpty()) {
            roots.sort(Comparator.comparing(TmplTpTreeVO::getSrt));
        }

        return roots;
    }

    /**
     * 从内存中查找所有子孙节点ID
     */
    private void findAllDescendantIds(List<TmplTpTreeVO> allNodes,
                                      Set<String> parentIds,
                                      Set<String> resultIds) {
        // 查找直接子节点
        Set<String> childIds = allNodes.stream()
                .filter(node -> node.getPrnId() != null
                        && parentIds.contains(node.getPrnId().toString()))
                .map(node -> node.getId().toString())
                .collect(Collectors.toSet());

        if (childIds.isEmpty()) {
            return;
        }

        // 添加到结果集
        resultIds.addAll(childIds);

        // 递归查找子节点的子节点
        findAllDescendantIds(allNodes, childIds, resultIds);
    }

    /**
     * 转换实体类到树节点VO
     */
    private TmplTpTreeVO convertToTreeVO(TmplTpDO entity) {
        return BeanUtils.toBean(entity, TmplTpTreeVO.class);
    }

    /**
     * 构建树形结构（指定根节点ID集合）
     */
    private List<TmplTpTreeVO> buildTreeStructure(List<TmplTpTreeVO> treeNodes, Set<String> rootIds) {
        // 1. 创建ID到节点的映射
        Map<String, TmplTpTreeVO> nodeMap = treeNodes.stream()
                .collect(Collectors.toMap(
                        node -> node.getId().toString(),
                        node -> node
                ));

        // 2. 构建父子关系
        List<TmplTpTreeVO> roots = new ArrayList<>();

        for (TmplTpTreeVO node : treeNodes) {
            String nodeId = node.getId().toString();
            String parentId = node.getPrnId() != null ? node.getPrnId().toString() : null;

            // 建立父子关系
            if (parentId != null && nodeMap.containsKey(parentId)) {
                TmplTpTreeVO parent = nodeMap.get(parentId);
                if (parent.getChildren() == null) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(node);
            }
        }

        // 3. 只将匹配的节点（rootIds）且没有父节点在结果集中的，作为根节点
        for (String rootId : rootIds) {
            TmplTpTreeVO node = nodeMap.get(rootId);
            if (node != null) {
                String parentId = node.getPrnId() != null ? node.getPrnId().toString() : null;
                // 如果父节点不在当前结果集中，则作为根节点
                if (parentId == null || !nodeMap.containsKey(parentId)) {
                    roots.add(node);
                }
            }
        }

        // 4. 对所有节点的子节点进行排序
        nodeMap.values().forEach(node -> {
            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                node.getChildren().sort(Comparator.comparing(TmplTpTreeVO::getSrt));
            }
        });

        // 5. 对根节点排序
        roots.sort(Comparator.comparing(TmplTpTreeVO::getSrt));

        return roots;
    }
}
