package com.yifu.cloud.plus.v1.yifu.archives.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasc.open.api.bean.base.BaseRes;
import com.fasc.open.api.bean.common.Actor;
import com.fasc.open.api.bean.common.OpenId;
import com.fasc.open.api.bean.common.TemplateField;
import com.fasc.open.api.exception.ApiException;
import com.fasc.open.api.v5_1.client.OpenApiClient;
import com.fasc.open.api.v5_1.client.ServiceClient;
import com.fasc.open.api.v5_1.client.SignTaskClient;
import com.fasc.open.api.v5_1.client.TemplateClient;
import com.fasc.open.api.v5_1.req.signtask.*;
import com.fasc.open.api.v5_1.req.template.GetSignTemplateListReq;
import com.fasc.open.api.v5_1.req.template.GetTemplatePreviewUrlReq;
import com.fasc.open.api.v5_1.req.template.SignTemplateDetailReq;
import com.fasc.open.api.v5_1.req.template.SignTemplateListFilterInfo;
import com.fasc.open.api.v5_1.res.service.AccessTokenRes;
import com.fasc.open.api.v5_1.res.signtask.CreateSignTaskRes;
import com.fasc.open.api.v5_1.res.signtask.SignTaskGetFileRes;
import com.fasc.open.api.v5_1.res.template.*;
import com.yifu.cloud.plus.v1.yifu.archives.config.FascConfig;
import com.yifu.cloud.plus.v1.yifu.archives.entity.*;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TAttaInfoMapper;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.TEmployeeContractPreMapper;
import com.yifu.cloud.plus.v1.yifu.archives.service.TFascPushLogService;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants;
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.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

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

/**
 * @Author: hgw
 * @Date: 2025-9-25 14:24:53
 * @return: 企业法大大专业版配置
 **/
@Component
public class FascUtil {

	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private FascConfig fascConfig;

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

	/**
	 * @Description: 获取token
	 * @Author: huyc
	 * @Date: 2023/7/28 14:46
	 * @return: java.lang.String
	 **/
	public String getFascToken(OpenApiClient openApiClient) throws ApiException {
		String tokenKey = CacheConstants.FASC_ACCOSS_TOKEN;
		Object wxToken = redisTemplate.opsForValue().get(tokenKey);
		if (null != wxToken) {
			return String.valueOf(wxToken);
		}
		if (openApiClient == null) {
			openApiClient = new OpenApiClient(fascConfig.getAppId(), fascConfig.getAppSecret(), fascConfig.getAppUrl());
		}
		ServiceClient serviceClient = new ServiceClient(openApiClient);
		BaseRes<AccessTokenRes> res = serviceClient.getAccessToken();
		String token = null;
		if (res != null && res.isSuccess() && res.getData() != null && res.getData().getAccessToken() != null) {
			token = res.getData().getAccessToken();
		}
		if (Common.isEmpty(token)) {
			throw new CheckedException("获取法大大专业版token失败");
		}
		redisTemplate.opsForValue().set(tokenKey, token);
		redisTemplate.expire(tokenKey, 3600, TimeUnit.SECONDS);
		return token;
	}

	/**
	 * @Description: 获取模板
	 * @Author: hgw
	 * @Date: 2025/10/10 17:59
	 * @return: java.util.List<com.fasc.open.api.v5_1.res.template.SignTemplateListInfo>
	 **/
	public List<SignTemplateListInfo> getTemplateList(String templateName, TFascPushLogService tFascPushLogService)
			throws ApiException {
		OpenApiClient openApiClient = new OpenApiClient(fascConfig.getAppId(), fascConfig.getAppSecret(), fascConfig.getAppUrl());
		TemplateClient templateClient = new TemplateClient(openApiClient);
		String accessToken = this.getFascToken(openApiClient);

		GetSignTemplateListReq getSignTemplateListReq = new GetSignTemplateListReq();
		getSignTemplateListReq.setListPageNo(1);
		getSignTemplateListReq.setListPageSize(100);
		OpenId ownerId = new OpenId();
		ownerId.setIdType(CacheConstants.FASC_ID_TYPE);
		ownerId.setOpenId(fascConfig.getOpenId());
		getSignTemplateListReq.setOwnerId(ownerId);
		SignTemplateListFilterInfo signTemplateListFilterInfo = new SignTemplateListFilterInfo();
		if (Common.isNotNull(templateName)) {
			// 签署任务模板名称，如果传了该参数，会根据名称模糊匹配查询，长度最大100个字符。
			signTemplateListFilterInfo.setSignTemplateName(templateName);
		} else {
			signTemplateListFilterInfo.setSignTemplateName("");
		}
		getSignTemplateListReq.setListFilter(signTemplateListFilterInfo);
		getSignTemplateListReq.setAccessToken(accessToken);

		// 新增推送日志
		TFascPushLog pushLog = new TFascPushLog();
		pushLog.setTransReferenceId(fascConfig.getOpenId());
		pushLog.setPushData(JSON.toJSONString(getSignTemplateListReq, features));
		pushLog.setTaskStatus(CommonConstants.ZERO_STRING);
		pushLog.setTypeKey("获取所有模板");
		pushLog.setTypeName("获取模板");
		tFascPushLogService.save(pushLog);

		BaseRes<SignTemplateListRes> res = templateClient.getSignTemplateList(getSignTemplateListReq);
		List<SignTemplateListInfo> list = null;
		if (res != null) {
			// 更新日志
			pushLog.setReturnData(JSON.toJSONString(res, features));
			pushLog.setTaskStatus(res.isSuccess() ? CommonConstants.ONE_STRING : CommonConstants.TWO_STRING);
			tFascPushLogService.updateById(pushLog);

			if (res.isSuccess() && res.getData() != null && res.getData().getSignTemplates() != null
					&& !res.getData().getSignTemplates().isEmpty()) {
				list = res.getData().getSignTemplates();
				if (res.getData().getListPageCount() != null) {
					int listPageCount = res.getData().getListPageCount();
					// 超过1页的循环查询
					if (listPageCount > 1) {
						for (int i = 2; i <= listPageCount; i++) {
							getSignTemplateListReq.setListPageNo(i);

							pushLog = new TFascPushLog();
							pushLog.setTransReferenceId(fascConfig.getOpenId());
							pushLog.setPushData(JSON.toJSONString(getSignTemplateListReq, features));
							pushLog.setTaskStatus(CommonConstants.ZERO_STRING);
							pushLog.setTypeKey(pushLog.getId() + "获取所有模板" + i);
							pushLog.setTypeName("分页循环获取模板");
							tFascPushLogService.save(pushLog);

							res = templateClient.getSignTemplateList(getSignTemplateListReq);
							if (res != null) {
								// 更新日志
								pushLog.setReturnData(JSON.toJSONString(res, features));
								pushLog.setTaskStatus(res.isSuccess() ? CommonConstants.ONE_STRING : CommonConstants.TWO_STRING);
								tFascPushLogService.updateById(pushLog);

								if (res.getData().getSignTemplates() != null && !res.getData().getSignTemplates().isEmpty()) {
									list.addAll(res.getData().getSignTemplates());
								}
							}
						}
					}
				}
			}
		}
		return list;
	}

	/**
	 * @Description: 获取明细映射
	 * @Author: hgw
	 * @Date: 2025/10/10 17:59
	 * @return: void
	 **/
	public void getTemplateDetailList(List<SignTemplateListInfo> templateList, List<TFascTemplate> tList
			, List<TFascTemplateDetail> detailList, TFascPushLogService tFascPushLogService) throws ApiException {
		OpenApiClient openApiClient = new OpenApiClient(fascConfig.getAppId(), fascConfig.getAppSecret(), fascConfig.getAppUrl());
		TemplateClient templateClient = new TemplateClient(openApiClient);
		String accessToken = this.getFascToken(openApiClient);

		OpenId openId = new OpenId();
		openId.setIdType(CacheConstants.FASC_ID_TYPE);
		openId.setOpenId(fascConfig.getOpenId());
		List<DocumentInfo> list = null;
		if (templateList != null && !templateList.isEmpty()) {
			// 调用查询模板详情接口
			SignTemplateDetailReq signTemplateDetailReq;
			BaseRes<SignTemplateDetailRes> res;
			TFascTemplate template;
			TFascTemplateDetail detail;
			String signTemplateId;
			String fieldType;
			String isMust;
			StringBuilder zhangName;
			String docId;
			for (SignTemplateListInfo mainInfo : templateList) {
				if (mainInfo != null && mainInfo.getSignTemplateId() != null) {
					zhangName = new StringBuilder();
					template = new TFascTemplate();
					signTemplateId = mainInfo.getSignTemplateId();
					template.setSignTemplateId(signTemplateId);
					template.setSignTemplateName(mainInfo.getSignTemplateName());
					template.setSignTemplateStatus(mainInfo.getSignTemplateStatus());
					template.setFascCreateTime(LocalDateTimeUtils.coverStringToLDT(mainInfo.getCreateTime()));
					template.setUpdateTime(LocalDateTimeUtils.coverStringToLDT(mainInfo.getUpdateTime()));
					// 有可能不对：template.setCompanyName(mainInfo.getCatalogName());
					template.setCompanyName(mainInfo.getCatalogName());
					template.setCreatorMemberName(mainInfo.getCreatorMemberName());
					template.setDeleteFlag(CommonConstants.NOT_DELETE_FLAG);
					tList.add(template);

					signTemplateDetailReq = new SignTemplateDetailReq();
					signTemplateDetailReq.setOwnerId(openId);
					signTemplateDetailReq.setSignTemplateId(mainInfo.getSignTemplateId());
					signTemplateDetailReq.setAccessToken(accessToken);

					// 新增推送日志
					TFascPushLog pushLog = new TFascPushLog();
					pushLog.setTransReferenceId(fascConfig.getOpenId());
					pushLog.setPushData(JSON.toJSONString(signTemplateDetailReq, features));
					pushLog.setTaskStatus(CommonConstants.ZERO_STRING);
					pushLog.setTypeKey("获取所有明细映射");
					pushLog.setTypeName("获取明细映射");
					tFascPushLogService.save(pushLog);

					res = templateClient.getSignTemplateDetail(signTemplateDetailReq);

					if (res != null) {
						// 更新日志
						pushLog.setReturnData(JSON.toJSONString(res, features));
						pushLog.setTaskStatus(res.isSuccess() ? CommonConstants.ONE_STRING : CommonConstants.TWO_STRING);
						tFascPushLogService.updateById(pushLog);

						if (res.isSuccess() && res.getData() != null && res.getData().getDocs() != null
								&& !res.getData().getDocs().isEmpty()) {
							if (list == null) {
								list = new ArrayList<>();
							}
							// 循环文档（1,2,3）
							for (DocumentInfo doc : res.getData().getDocs()) {
								if (doc.getDocFields() != null && Common.isNotNull(doc.getDocId())) {
									docId = String.valueOf(doc.getDocId());
									// 循环文档里的字段
									for (TemplateField fields : doc.getDocFields()) {
										fieldType = fields.getFieldType();
										if (Common.isNotNull(fieldType)) {
											if (FascConstants.FIELD_TEXT_TYPE.contains(fieldType)) {
												// 文本数字等控件
												detail = new TFascTemplateDetail();
												detail.setSignTemplateId(signTemplateId);
												detail.setFascDocId(docId);
												detail.setFascField(fields.getFieldName());
												detail.setFascFieldId(fields.getFieldId());
												isMust = CommonConstants.ONE_STRING;
												if (this.isFieldNotRequired(fields, fieldType)) {
													isMust = CommonConstants.ZERO_STRING;
												}
												detail.setIsMust(isMust);
												detail.setDeleteFlag(CommonConstants.NOT_DELETE_FLAG);
												detailList.add(detail);
											} else if (FascConstants.FIELD_ZHANG_TYPE.contains(fieldType)) {
												// 章控件
												if (zhangName.length() > 0) {
													zhangName.append("；");
												}
												zhangName.append(fields.getFieldName());
											}
										}
									}
								}
							}
						}
					}
					template.setZhangName(zhangName.toString());
				}
			}
		}
	}

	/**
	 * @param fields    字段属性
	 * @param fieldType 字段类型
	 * @Description: 统一判断字段是否非必填
	 * @Author: hgw
	 * @Date: 2025/10/10 16:10
	 * @return: boolean
	 **/
	private boolean isFieldNotRequired(TemplateField fields, String fieldType) {
		switch (fieldType) {
			case "text_single_line":
				return fields.getFieldTextSingleLine() != null && Boolean.FALSE.equals(fields.getFieldTextSingleLine().getRequired());
			case "text_multi_line":
				return fields.getFieldTextMultiLine() != null && Boolean.FALSE.equals(fields.getFieldTextMultiLine().getRequired());
			case "number":
				return fields.getFieldNumber() != null && Boolean.FALSE.equals(fields.getFieldNumber().getRequired());
			case "id_card":
				return fields.getFieldIdCard() != null && Boolean.FALSE.equals(fields.getFieldIdCard().getRequired());
			case "fill_date":
				return fields.getFieldFillDate() != null && Boolean.FALSE.equals(fields.getFieldFillDate().getRequired());
			default:
				return false;
		}
	}

	public R<String> submitContract(TEmployeeContractPre contract, TFascPushLogService tFascPushLogService
			, TEmployeeContractPreMapper tEmployeeContractPreMapper
			, TFascTemplate tFascTemplate, List<TFascTemplateDetail> detailList) throws ApiException {
		OpenApiClient openApiClient = new OpenApiClient(fascConfig.getAppId(), fascConfig.getAppSecret(), fascConfig.getAppUrl());
		String accessToken = this.getFascToken(openApiClient);
		OpenId openId = new OpenId();
		openId.setIdType(CacheConstants.FASC_ID_TYPE);
		openId.setOpenId(fascConfig.getOpenId());

		SignTaskClient signTaskClient = new SignTaskClient(openApiClient);
		CreateWithTemplateReq createWithTemplateReq = new CreateWithTemplateReq();
		createWithTemplateReq.setAccessToken(accessToken);
		createWithTemplateReq.setInitiator(openId);
		createWithTemplateReq.setSignTaskSubject("签署合同-" + contract.getEmpIdcard() + CommonConstants.DOWN_LINE_STRING + DateUtil.getThisTime());
		createWithTemplateReq.setAutoStart(false);// 不要自动提交
		createWithTemplateReq.setAutoFillFinalize(true);// 自动定稿
		createWithTemplateReq.setAutoFinish(true);// 签署完成后自动结束
		createWithTemplateReq.setCertCAOrg("CFCA");// 签署参与方使用的签章证书颁发机构，默认无要求。CFCA：要求使用CFCA（中国金融认证中心）；EZCA：要求使用东方中讯CA
		createWithTemplateReq.setSignTemplateId(contract.getFadadaTemplateId());

		// 核心代码：设置参与方列表
		createWithTemplateReq.setActors(this.buildActors(contract));
		// 新增推送日志
		TFascPushLog pushLog = new TFascPushLog();
		pushLog.setTransReferenceId(fascConfig.getOpenId());
		pushLog.setPushData(JSON.toJSONString(createWithTemplateReq, features));
		pushLog.setTaskStatus(CommonConstants.ZERO_STRING);
		String empIdCard = contract.getEmpIdcard();
		pushLog.setTypeKey("发起合同签署任务，身份证：" + empIdCard);
		pushLog.setTypeName("发起合同签署任务");
		pushLog.setContractId(contract.getId());
		tFascPushLogService.save(pushLog);

		BaseRes<CreateSignTaskRes> res = signTaskClient.createWithTemplate(createWithTemplateReq);
		String requestId = null;
		String msg = "法大大第一步创建签署任务失败！";
		if (res != null) {
			// 更新日志
			pushLog.setReturnData(JSON.toJSONString(res, features));
			pushLog.setTaskStatus(res.isSuccess() ? CommonConstants.ONE_STRING : CommonConstants.TWO_STRING);
			if (res.isSuccess() && res.getData() != null && res.getData().getSignTaskId() != null) {
				requestId = res.getData().getSignTaskId();
				pushLog.setSignTaskId(requestId);
			}
			tFascPushLogService.updateById(pushLog);
			if (Common.isNotNull(requestId)) {
				// 第二步：填写控件
				R<String> sendValue = buildDocFieldValue(contract, requestId, openApiClient, accessToken, detailList);
				if (R.isSuccess(sendValue)) {
					// 第三步：提交任务
					sendValue = submitTask(requestId, openApiClient, accessToken);
					if (R.isSuccess(sendValue)) {
						// 电子签签署中
						this.doSuccessContract(contract, tEmployeeContractPreMapper, requestId);
						return R.ok();
					} else {
						msg = "第三步失败：提交任务失败：" + sendValue.getMsg();
					}
				} else {
					msg = "第二步失败：填写控件失败：" + sendValue.getMsg();
				}
			} else {
				msg = "第一步失败：" + res.getMsg();
			}
		}
		this.doFailContract(contract, tEmployeeContractPreMapper, msg);
		return R.failed(msg);
	}

	// 发起失败，更新合同状态
	private void doFailContract(TEmployeeContractPre contract, TEmployeeContractPreMapper tEmployeeContractPreMapper, String msg) {
		contract.setProcessStatus(CommonConstants.dingleDigitStrArray[7]);
		contract.setRequestMsg(msg);
		tEmployeeContractPreMapper.updateById(contract);
	}

	// 发起成功，更新合同状态
	private void doSuccessContract(TEmployeeContractPre contract, TEmployeeContractPreMapper tEmployeeContractPreMapper, String requestId) {
		// 电子签签署中
		contract.setProcessStatus(CommonConstants.dingleDigitStrArray[6]);
		contract.setRequestId(requestId);
		contract.setRequestMsg("");
		tEmployeeContractPreMapper.updateById(contract);
	}


	// 第二步：填写控件
	private R<String> buildDocFieldValue(TEmployeeContractPre contract, String requestId
			, OpenApiClient openApiClient, String accessToken
			, List<TFascTemplateDetail> detailList) throws ApiException {
		SignTaskClient signTaskClient = new SignTaskClient(openApiClient);
		FillFieldValuesReq fillFieldValuesReq = new FillFieldValuesReq();
		fillFieldValuesReq.setSignTaskId(requestId);
		List<DocFieldValueInfo> docFieldValues = new ArrayList<>();

		if (detailList != null && !detailList.isEmpty()) {
			DocFieldValueInfo dfv;
			String fieldValue;
			String fieldName;
			for (TFascTemplateDetail detail : detailList) {
				if (Common.isNotNull(detail.getHrFieldId()) && Common.isNotNull(detail.getHrField())) {
					dfv = new DocFieldValueInfo();
					dfv.setDocId(detail.getFascDocId());
					dfv.setFieldId(detail.getFascFieldId());

					// 转化字段
					fieldName = detail.getHrFieldId();
					if (FascConstants.CONTRACT_DURATION.equals(fieldName)) {
						fieldValue = contract.getContractDurationYear() + CommonConstants.DOWN_LINE_STRING + contract.getContractDurationMonth();
					} else if (FascConstants.DISPATCH_PERIOD.equals(fieldName)) {
						fieldValue = contract.getDispatchPeriodYear() + CommonConstants.DOWN_LINE_STRING + contract.getDispatchPeriodMonth();
					} else {
						fieldValue = this.getContractFieldValueByReflection(contract, fieldName);
					}
					dfv.setFieldValue(fieldValue);

					docFieldValues.add(dfv);
				}
			}
		}
		/*DocFieldValueInfo dfv = new DocFieldValueInfo();
		dfv.setDocId("78112332");
		dfv.setFieldId("9738851979");
		dfv.setFieldValue(contract.getEmployeeName());
		docFieldValues.add(dfv);
		dfv = new DocFieldValueInfo();
		dfv.setDocId("78112332");
		dfv.setFieldId("2324432163");
		dfv.setFieldValue(contract.getEmpIdcard());
		docFieldValues.add(dfv);*/

		fillFieldValuesReq.setDocFieldValues(docFieldValues);
		fillFieldValuesReq.setAccessToken(accessToken);
		BaseRes<Void> res = signTaskClient.fillFieldValues(fillFieldValuesReq);
		if (res != null) {
			if (res.isSuccess()) {
				return R.ok();
			}
			return R.failed(res.getMsg());
		}
		return R.failed("res无返回");
	}

	/**
	 * 使用反射根据字段名获取合同对象中对应字段的值
	 * @param contract 合同对象
	 * @param fieldName 字段名
	 * @return 字段值
	 */
	private String getContractFieldValueByReflection(TEmployeeContractPre contract, String fieldName) {
		if (contract == null || fieldName == null) {
			return null;
		}

		try {
			// 获取对应的getter方法名
			String getterMethodName = "get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);

			// 获取方法并调用
			java.lang.reflect.Method method = contract.getClass().getMethod(getterMethodName);
			Object value = method.invoke(contract);

			return value != null ? value.toString() : null;
		} catch (Exception e) {
			// 如果找不到对应的方法，尝试直接匹配字段名
			try {
				java.lang.reflect.Field field = contract.getClass().getDeclaredField(fieldName);
				field.setAccessible(true);
				Object value = field.get(contract);
				return value != null ? value.toString() : null;
			} catch (Exception ex) {
				return null;
			}
		}
	}

	// 第三步：提交任务
	private R<String> submitTask(String requestId, OpenApiClient openApiClient, String accessToken) throws ApiException {
		SignTaskClient signTaskClient = new SignTaskClient(openApiClient);
		SignTaskBaseReq signTaskBaseReq = new SignTaskBaseReq();
		signTaskBaseReq.setSignTaskId(requestId);
		signTaskBaseReq.setAccessToken(accessToken);
		BaseRes<Void> res = signTaskClient.start(signTaskBaseReq);
		if (res != null) {
			if (res.isSuccess()) {
				return R.ok();
			}
			return R.failed(res.getMsg());
		}
		return R.failed("res无返回");
	}

	/**
	 * 构建参与方列表
	 */
	private List<AddActorsTempInfo> buildActors(TEmployeeContractPre contract) {
		List<AddActorsTempInfo> actors = new ArrayList<>();

		// 添加企业方（甲方）
		actors.add(buildCompanyActor(contract));

		// 核心代码：添加员工方（乙方）
		actors.add(buildEmployeeActor(contract));

		return actors;
	}

	/**
	 * 构建企业方参与方
	 */
	private AddActorsTempInfo buildCompanyActor(TEmployeeContractPre contract) {

		AddActorsTempInfo companyActor = new AddActorsTempInfo();

		Actor actor = new Actor();
		// TODO - 改造签署openID到mysql表里配置
		// TODO - 参与方1 在模板详情接口返回
		actor.setActorId("发起企业"); // 与模板中的参与方标识一致
		actor.setActorType(CacheConstants.FASC_ID_TYPE);
		actor.setActorName("安徽皖信人力资源管理有限公司");

		// 权限设置
		actor.setPermissions(Collections.singletonList("sign"));

		// 企业OpenId
		actor.setActorOpenId(fascConfig.getOpenId());

		// 通知设置
		actor.setSendNotification(true);
		// 通知地址:注：如参与方已传actorOpenId、acterFDDId或accountName，该字段会被忽略
		/*if Common.isNotNull(contract.getEmpPhone()))
			actor.setNotifyAddress(contract.getEmpPhone()
		}*/
		actor.setNotifyType(Collections.singletonList("start"));

		companyActor.setActor(actor);

		return companyActor;
	}

	/**
	 * 构建员工方参与方
	 */
	private AddActorsTempInfo buildEmployeeActor(TEmployeeContractPre contract) {
		AddActorsTempInfo employeeActor = new AddActorsTempInfo();

		Actor actor = new Actor();
		// TODO - 改造签署openID到mysql表里配置
		// TODO - 参与方1 在模板详情接口返回
		actor.setActorId("个人签署"); // 与模板中的参与方标识一致
		actor.setActorType(CacheConstants.FASC_ID_TYPE_PERSON);
		actor.setActorName(contract.getEmployeeName());

		// 权限设置
		actor.setPermissions(Collections.singletonList("sign"));

		// 通知设置
		actor.setSendNotification(true);
		if (Common.isNotNull(contract.getEmpPhone())) {
			actor.setNotifyAddress(contract.getEmpPhone());
		}
		actor.setNotifyType(Collections.singletonList("start"));


		employeeActor.setActor(actor);


		return employeeActor;
	}


	// 撤销签署
	public R<String> cancelTask(TEmployeeContractPre contract, TFascPushLogService tFascPushLogService
			, TEmployeeContractPreMapper tEmployeeContractPreMapper) throws ApiException {
		OpenApiClient openApiClient = new OpenApiClient(fascConfig.getAppId(), fascConfig.getAppSecret(), fascConfig.getAppUrl());
		String accessToken = this.getFascToken(openApiClient);

		SignTaskClient signTaskClient = new SignTaskClient(openApiClient);
		SignTaskCancelReq signTaskCancelReq = new SignTaskCancelReq();
		signTaskCancelReq.setSignTaskId(contract.getRequestId());
		signTaskCancelReq.setAccessToken(accessToken);
		// 新增推送日志
		TFascPushLog pushLog = new TFascPushLog();
		pushLog.setTransReferenceId(fascConfig.getOpenId());
		pushLog.setPushData(JSON.toJSONString(signTaskCancelReq, features));
		pushLog.setTaskStatus(CommonConstants.ZERO_STRING);
		String empIdCard = contract.getEmpIdcard();
		pushLog.setTypeKey("发起撤销签署任务，身份证：" + empIdCard);
		pushLog.setTypeName("发起撤销签署任务");
		pushLog.setContractId(contract.getId());
		tFascPushLogService.save(pushLog);
		BaseRes<Void> res = signTaskClient.cancel(signTaskCancelReq);
		if (res != null) {
			pushLog.setReturnData(JSON.toJSONString(res, features));
			pushLog.setTaskStatus(res.isSuccess() ? CommonConstants.ONE_STRING : CommonConstants.TWO_STRING);
			tFascPushLogService.updateById(pushLog);
			if (res.isSuccess()) {
				contract.setProcessStatus(CommonConstants.dingleDigitStrArray[1]);
				contract.setSignType(CommonConstants.dingleDigitStrArray[1]);
				contract.setRequestMsg("");
				tEmployeeContractPreMapper.updateById(contract);
				return R.ok();
			} else {
				// 撤销签署失败原因为 已完成签署（处理的同时员工完成签署公司免验证签完成），则更新为签署完成的“待归档”状态。
				if (Common.isNotNull(res.getMsg()) && FascConstants.FIELD_REASON.equals(res.getMsg())) {
					contract.setProcessStatus(CommonConstants.dingleDigitStrArray[8]);
					contract.setRevokeReason(FascConstants.TIME_OUT_REASON);
				}
				contract.setRequestMsg(res.getMsg());
				tEmployeeContractPreMapper.updateById(contract);
				return R.failed(res.getMsg());
			}
		}
		return R.failed("res无返回");
	}


	// 催办
	public R<String> urgeTask(TEmployeeContractPre contract, TFascPushLogService tFascPushLogService
			, TEmployeeContractPreMapper tEmployeeContractPreMapper) throws ApiException {
		OpenApiClient openApiClient = new OpenApiClient(fascConfig.getAppId(), fascConfig.getAppSecret(), fascConfig.getAppUrl());
		String accessToken = this.getFascToken(openApiClient);

		SignTaskClient signTaskClient = new SignTaskClient(openApiClient);
		SignTaskBaseReq signTaskBaseReq = new SignTaskBaseReq();
		signTaskBaseReq.setSignTaskId(contract.getRequestId());
		signTaskBaseReq.setAccessToken(accessToken);

		// 新增推送日志
		TFascPushLog pushLog = new TFascPushLog();
		pushLog.setTransReferenceId(fascConfig.getOpenId());
		pushLog.setPushData(JSON.toJSONString(signTaskClient, features));
		pushLog.setTaskStatus(CommonConstants.ZERO_STRING);
		String empIdCard = contract.getEmpIdcard();
		pushLog.setTypeKey("发起催办任务，身份证：" + empIdCard);
		pushLog.setTypeName("发起催办任务");
		pushLog.setContractId(contract.getId());
		tFascPushLogService.save(pushLog);

		BaseRes<Void> res = signTaskClient.signTaskUrge(signTaskBaseReq);
		if (res != null) {
			pushLog.setReturnData(JSON.toJSONString(res, features));
			pushLog.setTaskStatus(res.isSuccess() ? CommonConstants.ONE_STRING : CommonConstants.TWO_STRING);
			tFascPushLogService.updateById(pushLog);
			if (res.isSuccess()) {
				return R.ok();
			} else {
				contract.setRequestMsg(res.getMsg());
				tEmployeeContractPreMapper.updateById(contract);
				return R.failed(res.getMsg());
			}
		}
		return R.failed("res无返回");
	}


	// 获取模板详情预览链接
	public R<String> getTemplateDetailUrl(String signTemplateId, TFascPushLogService tFascPushLogService) throws ApiException {
		OpenApiClient openApiClient = new OpenApiClient(fascConfig.getAppId(), fascConfig.getAppSecret(), fascConfig.getAppUrl());
		String accessToken = this.getFascToken(openApiClient);

		TemplateClient templateClient = new TemplateClient(openApiClient) ;
		GetTemplatePreviewUrlReq getTemplatePreviewUrlReq =  new GetTemplatePreviewUrlReq() ;
		getTemplatePreviewUrlReq.setOpenCorpId(fascConfig.getOpenId()) ;
		getTemplatePreviewUrlReq.setTemplateId(signTemplateId) ;
		getTemplatePreviewUrlReq.setAccessToken(accessToken) ;


		// 新增推送日志
		TFascPushLog pushLog = new TFascPushLog();
		pushLog.setTransReferenceId(fascConfig.getOpenId());
		pushLog.setPushData(JSON.toJSONString(templateClient, features));
		pushLog.setTaskStatus(CommonConstants.ZERO_STRING);
		pushLog.setTypeKey("获取模板详情预览链接，signTemplateId：" + signTemplateId);
		pushLog.setTypeName("获取模板详情预览链接");
		pushLog.setContractId(signTemplateId);
		tFascPushLogService.save(pushLog);

		BaseRes<GetTemplatePreviewUrlRes> res = templateClient.getTemplatePreviewUrl(getTemplatePreviewUrlReq) ;
		if (res != null) {
			pushLog.setReturnData(JSON.toJSONString(res, features));
			pushLog.setTaskStatus(res.isSuccess() ? CommonConstants.ONE_STRING : CommonConstants.TWO_STRING);
			tFascPushLogService.updateById(pushLog);
			if (res.isSuccess() && Common.isNotNull(res.getData())) {
				return R.ok(res.getData().getTemplatePreviewUrl());
			} else {
				return R.failed(res.getMsg());
			}
		}
		return R.failed("res无返回");
	}

	// 获取附件
	public boolean getFileByRequestId(TEmployeeContractPre contract, TFascPushLogService tFascPushLogService
			, TAttaInfoMapper tAttaInfoMapper, OSSUtil ossUtil) throws ApiException {
		OpenApiClient openApiClient = new OpenApiClient(fascConfig.getAppId(), fascConfig.getAppSecret(), fascConfig.getAppUrl());
		String accessToken = this.getFascToken(openApiClient);

		SignTaskClient signTaskClient = new SignTaskClient(openApiClient);
		SignTaskGetFileReq signTaskGetFileReq = new SignTaskGetFileReq();
		signTaskGetFileReq.setSignTaskId(contract.getRequestId());
		signTaskGetFileReq.setAccessToken(accessToken);

		// 新增推送日志
		TFascPushLog pushLog = new TFascPushLog();
		pushLog.setTransReferenceId(fascConfig.getOpenId());
		pushLog.setPushData(JSON.toJSONString(signTaskClient, features));
		pushLog.setTaskStatus(CommonConstants.ZERO_STRING);
		String empIdCard = contract.getEmpIdcard();
		pushLog.setTypeKey("获取附件，身份证：" + empIdCard);
		pushLog.setTypeName("获取附件");
		pushLog.setContractId(contract.getId());
		tFascPushLogService.save(pushLog);

		BaseRes<SignTaskGetFileRes> res = signTaskClient.signTaskGetFile(signTaskGetFileReq);
		if (res != null) {
			pushLog.setReturnData(JSON.toJSONString(res, features));
			pushLog.setTaskStatus(res.isSuccess() ? CommonConstants.ONE_STRING : CommonConstants.TWO_STRING);
			tFascPushLogService.updateById(pushLog);
			if (res.isSuccess()) {
				if (Common.isNotNull(res.getData()) && Common.isNotNull(res.getData().getDocs())) {
					for (SignTaskGetFileRes.DocFileInfo doc : res.getData().getDocs()) {
						if (Common.isNotNull(doc.getFddFileUrl())) {
							// 存储文档
							// 将法大大回传的url字符串转化为流，存储到阿里云
							this.streamUpload(doc.getFddFileUrl(), ossUtil, tAttaInfoMapper, contract.getContractId(), doc.getDocName());
						}
					}
				}
				return true;
			} else {
				return false;
			}
		}
		return false;
	}

	public void streamUpload(String fileUrl, OSSUtil ossUtil, TAttaInfoMapper tAttaInfoMapper, String domainId, String fileName) {
		InputStream inputStream = null;
		HttpURLConnection connection = null;

		try {
			// 创建URL连接
			URL url = new URL(fileUrl);
			connection = (HttpURLConnection) url.openConnection();
			connection.setRequestMethod("GET");
			connection.setConnectTimeout(30000);
			connection.setReadTimeout(60000);
			// 获取输入流
			inputStream = connection.getInputStream();

			String fileType = ".pdf";
			fileName += fileType;
			// Bucket 命名规范：1)只能包括小写字母，数字和短横线（-）；2)必须以小写字母或者数字开头；3)长度必须在 3-63 字节之间。
			String ossKey = "fasc/" + domainId + "/" + System.currentTimeMillis() + fileName;

			// 直接流式上传到OSS
			ossUtil.uploadFileByStream(inputStream, ossKey, null);
			TAttaInfo unitAtta = new TAttaInfo();
			unitAtta.setDomainId(domainId);
			unitAtta.setRelationType(CommonConstants.FOUR_STRING);
			unitAtta.setAttaName(fileName);
			unitAtta.setAttaSrc(ossKey);
			unitAtta.setAttaType(fileType);
			unitAtta.setCreateTime(LocalDateTime.now());
			unitAtta.setCreateName("法大大电子签");
			tAttaInfoMapper.insert(unitAtta);

		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("法大大附件流式上传失败: " + e.getMessage());
		} finally {
			// 关闭资源
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (connection != null) {
				connection.disconnect();
			}
		}
	}

}
