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.param.TencentOcrSignParam;
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.io.Serial;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 腾讯 ocr 服务
 */
@Data
@Slf4j
@Service
public class TencentOrcSignService implements BizHandler<TencentOcrSignParam, 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("tencentOcrSign", "腾讯OCR签名");
    }

    @Override
    public OcrParamVO handle(TencentOcrSignParam tencentFaceParam, IpInterfacePO ipInterfacePO, ApiLogDto logDto) {

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

        OcrParamVO ocrParamVO = new OcrParamVO();
        String sign_ticket = getSign("NONCE",tencentFaceParam.getUserId(), tencentFaceDto).getSign_ticket();
        String sign2 = SignatureUtil.generateSign2(tencentFaceDto.getAppId(), String.valueOf(tencentFaceParam.getUserId()), nonce, tencentFaceDto.getVersion(), sign_ticket);
        String orderNo = generate32BitRandomNumber();
        ocrParamVO.setAgreementNo(orderNo);
        ocrParamVO.setOpenApiAppId(tencentFaceDto.getAppId());
        ocrParamVO.setOpenApiAppVersion(tencentFaceDto.getVersion());
        ocrParamVO.setOpenApiNonce(nonce);
        ocrParamVO.setOpenApiSign(sign2);
        ocrParamVO.setOpenApiUserId(String.valueOf(tencentFaceParam.getUserId()));
        ocrParamVO.setLicence(tencentFaceDto.getLicence());
        return ocrParamVO;
    }



    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<TencentOcrSignParam> getRequestClass() {
        return TencentOcrSignParam.class;
    }

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

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