package jnpf.certificate.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.ocr.v20181119.OcrClient;
import com.tencentcloudapi.ocr.v20181119.models.*;
import jnpf.base.ActionResult;
import jnpf.certificate.config.FoodSafetyOcrConfig;
import jnpf.model.certificate.req.CertificateFoodSafetyOcrReq;
import jnpf.model.certificate.vo.CertificateFoodSafetyOcrVO;
import jnpf.permission.vo.LicenseVo;
import jnpf.personnels.config.TengxunLicenseConfig;
import jnpf.util.JsonUtil;
import jnpf.util.RedisUtil;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 证照 OCR 控制器。
 */
@RestController
@Validated
@RequestMapping("/web/certificate-ocr")
@Slf4j
public class CertificateOcrController {

    private static final String FOOD_SAFETY_OCR_CACHE_KEY_PREFIX = "ftb:certificate:ocr:food:safety:";
    private static final long FOOD_SAFETY_OCR_CACHE_SECONDS = 24 * 60 * 60L;

    @Autowired
    private TengxunLicenseConfig licenseConfig;
    @Autowired
    private FoodSafetyOcrConfig foodSafetyOcrConfig;
    @Autowired
    private RedisUtil redisUtil;


    /**
     * 食品安全许可证识别（空实现）。
     *
     * @param req 图片地址
     * @return 识别结果
     */
    @PostMapping("/recognize-food-safety-license")
    public ActionResult<CertificateFoodSafetyOcrVO> recognizeFoodSafetyLicense(@Validated @RequestBody CertificateFoodSafetyOcrReq req) {
        return ActionResult.success(recognizeFoodSafetyLicense(req.getImageUrl())
                .orElse(new CertificateFoodSafetyOcrVO(false)));
    }

    private Optional<CertificateFoodSafetyOcrVO> recognizeFoodSafetyLicense(String imageUrl) {
        String tenantId = UserProvider.getUser().getTenantId();
        String cacheKey = buildFoodSafetyOcrCacheKey(tenantId,imageUrl);
        try {
            Object cached = redisUtil.getString(cacheKey);
            if (cached != null && StringUtil.isNotBlank(cached.toString())) {
                CertificateFoodSafetyOcrVO cacheVo = JsonUtil.getJsonToBean(cached.toString(), CertificateFoodSafetyOcrVO.class);
                if (cacheVo != null) {
                    return Optional.of(cacheVo);
                }
            }
        } catch (Exception e) {
            log.warn("read food safety ocr cache error, imageUrl={}", imageUrl, e);
        }

        try{
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(licenseConfig.getSecretId(), licenseConfig.getSecretKey());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(licenseConfig.getDomain());
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            OcrClient client = new OcrClient(cred, "ap-guangzhou", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象

            SmartStructuralOCRRequest smartStructuralOCRRequest = new SmartStructuralOCRRequest();
            smartStructuralOCRRequest.setImageUrl(imageUrl);
            SmartStructuralOCRResponse resp = client.SmartStructuralOCR(smartStructuralOCRRequest);
            if(Objects.isNull(resp)){
                return Optional.empty();
            }
            StructuralItem [] structuralItems = resp.getStructuralItems();
            if(structuralItems == null || structuralItems.length == 0){
                return Optional.empty();
            }

            Set<String> titleNames = foodSafetyOcrConfig.getTitleNames();
            Set<String> issueDateNames = foodSafetyOcrConfig.getIssueDateNames();
            Set<String> expireDateNames = foodSafetyOcrConfig.getExpireDateNames();
            Set<String> businessItemsNames = foodSafetyOcrConfig.getBusinessItemsNames();
            String title = null;
            String issueDate = null;
            String expireDate = null;
            String businessItems = null;
            for (StructuralItem structuralItem : structuralItems){
                String name = structuralItem.getName();
                String value = structuralItem.getValue();
                if(titleNames.contains(name)){
                    title = value;
                }else if(issueDateNames.contains(name)){
                    issueDate = value;
                } else if (expireDateNames.contains(name)) {
                    expireDate = value;
                } else if (businessItemsNames.contains(name)) {
                    businessItems = value;
                }
            }
            if(Objects.isNull(title) || Objects.isNull(issueDate) || Objects.isNull(expireDate) || Objects.isNull(businessItems)){
                log.error("ocr fail title,issueDate,expireDate,businessItems is null.structuralItems:{}",JsonUtil.getObjectToString(structuralItems));
                return Optional.empty();
            }
            CertificateFoodSafetyOcrVO result = new CertificateFoodSafetyOcrVO(issueDate, expireDate, businessItems,true);
            try {
                redisUtil.insert(cacheKey, JsonUtil.getObjectToString(result), FOOD_SAFETY_OCR_CACHE_SECONDS);
            } catch (Exception e) {
                log.warn("write food safety ocr cache error, imageUrl={}", imageUrl, e);
            }
            return Optional.of(result);
        } catch (TencentCloudSDKException e) {
            log.error("Tencent ocr error ",e);
        }
        return Optional.empty();
    }

    private String buildFoodSafetyOcrCacheKey(String tenantId,String imageUrl) {
        return FOOD_SAFETY_OCR_CACHE_KEY_PREFIX +tenantId+":"+ DigestUtil.md5Hex(StrUtil.nullToEmpty(imageUrl));
    }


    public static void main(String[] args) {
        String imgUrl = "https://img.cdn1.vip/i/69dda78d48f89_1776134029.webp";
        try{
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential("AKIDJTbdT7ayRuIAC848D7mKm2Ji5XHua7es", "HOI1iFakDZidu461qaEweHtNfjBY5Rfp");
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("ocr.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            OcrClient client = new OcrClient(cred, "ap-guangzhou", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象

            EnterpriseLicenseOCRRequest req = new EnterpriseLicenseOCRRequest();
            req.setImageUrl(imgUrl);
            // 返回的resp是一个BizLicenseOCRResponse的实例，与请求对象对应
            EnterpriseLicenseOCRResponse resp = client.EnterpriseLicenseOCR(req);

            SmartStructuralOCRV2Request smartStructuralOCRV2Request = new SmartStructuralOCRV2Request();
            smartStructuralOCRV2Request.setImageUrl(imgUrl);
            SmartStructuralOCRV2Response smartStructuralOCRV2Response = client.SmartStructuralOCRV2(smartStructuralOCRV2Request);

            SmartStructuralOCRRequest smartStructuralOCRRequest = new SmartStructuralOCRRequest();
            smartStructuralOCRRequest.setImageUrl(imgUrl);
            SmartStructuralOCRResponse smartStructuralOCRResponse = client.SmartStructuralOCR(smartStructuralOCRRequest);
            System.out.println(resp);
            System.out.println(JsonUtil.getObjectToString(smartStructuralOCRResponse.getStructuralItems()));
            // 输出json格式的字符串回包
        } catch (TencentCloudSDKException e) {
            log.error("Tencent ocr error ",e);
        }
    }
}
