package com.rehome.mqttclienttemperature.utils;


import cn.hutool.http.webservice.SoapClient;
import com.google.gson.Gson;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.NamedValue;
//import org.apache.axis2.kernel.http.HTTPConstants;
import org.apache.axis2.rpc.client.RPCServiceClient;
import org.apache.axis2.transport.http.HTTPConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPFault;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * @Author: HuangWenfei
 * @Description: 动态调用WebService, 用开源 hutool 第三库 SoapClient 调用远程rpc
 * @Date: 2025/04/15
 **/
public class WebServiceUtils {
    private static final Logger log = LoggerFactory.getLogger(WebServiceUtils.class);

    public static String invoke(String url, String namespace, String methodTemp, Map<String, String> paramsMap) {
        String result = "";
        try {
            SoapClient soapClient = SoapClient.create(url);
            soapClient.setMethod(methodTemp, namespace);
            if (paramsMap.size() > 0) {
                Gson gson = new Gson();
                log.info("paramsMap:{}",gson.toJson(paramsMap));
                for (Map.Entry<String, String> params : paramsMap.entrySet()) {
                    String key = params.getKey();
                    String value = params.getValue();
                    soapClient.setParam(key, value);
                }
            }
            soapClient.header("app-id", "DYW_ZHDC");
            SOAPBody soapBody = soapClient.sendForMessage().getSOAPBody();
            SOAPFault soapFault = soapBody.getFault();
            if(!ObjectUtils.isEmpty(soapFault)&&soapFault.hasDetail()){
                String faultCode = soapFault.getFaultCode();
                String faultStr = soapFault.getFaultString();
                log.info("WebService调用失败,调用方法:{}",methodTemp);
                log.info("faultCode:{}",faultCode);
                log.info("faultStr:{}",faultStr);
            }else{
                result = soapBody.getTextContent();
                log.info("WebService调用成功,调用方法:{}",methodTemp);
                log.info("WebService调用成功，返回结果数据:{}",result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String invokeAxis2(String url, String namespace, String method, Map<String, String> paramsMap) {
        String result = "";
        try {
            // 使用RPC方式调用WebService
            RPCServiceClient serviceClient = new RPCServiceClient();
            Options options = serviceClient.getOptions();
            // 指定调用WebService的URL
            EndpointReference targetEPR = new EndpointReference(url);
            options.setTo(targetEPR);
            // 添加HTTP请求头
            List<NamedValue> headerList = new ArrayList<>();
            // headerList.add(new NamedValue("userName", "xxx"));
            // 修改时候  字段大小写必须与原始一致
            headerList.add(new NamedValue("app-id", "DYW_ZHDC"));
            options.setProperty(HTTPConstants.HTTP_HEADERS, headerList);
            // 在创建QName对象时，QName类的构造方法的第一个参数表示WSDL文件的命名空间名，也就是<wsdl:definitions>元素的targetNamespace属性值
            // // 指定要调用的getWorld方法及WSDL文件的命名空间.....
            QName opAddEntry = new QName(namespace, method);

            Object[] opAddEntryArgs = null;
            if (paramsMap.size() > 0) {
                Gson gson = new Gson();
                System.out.println(gson.toJson(paramsMap));
                opAddEntryArgs = new Object[paramsMap.size()];
                opAddEntryArgs = joinParams(paramsMap, opAddEntryArgs);
            }
            //
            // 指定getGreeting方法的参数值，如果有多个，继续往后面增加即可，不用指定参数的名称
            //Object[] opAddEntryArgs = new Object[]{"lmycc"};
            // 返回参数类型，这个和axis1有点区别
            // invokeBlocking方法有三个参数，其中第一个参数的类型是QName对象，表示要调用的方法名；
            // 第二个参数表示要调用的WebService方法的参数值，参数类型为Object[]；
            // 第三个参数表示WebService方法的返回值类型的Class对象，参数类型为Class[]。
            // 当方法没有参数时，invokeBlocking方法的第二个参数值不能是null，而要使用new Object[]{}
            // 如果被调用的WebService方法没有返回值，应使用RPCServiceClient类的invokeRobust方法，
            // 该方法只有两个参数，它们的含义与invokeBlocking方法的前两个参数的含义相同
            // 指定getGreeting方法返回值的数据类型的Class对象.....
            Class[] classes = new Class[]{String.class};
            // 调用getGreeting方法并输出该方法的返回值.......
            result = (String) serviceClient.invokeBlocking(opAddEntry, opAddEntryArgs, classes)[0];
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * @Author: xinsihai
     * @Description: //拼接参数数据
     * @Date: 2024/10/22
     * @Param:
     * @Return:
     **/
    private static Object[] joinParams(Map<String, String> paramsMap, Object[] object) {
        int index = 0;
        for (Map.Entry<String, String> params : paramsMap.entrySet()) {
            String value = params.getValue();
            object[index] = value;
            index++;
        }
        return object;
    }

}
