package com.mmc.iuav.user.service.fdd.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fadada.sdk.utils.crypt.FddEncryptTool;
import com.fadada.sdk.verify.client.FddVerifyClient;
import com.fadada.sdk.verify.model.req.*;
import com.mmc.iuav.response.ResultBody;
import com.mmc.iuav.response.ResultEnum;
import com.mmc.iuav.user.constant.fdd.FddConnectConstant;
import com.mmc.iuav.user.constant.fdd.FddConstant;
import com.mmc.iuav.user.dao.UserServiceDao;
import com.mmc.iuav.user.dao.fdd.UserFddAuthDao;
import com.mmc.iuav.user.entity.UserAccountDO;
import com.mmc.iuav.user.entity.fdd.FddVerifyInfoDO;
import com.mmc.iuav.user.entity.fdd.UserFddDO;
import com.mmc.iuav.user.model.dto.LoginSuccessDTO;
import com.mmc.iuav.user.model.fdd.dto.UserFddDTO;
import com.mmc.iuav.user.model.fdd.resp.CompanyVerifyResp;
import com.mmc.iuav.user.model.fdd.resp.PersonVerifyResp;
import com.mmc.iuav.user.service.fdd.FddService;
import com.mmc.iuav.user.service.fdd.UserFddAuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * author:zhenjie
 * Date:2022/9/1
 * time:15:46
 */
@Service
public class UserFddAuthServiceImpl implements UserFddAuthService {

    @Autowired
    private FddService fddService;

    @Resource
    private UserServiceDao userServiceDao;

    @Autowired
    private UserFddAuthDao userFddAuthDao;

    @Autowired
    private UserFddAuthService userFddAuthService;

    @Override
    public String register(String uid, String accountType) {
        return fddService.register(uid, accountType);
    }

    @Override
    public ResultBody getPersonVerifyUrl(Integer userAccountId) {
        String unionId;
        UserAccountDO userInfo = userServiceDao.getUserAccountById(userAccountId);
        unionId = this.replaceUnableString(userInfo.getUnionId());
        // 判断是否使用unionId注册过企业认证，如果注册过那就用openid注册
        String companyCustomerId = this.checkRegisterFdd(unionId, 2);
        if (companyCustomerId != null) {
            unionId = this.replaceUnableString(userInfo.getOpenId());
        }
        //验证是否注册个人
        String customerId = this.checkRegisterFdd(unionId, 1);
        if (customerId == null) {
            return ResultBody.error(ResultEnum.REQUEST_PARAM_ILLEGAL_ERROR);
        }
        UserFddDO userFddDO = userFddAuthDao.checkRegisterFdd(unionId, 1);
        if (userFddDO == null) {
            return ResultBody.error(ResultEnum.NOT_FOUND);
        }
        //查看原来是否有申请
        FddVerifyInfoDO verifyInfoDO = userFddAuthDao.getVerifyUrl(userFddDO.getCustomerId());
        if (verifyInfoDO == null) {
            PersonVerifyResp personVerifyResp = this.getPersonVerifyUrl(customerId);
            if (personVerifyResp == null) {
                return ResultBody.error(ResultEnum.REQUEST_PARAM_ILLEGAL_ERROR);
            }
            FddVerifyInfoDO verifyInfoDO1 = new FddVerifyInfoDO();
            verifyInfoDO1.setUserFddId(userFddDO.getId());
            verifyInfoDO1.setCustomerId(customerId);
            verifyInfoDO1.setTransactionNo(personVerifyResp.getTransactionNo());
            verifyInfoDO1.setUrl(personVerifyResp.getUrl());
            userFddAuthDao.insertVerifyInfo(verifyInfoDO1);
            return ResultBody.success(personVerifyResp.getUrl());
        }
        return ResultBody.success(verifyInfoDO.getUrl());
    }

    public PersonVerifyResp getPersonVerifyUrl(String customerId) {
        FddVerifyClient client = new FddVerifyClient(FddConnectConstant.APP_ID, FddConnectConstant.APP_KEY, FddConnectConstant.VERSION, FddConnectConstant.HOST);
        PersonVerifyUrlParams params = new PersonVerifyUrlParams();
        params.setCustomerId(customerId); //客户编号
        params.setVerifiedWay("0"); //实名认证套餐类型
        params.setPageModify("1"); //是否允许用户页面修改 1允许 2不允许
        // 以下是非必填参数
        params.setNotifyUrl(FddConnectConstant.MMC_URL + FddConstant.NOTIFY_E_CERT_RES); //异步回调地址
//        params.setReturnUrl(""); //同步通知url
//        params.setCustomerName(""); //姓名
//        params.setCustomerIdentType(""); //证件类型
//        params.setCustomerIdentNo(""); //证件号码
//        params.setMobile(""); //手机号码
//        params.setIdentFrontPath(""); //证件正面照下载地址
//        params.setIdentBackPath(""); //证件反面照下载地址
//        params.setResultType(""); //刷脸是否显示结果页面
//        params.setCertFlag(""); //是否认证成功后自动申请实名证书
//        params.setCertType(""); //证件类型
//        params.setBankCardNo(""); //个人银行卡
//        params.setOption(""); //不传默认add
//        params.setIdPhotoOptional(""); //是否需要上传身份照片
        params.setIsMinProgram("3"); //是否跳转法大大公证处小程序认证
//        params.setLang("zh"); //zh：中文；en：英文
//        params.setIsAllowOverseasBankCardAuth(""); //海外用户是否支持银行卡认证
//        params.setIdentFrontImg(new File("")); //证件正面照图片文件
//        params.setIdentBackImg(new File("")); //证件反面照图片文件
        String result = client.invokePersonVerifyUrl(params);
        if (!com.alibaba.fastjson.JSONObject.parseObject(result).getString(FddConstant.CODE).equals(FddConstant.SUCCESS)) {
            return null;
        }
        PersonVerifyResp data = com.alibaba.fastjson.JSON.parseObject(com.alibaba.fastjson.JSONObject.parseObject(result).getString(FddConstant.DATA), PersonVerifyResp.class);
        return data;
    }


    @Override
    public ResultBody getCompanyVerifyUrl(Integer port, LoginSuccessDTO loginSuccessDTO) {
        String uId;
        if (port.equals(0)) {
            // 获取小程序用户信息拿到unionId
            UserAccountDO userInfo = userServiceDao.getUserAccountById(loginSuccessDTO.getUserAccountId());
            String unionId = this.replaceUnableString(userInfo.getUnionId());
            // 判断是否用uid注册个人认证，如果用了那么就用openid进行企业认证
            String customerId = this.checkRegisterFdd(unionId, 1);
            if (customerId == null) {
                uId = unionId;
            } else {
                uId = this.replaceUnableString(userInfo.getOpenId());
            }
        } else {
            uId = loginSuccessDTO.getUserAccountId().toString();
        }
        //验证是否注册企业
        String customerId = this.checkRegisterFdd(uId, 2);
        if (customerId == null) {
            return ResultBody.error(ResultEnum.REQUEST_PARAM_ILLEGAL_ERROR);
        }
        UserFddDO userFddDO = userFddAuthDao.checkRegisterFdd(uId, 2);
        if (userFddDO == null) {
            return ResultBody.error(ResultEnum.NOT_FOUND);
        }
        //查看原来是否有申请
        FddVerifyInfoDO verifyInfoDO = userFddAuthDao.getVerifyUrl(userFddDO.getCustomerId());
        if (verifyInfoDO == null) {
            CompanyVerifyResp companyVerifyResp = this.reqCompanyVerifyUrl(customerId);
            if (companyVerifyResp == null) {
                return ResultBody.error(ResultEnum.REQUEST_PARAM_ILLEGAL_ERROR);
            }
            FddVerifyInfoDO verifyInfoDO1 = new FddVerifyInfoDO();
            verifyInfoDO1.setUserFddId(userFddDO.getId());
            verifyInfoDO1.setCustomerId(customerId);
            verifyInfoDO1.setTransactionNo(companyVerifyResp.getTransactionNo());
            verifyInfoDO1.setUrl(companyVerifyResp.getUrl());
            userFddAuthDao.insertVerifyInfo(verifyInfoDO1);
            return ResultBody.success(companyVerifyResp.getUrl());
        }
        return ResultBody.success(verifyInfoDO.getUrl());
    }


    @Override
    public ResultBody notifyECertRes(Map<String, String> map) {
        String appId = map.get("appId");
        String serialNo = map.get("serialNo");
        String customerId = map.get("customerId");
        String status = map.get("status");
        String statusDesc = map.get("statusDesc");
        String certStatus = map.get("certStatus");
        String authenticationType = map.get("authenticationType");
        String timestamp = map.get("timestamp");
        String sign = map.get("sign");
        String sha1 = FddEncryptTool.sha1(FddConnectConstant.APP_KEY + authenticationType + certStatus + customerId + serialNo + status + statusDesc);
        try {
            String md5 = FddEncryptTool.md5Digest(timestamp);
            String outSha1 = FddEncryptTool.sha1(FddConnectConstant.APP_ID + md5 + sha1);
            String base64 = new String(FddEncryptTool.Base64Encode(outSha1.getBytes())).trim();
            if (!base64.equals(sign)) {
                return ResultBody.error(ResultEnum.NOT_FOUND);
            }
            if (!appId.equals(FddConnectConstant.APP_ID)) {
                return ResultBody.error(ResultEnum.NOT_FOUND);
            }
        } catch (Exception e) {
            return ResultBody.error(ResultEnum.NOT_FOUND);
        }
        FddVerifyInfoDO verifyInfoDO = userFddAuthDao.getVerifyUrl(customerId);
        if (verifyInfoDO == null) {
            return ResultBody.error(ResultEnum.NOT_FOUND);
        }
        //修改认证状态
        if ("2".equals(authenticationType)) {
            userFddAuthDao.updateCompanyCertStatus(customerId, status);
        } else {
            userFddAuthDao.updatePersonCertStatus(customerId, status);
        }
        //通过需要申请证书
        if (("2".equals(authenticationType) && "4".equals(status)) || ("1".equals(authenticationType) && "2".equals(status))) {
            fddService.getApplyCert(verifyInfoDO.getCustomerId(), verifyInfoDO.getTransactionNo());
        }
        return ResultBody.success();
    }


    @Override
    public ResultBody findCompanyCertInfo(Integer port, Integer flag, LoginSuccessDTO loginSuccessDTO) {
        String uId;
        String result;
        if (port.equals(0)) {
            UserAccountDO userInfo = userServiceDao.getUserAccountById(loginSuccessDTO.getUserAccountId());
            uId = this.replaceUnableString(userInfo.getUnionId());
            UserFddDO userFddInfo = userFddAuthDao.getAppUserFddInfo(uId);
            if (userFddInfo == null) {
                uId = userFddAuthService.replaceUnableString(userInfo.getOpenId());
            } else {
                if (flag.equals(1)) {
                    Integer accountType = userFddInfo.getAccountType();
                    Integer personVerifyStatus = userFddInfo.getPersonVerifyStatus();
                    boolean isPersonVerified = accountType.equals(1) && !personVerifyStatus.equals(2);
                    if (isPersonVerified) {
                        uId = userFddAuthService.replaceUnableString(userInfo.getOpenId());
                    }
                } else {
                    Integer accountType = userFddInfo.getAccountType();
                    Integer entVerifyStatus = userFddInfo.getEntVerifyStatus();
                    boolean isEntVerified = accountType.equals(1) && !entVerifyStatus.equals(4);
                    if (isEntVerified) {
                        uId = userFddAuthService.replaceUnableString(userInfo.getOpenId());
                    }
                }
            }
        } else {
            uId = loginSuccessDTO.getUserAccountId().toString();
        }

        UserFddDO appUserFddDO = userFddAuthDao.checkRegisterFdd(uId, flag);
        if (appUserFddDO == null) {
            return ResultBody.error(ResultEnum.REQUEST_PARAM_ILLEGAL_ERROR);
        }
        FddVerifyInfoDO fddVerifyInfoDO = userFddAuthDao.getVerifyUrl(appUserFddDO.getCustomerId());
        if (fddVerifyInfoDO == null) {
            return ResultBody.error(ResultEnum.REQUEST_PARAM_ILLEGAL_ERROR);
        }
        FddVerifyClient client = new FddVerifyClient(FddConnectConstant.APP_ID, FddConnectConstant.APP_KEY, FddConnectConstant.VERSION, FddConnectConstant.HOST);
        if (flag.equals(2)) {
            FindCompanyCertParams params = new FindCompanyCertParams();
            //此处填获取企业实名认证地址返回的交易号
            params.setVerifiedSerialNo(fddVerifyInfoDO.getTransactionNo());
            result = client.invokeFindCompanyCert(params);
        } else {
            FindPersonCertParams params = new FindPersonCertParams();
            //此处填获取个人实名认证地址返回的交易号
            params.setVerifiedSerialNo(fddVerifyInfoDO.getTransactionNo());
            result = client.invokeFindPersonCert(params);
        }
        if (!JSONObject.parseObject(result).getString(FddConstant.CODE).equals(FddConstant.SUCCESS)) {
            return ResultBody.error(ResultEnum.NOT_FOUND);
        }
        return ResultBody.success(JSONObject.parseObject(result).getString(FddConstant.DATA));
    }


    @Override
    public ResultBody<List<UserFddDTO>> getAppUserFddInfo(Integer port, LoginSuccessDTO loginSuccessDTO) {
        String uId;
        String openid;
        if (port == 0) {
            UserAccountDO userInfo = userServiceDao.getUserAccountById(loginSuccessDTO.getUserAccountId());
            uId = this.replaceUnableString(userInfo.getUnionId());
            openid = this.replaceUnableString(userInfo.getOpenId());
        } else {
            uId = loginSuccessDTO.getUserAccountId().toString();
            openid = null;
        }
        List<UserFddDO> userFddDO = userServiceDao.listUserFddInfo(uId, openid);
        return ResultBody.success(userFddDO == null ? null : userFddDO.stream().map(UserFddDO::buildUserFddDTO).collect(Collectors.toList()));
    }

    private CompanyVerifyResp reqCompanyVerifyUrl(String customerId) {
        FddVerifyClient client = new FddVerifyClient(FddConnectConstant.APP_ID, FddConnectConstant.APP_KEY, FddConnectConstant.VERSION, FddConnectConstant.HOST);
        CompanyVerifyUrlParams params = new CompanyVerifyUrlParams();
        params.setCustomerId(customerId);
        params.setPageModify("1");//1允许 2不允许 默认为1
        params.setVerifiedWay("3");
        //设置回调通知
        params.setNotifyUrl(FddConnectConstant.MMC_URL + FddConstant.NOTIFY_E_CERT_RES);
        params.setMVerifiedWay("4");
        String result = client.invokeCompanyVerifyUrl(params);
        if (!JSONObject.parseObject(result).getString(FddConstant.CODE).equals(FddConstant.SUCCESS)) {
            return null;
        }
        CompanyVerifyResp data = JSON.parseObject(JSONObject.parseObject(result).getString(FddConstant.DATA), CompanyVerifyResp.class);
        return data;
    }

    private String checkRegisterFdd(String unionId, Integer flag) {
        //查看是否已注册
        UserFddDO userFddDO = userFddAuthDao.checkRegisterFdd(unionId, flag);
        String customerId;
        if (userFddDO == null) {
            //账号类型1个人 2企业
            customerId = this.register(unionId, flag.toString());
            if (customerId == null) {
                return null;
            }
            UserFddDO userFdd = new UserFddDO();
            userFdd.setUnionId(unionId);
            userFdd.setCustomerId(customerId);
            userFdd.setAccountType(flag);
            userFdd.setEntVerifyStatus(0);
            userFdd.setPersonVerifyStatus(0);
            userFddAuthDao.insertAppUserFdd(userFdd);
        } else {
            customerId = userFddDO.getCustomerId();
        }
        return customerId;
    }

    //
    @Override
    public String replaceUnableString(String uid) {
        String u = uid.replaceAll(FddConstant.UID_REGEX, "");
        return u;
    }


    @Override
    public ResultBody getFileByUuid(String uuid, String docType) {
        FddVerifyClient client = new FddVerifyClient(FddConnectConstant.APP_ID, FddConnectConstant.APP_KEY, FddConnectConstant.VERSION, FddConnectConstant.HOST);
        FileForUUIDParams params = new FileForUUIDParams();
        //此处传个人实名认证接口查询中返回的认证图片id，或查询企业认证信息中返回 的企业认证申请表id
        params.setUuid(uuid);
        //0：图片（默认图片）1：pdf (仅支持企业申请表模板)
        params.setDocType(docType);
        String result = client.invokeFileForUUID(params);
        //防止被转移，把字符串转base64
        String base64 = new String(FddEncryptTool.Base64Encode(result.getBytes())).trim();
        return ResultBody.success(base64);
    }
}
