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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fadada.api.constants.GlobalConstants;
import com.fadada.api.utils.crypt.FddCryptUtil;
import com.yifu.cloud.plus.v1.yifu.archives.config.FddConfigProperties;
import com.yifu.cloud.plus.v1.yifu.archives.entity.*;
import com.yifu.cloud.plus.v1.yifu.archives.service.*;
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.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @auther huyc
 * @date 2022/6/29
 */
@RestController
@RequestMapping("/fdd")
@Tag(name = "法大大接口")
@Slf4j
@EnableConfigurationProperties(FddConfigProperties.class)
public class FddController {

    private static String FDD_EVENT = "X-FDD-Api-Event";
    private static String FDD_BIZ_CONTENT = "bizContent";

    @Autowired
    private FddConfigProperties fddConfigProperties;
    @Autowired
    private FddReqLogService reqLogService;
    @Autowired
    private FddPersonAccountService fddPersonAccountService;
    @Autowired
    private FddContractInfoService fddContractInfoService;
    @Autowired
    private FddCompanyInfoService fddCompanyInfoService;
    @Autowired
    private FddContractAttachInfoService fddContractAttachInfoService;
    @Autowired
    private TEmployeeContractInfoService employeeContractInfoService;
	
    ExecutorService executorService = Executors.newFixedThreadPool(10);

    /**
     * @param request
     * @Author: huyc
     * @Date: 2022/6/29
     * @Description: 个人实名重定向地址
     * @return: void https://developer-ae.fadada.com/main/apiExplorer?unionId=b8f78299877046428b9a6b3cfc111d11&clientId=151555313861&resultMsg=%E5%AE%A1%E6%A0%B8%E9%80%9A%E8%BF%87&result=0
     * http://192k6337f9.zicp.vip/hrBase/fdd/personRedirectUrl?unionId=c64bbd972c8d48e4846b9230f951cab8&clientId=1351443621139800065&result=0&resultMsg=%25E6%2588%2590%25E5%258A%259F
     **/
	@Operation(summary = "个人实名重定向地址", description = "个人实名重定向地址")
    @RequestMapping(value = "/personRedirectUrl")
    public R<String> personRedirectUrl(HttpServletRequest request) {
        saveReqLog(request);
        String clientId = request.getParameter("clientId");
        String unionId = request.getParameter("unionId");
        //查询clientId
        if (StringUtils.isNotEmpty(clientId) && StringUtils.isNotEmpty(unionId)) {
            FddPersonAccount fddPersonAccount = fddPersonAccountService.getById(clientId);
            if (fddPersonAccount != null) {
                fddPersonAccount.setUnionid(unionId);
                fddPersonAccount.setRealStatus(CommonConstants.ONE_STRING);
                fddPersonAccountService.updateById(fddPersonAccount);
            }
        }
		return R.ok(null,"success");
    }

    /**
     * 保存请求参数日志
     *
     * @param request
     */
    private void saveReqLog(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        FddReqLog fddReqLog = new FddReqLog();
        fddReqLog.setResData(JSON.toJSONString(parameterMap));
        fddReqLog.setMethodName(Thread.currentThread().getStackTrace()[1].getMethodName());
        fddReqLog.setClassName(Thread.currentThread().getStackTrace()[1].getClassName());
        reqLogService.save(fddReqLog);
    }


    /**
     * @param request
     * @Author: huyc
     * @Date: 2022/6/29
     * @Description: 邀请员工重定向地址重定向地址
     * http://192k6337f9.zicp.vip/hrBase/fdd/addEmployeeRedirectUrl?company=a2bd6e2595214824861cad25598d119e&employeeUnionId=f6ac9e9edabe4957bcc2f50611224af6
     **/
	@Operation(summary = "邀请员工重定向地址", description = "邀请员工重定向地址")
    @RequestMapping(value = "/addEmployeeRedirectUrl")
    public R<String> addEmployeeRedirectUrl(HttpServletRequest request) {
        saveReqLog(request);
        String company = request.getParameter("company");
        String employeeUnionId = request.getParameter("employeeUnionId");
        //查询clientId
        if (StringUtils.isNotEmpty(company) && StringUtils.isNotEmpty(employeeUnionId)) {
            FddPersonAccount fddPersonAccount = fddPersonAccountService.getOne(Wrappers.<FddPersonAccount>query().lambda()
                    .eq(FddPersonAccount::getUnionid, employeeUnionId).eq(FddPersonAccount::getSystemFlag,CommonConstants.ZERO_STRING));
            if (fddPersonAccount != null) {
                FddCompanyInfo companyInfo = fddCompanyInfoService.getOne(Wrappers.<FddCompanyInfo>query().lambda().eq(FddCompanyInfo::getCompanyUnionId, company));
                if (companyInfo != null) {
                    if (!Common.isEmpty(fddPersonAccount.getCompanyInfoId())) {
                        fddPersonAccount.setCompanyInfoId(fddPersonAccount.getCompanyInfoId().concat(",").concat(companyInfo.getId()));
                    } else {
                        fddPersonAccount.setCompanyInfoId(companyInfo.getId());
                    }
                    fddPersonAccountService.updateById(fddPersonAccount);
					return R.ok(null,"success");
                }
            }
        }
        return R.failed("回调失败");
    }

    /**
     * @param request
     * @param response
     * @Author: huyc
     * @Date: 2022/6/29
     * @Description: 异步通知
     * @return: void
     **/
	@Operation(summary = "异步通知", description = "异步通知")
    @RequestMapping(value = "/notifyUrl")
    public R<String> notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
		YifuUser user = SecurityUtils.getUser();
        checkSign(request);
        String fddEvent = request.getHeader(FDD_EVENT);
        String fddBizContent = request.getParameter(FDD_BIZ_CONTENT);
        //判断类型
        if (StringUtils.equals(fddEvent, "verify")) {
            //实名认证
            JSONObject jsonObject = JSON.parseObject(fddBizContent);
            String clientId = jsonObject.getString("clientId");
            String unionId = jsonObject.getString("unionId");
            if (StringUtils.equals(CommonConstants.TWO_STRING, jsonObject.getString("status"))) {
                //成功
                FddPersonAccount entity = fddPersonAccountService.getById(clientId);
                if (entity != null) {
                    entity.setRealStatus(CommonConstants.ONE_STRING);
                    entity.setUnionid(unionId);
                    fddPersonAccountService.updateById(entity);
                    if (StringUtils.equals(entity.getSystemFlag(), CommonConstants.ONE_STRING)) {
                        //实名认证成功发送电子合同
                        executorService.submit(() -> {
                            try {
                                //先查询下有没有没发送这个员工没发送的电子合同。如果有则发送
                                List<FddContractAttachInfo> attachInfos = fddContractAttachInfoService.getListByNoInfoByEmpIdcard(entity.getIdCard());
                                //自动创建定稿任务.查看是否有未定稿的数据。有的话自动发送
                                if (attachInfos.size() == CommonConstants.ZERO_INT) {
                                    return;
                                }
                                FddContractAttachInfo fddContractAttachInfo = attachInfos.get(CommonConstants.ZERO_INT);
                               R<String> returnR = fddContractInfoService.saveEmpContract(fddContractAttachInfo,user);
                                if (returnR != null) {
                                    //记录返回信息
                                    if(returnR.getCode()== CommonConstants.SUCCESS){
                                        fddContractAttachInfo.setRemark("成功");
                                    }else {
                                        fddContractAttachInfo.setRemark(returnR.getMsg());
                                    }
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        });
                    }
					return R.ok(null,"success");
                }
            }
        } else if (StringUtils.equals(fddEvent, "reviseTask")) {
            //定稿任务
            JSONObject jsonObject = JSON.parseObject(fddBizContent);
            String taskId = jsonObject.getString("taskId");
            String draftId = jsonObject.getString("draftId");
            if (StringUtils.equals(CommonConstants.ZERO_STRING, jsonObject.getString("result"))) {
                //成功
                FddContractInfo fddContractInfo = fddContractInfoService.getOne(Wrappers.<FddContractInfo>query().lambda().eq(FddContractInfo::getTaskId, taskId));
                if (fddContractInfo != null && StringUtils.isEmpty(fddContractInfo.getDraftId())) {
                    fddContractInfo.setDraftId(draftId);
                    fddContractInfo.setTaskStatus(CommonConstants.TWO_STRING);
                    fddContractInfoService.updateById(fddContractInfo);
                    executorService.submit(() -> {
                        try {
                            //自动创建定稿任务
                            R<String> returnR = fddContractInfoService.createTaskByDraftId(fddContractInfo);
                            if(returnR!=null){
                                //记录返回信息
                                if(returnR.getCode()==CommonConstants.SUCCESS){
                                    fddContractInfo.setRemark("成功");
                                }else {
                                    fddContractInfo.setRemark(returnR.getMsg());
                                }
                                fddContractInfoService.updateById(fddContractInfo);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
					return R.ok(null,"成功");
                }
            }
        } else if (StringUtils.equals(fddEvent, "sign")) {
            /**
             * 定稿任务{"X-FDD-Api-Nonce":"d4f7806145f3435eb67d4b80b5ab8e99","bizContent":"{\"authorizedUnionId\":\"a2bd6e2595214824861cad25598d119e\",\"completeTime\":\"2021-01-27 14:22:23\",\"corpId\":\"a2bd6e2595214824861cad25598d119e\",\"signStatus\":2,\"signerId\":\"f6ac9e9edabe4957bcc2f50611224af6\",\"taskId\":\"b1c7f8f31fd945689bd1e1987257e6ac\",\"taskStatus\":2,\"unionId\":\"f6ac9e9edabe4957bcc2f50611224af6\"}","X-FDD-Api-App-Id":"FA38847543","X-FDD-Api-Timestamp":"2021-01-27 14:31:24.370","X-FDD-Api-Sign-Type":"HMAC-SHA256","X-FDD-Api-Event":"sign"}
             */
            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");
            //成功
            FddContractInfo fddContractInfo = fddContractInfoService.getOne(Wrappers.<FddContractInfo>query().lambda().eq(FddContractInfo::getSignTaskId, taskId));
            if (fddContractInfo == null) {
                return R.failed("未获取到签署任务合同");
            }
            //判断是发送方还是接受方
            if (StringUtils.equals(signerId, fddContractInfo.getReceiveUnionid())) {
                //接受方
                fddContractInfo.setReceiveSignStatus(signStatus);
                fddContractInfo.setSignStatus(taskStatus);
            }
            if (StringUtils.equals(signerId, fddContractInfo.getSendUnionid())) {
                //发送方
                fddContractInfo.setSendSignStatus(signStatus);
                fddContractInfo.setSignStatus(taskStatus);
            }
            fddContractInfoService.updateById(fddContractInfo);

            // 2021-3-15 16:24 hgw 全部签名成功，更新合同的状态：
            if (CommonConstants.TWO_STRING.equals(fddContractInfo.getSendSignStatus())
                    && CommonConstants.TWO_STRING.equals(fddContractInfo.getReceiveSignStatus())) {
                fddContractAttachInfoService.saveEmpAndAttarch(fddContractInfo,user);

                TEmployeeContractInfo ec = employeeContractInfoService.getById(fddContractInfo.getContractId());
                // 如果合同的状态是待电子签，则变更为已电子签
                if (ec != null && ec.getIsSign() != null && ec.getIsSign() == CommonConstants.ONE_INT) {
                    ec.setIsSign(CommonConstants.ZERO_INT);
                    employeeContractInfoService.updateById(ec);
                }
            }
            return R.ok(null,"成功");
        }else if (StringUtils.equals(fddEvent, "notifyUrlVerify")) {
            return R.ok(null,"success");
        }
        return R.failed("失败");
    }


    //验证签名
    public void checkSign(HttpServletRequest request) throws Exception {
        Map<String, String> paraMap = new HashMap<>(8);
        paraMap.put(GlobalConstants.FDD_APPID, request.getHeader(GlobalConstants.FDD_APPID));
        paraMap.put(GlobalConstants.FDD_SIGN_TYPE, request.getHeader(GlobalConstants.FDD_SIGN_TYPE));
        paraMap.put(GlobalConstants.FDD_TIMESTAMP, request.getHeader(GlobalConstants.FDD_TIMESTAMP));
        paraMap.put(GlobalConstants.FDD_NONCE, request.getHeader(GlobalConstants.FDD_NONCE));
        paraMap.put(FDD_EVENT, request.getHeader(FDD_EVENT));
        String fddBizContent = request.getParameter(FDD_BIZ_CONTENT);
        paraMap.put(FDD_BIZ_CONTENT, fddBizContent);
        //得到排序后的字符串，FddCryptUtil为法大大提供得签名工具类
        String sortParam = FddCryptUtil.sortParameters(paraMap);
        //计算之后得到签名 该签名需要放到请求头
        String signature = FddCryptUtil.sign(sortParam, request.getHeader(GlobalConstants.FDD_TIMESTAMP), fddConfigProperties.getAppKey());
        if (StringUtils.equals(signature, request.getHeader(GlobalConstants.FDD_API_SIGN))) {
            FddReqLog fddReqLog = new FddReqLog();
            paraMap.put(GlobalConstants.FDD_TIMESTAMP, request.getHeader(GlobalConstants.FDD_TIMESTAMP));
            fddReqLog.setReqData(signature);
            fddReqLog.setResData(JSON.toJSONString(paraMap));
            fddReqLog.setMethodName(Thread.currentThread().getStackTrace()[1].getMethodName());
            fddReqLog.setClassName(Thread.currentThread().getStackTrace()[1].getClassName());
            reqLogService.save(fddReqLog);
            return;
        }
        throw new CheckedException("签名异常");
    }

}
