package org.jeecg.modules.stm.baosong.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.jeecg.modules.stm.baosong.entity.BaosongTpl;
import org.jeecg.modules.stm.baosong.entity.BaosongTplItem;
import org.jeecg.modules.stm.baosong.mapper.BaosongTplItemMapper;
import org.jeecg.modules.stm.baosong.service.IBaosongTplItemService;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.jeecg.modules.stm.utils.UserUtil;
import org.w3c.dom.*;

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

/**
 * @Description: 报送模板项
 * @Author: jeecg-boot
 * @Date:   2024-12-14
 * @Version: V1.0
 */
@Service
public class BaosongTplItemServiceImpl extends ServiceImpl<BaosongTplItemMapper, BaosongTplItem> implements IBaosongTplItemService {

    private List<BaosongTplItem>  allTplItem = null;
    private BaosongTpl baosongTpl = null;

    @Override
    public Boolean parseXmlFile(Document document, BaosongTpl baosongTpl, List<BaosongTplItem> tplItems) {
        try {
            this.allTplItem = new ArrayList<>();
            this.baosongTpl = baosongTpl;
            document.getDocumentElement().normalize();

            // 1. 准备数据
            Map<String, BaosongTplItem> existingItemsMap = createExistingItemsMap(tplItems);
            Map<String, BaosongTplItem> newItemsMap = new HashMap<>();

            parseXmlNodes(document.getLastChild().getChildNodes(), existingItemsMap, newItemsMap);
            buildRelationshipsAndPaths(document.getDocumentElement().getNodeName(), newItemsMap);

            this.saveOrUpdateBatch(allTplItem);
            updateParentIds(document.getDocumentElement().getNodeName());
            this.saveOrUpdateBatch(allTplItem);

            baosongTpl.setUpdatedUser(UserUtil.getUserId());
            baosongTpl.setUpdatedTime(new Date());
            baosongTpl.setChildNum(allTplItem.size());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 创建现有项的映射表
    private Map<String, BaosongTplItem> createExistingItemsMap(List<BaosongTplItem> tplItems) {
        Map<String, BaosongTplItem> map = new HashMap<>();
        if (tplItems != null&&tplItems.size()>0) {
            for (BaosongTplItem item : tplItems) {
                String key = buildItemKey(item.getCode(), item.getPcode(), item.getTplid());
                map.put(key, item);
            }
        }
        return map;
    }

    // 解析XML节点
    private void parseXmlNodes(NodeList nodes, Map<String, BaosongTplItem> existingItemsMap,
                                Map<String, BaosongTplItem> newItemsMap) {
        Map<String, String> ignoreMap = getIgnoreNodes();

        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            String nodeName = node.getNodeName();
            //String parentCode = node.getParentNode().getNodeName();
            Node parentNode = node.getParentNode();
            if (shouldSkipNode(node, nodeName, ignoreMap)) {
                handleSpecialNodes(node, nodeName);
                continue;
            }

            if (node.getNodeType() == Node.ELEMENT_NODE) {

                if(parentNode.getNodeType()!=Node.ELEMENT_NODE){
                    continue;
                }
                BaosongTplItem item = createTplItem(node, parentNode, existingItemsMap);
                String strKey = item.getPcode()+"_"+item.getCode();
                if(newItemsMap.containsKey(strKey)){
                    continue;
                }
                newItemsMap.put(strKey, item);
                if(item.getTitle()==null) {
                    continue;
                }
                allTplItem.add(item);

                // 递归处理子节点
                parseXmlNodes(node.getChildNodes(), existingItemsMap, newItemsMap);
            }
        }
    }

    // 创建模板项
    private BaosongTplItem createTplItem(Node node, Node parentNode,
                                         Map<String, BaosongTplItem> existingItemsMap) {
        String nodeName = node.getNodeName();
        String parentCode = parentNode.getNodeName();
        String key = buildItemKey(nodeName, parentCode, baosongTpl.getId());

        BaosongTplItem item = Optional.ofNullable(existingItemsMap.get(key))
                .orElse(new BaosongTplItem());

        item.setCode(nodeName);
        item.setPcode(parentCode);
        item.setTplid(baosongTpl.getId());
        item.setTplName(baosongTpl.getNm());
        item.setXmlcode(nodeName);
        String comment = getCommentContent(node);
        String commentParent = getCommentContent(parentNode);
        item.setTreepathName(comment);
        if (StringUtils.isNotBlank(comment)) {
            if(commentParent!=null&&!commentParent.isEmpty()){
//                int plen = commentParent.length();
//                if(comment.length()<=plen){
//                    item.setTitle(comment);
//                } else {
//                    item.setTitle(comment.substring(plen + 1));
//                }
                item.setTitle(comment.replace(commentParent+"/",""));

            } else {
                item.setTitle(comment);
            }
        }
        item.setChildNum(countElementChildren(node));
        return item;
    }



    // 辅助方法
    private boolean shouldSkipNode(Node node, String nodeName, Map<String, String> ignoreMap) {
        return (node.getNodeType() == Node.ELEMENT_NODE && ignoreMap.containsKey(nodeName)) ||
                (node.getNodeType() == Node.COMMENT_NODE);
    }

    private void handleSpecialNodes(Node node, String nodeName) {
        if ("itVersion".equals(nodeName)) {
            String version = node.getTextContent().trim();
            if (!version.isEmpty()) {
                baosongTpl.setVersion(version);
            }
        }
    }

    private String buildItemKey(String code, String pcode, Integer tplid) {
        return code + "_" + pcode + "_" + tplid;
    }

    private int countElementChildren(Node node) {
        int count = 0;
        NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
                count++;
            }
        }
        return count;
    }

    private Map<String,String> getIgnoreNodes() {
        Map<String,String> map = new HashMap<>();
        map.put("FILLIN_DEPT","1");
        map.put("FILLIN_DATE","2");
        map.put("FILLIN_PERSON","3");
        map.put("TELEPHONE","4");
        map.put("RES_PERSON","5");
        map.put("jiaoyanwei","6");
        map.put("isempty","7");
        map.put("itTitle","8");
        map.put("itVersion","9");
        map.put("FILE ","10");
        map.put("ATTACHMENT","11");
        return map;
    }

    private String getCommentContent(Node node) {
        if(node==null) return "";
        String strComment = "";
        if(Node.COMMENT_NODE == node.getNodeType()) {
            strComment = node.getNodeValue().trim();
        } else {
            while (Node.COMMENT_NODE != node.getNodeType()) {
                node = node.getPreviousSibling();
                if(node==null) break;
                if (Node.COMMENT_NODE == node.getNodeType()) {
                    strComment = node.getNodeValue().trim();
                    break;
                }
            }
        }
        if(strComment!=null&&!strComment.equals("")) {
            strComment = strComment.replace("-","/");
        }

        return strComment;
    }


    private void buildRelationshipsAndPaths(String rootNodeName, Map<String, BaosongTplItem> newItemsMap) {
        // 使用 code + pcode + tplid 作为复合键
        Map<String, BaosongTplItem> itemKeyMap = allTplItem.stream()
                .collect(Collectors.toMap(
                        item -> buildItemKey(item.getCode(), item.getPcode(), item.getTplid()),
                        Function.identity(),
                        (existing, replacement) -> existing
                ));

        for (BaosongTplItem item : allTplItem) {
            // 设置 pid
            if (!item.getPcode().equals(rootNodeName)) {
                // 父节点的key应该是: pcode + 父节点的pcode + tplid
                String parentKey = buildItemKey(item.getPcode(),
                        findParentPcode(item, allTplItem, rootNodeName),
                        item.getTplid());
                BaosongTplItem parent = itemKeyMap.get(parentKey);
                if (parent != null) {
                    item.setPid(parent.getId());
                }
            }

            // 设置 treepath
            item.setTreepath(buildTreePath(item, itemKeyMap, rootNodeName));
        }
    }

    private String findParentPcode(BaosongTplItem item, List<BaosongTplItem> allItems, String rootNodeName) {
        if (item.getPcode().equals(rootNodeName)) {
            return rootNodeName;
        }

        // 查找当前item的父节点
        for (BaosongTplItem potentialParent : allItems) {
            if (potentialParent.getCode().equals(item.getPcode())) {
                return potentialParent.getPcode();
            }
        }
        return rootNodeName;
    }

    private String buildTreePath(BaosongTplItem item, Map<String, BaosongTplItem> itemKeyMap,
                                 String rootNodeName) {
        LinkedList<String> pathParts = new LinkedList<>();
        pathParts.addFirst(item.getCode());

        String currentCode = item.getPcode();
        String currentPcode = findParentPcode(item, allTplItem, rootNodeName);
        Integer tplid = item.getTplid();

        while (!currentCode.equals(rootNodeName)) {
            String parentKey = buildItemKey(currentCode, currentPcode, tplid);
            BaosongTplItem parent = itemKeyMap.get(parentKey);
            if (parent == null) break;

            pathParts.addFirst(parent.getCode());
            currentCode = parent.getPcode();
            currentPcode = findParentPcode(parent, allTplItem, rootNodeName);
        }

        pathParts.addFirst(rootNodeName);
        return String.join("/", pathParts);
    }

    private void updateParentIds(String rootNodeName) {
        Map<String, BaosongTplItem> itemMap = allTplItem.stream()
        .collect(Collectors.toMap(
            item -> buildItemKey(item.getPcode(), item.getId()),
            Function.identity()
        ));

        for(BaosongTplItem item:allTplItem) {
            if(item.getPid()!=null){
                continue;
            }
            BaosongTplItem parent = itemMap.get(item.getPcode());
            if (parent != null) {
                item.setPid(parent.getId());
            }
        }
    }

    // 辅助方法：生成唯一键
    private String buildItemKey(String code, Integer tplid) {
        return code + "_" + tplid;
    }



}
