package com.engine.util;

import com.alibaba.druid.util.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import weaver.general.BaseBean;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class XMLUtils {
    //构建返回值
    public static String count2XML(Map<String,String> headerParam,Integer todocount , Integer toreadcount ) {
        try {
            // 创建文档对象
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();

//             创建根节点
            Element rootElement = doc.createElement("Service");
            doc.appendChild(rootElement);

            addServiceHeader(doc,rootElement,headerParam);

            // 创建Service_Body节点
            Element serviceBodyElement = doc.createElement("Service_Body");
            rootElement.appendChild(serviceBodyElement);

            // 创建response节点
            Element responseElement = doc.createElement("response");
            serviceBodyElement.appendChild(responseElement);

            // 创建todo节点
            Element todoElement = doc.createElement("todo");
            responseElement.appendChild(todoElement);

            // 创建count节点并设置值
            if(todocount != null) {
                Element countElement = doc.createElement("count");
                countElement.setTextContent(todocount + "");
                todoElement.appendChild(countElement);
            }
            if(toreadcount != null){
                Element countOneElement = doc.createElement("countOne");
                countOneElement.setTextContent(toreadcount+"");
                todoElement.appendChild(countOneElement);
            }


            // 将文档对象转换为XML字符串
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); // 设置不包含XML声明
            DOMSource source = new DOMSource(doc);

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            StreamResult result = new StreamResult(outputStream);

            transformer.transform(source, result);

            // 将XML结果转换为字符串
            String xmlString = outputStream.toString("UTF-8");
            //System.out.println(xmlString);
            return xmlString;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    private static void addServiceHeader(Document doc, Element rootElement, Map<String, String> headerParam) {

        // 创建Service_Body节点
        Element serviceHeaderElement = doc.createElement("Service_Header");
        rootElement.appendChild(serviceHeaderElement);
        //service_sn	ESB服务流水号
        if (!StringUtils.isEmpty(headerParam.get("service_sn"))){
            Element serviceSnElement = doc.createElement("service_sn");
            serviceSnElement.setTextContent(headerParam.get("service_sn"));
            serviceHeaderElement.appendChild(serviceSnElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("service_id"))){
            Element serviceIdElement = doc.createElement("service_id");
            serviceIdElement.setTextContent(headerParam.get("service_id"));
            serviceHeaderElement.appendChild(serviceIdElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("system_id"))){
            Element systemIdElement = doc.createElement("system_id");
            systemIdElement.setTextContent(headerParam.get("system_id"));
            serviceHeaderElement.appendChild(systemIdElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("requester_id"))){
            Element requesterIdElement = doc.createElement("requester_id");
            requesterIdElement.setTextContent(headerParam.get("requester_id"));
            serviceHeaderElement.appendChild(requesterIdElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("branch_id"))){
            Element branchIdElement = doc.createElement("branch_id");
            branchIdElement.setTextContent(headerParam.get("branch_id"));
            serviceHeaderElement.appendChild(branchIdElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("channel_id"))){
            Element channelIdElement = doc.createElement("channel_id");
            channelIdElement.setTextContent(headerParam.get("channel_id"));
            serviceHeaderElement.appendChild(channelIdElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("service_time"))){
            Element serviceTimeElement = doc.createElement("requester_id");
            serviceTimeElement.setTextContent(headerParam.get("service_time"));
            serviceHeaderElement.appendChild(serviceTimeElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("BnkSrlNo"))){
            Element BnkSrlNoElement = doc.createElement("BnkSrlNo");
            BnkSrlNoElement.setTextContent(headerParam.get("BnkSrlNo"));
            serviceHeaderElement.appendChild(BnkSrlNoElement);
        }
//        if (!StringUtils.isEmpty(headerParam.get("FileFlg"))){
        Element FileFlgElement = doc.createElement("FileFlg");
        FileFlgElement.setTextContent("0");
        serviceHeaderElement.appendChild(FileFlgElement);
//        }
        if (!StringUtils.isEmpty(headerParam.get("SvcCd"))){
            Element SvcCdElement = doc.createElement("SvcCd");
            SvcCdElement.setTextContent(headerParam.get("SvcCd"));
            serviceHeaderElement.appendChild(SvcCdElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("SvcScn"))){
            Element SvcScnElement = doc.createElement("SvcScn");
            SvcScnElement.setTextContent(headerParam.get("SvcScn"));
            serviceHeaderElement.appendChild(SvcScnElement);
        }
//        响应码
        Element service_responseElement = doc.createElement("service_response");
        serviceHeaderElement.appendChild(service_responseElement);
        if (!StringUtils.isEmpty(headerParam.get("status"))){
            Element statusElement = doc.createElement("status");
            statusElement.setTextContent(headerParam.get("status"));
            service_responseElement.appendChild(statusElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("code"))){
            Element codeElement = doc.createElement("code");
            codeElement.setTextContent(headerParam.get("code"));
            service_responseElement.appendChild(codeElement);
        }
        if (!StringUtils.isEmpty(headerParam.get("desc"))){
            Element descElement = doc.createElement("desc");
            descElement.setTextContent(headerParam.get("desc"));
            service_responseElement.appendChild(descElement);
        }

    }


    public static Map<String, String> parseXMLToMap2(String xmlString) {
        Map<String, String> resultMap = new HashMap<>();
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new ByteArrayInputStream(xmlString.getBytes()));

            Element rootElement = document.getDocumentElement();
            extractValues(rootElement, resultMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultMap;
    }

    private static void extractValues(Element element, Map<String, String> resultMap) {
        NodeList childNodes = element.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            if (childNodes.item(i) instanceof Element) {
                Element childElement = (Element) childNodes.item(i);
                String nodeName = childElement.getNodeName();
                String nodeValue = childElement.getTextContent();
                resultMap.put(nodeName, nodeValue);
                extractValues(childElement, resultMap);
            }
        }
    }
    public static String CW2XML(Map<String, String> headerParam, String retCd, String errorMessage) {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            Element rootElement = doc.createElement("Service");
            doc.appendChild(rootElement);
            addServiceHeader(doc, rootElement, headerParam);
            Element serviceBodyElement = doc.createElement("Service_Body");
            rootElement.appendChild(serviceBodyElement);
            Element responseElement = doc.createElement("response");
            serviceBodyElement.appendChild(responseElement);
            Element countOneElement;
            if (retCd != null) {
                countOneElement = doc.createElement("retCd");
                countOneElement.setTextContent(retCd + "");
                responseElement.appendChild(countOneElement);
            }

            if (errorMessage != null) {
                countOneElement = doc.createElement("errorMessage");
                countOneElement.setTextContent(errorMessage + "");
                responseElement.appendChild(countOneElement);
            }

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty("omit-xml-declaration", "no");
            DOMSource source = new DOMSource(doc);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            StreamResult result = new StreamResult(outputStream);
            transformer.transform(source, result);
            String xmlString = outputStream.toString("UTF-8");
            String length = String.format("%08d", xmlString.length());
            return length + xmlString;
        } catch (Exception var16) {
            var16.printStackTrace();
            return "";
        }
    }


    // public static Map<String, String> parseXMLToMap(String xmlString) {
    //     Map<String, String> resultMap = new HashMap<>();
    //     try {
    //         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    //         DocumentBuilder builder = factory.newDocumentBuilder();
    //         Document document = builder.parse(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
    //
    //         Element rootElement = document.getDocumentElement();
    //         // 直接从根元素开始处理
    //         NodeList children = rootElement.getChildNodes();
    //         for (int i = 0; i < children.getLength(); i++) {
    //             if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
    //                 Element child = (Element) children.item(i);
    //                 extractValues(child, resultMap);
    //             }
    //         }
    //     } catch (Exception e) {
    //         e.printStackTrace();
    //     }
    //     return resultMap;
    // }
    //
    // private static void extractValues(Element element, Map<String, String> resultMap) {
    //     // 检查是否有子元素
    //     boolean hasChildElement = false;
    //     NodeList childNodes = element.getChildNodes();
    //     for (int i = 0; i < childNodes.getLength(); i++) {
    //         if (childNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
    //             hasChildElement = true;
    //             break;
    //         }
    //     }
    //
    //     // 如果有子元素，只处理子元素
    //     if (hasChildElement) {
    //         for (int i = 0; i < childNodes.getLength(); i++) {
    //             Node node = childNodes.item(i);
    //             if (node.getNodeType() == Node.ELEMENT_NODE) {
    //                 Element childElement = (Element) node;
    //                 String nodeName = childElement.getNodeName();
    //                 // 去除前后空白字符
    //                 String nodeValue = childElement.getTextContent().trim();
    //                 resultMap.put(nodeName, nodeValue);
    //                 // 不再递归调用以避免重复添加
    //             }
    //         }
    //     }
    // }

    public static void main(String[] args) {
        System.out.println(new Date());
        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Service><Service_Header><service_sn>1010157060000065445</service_sn><system_id>0258</system_id><requester_id>0157</requester_id><branch_id>010231100</branch_id><channel_id>01</channel_id><service_time>20240315092648</service_time><need_request>true</need_request><SvcCd>500130004</SvcCd><SvcScn>12</SvcScn><BnkSrlNo>015720240315060000065445</BnkSrlNo><FileFlg>0</FileFlg></Service_Header><Service_Body><request><path>todo</path><method>getCount2</method><args><entry><key>userNum</key><value>10110707</value></entry></args></request></Service_Body></Service>";
        for (int i = 0; i < 2000; i++) {
            new Thread() {
                @Override
                public void run() {
                    // System.out.println(parseXMLToMap2(xml));
                    parseXMLToMap(xml);
                    parseXMLToMap(xml);
                    parseXMLToMap(xml);
                    parseXMLToMap(xml);
                    printMemoryUsage();

                }
            }.start();
            printMemoryUsage();
        }
        System.out.println(new Date());
    }


    public static Map<String, String> parseXMLToMap(String xmlString) {
        new BaseBean().writeLog("XMLUtils:xmlString==>"+xmlString);
        Map<String, String> resultMap = new HashMap<>();
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();

            InputStream xmlInput = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
            saxParser.parse(xmlInput, new SAXHandler(resultMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultMap;
    }


    private static class SAXHandler extends DefaultHandler {
        private Map<String, String> resultMap;
        private Stack<String> elementStack = new Stack<>();
        private StringBuilder elementValue = new StringBuilder();

        public SAXHandler(Map<String, String> resultMap) {
            this.resultMap = resultMap;
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            elementStack.push(qName);
            elementValue.setLength(0); // 清空字符缓存
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            String value = elementValue.toString().trim();
            if (!value.isEmpty()) {
                // 如果当前元素有值且没有子元素，则将其添加到结果Map中
                if (elementStack.size() > 1) {
                    resultMap.put(elementStack.peek(), value);
                }
            }
            elementStack.pop();
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            elementValue.append(ch, start, length);
        }
    }

    public static void printMemoryUsage() {
        Runtime runtime = Runtime.getRuntime();

        long totalMemory = runtime.totalMemory(); // JVM总内存
        long freeMemory = runtime.freeMemory(); // JVM空闲内存
        long usedMemory = totalMemory - freeMemory; // 已使用内存

        // System.out.println("Total Memory: " + totalMemory + " bytes");
        // System.out.println("Free Memory: " + freeMemory + " bytes");
        System.out.println("Used Memory: " + usedMemory + " bytes");
    }

}