package com.agent.management.service.impl;

import com.agent.management.model.entity.TranslationEntry;
import com.agent.management.model.vo.TranslationVO;
import com.agent.management.repository.TranslationCacheRepository;
import com.agent.management.service.AiModelService;
import com.agent.management.service.SseService;
import com.agent.management.service.TranslationService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 基于 Spring AI 的翻译服务实现
 * 支持同步/异步翻译去重：同一文本只会发起一次 AI 请求，后续调用复用结果
 */
@Slf4j
@Service
public class TranslationServiceImpl implements TranslationService {

    private static final long TRANSLATE_TIMEOUT_SECONDS = 120;
    private static final int MAX_CHUNK_LENGTH = 4000;

    private final AiModelService aiModelService;
    private final SseService sseService;
    private final TranslationCacheRepository cacheRepository;
    /** 已完成的翻译缓存：原文 -> 译文 */
    private final Map<String, String> translationCache = new ConcurrentHashMap<>();
    /** 正在进行中的翻译：原文 -> CompletableFuture<译文> */
    private final Map<String, CompletableFuture<String>> pendingTranslations = new ConcurrentHashMap<>();

    public TranslationServiceImpl(AiModelService aiModelService,
                                  SseService sseService,
                                  TranslationCacheRepository cacheRepository) {
        this.aiModelService = aiModelService;
        this.sseService = sseService;
        this.cacheRepository = cacheRepository;
    }

    /**
     * 启动时将 translations.json 全量预热到内存缓存
     */
    @PostConstruct
    void initCacheFromStore() {
        List<TranslationEntry> all = cacheRepository.findAll();
        for (TranslationEntry e : all) {
            if (e.getSourceText() != null && e.getTranslatedText() != null) {
                translationCache.put(e.getSourceText(), e.getTranslatedText());
            }
        }
        log.info("[翻译] 缓存预热完成，载入 {} 条翻译记录", all.size());
    }

    @Override
    public String translateToChinese(String text) {
        if (text == null || text.trim().isEmpty()) return text;

        String key = text.trim();

        // 1. 检查已完成缓存
        String cached = translationCache.get(key);
        if (cached != null) return cached;

        // 2. 获取或创建 Future（去重核心）
        CompletableFuture<String> future = getOrCreateFuture(key, text);

        // 3. 阻塞等待结果
        try {
            return future.get(TRANSLATE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            log.warn("[翻译] 等待翻译超时({}s), 返回原文: {}", TRANSLATE_TIMEOUT_SECONDS, truncate(text, 80));
            return text;
        } catch (Exception e) {
            log.error("[翻译] 等待翻译异常: {}", e.getMessage());
            return text;
        }
    }

    @Override
    public String getCachedTranslation(String text) {
        if (text == null || text.trim().isEmpty()) return text;
        if (containsChinese(text)) return text;
        return translationCache.get(text.trim());
    }

    @Async
    @Override
    public void asyncTranslateAndPush(String folderName, String displayName, String description) {
        log.info("[翻译-SSE] 开始异步翻译, folderName={}", folderName);
        String translatedDisplayName = translateToChinese(displayName);
        String translatedDescription = translateToChinese(description);
        TranslationVO vo = new TranslationVO(folderName, translatedDisplayName, translatedDescription);
        sseService.pushTranslation(vo);
        log.info("[翻译-SSE] 推送翻译结果完成, folderName={}", folderName);
    }

    /**
     * 获取或创建翻译 Future。使用 putIfAbsent 保证同一文本只创建一个 Future。
     * 如果已有 pending Future，直接复用（阻塞等待其完成）。
     * 如果缓存已存在，返回已完成的 Future。
     */
    private CompletableFuture<String> getOrCreateFuture(String key, String text) {
        // 快速路径：已完成缓存
        String cached = translationCache.get(key);
        if (cached != null) {
            return CompletableFuture.completedFuture(cached);
        }

        // 创建新 Future
        CompletableFuture<String> newFuture = new CompletableFuture<>();
        CompletableFuture<String> existing = pendingTranslations.putIfAbsent(key, newFuture);

        if (existing != null) {
            // 另一个线程已经在翻译该文本，复用其 Future
            log.info("[翻译] 复用已有的翻译任务: {}", truncate(text, 80));
            return existing;
        }

        // 当前线程负责执行翻译
        try {
            String result = doTranslate(text);
            newFuture.complete(result);
        } catch (Exception e) {
            newFuture.complete(text); // 降级返回原文
        } finally {
            pendingTranslations.remove(key);
        }

        return newFuture;
    }

    private String doTranslate(String text) {
        String key = text.trim();
        String cached = translationCache.get(key);
        if (cached != null) return cached;

        // 短文本直接翻译
        if (text.length() <= MAX_CHUNK_LENGTH) {
            return doTranslateSingle(text);
        }

        // 长文本：按段落分段翻译
        return doTranslateChunked(text);
    }

    private String doTranslateSingle(String text) {
        String key = text.trim();
        String cached = translationCache.get(key);
        if (cached != null) return cached;

        log.info("[翻译] 开始调用大模型翻译, 原文长度: {} 字符", text.length());
        long startTime = System.currentTimeMillis();
        try {
            String translated = aiModelService.systemChatCall(client ->
                    client.prompt()
                            .user(u -> u.text("将以下文本中的英文部分翻译为简体中文；已有的中文、专有名词缩写、代码、命令、文件路径等保留不变；只返回翻译结果，不要添加任何解释或额外文本：\n\n{text}")
                                    .param("text", text))
                            .call()
                            .content()
            );
            long elapsed = System.currentTimeMillis() - startTime;
            log.info("[翻译] 大模型响应耗时: {}ms", elapsed);
            if (translated != null && !translated.trim().isEmpty()) {
                String result = translated.trim();
                translationCache.put(key, result);
                cacheRepository.save(key, result);
                log.info("[翻译] 翻译成功: {} -> {}", truncate(text, 80), truncate(result, 80));
                return result;
            }
            log.warn("[翻译] 大模型返回空结果, 耗时: {}ms", elapsed);
            return text;
        } catch (Exception e) {
            log.error("[翻译] 大模型调用异常: {}", e.getMessage());
            return text;
        }
    }

    /**
     * 长文本分段翻译：按空行切分段落，每段不超过 MAX_CHUNK_LENGTH，逐段翻译后拼接
     */
    private String doTranslateChunked(String text) {
        log.info("[翻译] 长文本分段翻译开始, 总长度: {} 字符", text.length());
        long startTime = System.currentTimeMillis();

        String[] paragraphs = text.split("\n\\s*\n");
        List<String> chunks = new ArrayList<>();
        StringBuilder currentChunk = new StringBuilder();

        for (String para : paragraphs) {
            if (currentChunk.length() + para.length() + 2 > MAX_CHUNK_LENGTH && currentChunk.length() > 0) {
                chunks.add(currentChunk.toString());
                currentChunk = new StringBuilder();
            }
            if (currentChunk.length() > 0) currentChunk.append("\n\n");
            currentChunk.append(para);
        }
        if (currentChunk.length() > 0) {
            chunks.add(currentChunk.toString());
        }

        log.info("[翻译] 分为 {} 段", chunks.size());

        StringBuilder result = new StringBuilder();
        for (int i = 0; i < chunks.size(); i++) {
            String chunk = chunks.get(i);
            log.info("[翻译] 翻译第 {}/{} 段, 长度: {}", i + 1, chunks.size(), chunk.length());
            String translated = doTranslateSingle(chunk);
            if (i > 0) result.append("\n\n");
            result.append(translated);
        }

        long elapsed = System.currentTimeMillis() - startTime;
        log.info("[翻译] 长文本分段翻译完成, 总耗时: {}ms", elapsed);

        String finalResult = result.toString();
        translationCache.put(text.trim(), finalResult);
        cacheRepository.save(text.trim(), finalResult);
        return finalResult;
    }

    private String truncate(String text, int maxLen) {
        if (text == null) return "null";
        if (text.length() <= maxLen) return text;
        return text.substring(0, maxLen) + "...";
    }

    private boolean containsChinese(String text) {
        if (text == null) return false;
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            if (c >= '\u4e00' && c <= '\u9fff') return true;
        }
        return false;
    }
}
