package com.yifu.cloud.plus.v1.yifu.social.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.exception.CheckedException;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.social.entity.SysHouseHoldInfo;
import com.yifu.cloud.plus.v1.yifu.social.entity.TSocialFriendBackLog;
import com.yifu.cloud.plus.v1.yifu.social.service.TSocialFriendBackLogService;
import com.yifu.cloud.plus.v1.yifu.social.vo.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.*;
import org.springframework.security.core.parameters.P;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URL;
import java.security.SignatureException;
import java.time.LocalDateTime;
import java.util.*;

import static com.alibaba.fastjson.serializer.SerializerFeature.*;

/**
 * @Author: hgw
 * @Date: 2024-12-6 17:01:23
 * @Description:
 * @return: 税友配置
 **/
@Configuration
@Data
@Slf4j
public class SocialFriendConfig {

	// appKey
	@Value("${socialFriend.appKey}")
	private String appKey;
	// appSecret
	@Value("${socialFriend.appSecret}")
	private String appSecret;
	// url前缀
	@Value("${socialFriend.urlPre}")
	private String urlPre;
	// url推 增加
	@Value("${socialFriend.urlPushAdd}")
	private String urlPushAdd;
	// url拉结果数据 增加
	@Value("${socialFriend.urlGetInfoAdd}")
	private String urlGetInfoAdd;
	// url推 增加
	@Value("${socialFriend.urlPushReduce}")
	private String urlPushReduce;
	// url拉结果数据 增加
	@Value("${socialFriend.urlGetInfoReduce}")
	private String urlGetInfoReduce;
	// url拉结果数据
	@Value("${socialFriend.urlUpload}")
	private String urlUpload;
	// url人员维度网厅源文件下载(个人审核查询证明)
	@Value("${socialFriend.urlDownloadEmployeeAsync}")
	private String urlDownloadEmployeeAsync;
	@Value("${socialFriend.urlDownloadEmployeeFeedback}")
	// URL人员维度网厅源文件下载反馈
	private String urlDownloadEmployeeFeedback;


	private static final String APP_KEY = "appKey";
	private static final String TIMESTAMP = "timestamp";
	private static final String X_REQ_NONCE = "xReqNonce";
	private static final String VERSION = "version";

	private static final SerializerFeature[] features = new SerializerFeature[]{
			WriteMapNullValue, WriteNullNumberAsZero, WriteNullListAsEmpty,
			WriteNullStringAsEmpty, WriteDateUseDateFormat
	};

	/**
	 * @param : listVo 同一类（户、增减）的前100个
	 * @param : vo 第一个，存账密等信息
	 * @param : type 1社保增 2社保减 3医保增 4医保减
	 * @Description: 推送任务接口
	 * @Author: hgw
	 * @Date: 2024-12-9 16:54:31
	 * @return: java.lang.String
	 **/
	public String pushFriendByInfo(RestTemplate restTemplate, SociaFriendYgsAddVo vo, List<SociaFriendYgsAddVo> listVo
			, int type, String bizNo, List<TSocialFriendBackLog> backLogList
			, TSocialFriendBackLogService tSocialFriendBackLogService, boolean isHuiZhou) {
		String addId = "";
		String appAddUrl = urlPre;
		if (type == 1 || type == 3) {
			appAddUrl += urlPushAdd;
		} else {
			appAddUrl += urlPushReduce;
		}
		String version = "1.0.0";
		String timestamp = String.valueOf(new Date().getTime());
		String xReqNonce = "1";
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		// */*
		headers.add("accept", MediaType.ALL_VALUE);
		headers.add(APP_KEY, appKey);
		headers.add(TIMESTAMP, timestamp);
		try {

			String signature = SocialFriendSign.qianMing(getMapParam(appKey, appSecret, xReqNonce, version, timestamp, null));
			headers.add("signature", signature);
		} catch (SignatureException e) {
			log.error("税友签名失败", e);
			return addId;
		}
		headers.add(X_REQ_NONCE, xReqNonce);
		headers.add(VERSION, version);

		JSONObject json = new JSONObject();
		// 区分徽州区与其他地方，组装不同的参数格式：
		if (isHuiZhou) {
			this.getJsonObjectByHuiZhou(json, vo, listVo, type, bizNo);
		} else {
			this.getJsonObjectByBase(json, vo, listVo, type, bizNo);
		}

		HttpEntity<String> formEntity = new HttpEntity<>(json.toString(), headers);
		// 推的json
		TSocialFriendBackLog backLogPush = new TSocialFriendBackLog();
		backLogPush.setSocialId(vo.getSocialId());
		backLogPush.setType(5);
		backLogPush.setLogInfo(JSON.toJSONString(json, features));
		backLogPush.setCreateTime(LocalDateTime.now());
		backLogList.add(backLogPush);

		TSocialFriendBackLog errorSave = new TSocialFriendBackLog();
		errorSave.setSocialId(bizNo);
		errorSave.setType(20);
		errorSave.setLogInfo(JSON.toJSONString(json, features));
		errorSave.setCreateTime(LocalDateTime.now());
		tSocialFriendBackLogService.save(errorSave);
		String dataResultList = restTemplate.postForObject(appAddUrl, formEntity, String.class);
		// {"head":{"code":"00000000","description":"成功","msg":"成功","time":"2024-12-06 17:10:26","status":"Y"
		// ,"body":{"requestId":"85440b327d71466abcd9c5c81d5bb172"
		if (Common.isNotNull(dataResultList)) {
			errorSave.setType(21);
			tSocialFriendBackLogService.updateById(errorSave);
			// 拉取的数据日志
			TSocialFriendBackLog backLog = new TSocialFriendBackLog();
			StringBuilder ids = new StringBuilder();
			String idTemp;
			for (SociaFriendYgsAddVo tempVo : listVo) {
				if (Common.isNotNull(tempVo.getEmpIdcard())) {
					idTemp = tempVo.getEmpIdcard();
				} else if (Common.isNotNull(tempVo.getSocialId())) {
					idTemp = tempVo.getSocialId();
				} else {
					idTemp = vo.getSocialId();
				}
				ids.append(idTemp).append(",");
			}
			backLogPush.setSocialId(ids.toString());
			backLog.setSocialId(ids.toString());
			backLog.setType(type);
			backLog.setLogInfo(dataResultList);
			backLog.setCreateTime(LocalDateTime.now());
			JSONObject dataObject = JSON.parseObject(dataResultList);
			String head = dataObject.getString("head");
			if (Common.isNotNull(head)) {
				JSONObject headObject = JSON.parseObject(head);
				String status = headObject.getString("status");
				if ("Y".equals(status)) {
					String body = dataObject.getString("body");
					JSONObject bodyObject = JSON.parseObject(body);
					addId = bodyObject.getString("requestId");
					backLog.setRequestId(addId);
				}
			}
			backLogList.add(backLog);
		}
		return addId;
	}

	// 2组装安徽通用的所需要的json参数
	private void getJsonObjectByBase(JSONObject json, SociaFriendYgsAddVo vo, List<SociaFriendYgsAddVo> listVo
			, int type, String bizNo) {
		if (json == null) {
			json = new JSONObject();
		}
		// 外部业务订单号
		json.put("bizNo", bizNo);
		// 企业名称——户名
		json.put("qymc", vo.getSocialHouseholdName());
		// 税号——户配置的“单位统一信用代码”
		json.put("nsrsbh", vo.getUnitCreditCode());
		// 行政区划代码 户里的缴纳地，精确到市 "340100"
		json.put("areaid", vo.getAreaCode());
		JSONArray ywblzhlbArr = new JSONArray();
		if (type < 3) {
			JSONObject jsonYwblzhlbYgs = new JSONObject();
			// 密码
			jsonYwblzhlbYgs.put("mm", vo.getSocialPassword());
			// 办理项目 例如社保、医保等
			jsonYwblzhlbYgs.put("blxm", "社保");
			// 单位编号
			jsonYwblzhlbYgs.put("dwbh", vo.getCustomerNo());
			// 账号
			jsonYwblzhlbYgs.put("zh", vo.getSocialAccount());
			// 密码类型:安徽社保医保都是4：
			jsonYwblzhlbYgs.put("mmlx", "4");
			ywblzhlbArr.add(jsonYwblzhlbYgs);
		} else {
			JSONObject jsonYwblzhlbYsd = new JSONObject();
			jsonYwblzhlbYsd.put("mm", vo.getMediclPassword());
			jsonYwblzhlbYsd.put("blxm", "医保");
			//jsonYwblzhlbYsd.put("dwbh", "34010000000000333471")
			jsonYwblzhlbYsd.put("dwbh", vo.getCustomerNoYsd());
			jsonYwblzhlbYsd.put("zh", vo.getMediclAccount());
			jsonYwblzhlbYsd.put("mmlx", "4");
			ywblzhlbArr.add(jsonYwblzhlbYsd);
		}
		json.put("ywblzhlb", ywblzhlbArr);
		// type 1社保增 2社保减 3医保增 4医保减
		setEmpInfo(json, listVo, type, vo.getQyzgjbylbxcbdjb());
		// 企业职工社会保险增员花名册列表
		String fileName = "qyzgshbxzyhmclb";
		if (type == 2 || type == 4) {
			// 职工社会保险减少花名册
			fileName = "zgshbxjshmc";
			if (Common.isNotNull(vo.getQyzgshbxzyhmc())) {
				json.put(fileName, vo.getQyzgshbxzyhmc());
			} else if (Common.isNotNull(vo.getQyzgjbylbxcbdjb())) {
				json.put(fileName, vo.getQyzgjbylbxcbdjb());
			}
		} else {
			JSONArray qyzgshbxzyhmclbArr = new JSONArray();
			if (Common.isNotNull(vo.getQyzgshbxzyhmc())) {
				qyzgshbxzyhmclbArr.add(vo.getQyzgshbxzyhmc());
			} else if (Common.isNotNull(vo.getQyzgjbylbxcbdjb())) {
				qyzgshbxzyhmclbArr.add(vo.getQyzgjbylbxcbdjb());
			}
			if (type < 3 && vo.getImgListYgs() != null && !vo.getImgListYgs().isEmpty()) {
				// 税友新附件接口说用原来的：那就一批任务里面用一份文件就可以了 还是原来的那个字段 2025-5-16 16:57:00 王赣松
				qyzgshbxzyhmclbArr.addAll(vo.getImgListYgs());
			}
			if (type > 2 && vo.getImgListYsd() != null && !vo.getImgListYsd().isEmpty()) {
				// 税友新附件接口说用原来的：那就一批任务里面用一份文件就可以了 还是原来的那个字段 2025-5-16 16:57:00 王赣松
				qyzgshbxzyhmclbArr.addAll(vo.getImgListYsd());
			}
			if (!qyzgshbxzyhmclbArr.isEmpty()) {
				json.put(fileName, qyzgshbxzyhmclbArr);
			}
		}
	}

	// 2组装徽州区所需要的json参数
	private void getJsonObjectByHuiZhou(JSONObject json, SociaFriendYgsAddVo vo, List<SociaFriendYgsAddVo> listVo
			, int type, String bizNo) {
		if (json == null) {
			json = new JSONObject();
		}
		// 外部业务订单号
		json.put("bizNo", bizNo);
		// 企业名称——户名
		json.put("qymc", vo.getSocialHouseholdName());
		// 税号——户配置的“单位统一信用代码”
		json.put("nsrsbh", vo.getUnitCreditCode());
		// 行政区划代码 户里的缴纳地，精确到市 "340100"
		json.put("areaid", vo.getAreaCode());
		// 登记序号 - 徽州非必填(陈红给的表里是空的，不推送。)

		JSONArray ywblzhlbArr = new JSONArray();
		if (type < 3) {
			JSONObject jsonYwblzhlbYgs = new JSONObject();
			// 密码
			jsonYwblzhlbYgs.put("mm", vo.getSocialPassword());
			// 办理项目 例如社保、医保等
			jsonYwblzhlbYgs.put("blxm", "社保");
			// 单位编号
			jsonYwblzhlbYgs.put("dwbh", vo.getCustomerNo());
			// 账号
			jsonYwblzhlbYgs.put("zh", vo.getSocialAccount());
			// 密码类型:安徽社保医保都是4：
			jsonYwblzhlbYgs.put("mmlx", "4");
			ywblzhlbArr.add(jsonYwblzhlbYgs);
		} else {
			JSONObject jsonYwblzhlbYsd = new JSONObject();
			jsonYwblzhlbYsd.put("mm", vo.getMediclPassword());
			jsonYwblzhlbYsd.put("blxm", "医保");
			//jsonYwblzhlbYsd.put("dwbh", "34010000000000333471")
			jsonYwblzhlbYsd.put("dwbh", vo.getCustomerNoYsd());
			jsonYwblzhlbYsd.put("zh", vo.getMediclAccount());
			jsonYwblzhlbYsd.put("mmlx", "4");
			ywblzhlbArr.add(jsonYwblzhlbYsd);
		}
		json.put("ywblzhlb", ywblzhlbArr);

		// type 1社保增 2社保减 3医保增 4医保减
		setEmpInfoForHuiZhou(json, listVo, type, vo.getQyzgjbylbxcbdjb());

		if (type == 4 && Common.isNotNull(vo.getQyzgjbylbxcbdjb())) {
			json.put("zgjbylbxcbdjb", vo.getQyzgjbylbxcbdjb());
		}
		// 企业职工社会保险增员花名册列表
		/*String fileName = "qyzgshbxzyhmclb";
		if (type == 2 || type == 4) {
			// 职工社会保险减少花名册
			fileName = "zgshbxjshmc";
			if (Common.isNotNull(vo.getQyzgshbxzyhmc())) {
				json.put(fileName, vo.getQyzgshbxzyhmc());
			} else if (Common.isNotNull(vo.getQyzgjbylbxcbdjb())) {
				json.put(fileName, vo.getQyzgjbylbxcbdjb());
			}
		} else {
			JSONArray qyzgshbxzyhmclbArr = new JSONArray();
			if (Common.isNotNull(vo.getQyzgshbxzyhmc())) {
				qyzgshbxzyhmclbArr.add(vo.getQyzgshbxzyhmc());
			} else if (Common.isNotNull(vo.getQyzgjbylbxcbdjb())) {
				qyzgshbxzyhmclbArr.add(vo.getQyzgjbylbxcbdjb());
			}
			if (type < 3 && vo.getImgListYgs() != null && !vo.getImgListYgs().isEmpty()) {
				// 税友新附件接口说用原来的：那就一批任务里面用一份文件就可以了 还是原来的那个字段 2025-5-16 16:57:00 王赣松
				qyzgshbxzyhmclbArr.addAll(vo.getImgListYgs());
			}
			if (type > 2 && vo.getImgListYsd() != null && !vo.getImgListYsd().isEmpty()) {
				// 税友新附件接口说用原来的：那就一批任务里面用一份文件就可以了 还是原来的那个字段 2025-5-16 16:57:00 王赣松
				qyzgshbxzyhmclbArr.addAll(vo.getImgListYsd());
			}
			if (!qyzgshbxzyhmclbArr.isEmpty()) {
				json.put(fileName, qyzgshbxzyhmclbArr);
			}
		}*/
	}

	/**
	 * @param json 总传参json
	 * @param type 1社保增 2社保减 3医保增 4医保减
	 * @Description: 徽州地区参保人员信息设置
	 * @Author: hgw
	 * @Date: 2025/01/20 10:24
	 * @return: void
	 **/
	private void setEmpInfoForHuiZhou(JSONObject json, List<SociaFriendYgsAddVo> listVo, int type, String qyzgjbylbxcbdjb) {
		if (type == 1 || type == 3) {
			setEmpInfoAddByHuiZhou(json, listVo, type, qyzgjbylbxcbdjb);
		} else {
			setEmpInfoReduceByHuiZhou(json, listVo, type, qyzgjbylbxcbdjb);
		}
	}

	/**
	 * @param : type 1社保增 2社保减 3医保增 4医保减
	 * @Description: 推送任务接口
	 * @Author: hgw
	 * @Date: 2024-12-9 16:54:31
	 * @return: java.lang.String
	 **/
	public String uploadPng(RestTemplate restTemplate, String fileName, String file, TSocialFriendBackLog backLog) {
		String urlStr = "";
		String appAddUrl = urlPre + urlUpload;
		String version = "1.0.0";
		String timestamp = String.valueOf(new Date().getTime());
		String xReqNonce = "1";
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		// */*
		headers.add("accept", MediaType.ALL_VALUE);
		headers.add(APP_KEY, appKey);
		headers.add(TIMESTAMP, timestamp);
		try {
			String signature = SocialFriendSign.qianMing(getMapParam(appKey, appSecret, xReqNonce, version, timestamp, null));
			headers.add("signature", signature);
		} catch (SignatureException e) {
			log.error("税友签名失败", e);
			return urlStr;
		}
		headers.add(X_REQ_NONCE, xReqNonce);
		headers.add(VERSION, version);

		JSONObject json = new JSONObject();
		// 文件名称
		json.put("wjmc", fileName);
		// 	文件内容
		json.put("wjnr", file);
		// 业务类型 参保、停保、参保业务签名、停保业务签名、人员补缴、缴费工资变更、缴费工资业务签名
		// json.put("ywlx", vo.getUnitCreditCode())
		// 行政区划代码 户里的缴纳地，精确到市 "340100"

		HttpEntity<String> formEntity = new HttpEntity<>(json.toString(), headers);
		backLog.setLogInfo(String.valueOf(formEntity));
		backLog.setCreateTime(LocalDateTime.now());
		String dataResultList = restTemplate.postForObject(appAddUrl, formEntity, String.class);
		// {"head":{"code":"00000000","description":"成功","msg":"成功","time":"2024-12-06 17:10:26","status":"Y"
		// ,"body":{"requestId":"85440b327d71466abcd9c5c81d5bb172"
		if (Common.isNotNull(dataResultList)) {
			backLog.setLogInfo(dataResultList);
			JSONObject dataObject = JSON.parseObject(dataResultList);
			String head = dataObject.getString("head");
			if (Common.isNotNull(head)) {
				JSONObject headObject = JSON.parseObject(head);
				String status = headObject.getString("status");
				if ("Y".equals(status)) {
					String body = dataObject.getString("body");
					JSONObject bodyObject = JSON.parseObject(body);
					urlStr = bodyObject.getString("wjlj");
				}
			}
		} else {
			backLog.setSocialId(appAddUrl + "返回dataResultList为空");
		}
		return urlStr;
	}

	/**
	 * @param json 总传参json
	 * @param type 1社保增 2社保减 3医保增 4医保减
	 * @Description: 分流塞值
	 * @Author: hgw
	 * @Date: 2024/12/11 10:24
	 * @return: void
	 **/
	private void setEmpInfo(JSONObject json, List<SociaFriendYgsAddVo> listVo, int type, String qyzgjbylbxcbdjb) {
		if (type == 1 || type == 3) {
			setEmpInfoAdd(json, listVo, type, qyzgjbylbxcbdjb);
		} else {
			setEmpInfoReduce(json, listVo, type, qyzgjbylbxcbdjb);
		}
	}

	/**
	 * @param json 主json存数据
	 * @Description: 塞人员名单-1社保增
	 * @Author: hgw
	 * @Date: 2024/12/10 18:05
	 * @return: void
	 **/
	private void setEmpInfoAdd(JSONObject json, List<SociaFriendYgsAddVo> listVo, int type, String qyzgjbylbxcbdjb) {
		// 参保人员名单 数组
		JSONArray cbrymdArr = new JSONArray();
		JSONObject cbrymdOne;
		String areaName = "安徽省";
		String gj = "中国";
		String hkxz = "本地居民户口";
		JSONObject jyxx;
		String startDate;
		JSONArray blxmlbArr;
		JSONObject blxmlbOne;
		String blxm = "社保";
		// 险种类型 例如养老、工伤、医疗等
		String xzlb;
		if (type > 2) {
			blxm = "医保";
		}
		JSONObject tszdxx;
		// 企业职工基本医疗保险参保登记表 安徽非必填！ 数组
		String[] arr = {qyzgjbylbxcbdjb};
		JSONArray ybzyclArr;
		// 2025-3-14 15:44:32 单个改造为批量
		for (SociaFriendYgsAddVo vo : listVo) {
			cbrymdOne = new JSONObject();
			// 姓名
			cbrymdOne.put("xm", vo.getEmpName());
			// 证件类型
			cbrymdOne.put("zzlx", "居民身份证");
			// 证件号码"828888200908213819"
			cbrymdOne.put("zzhm", vo.getEmpIdcard());

			// 国籍（地区） "中国"
			cbrymdOne.put("gj", gj);
			// 性别
			cbrymdOne.put("xb", getSexName(vo.getEmpIdcard()));
			// 出生日期
			cbrymdOne.put("csrq", getBirthStr(vo.getEmpIdcard()));
			// 民族 空的默认汉族
			cbrymdOne.put("mz", vo.getEmpNational());
			// 手机号码
			cbrymdOne.put("sjhm", vo.getEmpMobile());
			// 户口地所在行政区
			cbrymdOne.put("hkszdxzq", areaName);
			// 户口所在地地址
			cbrymdOne.put("hkszddz", areaName);
			// 户口性质
			//cbrymdOne.put("hkxz", "居民户口（含农业户口、非农业户口）")
			cbrymdOne.put("hkxz", hkxz);
			// 居住地址
			cbrymdOne.put("jzdz", areaName);
			// 居住地行政区
			cbrymdOne.put("jzdzxzq", areaName);
			// 社保起缴日期（养老起缴）yyyy-MM-dd
			startDate = vo.getSocialStartDate();
			// 参加工作日期
			cbrymdOne.put("cjgzrq", startDate);
			// 文化程度 见字典“受教育程度” 空的默认“大学专科”
			//cbrymdOne.put("whcd", "大学专科")
			cbrymdOne.put("whcd", vo.getEducationName());

			// 办理项目列表
			blxmlbArr = new JSONArray();
			blxmlbOne = new JSONObject();
			// 险种类型 例如养老、工伤、医疗等
			xzlb = "企业职工养老,工伤保险,失业保险";
			if (type > 2) {
				xzlb = null;
				// 2025-12-8 10:30:50 mvp1.7.18-shuiyou分支，
				// 改为按单位+个人金额来判断是否需要这个险种，本次只改医疗+大病，生育没有个人金额，养工失没有浮动
				// ，同全服福保专员陈红确认
				if (Common.isNotNull(vo.getUnitMedicalMoney()) && CommonConstants.ONE_INTEGER.equals(vo.getUnitMedicalMoney())) {
					xzlb = "职工基本医疗保险";
				}
				if (Common.isNotNull(vo.getUnitBirthMoney()) && CommonConstants.ONE_INTEGER.equals(vo.getUnitBirthMoney())) {
					if (Common.isNotNull(xzlb)) {
						xzlb += ",生育保险";
					} else {
						xzlb = "生育保险";
					}
				}
				if (Common.isNotNull(vo.getUnitBigailmentMoney()) && CommonConstants.ONE_INTEGER.equals(vo.getUnitBigailmentMoney())) {
					if (Common.isNotNull(xzlb)) {
						xzlb += ",大额医疗";
					} else {
						xzlb = "大额医疗";
					}
				}
			}
			// 办理项目
			blxmlbOne.put("blxm", blxm);
			// 本次参保日期 格式：yyyy-MM-dd
			blxmlbOne.put("bccbrq", startDate);
			// 申报工资 社保派单里的“备案基数”
			blxmlbOne.put("sbgz", vo.getRecordBase());

			// 险种类型 例如养老、工伤、医疗等
			if (Common.isNotNull(xzlb)) {
				blxmlbOne.put("xzlb", xzlb.split(","));
			}
			blxmlbArr.add(blxmlbOne);
			cbrymdOne.put("blxmlb", blxmlbArr);

			// 特色字段信息
			tszdxx = new JSONObject();
			// 增员年月 社保必填；yyyyMM 社保起缴日期（养老起缴）到月
			tszdxx.put("zyny", vo.getSocialStartMonth());
			// 同步办理用工劳动备案 社保必填；是
			tszdxx.put("tbblygldhtba", "是");
			// 参保模式 新参、续参
			tszdxx.put("cbms", "续参");
			// 就业登记时间 社保必填；yyyy-MM-dd
			tszdxx.put("jydjsj", startDate);
			// 单位就业起始时间  社保必填；yyyy-MM-dd
			tszdxx.put("dwjyqssj", startDate);
			// 安徽非必填！社保个人身份材料 取文件上传后获取的文件路径。图片总大小不超过1M, 材料仅支持图片格式,支持上传jpeg/jpg/png格式。
			if (vo.getImgListYgs() != null && !vo.getImgListYgs().isEmpty()) {
				// 税友接口只允许一张
				tszdxx.put("sbzycl", vo.getImgListYgs().get(0));
			}

			// 用工形式 社保必填 // 盛宇文档对应，只有3种
			tszdxx.put("ygxs", vo.getContractType());
			// 劳动合同签署情况 社保必填 默认"初签"
			tszdxx.put("ldhtqsqk", "初签");
			// 人员类型 默认：在职职工
			tszdxx.put("rylx", "在职职工");
			// 医保个人身份材料 安徽非必填！ 无
			if (vo.getImgListYsd() != null && !vo.getImgListYsd().isEmpty()) {
				ybzyclArr = new JSONArray();
				ybzyclArr.addAll(vo.getImgListYsd());
				tszdxx.put("ybzycl", ybzyclArr);
			}
			// 职业工种 社保必填  默认“办事人员和有关人员”
			tszdxx.put("zygz", "办事人员和有关人员");
			// 人员身份 个人身份 社保必填 默认“职员”
			tszdxx.put("grsf", "职员");
			// 工作时间制度 社保必填
			tszdxx.put("gzsjzd", vo.getWorkingHours());
			// 医保用工形式 医保新参必填 默认“原固定职工”
			tszdxx.put("ybygxs", "原固定职工");
			// 毕业院校
			tszdxx.put("byyx", vo.getByyx());

			if (type < 3) {
				// 企业职工社会保险增员花名册 安徽非必填！
				// 社保增员必填
				tszdxx.put("qyzgshbxzyhmc", vo.getQyzgshbxzyhmc());

				// 社保是否批量
				if (Common.isNotNull(vo.getIsSingleYgsPush()) && CommonConstants.ONE_STRING.equals(vo.getIsSingleYgsPush())) {
					tszdxx.put("sfpl", "否");
				}
			} else {
				if (Common.isNotNull(vo.getYbsfqzcb())) {
					if (CommonConstants.ONE_STRING.equals(vo.getYbsfqzcb())) {
						tszdxx.put("ybsfqzcb", "是");
					} else if (CommonConstants.ZERO_STRING.equals(vo.getYbsfqzcb())) {
						tszdxx.put("ybsfqzcb", "否");
					}
				}
				//  增员、减员必填
				tszdxx.put("qyzgjbylbxcbdjb", arr);

				// 医保是否批量
				if (Common.isNotNull(vo.getIsSingleYsdPush()) && CommonConstants.ONE_STRING.equals(vo.getIsSingleYsdPush())) {
					tszdxx.put("ybsfpl", "否");
				}
			}
			cbrymdOne.put("tszdxx", tszdxx);

			// 就业信息 社保必填；
			jyxx = new JSONObject();
			// 劳动合同类型
			jyxx.put("ldhtlx", vo.getContractTypeTwo());
			// 劳动合同起始日期
			jyxx.put("ldhtqsrq", startDate);
			// 劳动合同截止日期 派单里的“合同截止日期”
			jyxx.put("ldhtjzrq", vo.getContractEnd());
			cbrymdOne.put("jyxx", jyxx);
			cbrymdArr.add(cbrymdOne);
		}
		// 人员名单
		String buyType = "cbrymd";
		json.put(buyType, cbrymdArr);
	}


	/**
	 * @param json 主json存数据
	 * @Description: 塞人员名单-1社保增
	 * @Author: hgw
	 * @Date: 2024/12/10 18:05
	 * @return: void
	 **/
	private void setEmpInfoAddByHuiZhou(JSONObject json, List<SociaFriendYgsAddVo> listVo, int type, String qyzgjbylbxcbdjb) {
		// 参保人员名单 数组
		JSONArray cbrymdArr = new JSONArray();
		JSONObject cbrymdOne;

		String gj = "中国";
		String areaName = "安徽省|黄山市|徽州区";
		String hkxz = "本地居民户口";

		JSONObject jyxx;
		String startDate;
		JSONArray blxmlbArr;
		JSONObject blxmlbOne;
		String blxm = "社保";
		// 险种类型 例如养老、工伤、医疗等
		String xzlb;
		if (type > 2) {
			blxm = "医保";
		}
		JSONObject tszdxx;
		// 企业职工基本医疗保险参保登记表 安徽非必填！ 数组
		String[] arr = {qyzgjbylbxcbdjb};
		JSONArray ybzyclArr;
		// 2025-3-14 15:44:32 单个改造为批量
		for (SociaFriendYgsAddVo vo : listVo) {
			cbrymdOne = new JSONObject();
			// 姓名
			cbrymdOne.put("xm", vo.getEmpName());
			// 证件类型
			cbrymdOne.put("zzlx", "居民身份证");
			// 证件号码"828888200908213819"
			cbrymdOne.put("zzhm", vo.getEmpIdcard());

			// 国籍（地区） "中国"
			cbrymdOne.put("gj", gj);
			// 性别
			cbrymdOne.put("xb", getSexName(vo.getEmpIdcard()));
			// 出生日期
			cbrymdOne.put("csrq", getBirthStr(vo.getEmpIdcard()));
			// 民族 空的默认汉族
			cbrymdOne.put("mz", vo.getEmpNational());
			// 手机号码
			cbrymdOne.put("sjhm", vo.getEmpMobile());
			// 户口地所在行政区
			cbrymdOne.put("hkszdxzq", areaName);
			// 户口所在地地址
			cbrymdOne.put("hkszddz", areaName);
			// 户口性质
			//cbrymdOne.put("hkxz", "居民户口（含农业户口、非农业户口）")
			cbrymdOne.put("hkxz", hkxz);
			// 居住地址
			cbrymdOne.put("jzdz", areaName);
			// 居住地行政区
			cbrymdOne.put("jzdzxzq", areaName);
			// 社保起缴日期（养老起缴）yyyy-MM-dd
			startDate = vo.getSocialStartDate();
			// 参加工作日期
			//cbrymdOne.put("cjgzrq", startDate);
			// 文化程度 见字典“受教育程度” 空的默认“大学专科”
			//cbrymdOne.put("whcd", "大学专科")
			cbrymdOne.put("whcd", vo.getEducationName());

			// 办理项目列表
			blxmlbArr = new JSONArray();
			blxmlbOne = new JSONObject();
			// 险种类型 例如养老、工伤、医疗等
			if (type > 2) {
				xzlb = null;
				// 2025-12-8 10:30:50 mvp1.7.18-shuiyou分支，
				// 改为按单位+个人金额来判断是否需要这个险种，本次只改医疗+大病，生育没有个人金额，养工失没有浮动
				// ，同全服福保专员陈红确认
				if (Common.isNotNull(vo.getUnitMedicalMoney()) && CommonConstants.ONE_INTEGER.equals(vo.getUnitMedicalMoney())) {
					xzlb = "职工基本医疗保险";
				}
				if (Common.isNotNull(vo.getUnitBirthMoney()) && CommonConstants.ONE_INTEGER.equals(vo.getUnitBirthMoney())) {
					if (Common.isNotNull(xzlb)) {
						xzlb += ",生育保险";
					} else {
						xzlb = "生育保险";
					}
				}
				if (Common.isNotNull(vo.getUnitBigailmentMoney()) && CommonConstants.ONE_INTEGER.equals(vo.getUnitBigailmentMoney())) {
					if (Common.isNotNull(xzlb)) {
						xzlb += ",大额医疗";
					} else {
						xzlb = "大额医疗";
					}
				}
				// 险种类型 徽州区社保不用传
				if (Common.isNotNull(xzlb)) {
					blxmlbOne.put("xzlb", xzlb.split(","));
				}
			}
			// 办理项目
			blxmlbOne.put("blxm", blxm);
			// 本次参保日期 格式：yyyy-MM-dd
			blxmlbOne.put("bccbrq", startDate);
			// 申报工资 社保派单里的“备案基数”
			blxmlbOne.put("sbgz", vo.getRecordBase());


			blxmlbArr.add(blxmlbOne);
			cbrymdOne.put("blxmlb", blxmlbArr);

			// 特色字段信息
			tszdxx = new JSONObject();

			// bzlx编制类型 - 非必填，默认非在编(陈红给的表里是空的，不推送。)
			// 徽州新字段：是否同步办理用工备案 - 非必填，默认是
			tszdxx.put("sftbblygba", "是");
			// sfsjgb是否是机关保 - 非必填，默认否(陈红给的表里是空的，不推送。)

			// 徽州新字段：sbjbqy社保经办区域 - 社保必填
			tszdxx.put("sbjbqy", "徽州区");

			// 徽州新字段：htqdlb合同签订类别 - 社保必填
			tszdxx.put("htqdlb", "新签");

			// 参保模式 新参、续参
			tszdxx.put("cbms", "续参");

			// 增员年月 社保必填；yyyyMM 社保起缴日期（养老起缴）到月
			//tszdxx.put("zyny", vo.getSocialStartMonth());

			// 同步办理用工劳动备案 社保必填；是
			//tszdxx.put("tbblygldhtba", "是");

			// 就业登记时间 社保必填；yyyy-MM-dd
			tszdxx.put("jydjsj", startDate);
			// 单位就业起始时间  社保必填；yyyy-MM-dd
			tszdxx.put("dwjyqssj", startDate);
			// 安徽非必填！社保个人身份材料 取文件上传后获取的文件路径。图片总大小不超过1M, 材料仅支持图片格式,支持上传jpeg/jpg/png格式。
			/*if (vo.getImgListYgs() != null && !vo.getImgListYgs().isEmpty()) {
				// 税友接口只允许一张
				tszdxx.put("sbzycl", vo.getImgListYgs().get(0));
			}*/

			// 用工形式 社保必填 // 盛宇文档对应，只有3种
			tszdxx.put("ygxs", vo.getContractType());
			// 劳动合同签署情况 社保必填 默认"初签"
			//tszdxx.put("ldhtqsqk", "初签");
			// 人员类型 默认：在职职工
			tszdxx.put("rylx", "在职职工");
			// 医保个人身份材料 安徽非必填！ 无
			if (vo.getImgListYsd() != null && !vo.getImgListYsd().isEmpty()) {
				ybzyclArr = new JSONArray();
				ybzyclArr.addAll(vo.getImgListYsd());
				tszdxx.put("ybzycl", ybzyclArr);
			}
			// 职业工种   默认“办事人员”
			// 是对应的 “录用工种代码”
			tszdxx.put("zygz", "办事人员");
			// 人员身份 个人身份 社保必填 默认“职员”
			tszdxx.put("grsf", "职员");
			// 工作时间制度 社保必填
			tszdxx.put("gzsjzd", vo.getWorkingHours());
			// 医保用工形式 医保新参必填 默认“原固定职工”
			tszdxx.put("ybygxs", "原固定职工");
			// 毕业院校
			//tszdxx.put("byyx", vo.getByyx());

			if (type < 3) {
				// 企业职工社会保险增员花名册 安徽非必填！
				// 社保增员必填
				//tszdxx.put("qyzgshbxzyhmc", vo.getQyzgshbxzyhmc());

				// 社保是否批量——徽州区目前无社保批量
				/*if (Common.isNotNull(vo.getIsSingleYgsPush()) && CommonConstants.ONE_STRING.equals(vo.getIsSingleYgsPush())) {
					tszdxx.put("sfpl", "否");
				}*/

			} else {
				if (Common.isNotNull(vo.getYbsfqzcb())) {
					if (CommonConstants.ONE_STRING.equals(vo.getYbsfqzcb())) {
						tszdxx.put("ybsfqzcb", "是");
					} else if (CommonConstants.ZERO_STRING.equals(vo.getYbsfqzcb())) {
						tszdxx.put("ybsfqzcb", "否");
					}
				}
				//  增员、减员必填
				tszdxx.put("qyzgjbylbxcbdjb", arr);

				// 医保是否批量
				if (Common.isNotNull(vo.getIsSingleYsdPush()) && CommonConstants.ONE_STRING.equals(vo.getIsSingleYsdPush())) {
					tszdxx.put("ybsfpl", "否");
				} else {
					tszdxx.put("ybsfpl", "是");
				}
			}
			cbrymdOne.put("tszdxx", tszdxx);

			// 就业信息 社保必填；
			jyxx = new JSONObject();
			// 劳动合同类型
			jyxx.put("ldhtlx", vo.getContractTypeTwo());
			// 劳动合同起始日期
			jyxx.put("ldhtqsrq", startDate);
			// 劳动合同截止日期 派单里的“合同截止日期”
			jyxx.put("ldhtjzrq", vo.getContractEnd());
			cbrymdOne.put("jyxx", jyxx);
			cbrymdArr.add(cbrymdOne);
		}
		// 人员名单
		String buyType = "cbrymd";
		json.put(buyType, cbrymdArr);
	}

	/**
	 * @param json 主json存数据
	 * @Description: 塞人员名单-2社保减
	 * @Author: hgw
	 * @Date: 2024/12/10 18:05
	 * @return: void
	 **/
	private void setEmpInfoReduce(JSONObject json, List<SociaFriendYgsAddVo> listVo, int type, String qyzgjbylbxcbdjb) {
		// 参保人员名单 数组
		JSONArray cbrymdArr = new JSONArray();
		JSONObject cbrymdOne;
		JSONArray blxmlbArr;
		JSONObject blxmlbOne;
		JSONObject tszdxx;
		String blxm = "社保";
		String[] arr = {qyzgjbylbxcbdjb};
		JSONArray ybjyclArr;
		if (type > 2) {
			blxm = "医保";
		}
		// 2025-3-14 15:44:32 单个改造为批量
		for (SociaFriendYgsAddVo vo : listVo) {
			cbrymdOne = new JSONObject();
			// 姓名
			cbrymdOne.put("xm", vo.getEmpName());
			// 证件类型
			cbrymdOne.put("zzlx", "居民身份证");
			// 证件号码"828888200908213819"
			cbrymdOne.put("zzhm", vo.getEmpIdcard());
			// 办理项目列表
			blxmlbArr = new JSONArray();
			blxmlbOne = new JSONObject();
			// 办理项目
			blxmlbOne.put("blxm", blxm);
			// 中断原因 除死亡以外，其他停保原因默认：“在职人员解除/终止劳动合同” 死亡对应“死亡或失踪”
			// 2025-4-14 16:03:54 陈红提的：tbyy 、 zzyy 、 bajcejyy 改为按t_social_friend_reduce_set配置来
			blxmlbOne.put("tbyy", vo.getTbyy());
			// 中断时间 yyyy-MM-dd 默认当前时间
			blxmlbOne.put("tbsj", DateUtil.getLastDay());
			blxmlbArr.add(blxmlbOne);
			cbrymdOne.put("blxmlb", blxmlbArr);

			// 特色字段信息
			tszdxx = new JSONObject();
			// 劳动用工备案解除/终止原因  数据字典文档 法律依据 [社保]必填；
			tszdxx.put("zzyy", vo.getZzyy());
			tszdxx.put("bajcejyy", vo.getBajcejyy());
			// 社保个人身份材料 无
			// tszdxx.put("shjycl", )
			// 医保个人身份材料 无
			// tszdxx.put("ybjycl", )
			// 职工社会保险减少花名册 无
			// tszdxx.put("zgshbxjshmc", )

			if (type > 2) {
				// 职工基本医疗保险参保登记表
				tszdxx.put("zgjbylbxcbdjb", arr);
				ybjyclArr = new JSONArray();
				if (Common.isNotNull(vo.getAutoLeaveDoc())) {
					ybjyclArr.add(vo.getAutoLeaveDoc());
				}
				if (vo.getImgListYsd() != null && !vo.getImgListYsd().isEmpty()) {
					ybjyclArr.addAll(vo.getImgListYsd());
				}
				tszdxx.put("ybjycl", ybjyclArr);
				if (type == 4 && "死亡".equals(vo.getTbyy())) {
					// 生存状态变更类型
					tszdxx.put("scztbglx", "死亡");
					// 生存状态变更原因
					tszdxx.put("scztbgyy", "死亡");
					// 入狱/失踪/死亡日期 yyyy-MM-dd
					tszdxx.put("ryszswrq", vo.getLeaveDay());
				}

				// 医保是否批量
				if (Common.isNotNull(vo.getIsSingleYsdPush()) && CommonConstants.ONE_STRING.equals(vo.getIsSingleYsdPush())) {
					tszdxx.put("ybsfpl", "否");
				}
			} else {
				// 是否强制停保：目前仅社保，税友暂不支持医保
				if (Common.isNotNull(vo.getSfqztb()) && "是".equals(vo.getSfqztb())) {
					tszdxx.put("sfqztb", vo.getSfqztb());
				}
				if (Common.isNotNull(vo.getAutoLeaveDoc())) {
					tszdxx.put("shjycl", vo.getAutoLeaveDoc());
				} else {
					if (vo.getImgListYgs() != null && !vo.getImgListYgs().isEmpty()) {
						// 税友接口只允许一张
						tszdxx.put("shjycl", vo.getImgListYgs().get(0));
					}
				}

				// 社保是否批量
				if (Common.isNotNull(vo.getIsSingleYgsPush()) && CommonConstants.ONE_STRING.equals(vo.getIsSingleYgsPush())) {
					tszdxx.put("sfpl", "否");
				}
			}
			cbrymdOne.put("tszdxx", tszdxx);
			cbrymdArr.add(cbrymdOne);
		}
		// 人员名单
		String buyType = "tbrymd";
		json.put(buyType, cbrymdArr);
	}

	/**
	 * @param json 主json存数据
	 * @Description: 塞人员名单-2社保减
	 * @Author: hgw
	 * @Date: 2024/12/10 18:05
	 * @return: void
	 **/
	private void setEmpInfoReduceByHuiZhou(JSONObject json, List<SociaFriendYgsAddVo> listVo, int type, String qyzgjbylbxcbdjb) {
		// 参保人员名单 数组
		JSONArray cbrymdArr = new JSONArray();
		JSONObject cbrymdOne;
		JSONArray blxmlbArr;
		JSONObject blxmlbOne;
		JSONObject tszdxx;
		String blxm = "社保";
		String[] arr = {qyzgjbylbxcbdjb};
		JSONArray ybjyclArr;
		if (type > 2) {
			blxm = "医保";
		}
		// 2025-3-14 15:44:32 单个改造为批量
		for (SociaFriendYgsAddVo vo : listVo) {
			cbrymdOne = new JSONObject();
			// 姓名
			cbrymdOne.put("xm", vo.getEmpName());
			// 证件类型
			cbrymdOne.put("zzlx", "居民身份证");
			// 证件号码"828888200908213819"
			cbrymdOne.put("zzhm", vo.getEmpIdcard());
			// 办理项目列表
			blxmlbArr = new JSONArray();
			blxmlbOne = new JSONObject();
			// 办理项目
			blxmlbOne.put("blxm", blxm);
			// 中断原因 除死亡以外，其他停保原因默认：“在职人员解除/终止劳动合同” 死亡对应“死亡或失踪”
			// 2025-4-14 16:03:54 陈红提的：tbyy 、 zzyy 、 bajcejyy 改为按t_social_friend_reduce_set配置来
			blxmlbOne.put("tbyy", vo.getTbyy());
			// 中断时间 yyyy-MM-dd 默认当前时间
			blxmlbOne.put("tbsj", DateUtil.getLastDay());
			blxmlbArr.add(blxmlbOne);
			cbrymdOne.put("blxmlb", blxmlbArr);

			// 特色字段信息
			tszdxx = new JSONObject();
			// 劳动用工备案解除/终止原因  数据字典文档 法律依据 [社保]必填；
			//tszdxx.put("zzyy", vo.getZzyy());
			// 是否同步办理用工备案
			tszdxx.put("sftbblygba", "是");
			tszdxx.put("bajcyy", vo.getZzyy());
			// 社保个人身份材料 无
			// tszdxx.put("shjycl", )
			// 医保个人身份材料 无
			// tszdxx.put("ybjycl", )
			// 职工社会保险减少花名册 无
			// tszdxx.put("zgshbxjshmc", )

			if (type > 2) {
				// 职工基本医疗保险参保登记表
				tszdxx.put("zgjbylbxcbdjb", arr);
				ybjyclArr = new JSONArray();
				if (Common.isNotNull(vo.getAutoLeaveDoc())) {
					ybjyclArr.add(vo.getAutoLeaveDoc());
				}
				if (vo.getImgListYsd() != null && !vo.getImgListYsd().isEmpty()) {
					ybjyclArr.addAll(vo.getImgListYsd());
				}
				tszdxx.put("ybjycl", ybjyclArr);
				if (type == 4 && "死亡".equals(vo.getTbyy())) {
					// 生存状态变更类型
					tszdxx.put("scztbglx", "死亡");
					// 生存状态变更原因
					tszdxx.put("scztbgyy", "死亡");
					// 入狱/失踪/死亡日期 yyyy-MM-dd
					tszdxx.put("ryszswrq", vo.getLeaveDay());
				}

				// 医保是否批量
				if (Common.isNotNull(vo.getIsSingleYsdPush()) && CommonConstants.ONE_STRING.equals(vo.getIsSingleYsdPush())) {
					tszdxx.put("ybsfpl", "否");
				} else {
					tszdxx.put("ybsfpl", "是");
				}
			} else {
				// 是否强制停保：目前仅社保，税友暂不支持医保
				/*if (Common.isNotNull(vo.getSfqztb()) && "是".equals(vo.getSfqztb())) {
					tszdxx.put("sfqztb", vo.getSfqztb());
				}*/
				/*if (Common.isNotNull(vo.getAutoLeaveDoc())) {
					tszdxx.put("shjycl", vo.getAutoLeaveDoc());
				} else {
					if (vo.getImgListYgs() != null && !vo.getImgListYgs().isEmpty()) {
						// 税友接口只允许一张
						tszdxx.put("shjycl", vo.getImgListYgs().get(0));
					}
				}*/

				// 社保是否批量——徽州区目前无社保批量
				/*if (Common.isNotNull(vo.getIsSingleYgsPush()) && CommonConstants.ONE_STRING.equals(vo.getIsSingleYgsPush())) {
					tszdxx.put("sfpl", "否");
				}*/
			}
			cbrymdOne.put("tszdxx", tszdxx);
			cbrymdArr.add(cbrymdOne);
		}
		// 人员名单
		String buyType = "tbrymd";
		json.put(buyType, cbrymdArr);
	}

	// 测试税友线上信息，慎用
	public String getFriendByRequestIdOnlineTest(RestTemplate restTemplate, String requestId, String type) {
		if (Common.isEmpty(requestId)) {
			return "requestId不可为空";
		}
		String appKey = "3082B14EE2114C2D93B3A222DD925C26=";
		String appSecret = "VmURqoxqmoKnNLXzAWynqQ==";
		String appAddUrl = "https://openapi.17win.com";
		if (Common.isNotNull(type) && CommonConstants.ONE_STRING.equals(type)) {
			appAddUrl += urlGetInfoReduce;
		} else {
			appAddUrl += urlGetInfoAdd;
		}
		appAddUrl += "?requestId=" + requestId;
		String version = "1.0.0";
		String timestamp = String.valueOf(new Date().getTime());
		String xReqNonce = "1";
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.add(APP_KEY, appKey);
		headers.add(TIMESTAMP, timestamp);
		try {
			String signature = SocialFriendSign.qianMing(getMapParam(appKey, appSecret, xReqNonce, version, timestamp, requestId));
			headers.add("signature", signature);
		} catch (SignatureException e) {
			log.error("税友签名失败", e);
			return "税友签名失败!";
		}
		headers.add(X_REQ_NONCE, xReqNonce);
		headers.add(VERSION, version);
		HttpEntity<String> formEntity = new HttpEntity<>(headers);
		ResponseEntity<String> response = restTemplate.exchange(appAddUrl, HttpMethod.GET, formEntity, String.class);
		if (Common.isEmpty(response) || Common.isEmpty(response.getBody())) {
			throw new CheckedException("获取税友结果失败");
		}
		int statusCode = response.getStatusCodeValue();
		if (statusCode != 200) {
			throw new CheckedException("获取税友结果失败，statusCode=" + statusCode);
		}
		String dataResultList = response.getBody();
		try {
			// 组装返回结果
			List<FriendResult> resultList = new ArrayList<>();
			if (Common.isNotNull(dataResultList)) {
				JSONObject dataObject = JSON.parseObject(dataResultList);
				String head = dataObject.getString("head");
				if (Common.isNotNull(head)) {
					JSONObject headObject = JSON.parseObject(head);
					String status = headObject.getString("status");
					if ("Y".equals(status)) {
						String body = dataObject.getString("body");
						JSONObject bodyObject = JSON.parseObject(body);
						// 获取核心结果
						if (Common.isNotNull(bodyObject)) {
							// 人员办理项目结果
							JSONArray ryywbljglbArr = (JSONArray) bodyObject.get("ryywbljglb");
							if (Common.isNotNull(ryywbljglbArr)) {
								// 注意：此处可以返回多条身份证，但是我们单条提交
								JSONObject ryywbljglb;
								FriendResult result;
								String idCard;
								JSONArray blxmjglbArr;
								JSONObject blxmjglb;
								String zt;
								String cwxx;
								for (int i = 0; i < ryywbljglbArr.size(); i++) {
									ryywbljglb = (JSONObject) ryywbljglbArr.get(i);
									result = new FriendResult();
									// 身份证
									idCard = ryywbljglb.getString("zzhm");
									result.setIdCard(idCard);
									// 办理项目列表
									blxmjglbArr = (JSONArray) ryywbljglb.get("blxmjglb");
									if (Common.isNotNull(blxmjglbArr)) {
										// 注意：此处可以返回多条办理，但是我们社保与医保分开提交
										blxmjglb = (JSONObject) blxmjglbArr.get(0);
										// 状态1-处理中，2-处理成功，3-处理失败，4-待办(提交成功，待网厅状态流转，上海特有)
										zt = blxmjglb.getString("zt");
										result.setZt(zt);
										// 明细状态：提交失败、审核失败、审核成功、待确认
										//String mxzt = blxmjglb.getString("mxzt")
										// 提示或者错误信息 SUCCESS
										cwxx = blxmjglb.getString("cwxx");
										if (Common.isEmpty(cwxx)) {
											return "requestId:"+requestId+"。详情："+JSON.toJSONString(blxmjglb);
										}
										result.setCwxx(cwxx);
									}
									resultList.add(result);
								}
							}
						}
					}
				}
			}
			resultList.clear();
		} catch (Exception e) {
			return requestId;
		}
		return null;
	}

	/**
	 * @param: type 0增加1减少
	 * @param: requestId ： 请求ID
	 * @Description: 任务查询接口
	 * @Author: hgw
	 * @Date: 2024-12-9 16:54:22
	 * @return: java.lang.String
	 **/
	public List<FriendResult> getFriendByRequestId(RestTemplate restTemplate, String requestId, TSocialFriendBackLog backLog, String type) {
		List<FriendResult> resultList = new ArrayList<>();
		if (Common.isEmpty(requestId)) {
			return resultList;
		}
		String appAddUrl = urlPre;
		if (CommonConstants.ZERO_STRING.equals(type)) {
			appAddUrl += urlGetInfoAdd;
		} else {
			appAddUrl += urlGetInfoReduce;
		}
		appAddUrl += "?requestId=" + requestId;
		String version = "1.0.0";
		String timestamp = String.valueOf(new Date().getTime());
		String xReqNonce = "1";
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.add(APP_KEY, appKey);
		headers.add(TIMESTAMP, timestamp);
		try {
			String signature = SocialFriendSign.qianMing(getMapParam(appKey, appSecret, xReqNonce, version, timestamp, requestId));
			headers.add("signature", signature);
		} catch (SignatureException e) {
			log.error("税友签名失败", e);
			return resultList;
		}
		headers.add(X_REQ_NONCE, xReqNonce);
		headers.add(VERSION, version);
		HttpEntity<String> formEntity = new HttpEntity<>(headers);
		ResponseEntity<String> response = restTemplate.exchange(appAddUrl, HttpMethod.GET, formEntity, String.class);
		if (Common.isEmpty(response) || Common.isEmpty(response.getBody())) {
			throw new CheckedException("获取税友结果失败");
		}
		int statusCode = response.getStatusCodeValue();
		if (statusCode != 200) {
			throw new CheckedException("获取税友结果失败，statusCode=" + statusCode);
		}
		String dataResultList = response.getBody();

		backLog.setCreateTime(LocalDateTime.now());
		backLog.setLogInfo(dataResultList);

		// 组装返回结果
		getResultToVo(dataResultList, resultList);
		return resultList;
	}

	// 组装返回结果
	private void getResultToVo(String dataResultList, List<FriendResult> resultList) {
		if (Common.isNotNull(dataResultList)) {
			JSONObject dataObject = JSON.parseObject(dataResultList);
			String head = dataObject.getString("head");
			if (Common.isNotNull(head)) {
				JSONObject headObject = JSON.parseObject(head);
				String status = headObject.getString("status");
				if ("Y".equals(status)) {
					String body = dataObject.getString("body");
					JSONObject bodyObject = JSON.parseObject(body);
					// 获取核心结果
					getResultToVoCore(resultList, bodyObject);
				}
			}
		}
	}

	// 提取方法，组装核心结果
	private void getResultToVoCore(List<FriendResult> resultList, JSONObject bodyObject) {
		if (Common.isNotNull(bodyObject)) {
			// 人员办理项目结果
			JSONArray ryywbljglbArr = (JSONArray) bodyObject.get("ryywbljglb");
			if (Common.isNotNull(ryywbljglbArr)) {
				// 注意：此处可以返回多条身份证，但是我们单条提交
				JSONObject ryywbljglb;
				FriendResult result;
				String idCard;
				JSONArray blxmjglbArr;
				JSONObject blxmjglb;
				String zt;
				String cwxx;
				String mxzt;
				for (int i = 0; i < ryywbljglbArr.size(); i++) {
					ryywbljglb = (JSONObject) ryywbljglbArr.get(i);
					result = new FriendResult();
					// 身份证
					idCard = ryywbljglb.getString("zzhm");
					result.setIdCard(idCard);
					// 办理项目列表
					blxmjglbArr = (JSONArray) ryywbljglb.get("blxmjglb");
					if (Common.isNotNull(blxmjglbArr)) {
						// 注意：此处可以返回多条办理，但是我们社保与医保分开提交
						blxmjglb = (JSONObject) blxmjglbArr.get(0);
						// 状态1-处理中，2-处理成功，3-处理失败，4-待办(提交成功，待网厅状态流转，上海特有)
						zt = blxmjglb.getString("zt");
						result.setZt(zt);
						// 明细状态：提交失败、审核失败、审核成功、待确认
						//String mxzt = blxmjglb.getString("mxzt")
						// 提示或者错误信息 SUCCESS
						cwxx = blxmjglb.getString("cwxx");
						if (Common.isNotNull(cwxx) && cwxx.length() > 100) {
							cwxx = cwxx.substring(0, 100);
						}
						mxzt = blxmjglb.getString("mxzt");
						if (Common.isNotNull(mxzt)) {
							if (cwxx == null) {
								cwxx = "";
							}
							if (cwxx.length() > 70) {
								cwxx = cwxx.substring(0, 70);
							}
							if (mxzt.length() > 27) {
								mxzt = mxzt.substring(0, 27);
							}
							cwxx += "；【"+mxzt+"】";
						}
						result.setCwxx(cwxx);
					}
					resultList.add(result);
				}
			}
		}
	}

	/*
	 * @Description: 塞请求参数
	 * @Author: hgw
	 * @Date: 2024/12/10 10:38
	 * @return: java.util.TreeMap<java.lang.String,java.lang.String>
	 **/
	private TreeMap<String, String> getMapParam(String appKey, String appSecret, String xReqNonce, String version, String timestamp, String requestId) {
		TreeMap<String, String> treeMap = new TreeMap<>();
		if (Common.isNotNull(requestId)) {
			treeMap.put("requestId", requestId);
		}
		treeMap.put(VERSION, version);
		treeMap.put(TIMESTAMP, timestamp);
		treeMap.put(APP_KEY, appKey);
		treeMap.put(X_REQ_NONCE, xReqNonce);
		treeMap.put("appSecret", appSecret);
		return treeMap;
	}

	/**
	 * @param idNum 身份证
	 * @Description: 获取身份证的性别-汉字（已知身份证正确）
	 * @Author: hgw
	 * @Date: 2024/12/11 17:00
	 * @return: java.lang.String
	 **/
	public static String getSexName(String idNum) {
		String sex = "男";
		if (idNum != null) {
			String sexString = "";
			if (idNum.length() == 18) {
				sexString = idNum.substring(16, 17);
			} else if (idNum.length() == 15) {
				sexString = idNum.substring(14, 15);
			}
			try {
				// 判断性别
				if (Integer.parseInt(sexString) % 2 == 0) {
					sex = "女";
				}
			} catch (Exception e) {
				sex = "男";
			}
		}
		return sex;
	}

	/**
	 * @param idNum 身份证
	 * @Description: 获取身份证的年月日（已知身份证正确）
	 * @Author: hgw
	 * @Date: 2024/12/11 17:07
	 * @return: java.lang.String
	 **/
	public static String getBirthStr(String idNum) {
		String birthStr = "1990-01-01";
		if (idNum != null) {
			if (idNum.length() == 18) {
				birthStr = idNum.substring(6, 10) + "-" + idNum.substring(10, 12) + "-" + idNum.substring(12, 14);
			} else if (idNum.length() == 15) {
				birthStr = "19" + idNum.substring(6, 8) + "-" + idNum.substring(8, 10) + "-" + idNum.substring(10, 12);
			}
		}
		return birthStr;
	}

	/**
	 * @return
	 * @Author fxj
	 * @Description
	 * @Date 14:33 2025/7/15
	 * @Param type  0 社保  1  医保
	 * @Param subType 0 增员  1 减员
	 **/
	public HashMap<String, String> getDownloadEmployeeAsync(RestTemplate restTemplate, SysHouseHoldInfo houseHold,
															SocialSoldierBackVo backVo) {
		HashMap<String, String> result = new HashMap<>();
		try {
			// 构建请求头
			HttpHeaders headers = buildCommonHeaders(null);

			// 构建请求体 JSON
			JSONObject requestBody = buildDownloadRequestJson(houseHold, backVo);
			HttpEntity<String> formEntity = new HttpEntity<>(requestBody.toJSONString(), headers);

			// 发起异步下载请求
			String downloadEmployeeAsyncUrl = urlPre + urlDownloadEmployeeAsync;
			String dataResultList = restTemplate.postForObject(downloadEmployeeAsyncUrl, formEntity, String.class);

			if (Common.isNotNull(dataResultList)) {
				JSONObject response = JSON.parseObject(dataResultList);
				JSONObject head = JSON.parseObject(response.getString("head"));

				if ("Y".equals(head.getString("status"))) {
					String requestId = JSON.parseObject(response.getString("body")).getString("requestId");
					result.put(backVo.getSocialId(), requestId);
				}
			}

		} catch (Exception e) {
			log.error("获取税友人员审核查询证明文件失败", e);
		}

		return result;
	}

	// 构建公共请求头
	private HttpHeaders buildCommonHeaders(String requestId) throws SignatureException {
		String version = "1.0.0";
		String timestamp = String.valueOf(new Date().getTime());
		String xReqNonce = "1";

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.add("accept", MediaType.ALL_VALUE);
		headers.add(APP_KEY, appKey);
		headers.add(TIMESTAMP, timestamp);
		headers.add(X_REQ_NONCE, xReqNonce);
		headers.add(VERSION, version);

		String signature = SocialFriendSign.qianMing(getMapParam(appKey, appSecret, xReqNonce, version, timestamp, requestId));
		headers.add("signature", signature);

		return headers;
	}

	// 构建请求参数 JSON
	private JSONObject buildDownloadRequestJson(SysHouseHoldInfo vo, SocialSoldierBackVo exportVo) {
		JSONObject json = new JSONObject();

		json.put("bizNo", exportVo.getSocialId() + DateUtil.getThisTime());
		json.put("qymc", vo.getName());
		json.put("nsrsbh", vo.getUnitCreditCode());
		json.put("areaid", vo.getAreaCode());

		JSONArray ywblzhlbArr = new JSONArray();
		JSONObject jsonYwblzhlbYgs = new JSONObject();
		jsonYwblzhlbYgs.put("mm", vo.getSocialPassword());
		jsonYwblzhlbYgs.put("blxm", "社保");
		jsonYwblzhlbYgs.put("dwbh", vo.getCustomerNo());
		jsonYwblzhlbYgs.put("zh", vo.getSocialAccount());
		jsonYwblzhlbYgs.put("mmlx", "4");
		ywblzhlbArr.add(jsonYwblzhlbYgs);
		json.put("ywblzhlb", ywblzhlbArr);

		JSONArray rylbArr = new JSONArray();
		JSONObject rylbContent = new JSONObject();
		rylbContent.put("xm", exportVo.getEmpName());
		rylbContent.put("zzlx", "居民身份证");
		rylbContent.put("zzhm", exportVo.getEmpIdcard());
		rylbContent.put("blxmlb", new String[]{});

		JSONObject tszdxx = new JSONObject();
		tszdxx.put("jblx", "增员");
		rylbContent.put("tszdxx", tszdxx);
		rylbArr.add(rylbContent);
		json.put("rylb", rylbArr);

		json.put("ywlx", "个人审核查询证明");
		JSONArray blxmbArr = new JSONArray();
		JSONObject blxm = new JSONObject();
		blxm.put("blxm", "社保");
		blxmbArr.add(blxm);
		json.put("blxmlb", blxmbArr);

		return json;
	}

	// 获取反馈 URL 列表
	public FeedBackUrlVo getDownloadFeedbackUrls(RestTemplate restTemplate, String requestId, List<TSocialFriendBackLog> backLogList, String socialId) {
		FeedBackUrlVo result = new FeedBackUrlVo();
		List<String> urls = new ArrayList<>();
		if (null == backLogList){
			backLogList = new ArrayList<>();
		}
		String downloadEmployeeFeedbackUrl = urlPre + urlDownloadEmployeeFeedback + "?requestId=" + requestId;
		int retryCount = 0;
		final int maxRetries = 4;
		final long delayMillis = 2000; // 2 seconds
		TSocialFriendBackLog  backLog;
		JSONObject dataObject = null;
		String msg = "";
		String zt= "0";
		try {
			// 构建请求头
			HttpHeaders headers = buildCommonHeaders(requestId);
			// 构建请求体
			HttpEntity<String> formEntity = new HttpEntity<>(headers);
			//具体的项目办理状态：1-处理中，2-处理成功，3-处理失败   如果是处理中继续重试2次，处理成功则返回反馈URL
			while (retryCount <= maxRetries) {

				ResponseEntity<String> response = restTemplate.exchange(
						downloadEmployeeFeedbackUrl, HttpMethod.GET, formEntity, String.class);

				// 处理返回值
				if (response != null && response.getStatusCodeValue() == 200) {
					dataObject = JSON.parseObject(response.getBody());
					String head = dataObject.getString("head");

					if (Common.isNotNull(head)) {
						JSONObject headObject = JSON.parseObject(head);
						if ("Y".equals(headObject.getString("status"))) {
							JSONObject bodyObject = JSON.parseObject(dataObject.getString("body"));
							//1:处理中 2:成功 3:失败
							zt = bodyObject.getString("zt");
							if ("2".equals(zt)){
								String ryywbljglb = bodyObject.getString("ryywbljglb");
								JSONArray ryywbljglbArr = JSON.parseArray(ryywbljglb);
								if (ryywbljglbArr != null && !ryywbljglbArr.isEmpty()){
									for (Object itemObj : ryywbljglbArr) {
										JSONObject ryywbljglbItem = (JSONObject) itemObj;
										JSONArray blxmjglbArr = JSON.parseArray(ryywbljglbItem.getString("blxmjglb"));
										if (blxmjglbArr != null && !blxmjglbArr.isEmpty()){
											for (Object blxmjglbObj : blxmjglbArr) {
												JSONObject blxmjglbItem = (JSONObject) blxmjglbObj;
												//具体的项目办理状态：1-处理中，2-处理成功，3-处理失败
												zt = blxmjglbItem.getString("zt");
												if ("2".equals(zt)){
													JSONArray jgmxlbArr = JSON.parseArray(blxmjglbItem.getString("jgmxlb"));
													if (jgmxlbArr != null && !jgmxlbArr.isEmpty()){
														for (Object jgmxlbObj : jgmxlbArr) {
															JSONObject jgmxlbItem = (JSONObject) jgmxlbObj;
															JSONArray wjdzlb = jgmxlbItem.getJSONArray("wjdzlb");

															if (wjdzlb != null && !wjdzlb.isEmpty()) {
																urls.addAll(wjdzlb.toJavaList(String.class));
															}
														}
													}
												}else {
													msg = bodyObject.getString("cwxx");
												}
											}
										}
									}
								}
							}else {
								msg = bodyObject.getString("cwxx");
							}
						}
					}
					// 先记录每次的反馈请求
				}

				// 如果成功获取到数据，则跳出循环
				if (!urls.isEmpty()) {
					break;
				}

				// 如果没有获取到数据，等待一段时间后重试 (处理中重试)
				if (retryCount < maxRetries &&  zt.equals("1")) {
					Thread.sleep(delayMillis*retryCount);
					retryCount++;
				} else {
					break;
				}
			}
		} catch (Exception e) {
			log.error("获取税友人员审核查询证明文件反馈链接失败", e);
		}
		backLog = new TSocialFriendBackLog();
		backLog.setId(socialId);
		backLog.setRequestId(requestId);
		backLog.setSocialId(socialId);
		backLog.setStatus(zt);
		backLog.setType(18);
		backLog.setLogInfo(null==dataObject?"":dataObject.toJSONString());
		backLog.setCreateTime(LocalDateTime.now());
		backLogList.add(backLog);
		result.setUrls(urls);
		result.setRequestId(requestId);
		result.setMsg(msg);
		return result;
	}


}
