package com.hr.externelSystem;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.hr.dto.ApiLogDto;
import com.hr.dto.TencentFaceDto;
import com.hr.param.TencentFaceParam;
import com.hr.repository.domain.IpInterfacePO;
import com.hr.repository.domain.IpOrderPO;
import com.hr.repository.domain.IpTokenInterfacePO;
import com.hr.util.ImageUtils;
import com.hr.util.SignatureUtil;
import com.hr.vo.CallbackResponseVO;
import com.hr.vo.OcrParamVO;
import com.hr.vo.ServiceTypeVO;
import com.hr.vo.TencentAuthVO;
import com.yy.basedevelop.common.http.config.RedisService;
import com.yy.basedevelop.common.util.HttpClientUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * 腾讯人脸识别服务
 */
@Data
@Slf4j
@Service
public class TencentFaceService implements BizHandler<TencentFaceParam, OcrParamVO>{

    private final String CODE = "0";
    private String nonce = "kHoSxvLZGxSoFsjxlbzEoUzh5PAnTU7T";
    private String LOAN_TOKEN = "loan:token:%s";

    @Autowired
    private RedisService redisService;

    @Override
    public ServiceTypeVO getType() {
        return new ServiceTypeVO("tencentFace", "腾讯人脸识别");
    }

    @Override
    public OcrParamVO handle(TencentFaceParam tencentFaceParam, IpInterfacePO ipInterfacePO, ApiLogDto logDto) {
        {
            OcrParamVO ocrParamVO = new OcrParamVO();
            try {

                String interfaceConfig = ipInterfacePO.getInterfaceConfig();
                TencentFaceDto tencentFaceDto = JSON.parseObject(interfaceConfig, TencentFaceDto.class);

                JSONObject jsonObject = new JSONObject();
                jsonObject.put("appId", tencentFaceDto.getAppId());
                String orderNo = generate32BitRandomNumber();
                jsonObject.put("orderNo", orderNo);
                jsonObject.put("name", tencentFaceParam.getUserName());
                jsonObject.put("idNo", tencentFaceParam.getIdCardNo());

                if (StringUtils.isNotEmpty(tencentFaceParam.getIdCardFrontPic())) {
                    jsonObject.put("sourcePhotoStr", ImageUtils.imageUrlToBase64(tencentFaceParam.getIdCardFrontPic()));
                    jsonObject.put("sourcePhotoType", 1);
                }
                jsonObject.put("userId", String.valueOf(tencentFaceParam.getUserId()));

                jsonObject.put("version", tencentFaceDto.getVersion());
                //给app端返回NONCE 获取faceId返回sign
                String NONCE_ticket = getSign("NONCE", tencentFaceParam.getUserId(), tencentFaceDto).getSign_ticket();
                String sign_ticket = getSign("SIGN", tencentFaceParam.getUserId(), tencentFaceDto).getSign_ticket();
                String long_sign = SignatureUtil.generateSign2(tencentFaceDto.getAppId(), String.valueOf(tencentFaceParam.getUserId()), nonce, tencentFaceDto.getVersion(), sign_ticket);
                String nonce_sign = SignatureUtil.generateSign2(tencentFaceDto.getAppId(), String.valueOf(tencentFaceParam.getUserId()), nonce, tencentFaceDto.getVersion(), NONCE_ticket);
                jsonObject.put("sign",long_sign);
                jsonObject.put("nonce", nonce);
                logDto.setUrl(tencentFaceDto.getTicketUrl());
                logDto.setRequestParam(JSON.toJSONString(jsonObject));
                log.info("腾讯人脸识别地址：{}", tencentFaceDto.getTicketUrl());
                log.info("腾讯人脸请求参数：{}", jsonObject.toJSONString());
                String post = HttpClientUtils.post(tencentFaceDto.getTicketUrl(), jsonObject.toJSONString());

                JSONObject resultJson = JSON.parseObject(post);
                logDto.setResponseParam(post);
                logDto.setHttpStatus(resultJson.getString("code"));
                if (resultJson.getString("code").equals(CODE)) {
                    ocrParamVO.setFaceId(String.valueOf(resultJson.getJSONObject("result").get("faceId")));
                    ocrParamVO.setAgreementNo(orderNo);
                    ocrParamVO.setOpenApiAppId(tencentFaceDto.getAppId());
                    ocrParamVO.setOpenApiAppVersion(tencentFaceDto.getVersion());
                    ocrParamVO.setOpenApiNonce(nonce);
                    ocrParamVO.setOpenApiUserId(String.valueOf(tencentFaceParam.getUserId()));
                    ocrParamVO.setOpenApiSign(nonce_sign);
                    ocrParamVO.setLicence(tencentFaceDto.getLicence());
                    return ocrParamVO;
                } else {
                    logDto.setErrorMessage(resultJson.getString("msg"));
                    log.warn("ocr param interface error {},idNo {}", resultJson.getString("msg"),tencentFaceParam.getIdCardNo());
                    throw new RuntimeException("ocr param interface error");
                }
            } catch (Exception e) {
                log.error("ocr param interface error {}", e);
                throw new RuntimeException("ocr param interface error");
            }
        }
    }

    public static void main(String[] args) {
        HttpClientUtils.post("https://webhook.site/5dac7d16-77dd-464d-992b-ca488b223369", "hellword");
    }



    public TencentAuthVO getSign(String type,Long userId, TencentFaceDto tencentFaceDto) {
        try {

            Map<String, String> map = new HashMap<>();
            map.put("app_id", tencentFaceDto.getAppId());
            map.put("access_token", getToken(tencentFaceDto).getAccess_token());
            map.put("type", type);
            if (type.equals("NONCE")) {
                map.put("user_id", String.valueOf(userId));
            }
            map.put("version", tencentFaceDto.getVersion());
            String result = HttpClientUtils.get(tencentFaceDto.getTicketUrl(), map);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getString("code").equals(CODE)) {
                TencentAuthVO tencentAuthVO = new TencentAuthVO();
                tencentAuthVO.setCode(jsonObject.getString("code"));
                tencentAuthVO.setBizSeqNo(jsonObject.getString("bizSeqNo"));
                JSONArray tickets = jsonObject.getJSONArray("tickets");
                if (CollectionUtils.isNotEmpty(tickets)) {
                    JSONObject jsonObject1 = tickets.getJSONObject(0);
                    tencentAuthVO.setSign_ticket(jsonObject1.getString("value"));
                    tencentAuthVO.setExpire_time(jsonObject1.getString("expire_time"));
                    tencentAuthVO.setExpire_in(jsonObject1.getString("expire_in"));
                }
                String orderNo = generate32BitRandomNumber();
                tencentAuthVO.setOrderNo(orderNo);
                tencentAuthVO.setOpenApiNonce(nonce);
                tencentAuthVO.setOpenApiAppId(tencentFaceDto.getAppId());
                tencentAuthVO.setLicence(tencentFaceDto.getLicence());
                tencentAuthVO.setOpenApiSign(SignatureUtil.generateSign2(tencentFaceDto.getAppId(), orderNo, nonce, tencentFaceDto.getVersion(), tencentAuthVO.getSign_ticket()));
                tencentAuthVO.setOpenApiAppVersion(tencentFaceDto.getVersion());
                return tencentAuthVO;
            } else {
                throw new RuntimeException("get tencent sign error");
            }
        } catch (Exception e) {
            log.error("get tencent sign error {}", e);
            throw new RuntimeException("get tencent sign error");
        }
    }


    public TencentAuthVO getToken(TencentFaceDto tencentFaceDto) {
        try {
            Map<String, Object> hmget = redisService.getCacheMap(String.format(LOAN_TOKEN, tencentFaceDto, tencentFaceDto.getAppId()));
//            Map<String, String> hmget = redisService.hmget(String.format(LOAN_TOKEN,tencentFaceDto.getAppId()));
            if (!hmget.isEmpty()) {
                TencentAuthVO tencentAuthVO = new TencentAuthVO();
                tencentAuthVO.setCode(hmget.get("code").toString());
                tencentAuthVO.setBizSeqNo(hmget.get("bizSeqNo").toString());
                tencentAuthVO.setAccess_token(hmget.get("access_token").toString());
                tencentAuthVO.setExpire_time(hmget.get("expire_time").toString());
                tencentAuthVO.setExpire_in(hmget.get("expire_in").toString());
                return tencentAuthVO;
            }
            Map<String, String> map = new HashMap<>();
            map.put("app_id", tencentFaceDto.getAppId());
            map.put("secret", tencentFaceDto.getSecret());
            map.put("grant_type", tencentFaceDto.getGrantType());
            map.put("version", tencentFaceDto.getVersion());
            String result = HttpClientUtils.get(tencentFaceDto.getTokenUrl(), map);

            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getString("code").equals(CODE)) {
                String formatKey = String.format(LOAN_TOKEN, tencentFaceDto.getAppId());
                redisService.setCacheMap(formatKey,JSONObject.parseObject(jsonObject.toJSONString(), new TypeReference<Map<String, String>>(){}));
                redisService.expire(formatKey,90L);
                Map<String, String> resultMap = redisService.getCacheMap(formatKey);
                TencentAuthVO tencentAuthVO = new TencentAuthVO();
                tencentAuthVO.setCode(resultMap.get("code"));
                tencentAuthVO.setBizSeqNo(resultMap.get("bizSeqNo"));
                tencentAuthVO.setAccess_token(resultMap.get("access_token"));
                tencentAuthVO.setExpire_time(resultMap.get("expire_time"));
                tencentAuthVO.setExpire_in(resultMap.get("expire_in"));
                return tencentAuthVO;
            } else {
                throw new RuntimeException("get tencent token error");
            }
        } catch (Exception e) {
            log.error("get tencent token error {}", e);
            throw new RuntimeException("get tencent token error");
        }
    }

    @Override
    public Class<TencentFaceParam> getRequestClass() {
        return TencentFaceParam.class;
    }

    @Override
    public CallbackResponseVO doCallBack(IpOrderPO ipOrderPO, JSONObject callbackParam) {
        return null;
    }

    public static String generate32BitRandomNumber() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replaceAll("-", "");
    }
}
