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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fadada.api.utils.crypt.FddCryptUtil;
import com.fasc.open.api.constants.RequestConstants;
import com.fasc.open.api.exception.ApiException;
import com.yifu.cloud.plus.v1.yifu.archives.config.FascConfig;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TFascPushLog;
import com.yifu.cloud.plus.v1.yifu.archives.service.FascService;
import com.yifu.cloud.plus.v1.yifu.archives.service.TFascPushLogService;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

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

/**
 * @auther huyc
 * @date 2022/6/29
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/fasc")
@Tag(name = "法大大专业版接口")
public class FascController {

	@Autowired
	private FascService fascService;
	@Autowired
	private FascConfig fascConfig;

	private final TFascPushLogService tFascPushLogService;

	private static String FASC_EVENT = "X-FASC-Event";
	private static String FASC_BIZ_CONTENT = "bizContent";

	/**
	 * @param templateName 签署任务模板名称，如果传了该参数，会根据名称模糊匹配查询，长度最大100个字符。
	 * @Description: 获取模板
	 * @Author: hgw
	 * @Date: 2025/9/26 16:21
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	@Operation(description = "获取模板")
	@GetMapping("/getTemplate")
	public R<String> getTemplate(@RequestParam(required = false) String templateName) throws ApiException {
		return fascService.getTemplate(templateName);
	}

	/**
	 * @param id 合同待签订任务记录表TEmployeeContractPre：id
	 * @Description: 发起电子签署
	 * @Author: hgw
	 * @Date: 2025/10/13 17:24
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	@Operation(description = "发起电子签署")
	@GetMapping("/submitContract")
	public R<String> submitContract(@RequestParam String id) throws ApiException {
		return fascService.submitContract(id);
	}

	/**
	 * @param id 合同待签订任务记录表TEmployeeContractPre：id
	 * @Description: 撤销签署
	 * @Author: hgw
	 * @Date: 2025/10/13 17:24
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	@Operation(description = "撤销签署")
	@GetMapping("/cancelTask")
	public R<String> cancelTask(@RequestParam String id) throws ApiException {
		return fascService.cancelTask(id);
	}

	/**
	 * @param id 合同待签订任务记录表TEmployeeContractPre：id
	 * @Description: 催办
	 * @Author: hgw
	 * @Date: 2025/10/13 17:24
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	@Operation(description = "催办")
	@GetMapping("/urgeTask")
	public R<String> urgeTask(@RequestParam String id) throws ApiException {
		return fascService.urgeTask(id);
	}


	// 法大大回调
	/*@ResponseBody
	@PostMapping(value = "/api/fascCallback")
	public String fddEventCallback(@RequestHeader HttpHeaders headers,
								   @RequestParam("bizContent") String bizContent) throws Exception {
		//appSecret，由开发者登陆到法大大官网，在应用管理管理中点击应用详情里面获取
		String appSecret = "xxxx";
		//获取请求头参数
		String appId = headers.getFirst("X-FASC-App-Id");
		String signType = headers.getFirst("X-FASC-Sign-Type");
		String sign = headers.getFirst("X-FASC-Sign");
		String timestamp = headers.getFirst("X-FASC-Timestamp");
		//事件名称，开发者可以根据不同事件名称去解析bizContent的值，实现不同的逻辑
		String event = headers.getFirst("X-FASC-Event");
		String nonce = headers.getFirst("X-FASC-Nonce");
		//验签
		Map<String, String> paramMap = new HashMap<>();
		paramMap.put("X-FASC-App-Id", appId);
		paramMap.put("X-FASC-Sign-Type", "HMAC-SHA256");
		paramMap.put("X-FASC-Timestamp", timestamp);
		paramMap.put("X-FASC-Nonce", nonce);
		paramMap.put("X-FASC-Event", event);
		paramMap.put("bizContent", bizContent);
		//参数排序，ascii码排序
		String sortParam = FddCryptUtil.sortParameters(paramMap);
		//生成签名后可以进行校验
		String signature =  FddCryptUtil.sign(sortParam, timestamp, appSecret);
		if(!signature.equals(sign)) {
			//log.error("日志记录，签名失败");
			//为了不重复接收该请求，建议这里返回success，返回success后这条消息法大大将中断重试回调机制
			return "{\"code\":\"200\";\"msg\":\"success\"}";
		}
		return "{\"code\":\"200\";\"msg\":\"success\"}";
	}*/

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

	@Operation(summary = "异步通知", description = "异步通知")
	@RequestMapping(value = "/api/fascCallback")
	public R<String> notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 新增推送日志
		TFascPushLog pushLog = new TFascPushLog();
		pushLog.setTransReferenceId(fascConfig.getOpenId());
		pushLog.setTaskStatus(CommonConstants.ONE_STRING);
		pushLog.setTypeKey("签署任务事件，异步通知");
		pushLog.setTypeName("签署任务事件，异步通知");
		tFascPushLogService.save(pushLog);

		if (checkSign(request, pushLog)) {
			pushLog.setTaskStatus(CommonConstants.TWO_STRING);
			tFascPushLogService.updateById(pushLog);
			return R.failed("验签失败");
		}
		tFascPushLogService.updateById(pushLog);
		String fddEvent = request.getHeader(FASC_EVENT);
		String fddBizContent = request.getParameter(FASC_BIZ_CONTENT);
		if (Common.isNotNull(fddEvent)) {
			JSONObject jsonObject = JSON.parseObject(fddBizContent);
			String taskId = jsonObject.getString("taskId");
			String taskStatus = jsonObject.getString("taskStatus");
			String signStatus = jsonObject.getString("signStatus");
			String signerId = jsonObject.getString("signerId");

			pushLog.setReturnData("fddEvent：" + fddEvent + "；fddBizContent：" + fddBizContent);
			if (fddEvent.equals("sign-task-finished")) {
				pushLog.setReturnData("签署任务完成事件：fddEvent：" + fddEvent + "；fddBizContent：" + fddBizContent);
				return R.ok(null, "success");
			} else if (fddEvent.equals("sign-task-canceled")) {
				pushLog.setReturnData("签署任务撤销事件：fddEvent：" + fddEvent + "；fddBizContent：" + fddBizContent);
				return R.ok(null, "success");
			} else if (fddEvent.equals("sign-task-sign-failed")) {
				pushLog.setReturnData("签署任务参与方签署失败事件：fddEvent：" + fddEvent + "；fddBizContent：" + fddBizContent);
				return R.ok(null, "success");
			} else if (fddEvent.equals("sign-task-abolish")) {
				pushLog.setReturnData("签署任务作废事件：fddEvent：" + fddEvent + "；fddBizContent：" + fddBizContent);
				return R.ok(null, "success");
			}
			tFascPushLogService.updateById(pushLog);
		}

		return R.ok(null, "success");
	}

	//验证签名，返回true表示失败
	public boolean checkSign(HttpServletRequest request, TFascPushLog pushLog) throws Exception {

		Map<String, String> paraMap = new HashMap<>();
		paraMap.put(RequestConstants.APP_ID, request.getHeader(RequestConstants.APP_ID));
		paraMap.put(RequestConstants.SIGN_TYPE, request.getHeader(RequestConstants.SIGN_TYPE));

		String timeStamp = request.getHeader(RequestConstants.TIMESTAMP);
		paraMap.put(RequestConstants.TIMESTAMP, timeStamp);
		paraMap.put(RequestConstants.NONCE, request.getHeader(RequestConstants.NONCE));
		paraMap.put(FASC_EVENT, request.getHeader(FASC_EVENT));
		paraMap.put(FASC_BIZ_CONTENT, request.getParameter(FASC_BIZ_CONTENT));
		//参数排序，ascii码排序
		String sortParam = FddCryptUtil.sortParameters(paraMap);
		pushLog.setPushData(sortParam);
		//计算之后得到签名 该签名需要放到请求头
		if (Common.isEmpty(sortParam) || Common.isEmpty(timeStamp)) {
			return true;
		}
		String signature = FddCryptUtil.sign(sortParam, timeStamp, fascConfig.getAppSecret());
		if (StringUtils.equals(signature, request.getHeader(RequestConstants.SIGN))) {
			return false;
		}
		// 表示验签失败：
		return true;
	}

}
