package com.bcxin.ins.third.build.taibao;

import com.bcxin.ins.util.DateUtil;
import com.bcxin.ins.util.GlobalResources;
import com.bcxin.ins.util.XMLUtil;
import com.bcxin.ins.vo.ConstProp;
import com.bcxin.ins.vo.OrderFormVo;
import com.bcxin.ins.vo.SpecialBidVo;
import com.bcxin.mybatisplus.toolkit.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author zxf
 * @desciption
 */
public class Communicator {

	private MarshalFactory marshalFactory = new MarshalFactoryImpl();
	
	private Logger communicatorLog =  LoggerFactory.getLogger("commuLog");
	
	private SimplePathResultXMLProcesser xmlProcesser = new SimplePathResultXMLProcesser();
	
	// 版本标识，固定值 3
	private static final String MESSAGEROUTER = "3";
	// 合作伙伴编码，由太保指定，每个商户不一样
	private static final String PARTNERCODE = "XMBCX";
	// 业务协议，固定值 CPIC_ECOM
	private static final String DOCUMENTPROTOCOL = "CPIC_ECOM";
	
	
	public String sendAndReturn(String tsNumber, SpecialBidVo policy,OrderFormVo dto,String tb_code, CommunicateType communicateType,String paymentType, TransType transType, String sign) {
		Marshaller marshaller = marshalFactory.getMarshaller(communicateType);
		try {
			String returnXML = "";
			String xml = marshaller.marshal(tsNumber,policy,dto,tb_code,paymentType,transType);
			communicatorLog.info(DateUtil.convertDateToString(new Date(),DateUtil.FORMAT1)+"请求报文：");
			communicatorLog.info(XMLUtil.formatXML(xml));
			if ( !CommunicateType.TAIBAO.equals(communicateType)) {
				return "300#产品与请求接口不匹配！";
			}
			for(int i=0;i<3;i++){
				returnXML = syncTB(xml);
				if(StringUtils.isNotEmpty(returnXML)){
					break;
				}
			}
			communicatorLog.info(DateUtil.convertDateToString(new Date(),DateUtil.FORMAT1)+"返回报文：");
			if(StringUtils.isEmpty(returnXML)){
				return "300#网络不稳定或数据丢失！";
			}
			if ( !xmlProcesser.isTBSuccess(returnXML) ) {
				return "300#"+xmlProcesser.isTBFailMessage(returnXML);
			}
			if ( TransType.EPIC_INS.equals(transType) ){
				communicatorLog.info(XMLUtil.formatXML(returnXML));
				return "200#"+xmlProcesser.getTBPolicyNumber(returnXML);
			} else if ( TransType.EPIC_QUERY.equals(transType) ){
				communicatorLog.info(XMLUtil.formatXML(returnXML));
				return "200#"+xmlProcesser.getTBPolicyEx(returnXML);
			} else if ( TransType.EPIC_EPOLICY.equals(transType) ){
				communicatorLog.info("107003业务，文件流过大，在此省略...");
				if("1".equals(sign)){
					communicatorLog.info("107003业务，电子保单");
					return "200#"+xmlProcesser.getTBPolicyPDF(returnXML,dto.getExternal_reference(),sign);
				}else {
					communicatorLog.info("107003业务，电子保函");
					return "200#"+xmlProcesser.getTBPolicyPDF(returnXML,dto.getExternal_reference(),sign);
				}
			}
			return "300#产品与请求接口不匹配！";
		} catch (Exception e) {
			communicatorLog.info(e.getMessage());
			return "300#请求异常："+e.getMessage();
		}
	}


	private String syncTB(String requestMeg){
		String result = ConstProp.BLANK_CHAR;
		try {
	        List<NameValuePair> params = new ArrayList<NameValuePair>();
	        // 版本标识
			params.add(new BasicNameValuePair("messageRouter", MESSAGEROUTER));
			// 业务伙伴代码
			params.add(new BasicNameValuePair("tradingPartner", PARTNERCODE));
			// 业务协议
			params.add(new BasicNameValuePair("documentProtocol", DOCUMENTPROTOCOL));
			// xml请求报文
			params.add(new BasicNameValuePair("requestMessage", requestMeg));
	        
	        HttpClient client = new DefaultHttpClient();
			registerSSLSocketFactory(client);
	        // 注意：必须以post方式发送请求
	        communicatorLog.info("request url:"+ GlobalResources.CPIC_INS_URL);
			HttpPost post = new HttpPost(GlobalResources.CPIC_INS_URL);
			post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
			HttpResponse response = client.execute(post);
			HttpEntity entity = response.getEntity();
			result = EntityUtils.toString(entity);
			
		} catch(Exception e) {
			communicatorLog.info(e.getMessage());
			e.printStackTrace();
		}
        return result;
	}
	
	private void registerSSLSocketFactory(HttpClient httpclient) throws Exception {
		KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());   
		GlobalResources res = new GlobalResources();
		FileInputStream instream = null;
		/*HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();

		String fileUrl = request.getSession().getServletContext().getRealPath("/WEB-INF/cpic_jttp.keystore");
		instream = new FileInputStream(new File(fileUrl));*/
        HttpServletRequest request = null;
        if(RequestContextHolder.getRequestAttributes() != null){
            request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        }
        String fileUrl = "";
        if(request != null){
            fileUrl = request.getSession().getServletContext().getRealPath("/WEB-INF/cpic_jttp.keystore");
            instream = new FileInputStream(new File(fileUrl));
        }
		/*if ( res.IS_WINDOWS_ENVI ) {
		} else {
			instream = new FileInputStream(new File(res.CPIC_KEY_STORE)); 
		}*/
        try {
            trustStore.load(instream, "cpicJttp".toCharArray());
        } finally {
            instream.close();
        }
        SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
        Scheme sch = new Scheme("https", socketFactory, 443);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);

	}
	

	/**
     * md5加密专用于接口签名
     * 因为需要显式将报文转换成UTF-8编码
     * @param plainText
     * @return
     * @throws NoSuchAlgorithmException 
     * @throws UnsupportedEncodingException 
     */
     public static String toMD5(String plainText) throws Exception{
            MessageDigest md = MessageDigest.getInstance("MD5");  
            md.update(plainText.getBytes("UTF-8"));
            byte b[] = md.digest();  
            
            int i;  
 
            StringBuffer buf = new StringBuffer(ConstProp.BLANK_CHAR);  
            for (int offset = 0; offset < b.length; offset++) {  
                i = b[offset];  
                if (i < 0)  
                    i += 256;  
                if (i < 16)  
                    buf.append("0");  
                buf.append(Integer.toHexString(i));  
            }  
            //32位加密  
            return buf.toString();  
            // 16位的加密  
            //return buf.toString().substring(8, 24);  
     }
}
