"""LLM 后端抽象接口（可插拔核心）。

新增一个 LLM 后端只需：① 继承 LLMBackend 实现 screen()；② 在 graph/llms/__init__.py
的 LLM_BACKENDS 注册表里登记。config 的 ``llm_screen.provider`` 选择用哪个。
"""
from abc import ABC, abstractmethod
from typing import Any, Dict, List


class LLMBackend(ABC):
    #: 注册名（与 config.llm_screen.provider 对应）
    name: str = "base"

    @abstractmethod
    def screen(
        self,
        topics: List[str],
        country: str,
        aesthetic_hint: str,
        system_prompt: str,
        blacklist: List[str],
        batch_size: int = 12,
    ) -> List[Dict[str, Any]]:
        """对一批话题做合规筛查 + 结构化四要素提取，返回列表。

        每条结构（与旧 llm_screen.screen_combined 的 screened 一致）：
        {
          "topic": <原始话题>,
          "safe_for_print": bool,
          "risk_level": "safe" | "review" | "blocked",
          "risk_reasons": [str],
          "suitable_for_print": bool,
          "design_category": "Style"|"Meme"|"Event"|"Niche"|"Pattern"|"Quote"|"Failed",
          "concept": <中文概念, 1 句>,
          "motif": <英文主体>,
          "art_style": <英文风格>,
          "color_palette": <英文配色>,
          "composition": <英文构图>,
          "negative_prompt": <负向>,
          "confidence": 0-1,
        }

        实现内部必须处理调用失败/超时，失败时抛出异常由节点降级逻辑接管（或直接返回兜底结果）。
        """
        raise NotImplementedError

    @abstractmethod
    def generate_seeds(self, context: Dict[str, Any]) -> Dict[str, Any]:
        """根据上下文（trending 派生 / 历史热点 / 月份节日）生成 Google Trends 相关查询种子词。

        返回 {"style_seeds": [str], "related_seeds": [str]}。
        context 字段：country, trending_seeds, history_hotspots, season, month_themes, upcoming_holidays。
        实现内部必须处理调用失败/超时，失败时抛异常由 seed_node 降级逻辑接管。
        """
        raise NotImplementedError
