package nc.util.uap.twxt;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.alibaba.fastjson.JSONObject;

import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.itf.twxt.log.IWuYeTwxtLogService;
import nc.itf.twxt.process.IWuYeTwxtBusiService;
import nc.itf.uap.IUAPQueryBS;
import nc.itf.uap.pf.IPFBusiAction;
import nc.itf.uap.pf.IPfExchangeService;
import nc.itf.uap.pf.IWorkflowMachine;
import nc.itf.ws.esb.IEsbDAO;
import nc.jdbc.framework.SQLParameter;
import nc.net.servlet.IReturnStatus;
import nc.pubitf.para.SysInitQuery;
import nc.vo.esb.EsbInfoVO;
import nc.vo.esb.EsbVO;
import nc.vo.esb.QueryInfoVO;
import nc.vo.esb.ResultEsbVO;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.workflownote.WorkflownoteVO;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.data.ValueUtils;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.tmpub.util.DateUtil;
import nc.vo.twxt.log.WYTwxtLogVO;
import nc.vo.wfengine.definition.WorkflowTypeEnum;
import nc.vo.wfengine.pub.WfTaskOrInstanceStatus;
import nc.vo.ws.esb.CertificateVO;
import nc.vo.ws.esb.EsbinfoVO;
import sun.misc.BASE64Encoder;
/**
 * @Description: 
 * 【碧桂园-物业板块-网报平台接口】	
 * @author 周蓝萍 
 * @date 2019-04-15
 */
public class WYTwxtUtil {
	
	private static BASE64Encoder base64;
	
	private static IEsbDAO service;

	public static IWuYeTwxtLogService getIWuYeTwxtLogService() {
		return NCLocator.getInstance().lookup(IWuYeTwxtLogService.class);
	}

	public static IWuYeTwxtBusiService getIWuYeTwxtBusiService() {
		return NCLocator.getInstance().lookup(IWuYeTwxtBusiService.class);
	}

	public static IPfExchangeService getExchangeService() {
		return  NCLocator.getInstance().lookup(IPfExchangeService.class);
	}

	/**
	 * 生成ESB响应对象
	 * @param esb
	 */
	public static void createResultEsbVO(ResultEsbVO esb){
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		EsbInfoVO esbInfo=new EsbInfoVO();
		QueryInfoVO queryInfo=new QueryInfoVO();
		Date date=Calendar.getInstance().getTime();//获取当前时间
		//设置响应时间
		esbInfo.setInstId(UUID.randomUUID().toString());//使用UUID作为流水号
		esbInfo.setRequestTime(dateFormat.format(Calendar.getInstance().getTime()));//设置请求开始时间
		esbInfo.setResponseTime(dateFormat.format(date));//设置响应时间
		esbInfo.setReturnStatus(IReturnStatus.ESB_SUCCEED);//默认响应成功
		esbInfo.setReturnCode(IReturnStatus.ESB_SUCCEED_CODE);//默认成功code
		esbInfo.setReturnMsg("成功");//默认响应成功提示
		esb.setEsbInfo(esbInfo);
		esb.setQueryInfo(queryInfo);
	}

	/**
	 * @param e	异常
	 * return 异常详细信息
	 */
	public static String getExceptionDetail(Exception e) {
		if(e==null)
			return null;
		StringBuffer stringBuffer = new StringBuffer(e.toString() + "\n");  
		if(e.getStackTrace()==null || e.getStackTrace().length==0)
			return stringBuffer.toString();  
		StackTraceElement[] messages = e.getStackTrace();  
		int length = messages.length;  
		for (int i = 0; i < length; i++) {
			stringBuffer.append("\t"+messages[i].toString()+"\n");  
		}
		return stringBuffer.toString();  
	}

	public static void callWyTwService(Map<String, Object> paraMap, String operationName,String itfName) throws BusinessException{
		WYTwxtLogVO logVO=new WYTwxtLogVO();

		String msg = null;
		String isSuccess = "Y";
		String billdata="请求报文:";
		String resdata="返回报文:";

		try {
			EsbinfoVO[] esbinfos=(EsbinfoVO[]) getService().findESB("code='NC-TW-FI-001' and nvl(dr,0)=0");
			String nameSpace = "http://tempuri.org/";
			String wsdlUrl = esbinfos[0].getUrl();
//			String elementName = "NCBILL_REVOKE";
			String userName=SysInitQuery.getParaString("GLOBLE00000000000000", "TWUSERNAME");
			String password=SysInitQuery.getParaString("GLOBLE00000000000000", "TWPASS");
			
			StringBuilder soap=new StringBuilder(); //构造请求报文
			soap.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
			soap.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
//			soap.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"");
//			soap.append(" xmlns:tem=\"http://tempuri.org/\">");
			soap.append(" <soap:Header>");
			soap.append("<CredentialSoapHeader  xmlns=\"http://tempuri.org/\">");
			soap.append("  <UserName>"+userName+"</UserName>");
			soap.append("  <Password>"+password+"</Password>");
			soap.append("</CredentialSoapHeader>");
			soap.append("</soap:Header>");

			soap.append(" <soap:Body>");
			soap.append(" <NCBILL_REVOKE  xmlns=\"http://tempuri.org/\">");
			soap.append(" <esbInfo>");
			soap.append(" <instId>DELBILL"+DateUtil.getCurrTime().toStdString()+"</instId>");
			soap.append("<requestTime>"+DateUtil.getCurrTime().toStdString()+"</requestTime>");
			soap.append("<attr1>?</attr1>");
			soap.append(" <attr2>?</attr2>");
			soap.append("<attr3>?</attr3>");
			soap.append("  </esbInfo>");
			soap.append(" <requestInfo>");
			soap.append(" <BILLINFO>");
			soap.append("<ORDERID>"+ValueUtils.getString(paraMap.get("ORDERID"))+"</ORDERID>");
			soap.append("<TYPE>"+ValueUtils.getString(paraMap.get("TYPE"))+"</TYPE>");
			soap.append("<REMARK>"+ValueUtils.getString(paraMap.get("REMARK"))+"</REMARK>");
			soap.append(" </BILLINFO>");
			soap.append(" </requestInfo>");
			soap.append(" </NCBILL_REVOKE>");
			soap.append("</soap:Body>");
			soap.append("</soap:Envelope>");
			String requestSoap=soap.toString();
			billdata=requestSoap;
			
			String soapAction ="http://tempuri.org/NCBILL_REVOKE";
			URL url = new URL(wsdlUrl);
//			InetAddress inetAddress=InetAddress.getByName(url.getHost());
//			URL realUrl=new URL(url.getPort()==-1?url.getProtocol()+"://"+inetAddress.getHostAddress()+url.getFile():url.getProtocol()+"://"+inetAddress.getHostAddress()+":"+url.getPort()+url.getFile());
			URLConnection con;
			con = (HttpURLConnection) url.openConnection();
			con.setDoOutput(true);
			con.setDoInput(true);
			con.setRequestProperty("accept", "*/*");
			con.setRequestProperty("connection", "Keep-Alive");
			con.setRequestProperty("user-agent",  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			con.setUseCaches(false);
			con.setRequestProperty("Content-type", "text/xml; charset=UTF-8");
			addHeaderBasic(esbinfos, con);
			con.setRequestProperty("SOAPAction", soapAction);
			OutputStream out = null;
			out = con.getOutputStream();
			con.getOutputStream().write(requestSoap.getBytes("utf-8"));
			out.flush();
			out.close();
			String tempString = null;
			StringBuffer sb1 = new StringBuffer();
				BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
				while ((tempString = reader.readLine()) != null) {
					sb1.append(tempString);
				}
				if (null != reader) {
					reader.close();
				}
			resdata=resdata+sb1.toString();
				
			Map resMap=readStringXmlOut(sb1.toString());
			
			if(null!=resMap){
				Object returnStatus =resMap.get("returnStatus");
				Object returnMsg=resMap.get("returnMsg");
				if(!"S".equals(returnStatus.toString().toUpperCase())){
					ExceptionUtils.wrappBusinessException("物业天问接口信息："+returnMsg);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			msg=WYTwxtUtil.getExceptionDetail(e);
			isSuccess = "N";
			ExceptionUtils.marsh(e);
		}finally{
			// 日志表
			logVO.setItfname(itfName);
			logVO.setBilldata(billdata+"参数："+paraMap.keySet().toString()+paraMap.values().toString());
			logVO.setMsg(msg);
			logVO.setIssuccess(isSuccess);
			logVO.setRsdata(resdata);
			WYTwxtUtil.getIWuYeTwxtLogService().insertLog_RequiresNew(logVO);
		}
	}
	
	/**
	 * 解析XML转换为Map
	 * @param xml
	 * @return
	 */
	public static Map readStringXmlOut(String xml) {
		Map map = new HashMap();
		Document doc = null;
		try {
			// 将字符串转为XML
			doc = DocumentHelper.parseText(xml); 
			// 获取根节点
			Element rootElt = doc.getRootElement(); 

			// 获取根节点下的子节点head
			Iterator iter = rootElt.elementIterator(rootElt.getName()); 
			
			GetElement(rootElt,map);
			
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}
	/**
	 * 
	 * @param element
	 * @param map
	 */
	public static void GetElement(Element element,Map map) {
		 for (Iterator i = element.elementIterator(); i.hasNext();) {
			 Element value = (Element) i.next();
			 map.put(value.getName(), value.getText());
			 if(value.elementIterator().hasNext()){
				 GetElement(value,map);
			 }
		 }
	}
	
	/**
	 * 通过Esb发送JSon数据到SAP/融资
	 * @param jsonData
	 * @param itfCode
	 * @return
	 * @throws Exception
	 */
	public static JSONObject sendToESB(String jsonData,String itfCode) throws Exception {
		JSONObject resultinfo = null;
		IEsbDAO service = NCLocator.getInstance().lookup(IEsbDAO.class);
		EsbinfoVO[] esbinfos = (EsbinfoVO[]) service.findESB("code='"+itfCode+"'");
		if(esbinfos==null){
			ExceptionUtils.wrappBusinessException("没有找到接口配置信息-接口编码："+itfCode);
		}
		if(esbinfos.length>1){
			ExceptionUtils.wrappBusinessException("接口配置信息查询结果大于1【"+esbinfos.length+"】-接口编码："+itfCode);
		}
		String isstart = esbinfos[0].getIsstart();
		if("1".equals(isstart)){
			//接口启用
			String url = esbinfos[0].getUrl();
			String code = esbinfos[0].getCode();
			String msg = "发送请求：接口编码："+itfCode+"\n"+"请求报文：\n"+jsonData;
			Logger.error(msg);
			resultinfo = sendJsonPost(url, jsonData, code);
			if(resultinfo!=null){
				msg += "\n返回报文：\n"+resultinfo.toString();
			}
			Logger.error(msg);
		}else{
			Logger.error("接口未启用！接口编码："+itfCode);
		}
		return resultinfo;
	}
	
	/**
	* 向指定 URL 发送POST方法的请求（发送值）
    * @param url 发送请求的 URL
    * @param paramJson json串格式的报文
    * @param esbcode 接口安全授权 编码
    * @return 所代表远程资源的响应结果(值类型为Json对象)
    */
   public static JSONObject sendJsonPost(String url, String paramJson,String esbcode) throws Exception{
	   OutputStreamWriter out = null;
       BufferedReader in = null;
       StringBuffer result = new StringBuffer();
       try {
           URL realUrl = new URL(url);
           // 打开和URL之间的连接
           URLConnection conn = realUrl.openConnection();
//           conn.setConnectTimeout(30000);
           // 设置通用的请求属性 
           conn.setRequestProperty("accept", "*/*");
           conn.setRequestProperty("connection", "Keep-Alive");
           conn.setRequestProperty("user-agent",  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
           //设置请求字符集  防止请求参数因字符集原因（非UTF-8）导致调用接口不一致报错（数据类型不一致） 
           conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
           addHeaderBasic(esbcode,conn);//Http添加Basic认证
           // 发送POST请求必须设置如下两行
           conn.setDoOutput(true);
           conn.setDoInput(true);
           // 获取URLConnection对象对应的输出流
           out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
           // 发送请求参数
           out.write(paramJson);
           // flush输出流的缓冲
           out.flush();
           // 定义BufferedReader输入流来读取URL的响应
           in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
           String line;
           while ((line = in.readLine()) != null) {
               result.append(line);
           }
       } catch (Exception e) {
           throw e;
       }
       //使用finally块来关闭输出流、输入流
       finally{
           try{
               if(out!=null){
                   out.close();
               }
               if(in!=null){
                   in.close();
               }
           }
           catch(IOException ex){
               ex.printStackTrace();
           }
       }
       if(result!=null && result.length()>0)//转换为Json对象输出
    	   return JSONObject.parseObject(result.toString());
       else
    	   return null;
   }
	
	/**
	 * Http添加Basic认证
	 * @param esbcode 接口安全授权 编码
	 * @param urlConn 访问地址对象
	 */
	public static void addHeaderBasic(String esbcode,final URLConnection urlConn){
		EsbinfoVO[] esbinfos=(EsbinfoVO[]) getService().findESB("code='"+esbcode+"'");
		if(esbinfos!=null && esbinfos.length>0){
			CertificateVO typevo=getService().findByPkCode(esbinfos[0].getCertificate());
			if(typevo!=null){
				String basic=typevo.getUsername()+":"+typevo.getPassword();
				urlConn.addRequestProperty("Authorization", "Basic "+getBase64().encode(basic.getBytes()));
				urlConn.addRequestProperty("esbkey",typevo.getEsbkey());
			}
		}
	}
	
	public static String getSendToEsbData(String instId,Object requestInfo){
		EsbVO esbVO = new EsbVO();
		EsbInfoVO esbInfoVO = new EsbInfoVO();
		QueryInfoVO queryInfoVO = new QueryInfoVO();
		//接口唯一 ID（填写说明：接口编码+Long 型当前时间，例：D02S-SAPMDM-1804-008-301235201459）
		esbInfoVO.setInstId(instId);
		//调用方调用接口时间,格式：“yyyy-MM-dd HH24:mm:ss:SSS”
		esbInfoVO.setRequestTime(AppContext.getInstance().getServerTime().toString());
		//弹性字段 （填写说明：必有字段，暂时无需填值）
		esbInfoVO.setAttr1("");
		esbInfoVO.setAttr2("");
		esbInfoVO.setAttr3("");
		
		//页大小
		queryInfoVO.setPageSize("1");
		//第几页
		queryInfoVO.setCurrentPage("1");
		
		esbVO.setEsbInfo(esbInfoVO);
		esbVO.setQueryInfo(queryInfoVO);
		esbVO.setRequestInfo(requestInfo);
		return JSONObject.toJSONString(esbVO);
	}
	
	/**
	 * 查询流程处理人
	 * @param billType
	 * @param billId
	 * @return
	 * @throws Exception
	 */
	public static String queryWorkUserID(String billType,String billId)throws Exception {
		String userID = null;
		String strWfTypeSql = " and workflow_type in" + WorkflowTypeEnum.getInstanceTypeInSql(WorkflowTypeEnum.Approveflow.getIntValue());
		String where = "pk_billtype=? and billversionpk=? and ismsgbind='N' "
				+ strWfTypeSql
				+ " and actiontype<>'"
				+ WorkflownoteVO.WORKITEM_TYPE_BIZ
				+ "' and approvestatus in("
				+ WfTaskOrInstanceStatus.getUnfinishedStatusSet()
				+ ") order by senddate";
		SQLParameter para = new SQLParameter();
		para.addParam(billType);
		para.addParam(billId);
		List<WorkflownoteVO> co = (List<WorkflownoteVO>)new BaseDAO().retrieveByClause(WorkflownoteVO.class, where, para);
		if(co!=null && co.size()>0){
			userID = co.get(0).getCheckman();
		}
		if(userID==null || userID.trim().length()<20){
			userID = InvocationInfoProxy.getInstance().getUserId();
		}
		return userID;
	}
	
	/**
	 * 查询流程信息
	 * @param actionCode
	 * @param billType
	 * @param billVO
	 * @return
	 * @throws BusinessException
	 */
	public static WorkflownoteVO getWorkflownoteVO(String actionCode,String billType,AggregatedValueObject billVO,HashMap hmPfExParams) throws BusinessException{
		WorkflownoteVO worknoteVO = getIWorkflowMachine().checkWorkFlow(actionCode, billType, billVO, hmPfExParams);
		if(worknoteVO!=null){
			worknoteVO.setApproveresult("Y");
			worknoteVO.setChecknote("批准");
		}
		return worknoteVO;
	}
	
	/**
	 * Http添加Basic认证
	 * @author 符耀铭
	 * @time 2019-11-29
	 * @param esbcode 接口安全授权 编码
	 * @param urlConn 访问地址对象
	 */
	public static void addHeaderBasic(EsbinfoVO[] esbinfos,final URLConnection urlConn){
		if(esbinfos!=null && esbinfos.length>0){
			CertificateVO typevo=getService().findByPkCode(esbinfos[0].getCertificate());
			if(typevo!=null){
				String basic=typevo.getUsername()+":"+typevo.getPassword();
				urlConn.addRequestProperty("Authorization", "Basic "+getBase64().encode(basic.getBytes()));
			}
		}
	}
	
	public static IUAPQueryBS getQueryBS() {
		return NCLocator.getInstance().lookup(IUAPQueryBS.class);
	}
	
	public static IWorkflowMachine getIWorkflowMachine() {
		return NCLocator.getInstance().lookup(IWorkflowMachine.class);
	}
	
	public static IPFBusiAction getIPFBusiAction(){
		return NCLocator.getInstance().lookup(IPFBusiAction.class);
	}
	
	 public static BASE64Encoder getBase64(){
		 if(base64==null)
			 base64=new BASE64Encoder();
		 return base64;
	 }
	 
	 public static IEsbDAO getService(){
	    	if(service==null)
	    		service=NCLocator.getInstance().lookup(IEsbDAO.class);
	    	return service;
		 }
	
}
