package org.jeecg.common.util;

import cn.hutool.core.util.BooleanUtil;
import com.alibaba.fastjson.JSON;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.faceid.v20180301.FaceidClient;
import com.tencentcloudapi.iai.v20180301.IaiClient;
import com.tencentcloudapi.iai.v20180301.models.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.config.TencentConfig;
import org.jeecg.modules.clockinauth.entity.ClockinAuth;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.UUID;

@Slf4j
@Component
@RequiredArgsConstructor
public class TencentUtils {

    private static TencentUtils tencentUtils;


    /**
     * 要在静态方法里面调用IOC容器的bean对象
     * PostConstruct 在构造函数执行之后执行。
     * 可以方便的把注入的bean对象给到静态属性
     * 源码： AutowiredAnnotationBeanPostProcessor 的 buildAutowiringMetadata 函数
     * isStatic 绕过了静态不进行注入
     */
    @PostConstruct
    public void postConstruct() {
        tencentUtils = this;
    }

    // 腾讯云配置
    private final TencentConfig tencentConfig;



    /**
     * 认证对象
     */
    private static IaiClient getIaiClient() {
        // 实例化一个认证对象
        Credential credential = new Credential(tencentUtils.tencentConfig.secretId, tencentUtils.tencentConfig.secretKey);
        // 实例化要请求产品的client对象,clientProfile是可选的
        return new IaiClient(credential, tencentUtils.tencentConfig.face.getRegion());
    }


    /**
     * 执行人员验证
     */
    public static VerifyPersonResponse verifyPersonRes(ClockinAuth clockinAuth) {
        IaiClient client = getIaiClient();
        // 创建人脸识别请求器
        VerifyPersonRequest request = new VerifyPersonRequest();
        request.setPersonId(String.valueOf(clockinAuth.getUserId()));
        request.setImage(clockinAuth.getPic());
        request.setQualityControl(4L);

        // 验证人员
        try {
            VerifyPersonResponse verifyPerson = client.VerifyPerson(request);
            log.info("人脸识别（人员）验证返回参数： {}", JSON.toJSONString(verifyPerson));
            // 进行活体检测 - 使用图片Base64转的会导致活体失败,到时候使用前端拍照即可
            // boolean liveFace = detectLiveFace(client, form.getPhoto());
            // verifyPerson.setIsMatch(verifyPerson.getIsMatch() && liveFace);
            return verifyPerson;
        } catch (TencentCloudSDKException e) {
            log.error("人脸验证失败：{0}", e);
            // 人员ID不存在 - 用于在新增人员的时候进行的校验 如果不存在则表示可以新增
            if (e.getErrorCode().equals("InvalidParameterValue.PersonIdNotExist")) {
                final VerifyPersonResponse response = new VerifyPersonResponse();
                response.setIsMatch(false);
                response.setScore(-0F);
                return response;
            }
            return null;
        }

    }


    /**
     * 执行人员识别验证
     */
    public static boolean verifyPerson(ClockinAuth clockinAuth) {
        // 验证人员
        VerifyPersonResponse verifyPerson = verifyPersonRes(clockinAuth);
        if (null == verifyPerson) {
            throw new RuntimeException("未查询到该人脸信息!");
        }
        log.info("人脸识别（人员）验证返回参数： {}", JSON.toJSONString(verifyPerson));
        Boolean isMatch = verifyPerson.getIsMatch();
        if (BooleanUtil.isFalse(isMatch)) {
            return isMatch;
        }
        try {
            IaiClient client = getIaiClient();
            // 进行活体检测
            boolean liveFace = detectLiveFace(client, clockinAuth.getPic());
            return isMatch && liveFace;
        } catch (TencentCloudSDKException e) {
            log.error("人脸验证失败：{0}", e);
            return false;
        }
    }

    /**
     * 执行人脸识别验证
     */
    public static VerifyFaceResponse verifyFaceRes(ClockinAuth clockinAuth) {
        try {
            VerifyFaceRequest request = new VerifyFaceRequest();
            request.setPersonId(String.valueOf(clockinAuth.getUserId()));
            request.setImage(clockinAuth.getPic());
            request.setQualityControl(4L);

            IaiClient client = getIaiClient();
            // 返回的resp是一个VerifyFaceResponse的实例，与请求对象对应
            VerifyFaceResponse verifyFace = client.VerifyFace(request);
            if (null == verifyFace) {
                throw new RuntimeException("未查询到该人脸信息!");
            }
            log.info("人脸识别（人脸）验证返回参数： {}", JSON.toJSONString(verifyFace));
            return verifyFace;
        } catch (TencentCloudSDKException e) {
            log.error("人脸验证失败：{0}", e);
            return null;
        }
    }


    /**
     * 执行人脸识别验证
     */
    public static boolean verifyFace(ClockinAuth clockinAuth) {
        try {
            // 返回的resp是一个VerifyFaceResponse的实例，与请求对象对应
            VerifyFaceResponse verifyFace = verifyFaceRes(clockinAuth);
            if (null == verifyFace) {
                throw new RuntimeException("未查询到该人脸信息!");
            }
            log.info("人脸识别（人脸）验证返回参数： {}", JSON.toJSONString(verifyFace));
            Boolean isMatch = verifyFace.getIsMatch();
            if (BooleanUtil.isFalse(isMatch)) {
                return isMatch;
            }
            // 进行活体检测
            IaiClient client = getIaiClient();
            boolean liveFace = detectLiveFace(client, clockinAuth.getPic());
            return isMatch && liveFace;
        } catch (TencentCloudSDKException e) {
            log.error("人脸验证失败：{0}", e);
            return false;
        }
    }


    /**
     * 活体检测
     */
    public static boolean detectLiveFace(IaiClient client, String image) throws TencentCloudSDKException {
        DetectLiveFaceRequest request = new DetectLiveFaceRequest();
        request.setImage(image);
        DetectLiveFaceResponse detectLiveFace = client.DetectLiveFace(request);
        log.info("活体验证（人脸）验证返回参数： {}", JSON.toJSONString(detectLiveFace));
        return detectLiveFace.getIsLiveness();
    }

    /**
     * 创建人员到腾讯云人脸识别（人员库）
     */
    public static void createPerson(ClockinAuth clockinAuth) {
        String userId = clockinAuth.getUserId();
        String photo = clockinAuth.getPic();
        // 实例化一个认证对象
        IaiClient client = getIaiClient();
        // 查询用户姓名和性别
        CreatePersonRequest request = new CreatePersonRequest();
        request.setGroupId(tencentUtils.tencentConfig.face.getGroupName());
        request.setPersonId(userId);
        try {
            DetectFaceRequest req = new DetectFaceRequest();
            req.setMaxFaceNum(1L);
            req.setUrl(clockinAuth.getPic());
            req.setNeedFaceAttributes(1L);
            req.setNeedQualityDetection(1L);
            // 返回的resp是一个DetectFaceResponse的实例，与请求对象对应
            DetectFaceResponse resp = client.DetectFace(req);
            final FaceInfo[] faceInfos = resp.getFaceInfos();
            final FaceAttributesInfo faceAttributesInfo = faceInfos[0].getFaceAttributesInfo();
            final short gender = faceAttributesInfo.getGender().shortValue();
            request.setGender((long) (gender > 2 ? 0 : gender)); // 1 男 2 女
            request.setQualityControl(4L);
            request.setPersonName(clockinAuth.getName());
            request.setUrl(photo);

            CreatePersonResponse response = client.CreatePerson(request);
            log.info("创建人脸模型返回参数:{}", JSON.toJSONString(response));

            // 新增到库当中
//            tencentUtils.
//            tencentUtils.userFaceInfoMapper.insert(UserFaceInfo.builder()
//                    .faceId(userId)
//                    .age(faceAttributesInfo.getAge().intValue())
//                    .gender(gender > 2 ? 0 : gender)
//                    .groupId(tencentUtils.tencentConfig.face.getGroupName())
//                    .build());

        } catch (TencentCloudSDKException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 创建人脸识别库
     * 对应文档：...
     */
    public static void CreateGroup() {
        try {
            IaiClient client = getIaiClient();
            // 实例化一个请求对象,每个接口都会对应一个request对象
            CreateGroupRequest req = new CreateGroupRequest();
            req.setGroupId("yby6");
            req.setGroupName("杨不易呀测试人脸识别");
            // 返回的resp是一个CreateGroupResponse的实例，与请求对象对应
            CreateGroupResponse resp = client.CreateGroup(req);
            // 输出json格式的字符串回包
            System.out.println(CreateGroupResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }
    }


    /**
     * 人脸验证
     */
    public static VerifyFaceResponse VerifyFace(String UserId,String pic,Long qualityControl) {
        try {
            IaiClient client = getIaiClient();
            // 实例化一个请求对象,每个接口都会对应一个request对象
            VerifyFaceRequest req = new VerifyFaceRequest();
            req.setPersonId(UserId);
            req.setUrl(pic);
            req.setQualityControl(qualityControl);
            // 返回的resp是一个VerifyFaceResponse的实例，与请求对象对应
            VerifyFaceResponse resp = client.VerifyFace(req);
            // 输出json格式的字符串回包
            log.info(VerifyFaceResponse.toJsonString(resp));
            return resp;

        } catch (TencentCloudSDKException e) {
            log.error(e.toString());
            throw new JeecgBootException("人脸识别错误");
        }
    }


    /**
     * 人脸检测和分析
     */
    public static void DetectFace(ClockinAuth clockinAuth) {

        try {
            IaiClient client = getIaiClient();
            // 参数查看: https://console.cloud.tencent.com/api/explorer?Product=iai&Version=2018-03-01&Action=DetectFace
            // 实例化一个请求对象,每个接口都会对应一个request对象
            DetectFaceRequest req = new DetectFaceRequest();
            req.setMaxFaceNum(1L);
            req.setImage(clockinAuth.getPic());
            req.setNeedFaceAttributes(1L);
            req.setNeedQualityDetection(1L);
            // 返回的resp是一个DetectFaceResponse的实例，与请求对象对应
            DetectFaceResponse resp = client.DetectFace(req);
            // 输出json格式的字符串回包
            System.out.println(DetectFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }

    }

    public static void IdCardVerify(){


        IaiClient client = getIaiClient();

    }

}
