/**
 * @ProjectName: 智慧评标-主观分助手
 * @Package: com.zhpb.gdyd_zhpb_zgf.service.impl
 * @ClassName: PrivateModelServiceImpl
 * @Description: 私有大模型服务实现
 * @Author: 张志锋
 * @Date: 2025-11-05
 * @Version: 1.0
 * @Copyright: © 2025 智慧评标-主观分助手
 */
package com.zhpb.gdyd_zhpb_zgf.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.zhpb.gdyd_zhpb_zgf.context.ModelRequestContextHolder;
import com.zhpb.gdyd_zhpb_zgf.entity.mysql.ModelRequestLog;
import com.zhpb.gdyd_zhpb_zgf.service.AIModelService;
import com.zhpb.gdyd_zhpb_zgf.service.ModelRequestLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpStatusCodeException;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 私有大模型服务实现
 */
@Service
public class PrivateModelServiceImpl implements AIModelService {

    private static final Logger logger = LoggerFactory.getLogger(PrivateModelServiceImpl.class);

    @Value("${private-model.url}")
    private String apiUrl;

    @Value("${private-model.appid}")
    private String appId;

    @Value("${private-model.appkey}")
    private String appKey;

    @Value("${private-model.capabilityname:semantic0000000000000000}")
    private String capabilityName;

    @Value("${private-model.model:JiuTian-75B-8K}")
    private String model;

    @Value("${private-model.temperature:0.1}")
    private double temperature;

    // max_tokens不再限制，让模型自由决定输出长度

    private final RestTemplate restTemplate;
    private final ModelRequestLogService modelRequestLogService;

    /**
     * 创建带超时配置的RestTemplate
     */
    private static RestTemplate createRestTemplateWithTimeout() {
        org.springframework.http.client.SimpleClientHttpRequestFactory factory = 
            new org.springframework.http.client.SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(30000);  // 连接超时30秒
        factory.setReadTimeout(120000);    // 读取超时120秒（AI模型响应可能较慢）
        return new RestTemplate(factory);
    }

    public PrivateModelServiceImpl(ModelRequestLogService modelRequestLogService) {
        this.restTemplate = createRestTemplateWithTimeout();
        this.modelRequestLogService = modelRequestLogService;
    }

    @Override
    public String generateResponse(String systemPrompt, String userMessage) {
        return generateResponse(systemPrompt, userMessage, false);
    }

    @Override
    public String generateResponse(String systemPrompt, String userMessage, boolean stream) {
        long startTime = System.currentTimeMillis();
        String requestJson = null;
        String responseBody = null;
        boolean success = false;
        String errorMessage = null;
        Integer promptTokens = null;
        Integer completionTokens = null;
        Integer totalTokens = null;
        String extraInfo = null;
        try {
            logger.info("调用私有模型API - 模型: {}, 系统提示长度: {}, 用户消息长度: {}",
                       model, systemPrompt.length(), userMessage.length());

            // 生成请求参数
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String capabilityName24 = getCapabilityName24(capabilityName);
            String csid = appId + capabilityName24 + uuid;
            String curTime = String.valueOf(System.currentTimeMillis() / 1000);

            // 构建X-Server-Param
            Map<String, String> serverParam = new HashMap<>();
            serverParam.put("appid", appId);
            serverParam.put("csid", csid);

            String serverParamJson = JSON.toJSONString(serverParam);
            String serverParamBase64 = Base64.getEncoder().encodeToString(
                serverParamJson.getBytes(StandardCharsets.UTF_8));

            // 计算校验和
            String checkSum = calculateMD5(appKey + curTime + serverParamBase64);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("X-Server-Param", serverParamBase64);
            headers.set("X-CurTime", curTime);
            headers.set("X-CheckSum", checkSum);
            extraInfo = String.format("X-Server-Param=%s;X-CurTime=%s;X-CheckSum=%s", serverParamBase64, curTime, checkSum);

            // 构建消息
            Map<String, String> systemMessage = new HashMap<>();
            systemMessage.put("role", "system");
            systemMessage.put("content", systemPrompt);

            Map<String, String> userMessageMap = new HashMap<>();
            userMessageMap.put("role", "user");
            userMessageMap.put("content", userMessage);

            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("messages", Arrays.asList(systemMessage, userMessageMap));
            requestBody.put("model", model);
            // 不设置max_tokens限制，让模型自由决定输出长度
            requestBody.put("stream", stream);
            requestBody.put("temperature", temperature);

            requestJson = JSON.toJSONString(requestBody);
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 发送请求
            ResponseEntity<String> responseEntity = restTemplate.exchange(
                apiUrl, HttpMethod.POST, requestEntity, String.class);

            if (responseEntity.getStatusCode() == HttpStatus.OK) {
                responseBody = responseEntity.getBody();
                JSONObject jsonResponse = JSON.parseObject(responseBody);

                // 检查是否符合安全要求
                String finishReason = jsonResponse.getJSONArray("choices")
                    .getJSONObject(0)
                    .getString("finish_reason");

                if ("content_filter".equals(finishReason)) {
                    logger.warn("私有模型响应被内容过滤器拦截");
                    return "抱歉，您的请求包含不适当的内容，请重新表述。【大模型返回拦截内容·】";
                } else {
                    // 提取回复内容
                    String content = jsonResponse.getJSONArray("choices")
                        .getJSONObject(0)
                        .getJSONObject("message")
                        .getString("content");

                    JSONObject usage = jsonResponse.getJSONObject("usage");
                    if (usage != null) {
                        promptTokens = usage.getInteger("prompt_tokens");
                        completionTokens = usage.getInteger("completion_tokens");
                        totalTokens = usage.getInteger("total_tokens");
                    }

                    success = true;
                    logger.info("私有模型API调用成功，响应长度: {}", content.length());
                    return content;
                }
            } else {
                logger.error("私有模型API调用失败，状态码: {}", responseEntity.getStatusCode());
                throw new RuntimeException("私有模型API调用失败: " + responseEntity.getStatusCode());
            }

        } catch (HttpStatusCodeException e) {
            responseBody = e.getResponseBodyAsString();
            errorMessage = e.getMessage();
            logger.error("调用私有模型API异常: {}", e.getMessage());
            throw new RuntimeException("调用AI模型失败: " + e.getMessage(), e);
        } catch (Exception e) {
            errorMessage = e.getMessage();
            logger.error("调用私有模型API异常", e);
            throw new RuntimeException("调用AI模型失败: " + e.getMessage(), e);
        } finally {
            ModelRequestLog logEntry = new ModelRequestLog();
            logEntry.setRequestSource(ModelRequestContextHolder.getRequestSourceOrDefault("AI_PRIVATE"));
            logEntry.setRequestUrl(apiUrl);
            logEntry.setRequestMethod("POST");
            logEntry.setModelName(model);
            logEntry.setAppKey(appKey);
            logEntry.setAppSecret(capabilityName);
            logEntry.setRequestPayload(requestJson);
            logEntry.setResponsePayload(responseBody);
            logEntry.setStatus(success ? "SUCCESS" : "FAILED");
            logEntry.setDurationMs(System.currentTimeMillis() - startTime);
            logEntry.setPromptTokens(promptTokens);
            logEntry.setCompletionTokens(completionTokens);
            logEntry.setTotalTokens(totalTokens);
            logEntry.setErrorMessage(errorMessage);
            logEntry.setExtraInfo(extraInfo);
            modelRequestLogService.record(logEntry);
            ModelRequestContextHolder.clear();
        }
    }

    /**
     * 将capabilityname补齐到24位
     */
    private String getCapabilityName24(String rawCapabilityName) {
        StringBuilder sb = new StringBuilder(rawCapabilityName);
        while (sb.length() < 24) {
            sb.append("0");
        }
        return sb.toString();
    }

    /**
     * 计算MD5值
     */
    private String calculateMD5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : hashBytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5计算失败", e);
        }
    }
}
