package com.ruoyi.app.service.impl;
import cn.hutool.core.convert.NumberChineseFormatter;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.baiduUtil.Base64Util;
import com.ruoyi.common.utils.baiduUtil.FileUtil;
import com.ruoyi.common.utils.baiduUtil.HttpUtil;


import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.ruoyi.app.service.IPicParseService;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
public class PicParseServiceImpl implements IPicParseService {
    //AK
    private final String clientId = "VwHRSCHIlOgXvCtHwqduvA2a";
    //SK
    private final String clientSecret = "QprKtAp4nJMXiEV9Pf3ELsjyVqsRxICo";

    //模板ID
    private final String templateSign = "5d7aebe80058550477df76a3b2ce5d52";
    private final String templateSignA = "7ecaefde0ecc6e3abd2d51b1b682d3cc";
    private final String ACCESS_TOKEN = "OCR_ACCESS_TOKEN";
    private final Integer ACCESS_TOKEN_EXPIRATION = 60*60*24*20;
    @Autowired
    private RedisCache redisCache;

    private static final Logger log = LoggerFactory.getLogger(PicParseServiceImpl.class);
    public static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().readTimeout(300, TimeUnit.SECONDS).build();
    private  String  getAccessToken() throws Exception{

        try {
            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(mediaType, "");
            Request request = new Request.Builder()
                    .url(String.format("https://aip.baidubce.com/oauth/2.0/token?client_id=%s&client_secret=%s&grant_type=client_credentials",clientId,clientSecret))
                    .method("POST", body)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Accept", "application/json")
                    .build();
            Response response = HTTP_CLIENT.newCall(request).execute();
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode resp = objectMapper.readTree(response.body().string());
            // 检查字段是否存在
            if (resp.has("access_token")) {
                String accessToken = resp.get("access_token").asText();
                redisCache.setCacheObject(ACCESS_TOKEN, accessToken, ACCESS_TOKEN_EXPIRATION, TimeUnit.SECONDS);
                return accessToken;
            } else {
                log.error("获取token失败");
            }

        }  catch (Exception err) {
            log.error("获取token失败: {}", err.getMessage());
        }
        return null;
    }
    /**
     * 获取AccessToken
     *
     * @return
     */

    public String getToken() throws Exception {
        String token =  redisCache.getCacheObject(ACCESS_TOKEN);
        if (token == null) {
            return getAccessToken();
        }
        return token;
    }
    //百度OCR
    @Override
    public Map<String, Object> picParse(MultipartFile multipartFile)throws Exception{
        Map<String, Object> formData = new LinkedHashMap<>();
        // iocr识别apiUrl
        String recogniseUrl = "https://aip.baidubce.com/rest/2.0/solution/v1/iocr/recognise";

        try {
            byte[] imgData = multipartFile.getBytes();//FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            // 请求模板参数
            String recogniseParams = "templateSign="+templateSign+"&image=" + URLEncoder.encode(imgStr, "UTF-8");

            String accessToken = getToken();
            // 请求模板识别
            String jsonResponse = HttpUtil.post(recogniseUrl, accessToken, recogniseParams);
            ApiResult result = parseApiResponse(jsonResponse);

            if (result.isSuccess()) {
                for (Map.Entry<String, String> entry : result.getWordMap().entrySet()) {
                    if(Objects.equals(entry.getKey(), "animalCertNo")){
                        formData.put("animalCertNo",entry.getValue().replaceAll("NO.", ""));//备用动物检疫证号
                    }else if(Objects.equals(entry.getKey(), "amount")) {
                        String num = entry.getValue().substring(0, entry.getValue().length() - 1);
                        if (StringUtils.isPositiveInteger(num)){
                            formData.put("amount",num);
                        }else{
                            formData.put("amount", String.valueOf(NumberChineseFormatter.chineseToNumber(num)));//中文转数字
                        }
                        formData.put("units", entry.getValue().isEmpty() ?"":entry.getValue().substring(entry.getValue().length() - 1));//单位
                    }else if(Objects.equals(entry.getKey(), "animalEartags")){
                        //拆分耳标号
                        formData.put("animalEartags",expandNumberRangesSafe(entry.getValue()));
                    }else{
                        formData.put(entry.getKey(), entry.getValue());
                    }
                }
            } else {
                log.error("接口调用失败: " + result.getErrorMsg());
            }
        } catch (Exception e) {
            log.error("解析图片失败: {}", e.getMessage());
            throw e;
        }
        return formData;
    }

    //百度OCR
    @Override
    public Map<String, Object> picParseA(MultipartFile multipartFile)throws Exception{
        Map<String, Object> formData = new LinkedHashMap<>();
        // iocr识别apiUrl
        String recogniseUrl = "https://aip.baidubce.com/rest/2.0/solution/v1/iocr/recognise";

        try {
            byte[] imgData = multipartFile.getBytes();//FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            // 请求模板参数
            String recogniseParams = "templateSign="+templateSignA+"&image=" + URLEncoder.encode(imgStr, "UTF-8");

            String accessToken = getToken();
            // 请求模板识别
            String jsonResponse = HttpUtil.post(recogniseUrl, accessToken, recogniseParams);
            ApiResult result = parseApiResponse(jsonResponse);

            if (result.isSuccess()) {
                System.out.println(result);
                for (Map.Entry<String, String> entry : result.getWordMap().entrySet()) {
                    if(Objects.equals(entry.getKey(), "animalCertNo")){
                        formData.put("animalCertNo",entry.getValue().replaceAll("NO.", ""));//备用动物检疫证号
                    }else if(Objects.equals(entry.getKey(), "amount")) {
                        String num = entry.getValue().substring(0, entry.getValue().length() - 1);
                        if (StringUtils.isPositiveInteger(num)){
                            formData.put("amount",num);
                        }else{
                            formData.put("amount", String.valueOf(NumberChineseFormatter.chineseToNumber(num)));//中文转数字
                        }
                        formData.put("units", entry.getValue().isEmpty() ?"":entry.getValue().substring(entry.getValue().length() - 1));//单位
                    }else if(Objects.equals(entry.getKey(), "animalEartags")){
                        //拆分耳标号
                        formData.put("animalEartags",expandNumberRangesSafe(entry.getValue()));
                    }else{
                        formData.put(entry.getKey(), entry.getValue());
                    }
                }
            } else {
                log.error("接口调用失败: " + result.getErrorMsg());
            }
        } catch (Exception e) {
            log.error("解析图片失败: {}", e.getMessage());
            throw e;
        }
        return formData;
    }

    private static ApiResult parseApiResponse(String jsonResponse) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = objectMapper.readTree(jsonResponse);

        // 检查接口是否成功
        int errorCode = rootNode.get("error_code").asInt();
        String errorMsg = rootNode.get("error_msg").asText();

        ApiResult result = new ApiResult();
        result.setErrorCode(errorCode);
        result.setErrorMsg(errorMsg);

        // 如果接口成功，解析data中的数据
        if (errorCode == 0) {
            JsonNode dataNode = rootNode.get("data");
            if (dataNode != null && dataNode.has("ret")) {
                JsonNode retArray = dataNode.get("ret");
                Map<String, String> wordMap = new HashMap<>();

                for (JsonNode item : retArray) {
                    if (item.has("word_name") && item.has("word")) {
                        String wordName = item.get("word_name").asText();
                        String word = item.get("word").asText();
                        wordMap.put(wordName, word);
                    }
                }

                result.setWordMap(wordMap);
            }
        }

        return result;
    }

    // 结果封装类
    static class ApiResult {
        private int errorCode;
        private String errorMsg;
        private Map<String, String> wordMap = new HashMap<>();

        public boolean isSuccess() {
            return errorCode == 0;
        }

        // getters and setters
        public int getErrorCode() { return errorCode; }
        public void setErrorCode(int errorCode) { this.errorCode = errorCode; }

        public String getErrorMsg() { return errorMsg; }
        public void setErrorMsg(String errorMsg) { this.errorMsg = errorMsg; }

        public Map<String, String> getWordMap() { return wordMap; }
        public void setWordMap(Map<String, String> wordMap) { this.wordMap = wordMap; }
    }

    //处理区间类型的耳标号拆分，区间范围最大不能超过1000
    private static String expandNumberRangesSafe(String input) throws Exception {
        if (input == null || input.trim().isEmpty()) {
            return "";
        }
        List<String> allNumbers = new ArrayList<>();
        String[] ranges = input.split(";");

        for (String range : ranges) {
            if (range.contains("-")) {
                String[] parts = range.split("-");
                if (parts.length == 2) {
                    try {
                        String prefix = parts[0];
                        String endSuffix = parts[1];
                        int suffixLength = endSuffix.length();

                        // 获取基础前缀（去掉最后suffixLength位）
                        String base = prefix.substring(0, prefix.length() - suffixLength);
                        // 获取起始后缀（最后suffixLength位）
                        String startSuffix = prefix.substring(prefix.length() - suffixLength);

                        long start = Long.parseLong(startSuffix);
                        long end = Long.parseLong(endSuffix);
                        // 添加安全检查，防止范围过大
                        if (end - start > 1000) {
                            throw new Exception("耳标号区间范围过大");
                        }
                        // 展开数字范围
                        for (long i = start; i <= end; i++) {
                            // 保持后缀位数一致，不足补零
                            String formattedSuffix = String.format("%0" + suffixLength + "d", i);
                            allNumbers.add(base + formattedSuffix);
                        }
                    } catch (NumberFormatException e) {
                        throw new Exception("无效的数字格式: " + range);
                    }
                }
            }else {
                allNumbers.add(range);
            }
        }

        return String.join(",", allNumbers);
    }
}
