"""
NVIDIA 专用 LLM 客户端（fixed configuration）
使用 OpenAI 兼容接口调用 stepfun-ai/step-3.5-flash
"""

import requests
import json
from typing import Optional

class LLMError(Exception):
    pass

# 固定配置（你的可用 key）
CONFIG = {
    "base_url": "https://integrate.api.nvidia.com/v1",
    "api_key": "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",
    "model": "stepfun-ai/step-3.5-flash",
}

def call_llm(
    prompt: str,
    system_prompt: str = "你是一个专业的内容创作助手。",
    temperature: float = 0.7,
    max_tokens: int = 2000,
    stream: bool = False,
) -> str:
    """
    调用 NVIDIA LLM 生成文本
    """
    endpoint = f"{CONFIG['base_url'].rstrip('/')}/chat/completions"
    headers = {
        "Authorization": f"Bearer {CONFIG['api_key']}",
        "Content-Type": "application/json"
    }
    payload = {
        "model": CONFIG["model"],
        "messages": [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": prompt}
        ],
        "temperature": temperature,
        "max_tokens": max_tokens,
        "stream": stream,
    }

    try:
        resp = requests.post(endpoint, json=payload, headers=headers, timeout=120, stream=stream)
        if resp.status_code != 200:
            raise LLMError(f"HTTP {resp.status_code}: {resp.text[:200]}")
        if stream:
            full = []
            for line in resp.iter_lines():
                if not line:
                    continue
                if line.startswith(b'data: '):
                    data = line[6:]
                    if data == b'[DONE]':
                        break
                    try:
                        chunk = json.loads(data)
                        delta = chunk['choices'][0]['delta']
                        # 支持 reasoning_content 或 reasoning 字段
                        if 'reasoning_content' in delta and delta['reasoning_content']:
                            full.append(delta['reasoning_content'])
                        if 'content' in delta and delta['content']:
                            full.append(delta['content'])
                    except Exception:
                        continue
            return "".join(full)
        else:
            data = resp.json()
            msg = data["choices"][0]["message"]
            content = msg.get('content') or msg.get('reasoning') or msg.get('reasoning_content')
            return content.strip() if content else ''
    except requests.RequestException as e:
        raise LLMError(f"Request failed: {e}")

def expand_content_with_llm(topic: dict, section_title: str, section_content: str, context: str = "") -> str:
    """扩写大纲章节，返回包含 ## 标题的完整 Markdown"""
    prompt = f"""你是一个专业的内容创作者。请将以下大纲扩展为完整的文章章节。

# 选题信息
- 标题：{topic.get('title')}
- 领域：{topic.get('field')}
- 核心观点：{topic.get('core_concept', '')}
- 受众痛点：{topic.get('audience_pain', '')}
- 独特视角：{topic.get('unique_angle', '')}

# 当前章节
## {section_title}
{section_content}

# 要求
- 以 `## {section_title}` 作为章节标题开头
- 字数：300-500字
- 风格：客观、专业、易懂
- 使用 Markdown 格式
- 包含具体数据或案例（如果有）
- 保持与整体文章调性一致

直接输出完整的 Markdown 章节（包括 ## 标题和正文段落）。"""
    if context:
        prompt = f"# 参考资料\n{context}\n\n{prompt}"

    try:
        result = call_llm(prompt, temperature=0.8, max_tokens=2000)
        return result.strip()
    except Exception as e:
        return f"## {section_title}\n\n（LLM 调用失败：{e}，请手动补充）"

# 测试
if __name__ == "__main__":
    try:
        print(f"[nvidia_client] 使用模型: {CONFIG['model']}")
        resp = call_llm("你好，请用一句话介绍你自己。", max_tokens=50)
        print(f"[nvidia_client] 响应: {resp}")
    except Exception as e:
        print(f"[nvidia_client] 错误: {e}")
