package com.spider.quartz.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class TranslationCacheService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Value("${translation.cache.prefix:trans:baidu:}")
    private String cacheKeyPrefix;

    @Value("${translation.cache.ttl-days:30}")
    private long cacheTtlDays;

    /**
     * 获取缓存
     * @param sourceText 原文
     * @param sourceLang 源语言
     * @param targetLang 目标语言
     * @return 缓存译文，未命中时返回null
     */
    public String get(String sourceText, String sourceLang, String targetLang) {
        String cacheKey = buildCacheKey(sourceText, sourceLang, targetLang);
        try {
            String cached = redisTemplate.opsForValue().get(cacheKey);
            if (cached != null) {
                log.debug("Redis缓存命中: key={}", cacheKey);
                return cached;
            }
        } catch (Exception e) {
            // Redis异常：不降级到本地，而是记录警告并继续走翻译流程
            log.warn("Redis缓存读取异常，将直接调用翻译API。键: {}, 错误: {}", cacheKey, e.getMessage());
            // 生产环境可在此触发监控告警
        }
        return null;
    }

    /**
     * 设置缓存
     * @param sourceText 原文
     * @param sourceLang 源语言
     * @param targetLang 目标语言
     * @param translatedText 译文
     */
    public void set(String sourceText, String sourceLang, String targetLang, String translatedText) {
        String cacheKey = buildCacheKey(sourceText, sourceLang, targetLang);
        try {
            redisTemplate.opsForValue().set(
                    cacheKey,
                    translatedText,
                    cacheTtlDays,
                    TimeUnit.DAYS
            );
            log.debug("Redis缓存写入成功: key={}", cacheKey);
        } catch (Exception e) {
            // Redis写入失败只记录错误，不影响主流程
            log.error("Redis缓存写入失败，翻译结果未缓存。键: {}, 错误: {}", cacheKey, e.getMessage());
            // 生产环境可在此触发监控告警
        }
    }

    /**
     * 构建缓存键
     * 格式: prefix:sourceLang:targetLang:hash(sourceText)
     * 使用hash而非完整原文，节省Redis内存且避免特殊字符问题
     */
    private String buildCacheKey(String sourceText, String sourceLang, String targetLang) {
        // 使用MD5或SHA-256生成哈希，这里用SHA-256减少碰撞风险
        String textHash = getSha256Hash(sourceText);
        return String.format("%s:%s:%s:%s",
                cacheKeyPrefix,
                sourceLang,
                targetLang,
                textHash);
    }

    /**
     * 生成文本的SHA-256哈希
     * 避免直接使用hashCode可能产生的碰撞
     */
    private String getSha256Hash(String text) {
        try {
            java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(text.getBytes(java.nio.charset.StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            // 如果哈希失败，回退到hashCode
            log.warn("SHA-256哈希计算失败，使用hashCode回退", e);
            return String.valueOf(text.hashCode());
        }
    }
}