# AiGlossaryService.java

    package com.yumu.noveltranslator.domain.service;

    import com.yumu.noveltranslator.domain.model.AiGlossary;
    import com.yumu.noveltranslator.port.out.GlossaryRepositoryPort;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;

    import java.util.List;

    /**
     * AI 术语表服务
     * 负责维护每个小说项目的 AI 提取术语
     * 支持 upsert（同一项目 + 原文术语已存在则更新译文）
     */
    @Service
    @RequiredArgsConstructor
    @Slf4j
    public class AiGlossaryService {

        private final GlossaryRepositoryPort glossaryPort;

        /**
         * 获取项目所有已确认的术语
         * 如果表不存在或查询失败，返回空列表（不阻断翻译流程）
         */
        public List<AiGlossary> getProjectGlossary(Long projectId) {
            try {
                return glossaryPort.findAiGlossaryByProjectIdAndStatus(projectId, "confirmed");
            } catch (Exception e) {
                log.warn("获取 AI 术语表失败（可能表未创建）: {}", e.getMessage());
                return List.of();
            }
        }

        /**
         * 添加术语（upsert）
         * 如果同一项目下 sourceWord 已存在，则更新 targetWord；否则插入新记录
         * AI 提取的术语默认状态为 pending
         */
        public void addTerm(Long projectId, String sourceWord, String targetWord,
                            String context, String entityType, Long chapterId) {
            glossaryPort.upsertAiGlossary(projectId, sourceWord, targetWord, context, entityType, chapterId);
            log.debug("AI 术语表 upsert: projectId={}, sourceWord={}", projectId, sourceWord);
        }

        /**
         * 批量添加术语
         */
        public void batchAddTerms(Long projectId, List<AiGlossary> terms) {
            if (terms == null || terms.isEmpty()) {
                return;
            }
            for (AiGlossary term : terms) {
                term.setProjectId(projectId);
                if (term.getStatus() == null) {
                    term.setStatus("pending");
                }
                if (term.getConfidence() == null) {
                    term.setConfidence(0.8);
                }
                addTerm(projectId, term.getSourceWord(), term.getTargetWord(),
                        term.getContext(), term.getEntityType(), term.getChapterId());
            }
            log.info("批量添加 AI 术语: projectId={}, count={}", projectId, terms.size());
        }

        /**
         * 更新术语状态（pending -> confirmed / rejected）
         */
        public boolean updateTermStatus(Long termId, String status) {
            return glossaryPort.findAiGlossaryById(termId).map(term -> {
                term.setStatus(status);
                glossaryPort.updateAiGlossary(term);
                return true;
            }).orElseGet(() -> {
                log.warn("术语不存在: termId={}", termId);
                return false;
            });
        }

        /**
         * 删除术语
         */
        public boolean deleteTerm(Long termId) {
            glossaryPort.deleteAiGlossary(termId);
            return true;
        }

        /**
         * 获取项目的待确认术语
         */
        public List<AiGlossary> getPendingTerms(Long projectId) {
            return glossaryPort.findAiGlossaryByProjectIdAndStatus(projectId, "pending");
        }
    }