package com.hotwj.platform.integration.face.baidu;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hotwj.platform.integration.face.FaceMatchResult;
import com.hotwj.platform.integration.face.FaceRecognitionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;

@Slf4j
@Service
@RequiredArgsConstructor
public class BaiduFaceRecognitionService implements FaceRecognitionService {

    private final BaiduFaceProperties properties;
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final HttpClient httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    private volatile String cachedToken;
    private volatile long tokenExpireAt;

    @Override
    public boolean detect(String base64Image) {
        String token = getAccessToken();
        if (!StringUtils.hasText(token)) {
            log.warn("人脸检测失败：访问令牌为空，无法调用百度接口");
            return false;
        }
        try {
            String url = properties.getDetectUrl() + "?access_token=" + URLEncoder.encode(token, StandardCharsets.UTF_8);
            String body = "{\"image\":\"" + base64Image + "\",\"image_type\":\"BASE64\"}";

            log.info("开始人脸检测，请求URL：{}", url);
            log.debug("检测图片长度：{}", base64Image == null ? 0 : base64Image.length());
            HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                    .timeout(Duration.ofSeconds(15))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(body))
                    .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            log.info("人脸检测响应状态：{}，响应体长度：{}", response.statusCode(), response.body() == null ? 0 : response.body().length());
            JsonNode root = objectMapper.readTree(response.body());
            String errorMsg = root.path("error_msg").asText();
            if (!"SUCCESS".equalsIgnoreCase(errorMsg)) {
                log.warn("人脸检测返回失败，错误信息：{}", errorMsg);
            } else {
                log.info("人脸检测成功");
            }
            return "SUCCESS".equalsIgnoreCase(errorMsg);
        } catch (Exception e) {
            log.error("人脸检测调用异常：{}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public FaceMatchResult match(String base64Image1, String base64Image2) {
        String token = getAccessToken();
        if (!StringUtils.hasText(token)) {
            log.warn("人脸比对失败：访问令牌为空，无法调用百度接口");
            FaceMatchResult result = new FaceMatchResult();
            result.setMatch(false);
            result.setScore(0.0);
            return result;
        }
        FaceMatchResult result = new FaceMatchResult();
        try {
            String url = properties.getMatchUrl() + "?access_token=" + URLEncoder.encode(token, StandardCharsets.UTF_8);
            String body = "[{\"image\":\"" + base64Image1 + "\",\"image_type\":\"BASE64\"}," +
                    "{\"image\":\"" + base64Image2 + "\",\"image_type\":\"BASE64\"}]";

            log.info("开始人脸比对，请求URL：{}", url);
            log.debug("比对图片1长度：{}，图片2长度：{}", base64Image1 == null ? 0 : base64Image1.length(), base64Image2 == null ? 0 : base64Image2.length());
            HttpRequest request = HttpRequest.newBuilder(URI.create(url))
                    .timeout(Duration.ofSeconds(15))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(body))
                    .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            result.setRawResponse(response.body());
            log.info("人脸比对响应状态：{}，响应体长度：{}", response.statusCode(), response.body() == null ? 0 : response.body().length());

            JsonNode root = objectMapper.readTree(response.body());
            JsonNode resultNode = root.path("result");
            double score = resultNode.path("score").asDouble(0.0);
            result.setScore(score);
            result.setMatch(score >= properties.getScoreThreshold());
            log.info("人脸比对得分：{}，阈值：{}，是否匹配：{}", score, properties.getScoreThreshold(), result.isMatch());
            return result;
        } catch (Exception e) {
            log.error("人脸比对调用异常：{}", e.getMessage(), e);
            result.setMatch(false);
            result.setScore(0.0);
            return result;
        }
    }

    private String getAccessToken() {
        if (!StringUtils.hasText(properties.getApiKey()) || !StringUtils.hasText(properties.getSecretKey())) {
            log.error("百度人脸识别配置缺失：API Key 或 Secret Key 为空。请在 application.yml 中配置 ext.baidu.face.api-key 和 secret-key");
            return "";
        }
        long now = System.currentTimeMillis();
        if (StringUtils.hasText(cachedToken) && now < tokenExpireAt) {
            log.debug("命中百度令牌缓存，剩余有效期(ms)：{}", tokenExpireAt - now);
            return cachedToken;
        }
        try {
            log.info("开始获取百度访问令牌");
            String form = "grant_type=client_credentials" +
                    "&client_id=" + URLEncoder.encode(properties.getApiKey(), StandardCharsets.UTF_8) +
                    "&client_secret=" + URLEncoder.encode(properties.getSecretKey(), StandardCharsets.UTF_8);
            HttpRequest request = HttpRequest.newBuilder(URI.create(properties.getTokenUrl()))
                    .timeout(Duration.ofSeconds(10))
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .POST(HttpRequest.BodyPublishers.ofString(form))
                    .build();
            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            String responseBody = response.body();
            JsonNode root = objectMapper.readTree(responseBody);
            
            if (root.has("error")) {
                String error = root.path("error").asText();
                String errorDesc = root.path("error_description").asText();
                log.error("获取百度访问令牌失败，API返回错误：{} - {}", error, errorDesc);
                return "";
            }
            
            if (!root.has("access_token")) {
                log.error("获取百度访问令牌失败，响应中未包含access_token。响应内容：{}", responseBody);
                return "";
            }

            cachedToken = root.path("access_token").asText();
            int expiresIn = root.path("expires_in").asInt(2592000);
            tokenExpireAt = now + (expiresIn - 60) * 1000L;
            log.info("成功获取百度令牌，过期秒：{}，缓存到期时间戳：{}", expiresIn, tokenExpireAt);
            return cachedToken;
        } catch (Exception e) {
            log.error("获取百度访问令牌失败：{}", e.getMessage(), e);
            return "";
        }
    }
}
