package nc.bs.arap.util;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import nc.bs.framework.common.NCLocator;
import nc.itf.ws.esb.IEsbDAO;
import nc.net.pu.utils.PubUtils;
import nc.vo.esb.EsbInfoAnnotatioVO;
import nc.vo.esb.RequestToEsbVO;
import nc.vo.esb.ResultEsbMyToNcVO;
import nc.vo.esb.ResultMyToNcVO;
import nc.vo.pub.BusinessException;
import nc.vo.sap.log.SapPurchaseLogVO;
import nc.vo.ws.esb.CertificateVO;
import nc.vo.ws.esb.EsbinfoVO;
import sun.misc.BASE64Encoder;

/**
 * @author zhengyao3/郑瑶
 * @date 2018-9-24 下午11:20:22
 * @Description:bean对象转换为XML
 * 
 */
public class NCToMyXmlUtil {

	private static IEsbDAO service;
	private static BASE64Encoder base64;
//add by zhengyao3@郑瑶 2018年10月24日11:56:24 begin

	/**
	 * 解析正向接口的XML
	 * 
	 * @param resultXml
	 * @return
	 * @throws BusinessException
	 */
	public static ResultEsbMyToNcVO getResultEsbMyToNcVO(String resultXml)
			throws BusinessException {
		SAXReader saxReader = new SAXReader();
		Document document = null;
		Element resultElement = null;
		try {
			document = saxReader.read(new ByteArrayInputStream(resultXml
					.getBytes("UTF-8")));

			// 得到根节点对象
			Element rootElements = document.getRootElement();
			// 得到根节点的节点名称
			if (rootElements == null) {
				throw new BusinessException(
						"调用明源接口信息异常,请联系用友顾问查看日志!!日志表名 sap_po_log");
			}
			resultElement = rootElements.element("Body")
					.element("SyncPayStatusToPropertySystemResponse")
					.element("SyncPayStatusToPropertySystemResult");
		} catch (Exception e) {
			throw new BusinessException(
					"调用明源接口信息异常,请联系用友顾问查看日志!!日志表名 sap_po_log");
		}
		if(resultElement == null){
			throw new BusinessException(
					"调用明源接口信息异常,请联系用友顾问查看日志!!日志表名 sap_po_log");
		}
		XStream xStream = new XStream();
		xStream.alias("SyncPayStatusToPropertySystemResult",
				ResultEsbMyToNcVO.class);
		xStream.alias("esbInfo", EsbInfoAnnotatioVO.class);
		xStream.alias("resultInfo", ResultMyToNcVO.class);
		return (ResultEsbMyToNcVO) xStream.fromXML(resultElement.asXML());
	}

	/**
	 * 解析逆向接口返回的XML
	 * 
	 * @param resultXml
	 * @return
	 * @throws BusinessException
	 */
	public static ResultEsbMyToNcVO getReverseResultEsbMyToNcVO(
			String resultXml, String elementResponse, String elementResult)
			throws BusinessException {
		SAXReader saxReader = new SAXReader();
		Document document = null;
		Element resultElement = null;
		try {
			document = saxReader.read(new ByteArrayInputStream(resultXml
					.getBytes("UTF-8")));

			// 得到根节点对象
			Element rootElements = document.getRootElement();
			// 得到根节点的节点名称
			if (rootElements == null) {
				throw new BusinessException(
						"调用明源接口信息异常,请联系用友顾问查看日志!!日志表名 sap_po_log");
			}

			resultElement = rootElements.element("Body")
					.element(elementResponse).element(elementResult);
		} catch (Exception e) {
			throw new BusinessException(
					"调用明源接口信息异常,请联系用友顾问查看日志!!日志表名 sap_po_log");
		}
		if(resultElement == null){
			throw new BusinessException(
					"调用明源接口信息异常,请联系用友顾问查看日志!!日志表名 sap_po_log");
		}
		XStream xStream = new XStream();
		xStream.alias(elementResult, ResultEsbMyToNcVO.class);
		xStream.alias("esbInfo", EsbInfoAnnotatioVO.class);
		xStream.alias("resultInfo", ResultMyToNcVO.class);
		return (ResultEsbMyToNcVO) xStream.fromXML(resultElement.asXML());
	}
//add by zhengyao3@郑瑶 2018年10月24日11:56:24 end

	/**
	 * 传输XML至明源接口
	 * 
	 * @param 传输明源调用总线的VO
	 * @param bgy_esbinfo的Code字段
	 * @return
	 * @throws Exception
	 * update by zhengyao3@郑瑶 抛出异常 2018年10月24日12:03:41 begin
	 */
	public static String sendHttpXmlToMy(RequestToEsbVO vo, String URLCode)
			throws BusinessException {
	//update by zhengyao3@郑瑶 抛出异常 2018年10月24日12:03:41 end
		String guid = vo.getRequestInfo().getFKApplyGUID();
		String xml = beanToXml(vo, RequestToEsbVO.class);
		return sendXMLToMy(xml, URLCode, guid);
	}

	/**
	 * @param VO
	 * @param 对应VO类
	 * @return XML类型数据
	 */
	public static <T> String beanToXml(RequestToEsbVO vo, Class<T> clazz) {
		XStream x = new XStream(new DomDriver("utf-8"));
		x.autodetectAnnotations(true);
		x.processAnnotations(clazz);
		return x.toXML(vo);
	}

	/**
	 * 传输XML至明源接口
	 * 
	 * @param XML数据
	 * @param bgy_esbinfo的Code字段
	 * @return
	 * @throws Exception
	 */
	public static String sendXMLToMy(String xml, String URLCode, String guid)
			throws BusinessException {
	//add by zhengyao3@郑瑶 增加逆向接口 2018年10月24日12:04:13 begin		
		//add by 黄冠华 40331 【联测】无法新增保存部门节点 begin
		//明源部门接口有更改，xml头需要使用新的
		StringBuilder str = new StringBuilder(
				"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\"> \n");
//		StringBuilder str = new StringBuilder();
//		if("NC-MY-FY-001".equals(URLCode)){
//			str.append("<soape:Envelope xmlns:soape=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:tem=\"http://tempuri.org/\"> \n");
//		}else {
//			str.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\"> \n");
//		}
		//add by 黄冠华 40331 【联测】无法新增保存部门节点 end		
		str.append("  <soapenv:Header/> \n");
		str.append(" <soapenv:Body> \n");
		if ("MY-NC-PM-002".equals(URLCode)) {
			str.append("<DeleteOrder xmlns=\"http://tempuri.org/\"> \n");
			str.append(xml);
			str.append("\n </DeleteOrder> \n");
		} else if ("MY-NC-PM-003".equals(URLCode)) {
			str.append("<CheckOrder xmlns=\"http://tempuri.org/\">  \n");
			str.append(xml);
			str.append("\n </CheckOrder> \n");
			//add by libx3@李炳雄 增加甲供材_NC财务部门接口转XML对象时requestinfo实体属性  2019年3月27日11:36:24 begin
		} else if("NC-MY-FY-001".equals(URLCode)){
			str.append("<tem:FinanceDepartmentFramNC> \n");
			str.append(xml);
			str.append("\n </tem:FinanceDepartmentFramNC> \n");
			//add by libx3@李炳雄 增加甲供材_NC财务部门接口转XML对象时requestinfo实体属性  2019年3月27日11:36:24 end
		} else {
			str.append("<tem:SyncPayStatusToPropertySystem> \n");
			str.append(xml);
			str.append("\n </tem:SyncPayStatusToPropertySystem> \n");
		}
	////add by zhengyao3@郑瑶 增加逆向接口 2018年10月24日12:04:13 end	
		str.append(" </soapenv:Body> \n");
		str.append(" </soapenv:Envelope> \n");
		xml = str.toString();
		IEsbDAO service = NCLocator.getInstance().lookup(IEsbDAO.class);
		EsbinfoVO[] esbinfos = (EsbinfoVO[]) service.findESB("code='" + URLCode
				+ "'");
		if (esbinfos == null || esbinfos.length == 0) {
			throw new BusinessException("接口安全授权节点未对接口" + URLCode + "授权");
		}
		String url = esbinfos[0].getUrl();

		String result = "";
		BufferedReader in = null;
		String issuccess_sn = "Y";
		String line = null;
		String exception = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("Content-Type",
					"text/xml; charset=utf-8");
			connection.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			CertificateVO typevo = getService().findByPkCode(
					esbinfos[0].getCertificate());
			if (typevo != null) {
				String basic = typevo.getUsername() + ":"
						+ typevo.getPassword();
				connection.setRequestProperty("Authorization", "Basic "
						+ getBase64().encode(basic.getBytes()));
				connection.setRequestProperty("key","123");
			}
			// 建立实际的连接
			connection.setDoOutput(true);
			connection.connect();

			OutputStream out = connection.getOutputStream();

			// 写入请求的字符串
			out.write((xml.toString()).getBytes("utf-8"));
			out.flush();
			out.close();
			// 定义 BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(
					connection.getInputStream(), "utf-8"));
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			issuccess_sn = "N";
			exception = e.getMessage();
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
				List<SapPurchaseLogVO> logvo_list = new ArrayList<SapPurchaseLogVO>();
				SapPurchaseLogVO log = new SapPurchaseLogVO();
				log.setPk_org(URLCode);
				log.setBillid(guid);
				log.setBillno(guid);
				log.setPk_billtypecode("MY");
				log.setPk_transtypecode("");
				log.setSend_data_sn(xml.toString());
				log.setResultdata_sn(result);
				log.setMsg_sn(exception);
				log.setIssuccess_sn(issuccess_sn);
				log.setDef1("nc.bs.arap.util.NCToMyXmlUtil.sendXMLToMy");
				logvo_list.add(log);
				PubUtils.getSaplog().insertPurchaseLog_RequiresNew(logvo_list);
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * @return
	 */
	public static IEsbDAO getService() {
		if (service == null)
			service = NCLocator.getInstance().lookup(IEsbDAO.class);
		return service;
	}

	/**
	 * @return
	 */
	public static BASE64Encoder getBase64() {
		if (base64 == null)
			base64 = new BASE64Encoder();
		return base64;
	}
}
