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

import com.bcxin.ins.entity.common.LogBusinessrequest;
import com.bcxin.ins.service.common.ComAreaCodeAPIService;
import com.bcxin.ins.service.order.LogBusinessrequestService;
import com.bcxin.ins.service.order.PolicyService;
import com.bcxin.ins.service.product.InsProductRuleXWCKAPIService;
import com.bcxin.ins.third.build.taibao.TransType;
import com.bcxin.ins.entity.common.ComAreaCode;
import com.bcxin.ins.entity.common.ComRegion;
import com.bcxin.ins.util.DateUtil;
import com.bcxin.ins.util.GlobalResources;
import com.bcxin.ins.util.RegionUtils;
import com.bcxin.ins.util.XMLUtil;
import com.bcxin.ins.vo.*;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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;
import java.util.Map;


/**
 * <b> 太保-信用险http接口请求业务 </b>
 * @author ZXF
 * @create 2018/01/30 0030 10:31
 * @version 
 * @注意事项 </b>
 */
@Service("xYX_TBRequestService")
@Transactional
public class XYX_TBRequestService {

	private Logger communicatorLog =  LoggerFactory.getLogger(XYX_TBRequestService.class);

	@Autowired
	private PolicyService policyService;
	@Autowired
	private LogBusinessrequestService logBusinessrequestService;
	@Autowired
	private ComAreaCodeAPIService comAreaCodeAPIService;
	@Autowired
	private InsProductRuleXWCKAPIService insProductRuleXWCKAPIService;

	// 版本标识，固定值 3
	private static final String MESSAGEROUTER = "3";
	// 合作伙伴编码，由太保指定，每个商户不一样
	private static final String PARTNERCODE = "XMBCX";
	// 业务协议，固定值 CPIC_ECOM
	private static final String DOCUMENTPROTOCOL = "CPIC_ECOM";


	/**
	 * 太保请求方法
	 * 
	 * @return
	 */
	public String requestTB(Long order_id, String transType, Map<String,String> map) throws Exception {
		communicatorLog.info("requestTB-XYX：star-----------------------");
		communicatorLog.info("requestTB-XYX：接口编码-"+transType+",订单id-"+order_id+",MAP-"+(map != null ? map.toString() : "null"));
		OrderFormVo dto = policyService.accordingToOrderIDToGetPolicyDto(order_id);
		MicroExportVo vo = policyService.accordingToOrderIDToGetMicroExportVo(order_id);
		String result = "300#（APP-XWCK-001）网络不稳定，请重新请求！";
		LogBusinessrequest lb = null;
		try {
			String xml = ConstProp.BLANK_CHAR;
			//核保报文组装
			if ( TransType.EPIC_INS_XW.getValue().equals(transType) ){
				final String _init = ConstProp.BLANK_CHAR;
				//TODO 市级代码
				String cityCode = vo.getRoleSubjectList().get(0).getReg_city();
				//TODO 省级代码
				String provinceCode = vo.getRoleSubjectList().get(0).getReg_province();
				RuleXWCKVo ruleXWCKVo = insProductRuleXWCKAPIService.getRuleXWCKVoByProductIDAndCity(dto.getProduct_oid(), cityCode);
				ComRegion regionCity = RegionUtils.getComRegionByCode(cityCode);
				//先匹配市级
				String val1_ = regionCity.getNamed().substring(0, regionCity.getNamed().length()-1);
				List<ComAreaCode> tbsList = comAreaCodeAPIService.findComAreaCodeByCode(_init,_init,val1_);
				ComAreaCode tb = null;
				if(tbsList.size()>0){
					tb = tbsList.get(0);
				}
				String tb_code = getTBRegionCode(_init, provinceCode, tb);
				xml = XYX_PackageMessageTaiBao.marshal(vo, dto, ruleXWCKVo, tb_code, transType);
			} else if ( TransType.EPIC_YX_XW.getValue().equals(transType) ){//承保接口
				xml = XYX_PackageMessageTaiBao.marshal(vo, dto, null, "", transType);
			} else if ( TransType.EPIC_CB_XW.getValue().equals(transType) ){//承保接口
				xml = XYX_PackageMessageTaiBao.marshal(vo, dto, null, "", transType);
			} else if ( TransType.EPIC_DZBD_XW.getValue().equals(transType) ){//电子保单下载接口
				xml = XYX_PackageMessageTaiBao.marshal(vo, dto, null, "", transType);
			}
			communicatorLog.info(DateUtil.convertDateToString(new Date(),DateUtil.FORMAT1)+"请求报文：");
			communicatorLog.info(XMLUtil.formatXML(xml));
			Date bTime = new Date();
			String returnXML = ConstProp.BLANK_CHAR;
			for(int i=0;i<3;i++){
				returnXML = syncTB(xml);
				if(StringUtils.isNotEmpty(returnXML)){
					break;
				}
			}
			lb = logBusinessrequestService.initLogBusinessrequest(String.valueOf(order_id),transType,GlobalResources.map.get("CPIC_XYX_INS_URL"),xml,returnXML,bTime,new Date(), TransType.getAlias(transType));
			communicatorLog.info(DateUtil.convertDateToString(new Date(),DateUtil.FORMAT1)+"返回报文：");
			communicatorLog.info(XMLUtil.formatXML(returnXML));
			if(StringUtils.isNotEmpty(returnXML)){
				result = XYX_PackageMessageTaiBao.returnAnalysisXML(returnXML,transType);
			}else{
				result = "300#网络不稳定或数据丢失！";
			}
			communicatorLog.info("返回报文处理："+result);
			logBusinessrequestService.supplementDecAndSave(lb,result.startsWith(ConstProp.CODE_FAILURE)?1:0,ConstProp.BLANK_CHAR);
		}catch (Exception ex){
			logBusinessrequestService.supplementDecAndSave(lb,2,ex.getMessage());
			ex.printStackTrace();
		}
		communicatorLog.info("requestTB-XYX：end-----------------------");
		return result;
	}

	/**
	 * <b> 区域编码转换 </b>
	 * @author ZXF
	 * @create 2020/09/29 0029 17:45
	 * @version
	 * @注意事项 </b>
	 */
	private String getTBRegionCode(String _init, String provinceCode, ComAreaCode tb) {
		//如果市级未匹配到就匹配省级
		if(tb == null){
            ComRegion regionPro = RegionUtils.getComRegionByCode(provinceCode);
            String val2_ = regionPro.getNamed().substring(0, regionPro.getNamed().length()-1);
            List<ComAreaCode> tbpList = comAreaCodeAPIService.findComAreaCodeByCode(_init,_init,val2_);
            if(tbpList.size()>0){
                tb = tbpList.get(0);
            }
        }
		return tb.getCodes();
	}

	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);*/
			String url = String.valueOf(GlobalResources.map.get("CPIC_XYX_INS_URL"));
			communicatorLog.info("request url:"+url);//https://test.cpic.com.cn/jttpitx/itxsvc/param
			HttpPost post = new HttpPost(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());
		String fileUrl = "";
		if(System.getProperty("os.name").contains("indows")){
			fileUrl = "F:\\D_pan\\test\\upload\\cpic_jttp.keystore";
		}else{
			fileUrl = "/data/upload/blb/cpic/cpic_jttp.keystore";
		}
		try (FileInputStream instream = new FileInputStream(new File(fileUrl))) {
			trustStore.load(instream, "cpicJttp".toCharArray());
			System.out.println("instream:"+instream);
		}
		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);
	}
}
