package nc.net.pu.utils;

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.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

import com.alibaba.fastjson.JSONObject;

import nc.bs.framework.common.NCLocator;
import nc.itf.sap.log.ISapLog;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.vo.esb.EsbInfoVO;
import nc.vo.esb.EsbVO;
import nc.vo.esb.QueryInfoVO;
import nc.vo.pub.BusinessException;
import nc.vo.sap.log.SapPurchaseLogVO;
import nc.vo.ws.esb.BasicTool;

/**
 * @author 国惠洋 2018-04-11
 * 调用SAP系统ESB接口方法类(发送请求工具类)
 *
 */
public class PubUtils {
	
	
	/**
	 * 交互时间精确到毫秒
	 */
	public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
	
	private static ISapLog saplog;
	
	private static IUAPQueryBS queryBS;
	
	/**
	* 向指定 URL 发送POST方法的请求（发送值）
    * @param url 发送请求的 URL
    * @param paramJson json串格式的报文
    * @param esbcode 接口安全授权 编码
    * @return 所代表远程资源的响应结果(值类型为Json对象)
    */
   public static JSONObject sendJsonPost_GX(String url, String paramJson,String esbcode) throws Exception{
	   OutputStreamWriter out = null;
       BufferedReader in = null;
       InputStreamReader conninput = null;
       int responseCode = 0;    //远程主机响应的HTTP状态码
       StringBuffer result = new StringBuffer();
       try {
           URL realUrl = new URL(url);
           // 打开和URL之间的连接
           HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
           // 设置通用的请求属性 
           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");
           BasicTool.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();
           responseCode = conn.getResponseCode();  
           //获取请求的资源
           if(responseCode == HttpURLConnection.HTTP_OK) {//xug 
        	   // 定义BufferedReader输入流来读取URL的响应
               conninput = new InputStreamReader(conn.getInputStream(), "UTF-8");//xug 流 单独new，用完之后释放
           }else {
        	   // 定义BufferedReader输入流来读取URL的响应
               conninput = new InputStreamReader(conn.getErrorStream(), "UTF-8");//xug 流 单独new，用完之后释放
           }
           in = new BufferedReader(conninput);
           String line;
           while ((line = in.readLine()) != null) {
               result.append(line);
           }
       } catch (Exception e) {
    	   throw new Exception("x接口调用错误", e);
       }
       //使用finally块来关闭输出流、输入流
       finally{
           try{
               if(out!=null){
                   out.close();
               }
               if(in!=null){
                   in.close();
               }
               if(conninput!=null){
            	   conninput.close();
               }
           }
           catch(IOException ex){
               ex.printStackTrace();
           }
       }
       //xug add 消息修复
       if(responseCode == HttpURLConnection.HTTP_OK) {
           if(result!=null && result.length()>0)//转换为Json对象输出
        	   return com.alibaba.fastjson.JSONObject.parseObject(result.toString());
           else
        	   return null; 
       }else {
    	   throw new Exception("对方接口返回状态:"+responseCode+";msg="+result);
       }
       //xug end 消息修复
   }
   
	/**
	* 向指定 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;
       InputStreamReader conninput = null;
       StringBuffer result = new StringBuffer();
       try {
           URL realUrl = new URL(url);
           // 打开和URL之间的连接
           URLConnection conn = realUrl.openConnection();
           // 设置通用的请求属性 
           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");
           BasicTool.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的响应
           conninput = new InputStreamReader(conn.getInputStream(), "UTF-8");//xug 流 单独new，用完之后释放
           in = new BufferedReader(conninput);
           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();
               }
               if(conninput!=null){
            	   conninput.close();
               }
           }
           catch(IOException ex){
               ex.printStackTrace();
           }
       }
       if(result!=null && result.length()>0)//转换为Json对象输出
    	   return com.alibaba.fastjson.JSONObject.parseObject(result.toString());
       else
    	   return null;
   }
   
   public static JSONObject sendHttpJsonPost(String url,String param,String esbcode) throws Exception{  
       HttpURLConnection httpURLConnection = null;  
       OutputStream out = null; //写  
       BufferedReader br = null;   //读  
       int responseCode = 0;    //远程主机响应的HTTP状态码 
       InputStreamReader conninput = null;
       StringBuffer result=new StringBuffer();  
       try{  
           URL sendUrl = new URL(url);  
           httpURLConnection = (HttpURLConnection)sendUrl.openConnection();  
           //post方式请求  
           httpURLConnection.setRequestMethod("POST");  
           //设置头部信息  
           httpURLConnection.setRequestProperty("headerdata", "ceshiyongde");  
           //一定要设置 Content-Type 要不然服务端接收不到参数  
           httpURLConnection.setRequestProperty("Content-Type", "application/Json; charset=UTF-8");  
           //指示应用程序要将数据写入URL连接,其值默认为false（是否传参）  
           httpURLConnection.setDoOutput(true);  
           httpURLConnection.setDoInput(true);   
             
           httpURLConnection.setUseCaches(false);//不使用缓存
           httpURLConnection.setConnectTimeout(120000); //120秒连接超时  
           httpURLConnection.setReadTimeout(120000);    //120秒读取超时  
           BasicTool.addHeaderBasic(esbcode,httpURLConnection);//Http添加Basic认证
           //传入参数  
           out = httpURLConnection.getOutputStream();  
           out.write(param.getBytes());  
           out.flush(); //清空缓冲区,发送数据  
           responseCode = httpURLConnection.getResponseCode();  
           //获取请求的资源 
           conninput = new InputStreamReader(httpURLConnection.getInputStream(),"UTF-8");//xug 流 单独new，用完之后释放
           br = new BufferedReader(conninput);  
           String line="";
           while ((line = br.readLine()) != null) {
               result.append(line);
           }
       }catch(Exception e) {
    	   throw e;
       }finally{
			try {
				if(out!=null)
					out.close();
				if(br!=null)
					br.close();
	            if(conninput!=null){
	               conninput.close();
	            }
			} catch (IOException e) {
				e.printStackTrace();
			}  
       }
       if(result!=null && result.length()>0)//转换为Json对象输出
    	   return com.alibaba.fastjson.JSONObject.parseObject(result.toString());
       else
    	   return null; 
   }
   
   /**
	 * 创建ESB请求对象，
	 * 调用自动组装请求对象EsbVO
	 */
	public static EsbVO createRequestEsbVO(final EsbVO esb){
		Date date=Calendar.getInstance().getTime();//获取当前时间
		EsbInfoVO esbInfo=new EsbInfoVO();
		esbInfo.setInstId(getStringUUID());//使用UUID作为流水号
		QueryInfoVO queryInfo=new QueryInfoVO();
//		queryInfo.setTotal_Page("1");//默认总页数为 1
//		queryInfo.setCurrent_page("1");//默认当前页数为 1
		esbInfo.setRequestTime(dateFormat.format(date));//设置请求时间
		esb.setEsbInfo(esbInfo);
		esb.setQueryInfo(queryInfo);
		return esb;
	}
	
	/**
	 * 获得UUID值
	 */
	public static String getStringUUID(){
		return UUID.randomUUID().toString();
	}
	
	/**
	 * 日志操作对象，用于将日志SapPurchaseLogVO独立事物插入数据库
	 */
    public static ISapLog getSaplog(){
    	if(saplog==null)
    		saplog=NCLocator.getInstance().lookup(ISapLog.class);
    	return saplog;
    }
    
    /**
     * 创建 NC请求SAP 日志VO
     * @param pk_org 组织
     * @param billid 单据ID
     * @param billno 单据号
     * @param pk_billtypecode	单据类型
     * @param pk_transtypecode	交易类型
     * @param send_data_ns	请求报文
     * @param resultdata_ns	响应报文
     * @param msg_ns	提示信息
     * @param issuccess_ns	是否成功  Y(成功)/N(失败)
     * @param classname	执行类全名
     * @return 日志VO对象
     */
    public static SapPurchaseLogVO createNSLog(String pk_org,String billid,String billno,String pk_billtypecode,
    		String pk_transtypecode,String send_data_ns,String resultdata_ns,String msg_ns,String issuccess_ns,String classname){
    	SapPurchaseLogVO log=new SapPurchaseLogVO();
    	log.setPk_org(pk_org);
    	log.setBillid(billid);
    	log.setBillno(billno);
    	log.setPk_billtypecode(pk_billtypecode);
    	log.setPk_transtypecode(pk_transtypecode);
    	log.setSend_data_ns(send_data_ns);
    	log.setResultdata_ns(resultdata_ns);
    	log.setMsg_ns(msg_ns);
    	log.setIssuccess_ns(issuccess_ns);
    	log.setDef1(classname);
    	
    	//wby 20211017 补充日志时间
    	SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
    	log.setTs(df.format(new Date()));
    	return log;
    }
    
    /**
     * 创建 SAP请求NC 日志VO
     * @param pk_org 组织
     * @param billid 单据ID
     * @param billno 单据号
     * @param pk_billtypecode	单据类型
     * @param pk_transtypecode	交易类型
     * @param send_data_sn	请求报文
     * @param resultdata_sn	响应报文
     * @param msg_sn	提示信息
     * @param issuccess_sn	是否成功  Y(成功)/N(失败)
     * @param classname	执行类全名
     * @return 日志VO对象
     */
    public static SapPurchaseLogVO createSNLog(String pk_org,String billid,String billno,String pk_billtypecode,
    		String pk_transtypecode,String send_data_sn,String resultdata_sn,String msg_sn,String issuccess_sn,String classname){
    	SapPurchaseLogVO log=new SapPurchaseLogVO();
    	log.setPk_org(pk_org);
    	log.setBillid(billid);
    	log.setBillno(billno);
    	log.setPk_billtypecode(pk_billtypecode);
    	log.setPk_transtypecode(pk_transtypecode);
    	log.setSend_data_sn(send_data_sn);
    	log.setResultdata_sn(resultdata_sn);
    	log.setMsg_sn(msg_sn);
    	log.setIssuccess_sn(issuccess_sn);
    	log.setDef1(classname);
    	
    	//wby 20211017 补充日志时间
    	SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
    	log.setTs(df.format(new Date()));
    	return log;
    }
    
    /**
	 * @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();  
    }
	
	/**
	 * 判断组织区域是否已上SAP (由于部分单据没有日期判断重新启用此方法)
	 * @author 廖声豪 20180625
	 * @param pk_org 组织PK值
	 * @return true（已上）/false（未上）
	 * @throws BusinessException
	 */
	public static boolean isSapOrg(String pk_org) throws BusinessException{
		String sql="select count(pk_org) from org_orgs where pk_org='"+pk_org+"' and def38='Y' and enablestate=2 and isnull(dr,0)=0";
		Integer num=(Integer) getQueryBS().executeQuery(sql, new ColumnProcessor());
		return num!=null && num.intValue()>0;
	}
	
	/**
	 * 判断组织区域是否已上SAP（审批时间必须大于SAP上线时间）
	 * @author 廖声豪 20180623
	 * @param pk_org 组织PK值
	 * @param date 制单日期
	 * @return true（已上）/false（未上）
	 * @throws BusinessException
	 */
	public static boolean isSapOrg(String pk_org,String date) throws BusinessException{
		String sql="select def38,def39 from org_orgs where pk_org='"+pk_org+"' and enablestate=2 and isnull(dr,0)=0";
		HashMap<String,String> orgmap=(HashMap<String,String>) getQueryBS().executeQuery(sql, new MapProcessor());
		if(orgmap==null || orgmap.size()==0 || orgmap.get("def38")==null || orgmap.get("def39")==null)
			return false;
		if(!"Y".equals(orgmap.get("def38")))//是否已上SAP，不等于Y则未上
			return false;
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date qdate=df.parse(orgmap.get("def39"));//上线日期
			Date sdate=df.parse(date);//单据审批日期
			if(sdate.getTime()<qdate.getTime()){
				return false;
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	public static IUAPQueryBS getQueryBS(){
		if(queryBS==null)
			queryBS=NCLocator.getInstance().lookup(IUAPQueryBS.class);
		return queryBS;
	}
}
