package com.bcxin.ins.third.gzx.huatai;

import com.bcxin.ins.entity.common.LogBusinessrequest;
import com.bcxin.ins.enums.TransTypeEnum;
import com.bcxin.ins.service.order.LogBusinessrequestService;
import com.bcxin.ins.third.build.taibao.TransType;
import com.bcxin.ins.third.gzx.huatai.util.Policy_ActivityFireFight;
import com.bcxin.ins.third.gzx.huatai.util.Policy_ActivityLocal;
import com.bcxin.ins.third.gzx.huatai.util.Policy_ActivityType;
import com.bcxin.ins.third.gzx.huatai.util.Whether;
import com.bcxin.ins.entity.policy_core.InsInsuranceSlip;
import com.bcxin.ins.entity.policy_core.InsTransaction;
import com.bcxin.ins.util.*;
import com.bcxin.ins.util.MD5Util;
import com.bcxin.ins.vo.*;
import com.bcxin.ins.vo.ConstProp;
import com.google.common.collect.Lists;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
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 javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

/**
 * @author liyongqiang 华泰保险项目
 *
 */
@Service
@Transactional
public class HtPolicyService {

	private Logger log =  LoggerFactory.getLogger(HtPolicyService.class);
	@Autowired
	private LogBusinessrequestService logBusinessrequestService;

	/**
	 * 
	 * <b>Function </b> 组装保单信息
	 * 
	 * @param policy
	 * @param policyExtra
	 * @return
	 * @throws UnsupportedEncodingException
	 * @author LuoPeng
	 * @date 2017年1月4日 下午9:05:41
	 * @注意事项 </b>
	 * <b>
	 */
	private String assemblePolicy(InsInsuranceSlip policy, SpecialPublicDutyVo policyExtra,InsTransaction transaction)
			throws UnsupportedEncodingException {

		JSONObject json = new JSONObject();
		// 渠道信息
		JSONObject channelObject = new JSONObject();

		channelObject.put("bizCode", "101");// 交易类型 101：投保请求
		channelObject.put("channelCode", GlobalResources.HT_CHANNELCODE);// 渠道编码 由华泰分配的商户编码
		channelObject.put("channelName", "百川信（厦门）网络信息服务有限公司");// 商户名称
		// //投保日期
		Date d= new Date();
		channelObject.put("createTime", DateUtil.convertDateToString(d, DateUtil.FORMAT1));// 投保时间
		// 渠道年月日时分秒随机8位数
		channelObject.put("orderId", policy.getTrade_serial_number());// 第三方订单编号
		
		// 险种信息
		JSONObject insuranceObject = new JSONObject();
		insuranceObject.put("insuranceCode", "2502");// 险种代码
		insuranceObject.put("insuranceName", "公众责任险");// 产品名称
		insuranceObject.put("amount", convertAmount(policyExtra.getInsured_amount())/*+"0000"*/);// 保费
		insuranceObject.put("plan", "A");// 款别 默认值：A
		insuranceObject.put("prmCur", "01");// 保费币种 枚举
		insuranceObject.put("premium", confirmPayEnvi(policy.getPremium()));//保费
		insuranceObject.put("amtCur", "01");// 保额币种
		insuranceObject.put("copy", "1");// 份数
		insuranceObject.put("effectiveTime", DateUtil.convertDateToString(policy.getInception_date(), DateUtil.FORMAT1));//保险起期
		insuranceObject.put("terminalTime", ""+DateUtil.dateFormatLast(DateUtil.convertDateToString(policy.getPlanned_end_date(), DateUtil.FORMAT1)));//保险止期

		BigDecimal  baofei = new BigDecimal(policy.getPremium().toString());
		BigDecimal  baoe = new BigDecimal( convertAmount(policyExtra.getInsured_amount())/*+"0000"*/);

		insuranceObject.put("rate", baofei.multiply(new BigDecimal("1000")).divide(baoe,4,RoundingMode.HALF_UP).toString());//费率    保费除以保额

		// 投保人信息
		RoleSubjectVo   rpApplicant=policyExtra.getRoleSubjectList().get(0);
		JSONObject appntObject = new JSONObject();
		if( "7".equals(rpApplicant.getId_type())){//BUSINESSLICENSE
			appntObject.put("appIDType", "96");// 投保人证件类型96-营业执照
		} else if("8".equals(rpApplicant.getId_type())){//TAXREGISTRATIONCERTIFICATE
			appntObject.put("appIDType", "97");// 投保人证件类型97-税务登记证
		} else if("9".equals(rpApplicant.getId_type())){//ORGANIZATIONCODECERTIFICATE
			appntObject.put("appIDType", "06");// 投保人证件类型06-组织机构代码证
		}
		appntObject.put("appName", rpApplicant.getName_cn());//	投保人姓名
		appntObject.put("appNumber",rpApplicant.getOrganization_code());// 投保人证件号
		appntObject.put("appType", "2");// 投保人类型 枚举 1：个人 2：团体
		appntObject.put("appAddr", RegionUtils.getRegionNameByALLCode(rpApplicant.getReg_province(),rpApplicant.getReg_city(),rpApplicant.getReg_district())+rpApplicant.getReg_address());// 投保人地址
		
		if(policy.getMailPolicy()!=null&& Constant.POLICY_NEED_RECEIPT.equals(policy.getMailPolicy().getNeed_receipt())){
			//增值税
			//need_receipt
					//invoice_type
			if(Constant.POLICY_INVOICE_TYPE_TWO.equals(policy.getMailPolicy().getInvoice_type())){
				appntObject.put("isTaxInvoice", "1");// z
				appntObject.put("appTelNumber", policy.getMailPolicy().getReceipt_phone());// 投保人电话号
				appntObject.put("appContact", "联系人名字");// 投保人联系人 N
				appntObject.put("taxCertifi", "税务登记证号");// 税务登记证号
				appntObject.put("depositBank", "开户银行");// 开户银行
				appntObject.put("bankAccount", "银行账户");// 银行账户
			}

		}else{
			appntObject.put("isTaxInvoice", "0");// z
		}
		
		// 被保人信息
		//获取被保人

		RoleSubjectVo rpInsured=policyExtra.getRoleSubjectList().get(1);
		JSONArray insuredObjectArray = new JSONArray();
		JSONObject insuredObject = new JSONObject();
		if("7".equals(rpInsured.getId_type())){
			insuredObject.put("insuredIDType", "96");// 被保人证件类型96-营业执照
		}else if("8".equals(rpInsured.getId_type())){
			insuredObject.put("insuredIDType", "97");// 被保人证件类型97-税务登记证
		}else if("9".equals(rpInsured.getId_type())){
			insuredObject.put("insuredIDType", "06");// 被保人证件类型06-组织机构代码证
		}
		insuredObject.put("insuredName",rpInsured.getName_cn());// 被保人姓名
		insuredObject.put("insuredNumber", rpInsured.getOrganization_code());// 被保人证件号
		insuredObject.put("insuredTelNumber",rpInsured.getLink_phone());//被保人电话号
		insuredObject.put("insuredType", "2");// 被保人类型 1：个人 2：团体
		insuredObject.put("isLegal", "1");// 是否是法定受益人
		insuredObject.put("insuredAddress", RegionUtils.getRegionNameByALLCode(rpInsured.getReg_province(),rpInsured.getReg_city(),rpInsured.getReg_district())+rpInsured.getReg_address());
		insuredObjectArray.add(insuredObject);

		// 自定义责任信息[集合]
		JSONObject definedSafeObj = new JSONObject();
		definedSafeObj.put("isDefinedSafe", "1");// 是否自定义责任 0：否 默认1：是
		JSONArray rdrDTOs = new JSONArray();
		JSONObject rdrDTO1 = new JSONObject();
		rdrDTO1.put("itemId", 1);
		rdrDTO1.put("rdrAmount",convertAmount(policyExtra.getInsured_amount())/*+"0000.0"*/);
		rdrDTO1.put("rdrCode", "01");
		rdrDTO1.put("rdrName", "公众责任险");
		rdrDTO1.put("rdrPremium", policy.getPremium().toString());
		rdrDTO1.put("rdrDeductible", ""); 
		rdrDTO1.put("rdrRemark", "");
		JSONObject rdrDTO2 = new JSONObject();
		rdrDTO2.put("itemId", 2);
		rdrDTO2.put("rdrAmount", "0");
		rdrDTO2.put("rdrCode", "02");
		rdrDTO2.put("rdrName", "交叉责任条款");
		rdrDTO2.put("rdrPremium", "0");
		rdrDTO2.put("rdrDeductible", ""); 
		rdrDTO2.put("rdrRemark", "");
		JSONObject rdrDTO3 = new JSONObject();
		rdrDTO3.put("itemId", 3);
		rdrDTO3.put("rdrAmount", "0");
		rdrDTO3.put("rdrCode", "03");
		rdrDTO3.put("rdrName", "罢工、暴乱、民众骚动及恶意破坏条款");
		rdrDTO3.put("rdrPremium", "0");
		rdrDTO3.put("rdrDeductible", ""); 
		rdrDTO3.put("rdrRemark", "");
		JSONObject rdrDTO4 = new JSONObject();
		rdrDTO4.put("itemId", 4);
		rdrDTO4.put("rdrAmount", "0");
		rdrDTO4.put("rdrCode", "04");
		rdrDTO4.put("rdrName", "火灾和爆炸责任条款");
		rdrDTO4.put("rdrPremium", "0");
		rdrDTO4.put("rdrDeductible", ""); 
		rdrDTO4.put("rdrRemark", "");
		JSONObject rdrDTO5 = new JSONObject();
		rdrDTO5.put("itemId", 5);
		rdrDTO5.put("rdrAmount", "0");
		rdrDTO5.put("rdrCode", "05");
		rdrDTO5.put("rdrName", "急救费用条款");
		rdrDTO5.put("rdrPremium", "0");
		rdrDTO5.put("rdrDeductible", ""); 
		rdrDTO5.put("rdrRemark", "");
		JSONObject rdrDTO6 = new JSONObject();
		rdrDTO6.put("itemId", 6);
		rdrDTO6.put("rdrAmount", "0");
		rdrDTO6.put("rdrCode", "06");
		rdrDTO6.put("rdrName", "广告招牌及装饰物责任条款");
		rdrDTO6.put("rdrPremium", "0");
		rdrDTO6.put("rdrDeductible", ""); 
		rdrDTO6.put("rdrRemark", "");
		
		rdrDTOs.add(rdrDTO1);
		rdrDTOs.add(rdrDTO2);
		rdrDTOs.add(rdrDTO3);
		rdrDTOs.add(rdrDTO4);
		rdrDTOs.add(rdrDTO5);
		rdrDTOs.add(rdrDTO6);
		definedSafeObj.put("rdrDTOs", rdrDTOs.toString());
		// 支付信息
		JSONObject payObject = new JSONObject();
		payObject.put("isSinglePay", "1");// 是否逐单支付
		payObject.put("payMode", "23");//支付类型
		payObject.put("payDate", DateUtil.convertDateToString(d, DateUtil.FORMAT1));//支付时间
		payObject.put("payBankNo", transaction.getPay_order_number());//支付流水号
		// 约定信息
		JSONObject agreementObject = new JSONObject();
		agreementObject.put("policyDeductible", "财产损失500元，人身伤害无免赔");// 保单免赔信息
		// agreementObject.put("policySpec", "特别约定");
		// 产品差异字段
		JSONObject productDiffObject = new JSONObject();
		String localAddress=policyExtra.getReport_local();
		if( localAddress.endsWith(com.bcxin.ins.vo.ConstProp.POUND_SIGN)){
			localAddress=localAddress.substring(0, localAddress.length()-1);
		}
		productDiffObject.put("activityArea",localAddress);//承保区域
		productDiffObject.put("activityName",policyExtra.getReport_name());//活动名称
		Policy_ActivityType  activityType=Policy_ActivityType.convert_value(policyExtra.getReport_active());
		productDiffObject.put("activityType",activityType.getName());//活动类型
		productDiffObject.put("activityTime",policyExtra.getReport_begin_date()+ ConstProp.MINUS+ policyExtra.getReport_end_date());//活动时间
		Policy_ActivityLocal  activityLocal=Policy_ActivityLocal.convert_name(policyExtra.getActivity_local());
		productDiffObject.put("activityPlace",activityLocal.getName());//活动地点
		Policy_ActivityFireFight activityFireFight=Policy_ActivityFireFight.convert_name(policyExtra.getActivity_fire_fight());
		productDiffObject.put("activityFireFight",activityFireFight.getName());////活动场所消防情况
		Whether whether = Whether.convert_name(policyExtra.getDanger());
		productDiffObject.put("isActivityDanger",whether.getName());//有无危险环节
		productDiffObject.put("activityAttendSum",policyExtra.getPeople_num());//预计参加人数
		productDiffObject.put("accidentRdrAmount",convertAmount(policyExtra.getInsured_amount())/*+"0000"*/);//每次事故责任限额
		productDiffObject.put("injuryRdrAmount","250000");//每人人身伤亡责任限额
		productDiffObject.put("businessNature",rpInsured.getCom_type());//被保险人营业性质
		String disputeString = policyExtra.getDispute();
		if ( "0".equals(disputeString) ) {
			productDiffObject.put("disputeHandling","02");
			productDiffObject.put("arbitrationOrg","");
		} else {
			productDiffObject.put("disputeHandling","01");
			productDiffObject.put("arbitrationOrg",policyExtra.getPolicy_extra_dispute());
		}
		
		productDiffObject.put("reMark", "本保单不负责赔偿由于第三者自身原因（包括但不限于自身疾病、自身运动损伤、自身体质等）导致的人身伤亡或财产损失事故 , 被保险人所承担的经济赔偿责任,参与文艺演出、体育赛事的演员、运动员不在本保单承保范围内,用于展出的展品遭受的任何损失，不在本保单承保范围内");
		
		json.put("agreementObject", agreementObject);
		json.put("appntObject", appntObject);
		json.put("channelObject", channelObject);
		json.put("definedSafeObj", definedSafeObj);
		json.put("insuranceObject", insuranceObject);
		json.put("insuredObject", insuredObjectArray);
		json.put("payObject", payObject);
		json.put("productDiffObject", productDiffObject);

		System.out.println("华泰投保请求报文："+json.toString());

		return json.toString();

	}

	/**
	 * 投保请求，请求服务中心
	 * @throws Exception
	 */
	public String insureInvoke(InsInsuranceSlip policy, SpecialPublicDutyVo policyExtra,InsTransaction transaction) throws Exception {
		String insureJson = assemblePolicy(policy,policyExtra,transaction);
		log.info("HtPolicyService华泰请求报文:"+insureJson);
		insureJson = insureJson.replaceAll("%","%25").replaceAll("&","%26").replaceAll("\\+","%2B");
		log.info("HtPolicyService华泰请求报文（过滤）:"+insureJson);
		String result = "";
		List<NameValuePair> params = Lists.newArrayList();
		params.add(new BasicNameValuePair("insureJson", insureJson));
		params.add(new BasicNameValuePair("channel", GlobalResources.HT_CHANNELCODE));
		params.add(new BasicNameValuePair("transSign", MD5Util.string2MD5( GlobalResources.HT_CHANNELCODE+DateUtil.getCurrentDate()) ));
		String url = GlobalResources.P_SERVICES_URL+"/ht/policy/insure";
		result = HttpUtil.sendPostRequest(url, params);
		Date bTime = new Date();
		LogBusinessrequest lb = logBusinessrequestService.initLogBusinessrequest(String.valueOf(policy.getTrade_serial_number()),ConstProp.DIGIT_FIVE,url,insureJson,result,bTime,new Date(), TransTypeEnum.getAlias(ConstProp.DIGIT_FIVE));
		logBusinessrequestService.supplementDecAndSave(lb,result.contains("policyNO")?1:0,ConstProp.BLANK_CHAR);
		return result;
	}

	
	/**
	 * 产品支付
	 * @param applicant 
	 * @return
	 * @throws Exception
	 */
	public String htPay(HttpServletResponse res, InsInsuranceSlip policy, RoleSubjectVo applicant) { // 投保用例
		List<NameValuePair> params = Lists.newArrayList();
		params.add(new BasicNameValuePair("premium", confirmPayEnvi(policy.getPremium())));
		params.add(new BasicNameValuePair("orderNo", policy.getTrade_serial_number()));
		params.add(new BasicNameValuePair("phone", applicant.getPhone()));
		params.add(new BasicNameValuePair("thirdType", "03"));
		params.add(new BasicNameValuePair("tradeName", "公共责任险"));
//		params.add(new BasicNameValuePair("tradeTime", "2017-06-15"));
		params.add(new BasicNameValuePair("tradeTime", DateUtil.convertDateToString(policy.getSigned_date(),DateUtil.FORMAT1)));
//		params.add(new BasicNameValuePair("tradeTime", "2017-06-15"));
		params.add(new BasicNameValuePair("tradeType", "08"));
		params.add(new BasicNameValuePair("channel",  GlobalResources.HT_CHANNELCODE));
		params.add(new BasicNameValuePair("callbackUrl", GlobalResources.WEB_PRO_URL + "/api/afr/pay/ht/callback/back"));
		params.add(new BasicNameValuePair("callfrontUrl", GlobalResources.WEB_PRO_URL + "/api/afr/pay/ht/callback/front"));
		try {
			String result = HttpUtil.sendPostRequest(GlobalResources.P_SERVICES_URL+"/ht/policy/pay", params);
			return result;
		} catch (Exception e){
			e.printStackTrace();
		}
		return "";
	}
	

	
	/**
	 * 确认支付环境，如果为测试环境，则支付金额为0.01元
	 * @param premium
	 * @return
	 */
	private static String confirmPayEnvi(BigDecimal premium){
		if ( GlobalResources.IS_TEST_ENVI ) {
			return "0.01";
		} else {
			return premium.toString();
		}
	}

	private  static  String   convertAmount(String num){
		//带小数点的字符串 装 成int

		double  d=Double.parseDouble(num);
		int  a=(int)d;
		return  a+"";
	}
}