package com.bcxin.ins.coninsweb.order.controller.api.gzzrx.taibao;

import com.alibaba.fastjson.JSON;
import com.bcxin.ins.core.base.web.BaseController;
import com.bcxin.ins.entity.policy_core.InsPreservationRecord;
import com.bcxin.ins.enums.TransTypeEnum;
import com.bcxin.ins.service.order.InsTransactionAPIService;
import com.bcxin.ins.service.order.PolicyService;
import com.bcxin.ins.service.preservation.InsPreservationRecordAPIService;
import com.bcxin.ins.spring.util.JedisUtils;
import com.bcxin.ins.third.gzzrx.taibao.GZZRX_TBRequestService;
import com.bcxin.ins.vo.*;
import com.bcxin.mybatisplus.toolkit.StringUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

/**
 * <b> 前海雇主责任险接口Controller控制器，用于回调 </b>
 * @author ZXF
 * @create 2023/02/08 0008 11:27
 * @version
 * @注意事项 </b>
 */
@Controller
public class GZZRX_TB_API_Controller extends BaseController {


	@Autowired
	private InsTransactionAPIService insTransactionAPIService;
	@Autowired
	private PolicyService policyService;
	@Autowired
	private GZZRX_TBRequestService gZZRX_TBRequestService;
	@Autowired
	private InsPreservationRecordAPIService insPreservationRecordAPIService;

	/**
	 * 保单接口回调
	 * @param json 请求报文
	 */
	@RequestMapping(value = "/TB-API/GZZRX/callback-policy")
	public void callbackPolicy(@RequestBody String json) throws UnsupportedEncodingException {
		if(json.contains("%3C%")){
			json = URLDecoder.decode(json, ConstProp.ENCODE_UTF8);
		}
		logger.info("保单生效接口回调-callback-policy-TB-GZZRX：请求报文-"+json);
		Map<String,String> map  = JSON.parseObject(json,Map.class);
		String efficientDate = map.get("efficientDate");
		String terminationDate = map.get("terminationDate");
		String policyApplyNo = map.get("policyApplyNo");
		String paymentTime = map.get("paymentTime");
		String policyNo = map.get("policyNo");
		String signMsg = map.get("signMsg");
		String epolicyUrl = map.get("epolicyUrl");
		// 防重复提交处理：使用policyNo作为唯一标识，防止短时间内重复处理同一回调
		if (StringUtils.isNotEmpty(policyNo)) {
			String redisKey = "GZZRX_TB_CALLBACK_POLICY_" + policyNo;
			String redisValue = JedisUtils.get(redisKey);
			if (StringUtils.isNotEmpty(redisValue)) {
				logger.info("保单支付接口回调-callback-policy-TB-GZZRX：重复提交请求，policyNo={}", policyNo);
				renderString(response, returnRet("500","请求频繁，驳回本次操作"), ConstProp.CT_JSON);
				logger.info("保单生效接口回调-callback-policy-TB-GZZRX：业务结束：end");
				return;
			} else {
				// 设置10秒过期时间，防止重复处理
				JedisUtils.set(redisKey, "1", 10);
			}
		}
		String signMsgNow = DigestUtils.md5Hex(efficientDate + terminationDate + policyApplyNo + paymentTime + policyNo + "P_CPIC");
		if(!signMsgNow.equals(signMsg)){
			renderString(response, returnRet("500","报文验签失败"), ConstProp.CT_JSON);
			logger.info("保单生效接口回调-callback-policy-TB-GZZRX：业务结束：end");
			return;
		}
		OrderFormVo orderVo = policyService.getPolicyDtoByRcptNo(policyApplyNo);
		if(orderVo == null){
			renderString(response, returnRet("500","订单不存在"), ConstProp.CT_JSON);
			logger.info("保单生效接口回调-callback-policy-TB-GZZRX：业务结束：end");
			return;
		}
		if(StringUtils.isEmpty(orderVo.getExternal_reference())){
			PolicyTransactionVo vo= new PolicyTransactionVo();
			//保存保单号
			vo.setPolicy_number(policyNo);//policy.setExternalReference();
			vo.setPolicy_id(orderVo.getOid());
			insTransactionAPIService.savePolicyExternalReference(vo);
			if(StringUtils.isNotEmpty(epolicyUrl)){
				//保存保单地址
				vo.setInsure_path(epolicyUrl);//保单地址
				insTransactionAPIService.savePolicyOther(vo);
			}
			new Thread(()->{ //异步
				try {
					//返回订单给指定平台
					policyService.returnsAnOrderToTheSpecifiedPlatform(orderVo.getOid());
				} catch(Exception e) {
					logger.error("------------雇主责任险推送百保盾，异常："+e.getMessage());
				}
			}).start();
		}
		renderString(response, returnRet("200","成功"), ConstProp.CT_JSON);
		logger.info("保单生效接口回调-callback-policy-TB-GZZRX：业务结束：end");
	}

	/**
	 * 保单增员支付接口回调
	 * @param json 请求报文
	 */
	@RequestMapping(value = "/TB-API/GZZRX/callback-record")
	public void callbackRecord(@RequestBody String json) throws UnsupportedEncodingException {
		if(json.contains("%3C%")){
			json = URLDecoder.decode(json, ConstProp.ENCODE_UTF8);
		}
		logger.info("保单生效接口回调-callback-record-TB-GZZRX：请求报文-"+json);
		Map<String,Object> map  = JSON.parseObject(json,Map.class);
		String efficientDate = map.get("efficientDate") != null ? map.get("efficientDate").toString() : "";
		String resultCode = map.get("resultCode") != null ? map.get("resultCode").toString() : "";
		String terminationDate = map.get("terminationDate") != null ? map.get("terminationDate").toString() : "";
		String policyApplyNo = map.get("policyApplyNo") != null ? map.get("policyApplyNo").toString() : "";
		String endorsementRequestNo = map.get("endorsementRequestNo") != null ? map.get("endorsementRequestNo").toString() : "";//批单申请号
		String endorsementNo = map.get("endorsementNo") != null ? map.get("endorsementNo").toString() : "";//批单号
		String paymentTime = map.get("paymentTime") != null ? map.get("paymentTime").toString() : "";
		String policyNo = map.get("policyNo") != null ? map.get("policyNo").toString() : "";
		String signMsg = map.get("signMsg") != null ? map.get("signMsg").toString() : "";
		String epolicyUrl = map.get("epolicyUrl") != null ? map.get("epolicyUrl").toString() : "";
		String signMsgNow = DigestUtils.md5Hex(efficientDate + terminationDate + policyApplyNo + paymentTime + policyNo + "P_CPIC");

		// 防重复提交处理：使用endorsementNo作为唯一标识，防止短时间内重复处理同一回调
		if (StringUtils.isNotEmpty(endorsementNo)) {
			String redisKey = "GZZRX_TB_CALLBACK_RECORD_" + endorsementNo;
			String redisValue = JedisUtils.get(redisKey);
			if (StringUtils.isNotEmpty(redisValue)) {
				logger.info("保单增员支付接口回调-callback-record-TB-GZZRX：重复提交请求，endorsementNo={}", endorsementNo);
				renderString(response, returnRet("500","请求频繁，驳回本次操作"), ConstProp.CT_JSON);
				logger.info("保单生效接口回调-callback-record-TB-GZZRX：业务结束：end");
				return;
			} else {
				// 设置10秒过期时间，防止重复处理
				JedisUtils.set(redisKey, "1", 10);
			}
		}

		if(!signMsgNow.equals(signMsg)){
			renderString(response, returnRet("500","报文验签失败"), ConstProp.CT_JSON);
			logger.info("保单生效接口回调-callback-record-TB-GZZRX：业务结束：end");
			return;
		}
		String result = insPreservationRecordAPIService.updateHTRecordStatus(endorsementRequestNo,endorsementNo,epolicyUrl,resultCode.equals("1")?"01":"00",resultCode.equals("1")?"承保成功":"承保失败");
		if(StringUtils.isNotEmpty(result)){
			renderString(response, returnRet("500",result), ConstProp.CT_JSON);
			logger.info("保单生效接口回调-callback-record-TB-GZZRX：业务结束：end");
			return;
		}
		renderString(response, returnRet("200","成功"), ConstProp.CT_JSON);
		logger.info("保单生效接口回调-callback-record-TB-GZZRX：业务结束：end");
	}

	public static void main(String[] args) {
//		String xml="<Packet><Head><UUID>4b07e8b0-0c49-4cf0-a9eb-db3376b2442b</UUID><CRequestType>220005</CRequestType><CBusiChnl>BLB</CBusiChnl><TAcctTm>2023-12-04 13:42:13.0</TAcctTm><CheckCode>440410781dc91e884ab6e136a4c09432</CheckCode></Head><Body><Base><AppNo>0BLB2023120437056318</AppNo><TradeAmount>5292</TradeAmount><TradeDate>2023-12-04 13:42:13.0</TradeDate><TradeState>1</TradeState><TradeMsg>成功</TradeMsg><ResultCode>1</ResultCode><ResultMsg>成功</ResultMsg><PlyNo>1BLB2023120437056318</PlyNo><PlyDocUrl>https://www.qhins.com/webins/epoliy?pNo=1BLB2023120437056318&sign=c726b1b1f6050fcecaf6afcbad1a0b1a</PlyDocUrl></Base></Body></Packet>";
//		String jsonObject = postJsonString("https://www.bailianbao.cn/QH-API/GZZRX/callback-policy", xml);
//		String jsonObject = postJsonString("http://www.bailianbao.cn/QH-API/GZZRX/callback-policy", xml);
//		System.out.println(jsonObject);
		String url = "http://www.bailianbao.cn/TB-API/GZZRX/callback-policy";
		GZZRX_TB_API_Controller.TaipingyangNotifyForm form = new GZZRX_TB_API_Controller.TaipingyangNotifyForm();
		String content = "{\"terminationDate\":\"2026-03-14 00:00:00\",\"payuserid\":\"AMSUSABLEMATCH\",\"payername\":\"北京容盛保洁服务有限公司\",\"payeraccount\":\"11122301040005691\",\"policyApplyNo\":\"ABEJ13037125FM00001E\",\"resultCode\":1,\"efficientDate\":\"2025-03-14 00:00:00\",\"policyNo\":\"ABEJ13037125FN00001A\",\"paymentTime\":\"20250313114000\",\"signMsg\":\"8008080dc79a4c360856bd1683a16ea7\",\"epolicyUrl\":\"https://jttp.cpic.com.cn/jttpitx/externalpartner/link?eluowKHu3nsGSb3QlYyKBr4/eYp8zobBmO3YjYgoPjpk1j6vZ2jBCE5VlBSGhxmd%7C91350200302969730N\"}  ";
		form.setPolicyApplyNo("111111");
		form.setPaymentTime(DateFormatUtils.format(new Date(), "yyyyMMddHHmmss"));
		form.setResultCode(1);
		form.setPolicyNo("2134566");
		StringBuilder builder = new StringBuilder()
				.append(form.getPolicyApplyNo())
				.append(form.getPaymentTime())
				.append(form.getPolicyNo())
				.append("P_CPIC");
		form.setSignMsg(DigestUtils.md5Hex(builder.toString()));
		String result = sendPostJsonRequest(url, content/*JSON.toJSONString(form)*/, "UTF-8");
		System.out.println(result);
	}

	public static String sendPostJsonRequest(String urlStr, String jsonStr, String charSet) {

		DefaultHttpClient client = new DefaultHttpClient();
		client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 12 * 1000);; // 12秒

		HttpPost post = new HttpPost(urlStr);// 表示用Post方式提交
		post.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, charSet);
		post.addHeader("Content-Type", "application/json;charset=utf-8");
		post.addHeader("Accept", "application/json;charset=utf-8");

		// 设置请求参数
		StringEntity entity =  new StringEntity(jsonStr, charSet);
		post.setEntity(entity);

		try {
			HttpResponse resp = client.execute(post);
			if (resp.getStatusLine().getStatusCode() == 200) {
				String result = EntityUtils.toString(resp.getEntity(), charSet);
				return result;
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			post.abort();
			post.releaseConnection();
			client.getConnectionManager().shutdown();
		}
		return null;
	}

	public static String postJsonString(String url, String json) {
		try (CloseableHttpClient httpclient = HttpClients.createDefault()){
			HttpPost httppost = new HttpPost(url);
			httppost.addHeader(HTTP.CONTENT_TYPE, "application/json");
			if(StringUtils.isNotEmpty(json)){
				StringEntity se = new StringEntity(json, StandardCharsets.UTF_8);
				se.setContentType("text/json");
				se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
				httppost.setEntity(se);
			}
			try (CloseableHttpResponse response = httpclient.execute(httppost) ){
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					return EntityUtils.toString(entity, StandardCharsets.UTF_8);
				}
			}
		} catch (IOException e) {
		}
		return "";
	}

	/**
	 * <b> 申请电子发票 </b>
	 * @author ZXF
	 * @create 2023/04/03 0003 17:48
	 * @version
	 * @注意事项 </b>
	 */
	@RequestMapping("/TB-API/GZZRX/PRINT_INVOICE/{oid}")
	@ResponseBody
	public ResultDto printInvoice(@PathVariable long oid) throws Exception {
		OrderFormVo dto = policyService.accordingToOrderIDToGetPolicyDto(oid);

		if(dto == null || !DictConst.ORDER_STATUS_YCB.equals(dto.getPolicy_status())){
			return new ResultDto("无法获取发票！", ConstProp.CODE_FAILURE, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
		}
		SpecialHirelingVo vo = policyService.accordingToOrderIDToGetSpecialHirelingVo(oid);
		if(StringUtils.isNotEmpty(vo.getMailPolicyVo().getE_invoice_url())){
			return new ResultDto(vo.getMailPolicyVo().getE_invoice_url(), ConstProp.CODE_SUCCESS, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
		}
		String result = gZZRX_TBRequestService.request_tb_gzzrx(oid, TransTypeEnum.DZFP.getValue(),null);
		if(StringUtils.isEmpty(result)){
			return new ResultDto("获取电子发票接口异常！", ConstProp.CODE_FAILURE, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
		}
		String[] strs = result.split(ConstProp.POUND_SIGN);
		if(!ConstProp.CODE_SUCCESS.equals(strs[0])){
			return new ResultDto(strs[1], ConstProp.CODE_FAILURE, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
		}
		String e_invoice_url = strs[1];
		policyService.updateUrlByExternalreference(e_invoice_url,dto.getExternal_reference());
		return new ResultDto(e_invoice_url, ConstProp.CODE_SUCCESS, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
	}

	/**
	 * <b> 申请批单电子发票 </b>
	 * @author ZXF
	 * @create 2025/10/11 0011 13:31
	 * @version
	 * @注意事项 </b>
	 */
	@RequestMapping("/TB-API/GZZRX/PRINT_RECORD_INVOICE/{oid}")
	@ResponseBody
	public ResultDto printRecordInvoice(@PathVariable long oid) throws Exception {
		InsPreservationRecordVo iprVo = insPreservationRecordAPIService.findInsPreservationRecordVoById(oid);

		if(iprVo == null
				|| !DictConst.REVISE_TYPE_Z.equals(iprVo.getRevise_type())
				|| !"45".contains(iprVo.getRevise_status())
				|| StringUtils.isEmpty(iprVo.getRevise_pay())){
			return new ResultDto("无法获取发票！", ConstProp.CODE_FAILURE, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
		}
		if(StringUtils.isNotEmpty(iprVo.getE_invoice_url())){
			return new ResultDto(iprVo.getE_invoice_url(), ConstProp.CODE_SUCCESS, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
		}
		String result = gZZRX_TBRequestService.request_tb_gzzrx(Long.parseLong(iprVo.getIns_insurance_slip_id()), TransTypeEnum.DZFPXZ.getValue(),iprVo);
		if(StringUtils.isEmpty(result)){
			return new ResultDto("获取电子发票接口异常！", ConstProp.CODE_FAILURE, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
		}
		String[] strs = result.split(ConstProp.POUND_SIGN);
		if(!ConstProp.CODE_SUCCESS.equals(strs[0])){
			return new ResultDto(strs[1], ConstProp.CODE_FAILURE, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
		}
		String e_invoice_url = strs[1];
		InsPreservationRecord ipr = insPreservationRecordAPIService.selectById(oid);
		ipr.setE_invoice_url(e_invoice_url);
		insPreservationRecordAPIService.updateById(ipr);
		return new ResultDto(e_invoice_url, ConstProp.CODE_SUCCESS, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR, ConstProp.BLANK_CHAR);
	}

	private String returnRet(String code,String msg){
		return "{\"code\":\""+code+"\",\"message\":\""+msg+"\"}";
	}

	static class TaipingyangNotifyForm {

		private String policyApplyNo;// 申请单号（申请投保成功保险公司返回）
		private String paymentTime;// 支付成功时间（yyyyMMddHHmmss）
		private Integer resultCode;// 承保结果（1.支付成功且承保成功，-1.支付成功承保失败）
		private String policyNo; // 保单号
		private String errorMsg;// 失败信息
		private String signMsg;// 加密结果

		public String getPolicyApplyNo() {
			return policyApplyNo;
		}

		public void setPolicyApplyNo(String policyApplyNo) {
			this.policyApplyNo = policyApplyNo;
		}

		public String getPaymentTime() {
			return paymentTime;
		}

		public void setPaymentTime(String paymentTime) {
			this.paymentTime = paymentTime;
		}

		public String getPolicyNo() {
			return policyNo;
		}

		public void setPolicyNo(String policyNo) {
			this.policyNo = policyNo;
		}

		public Integer getResultCode() {
			return resultCode;
		}

		public void setResultCode(Integer resultCode) {
			this.resultCode = resultCode;
		}

		public String getErrorMsg() {
			return errorMsg;
		}

		public void setErrorMsg(String errorMsg) {
			this.errorMsg = errorMsg;
		}

		public String getSignMsg() {
			return signMsg;
		}

		public void setSignMsg(String signMsg) {
			this.signMsg = signMsg;
		}

	}
}

