"""
Architecture C: Hermes 大脑插件 — Gemini 语音 + Hermes 深度推理

Gemini Multimodal Live 原生全双工音频（听+说），延迟极低。
遇到需要深度推理/专业知识/知识库的问题时，通过 function calling 按需调 Hermes。

日常对话 ──Gemini Live──→ 极低延迟，原生打断
复杂问题 ──query_hermes()──→ Hermes Proxy (SOUL.md + 三实体 + 技能)
"""

import os
import logging
import json
import httpx
from dotenv import load_dotenv
from livekit.agents import Agent, AgentSession, JobContext, WorkerOptions, cli
from livekit.agents.llm import function_tool
from livekit.plugins.google.realtime import RealtimeModel

load_dotenv()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("jarvis-agent")

HERMES_URL = os.getenv("HERMES_PROXY_URL", "http://192.168.31.124:8600/v1/chat/completions")
HERMES_KEY = os.getenv("HERMES_API_KEY", "***")


@function_tool(
    name="query_hermes",
    description=(
        "向 Hermes Agent 系统查询需要深度推理或专业知识的问题。"
        "Hermes 拥有 SOUL.md 人格定义、三个 Agent 实体分流"
        "（jarvis 语音主控/通用、brainstorm 哲学思辨）"
        "和技能系统（可访问主人 Obsidian 知识库）。"
        "日常寒暄、简单事实性问题不需要调用此函数。"
    ),
)
async def query_hermes(
    question: str,
    agent_profile: str = "jarvis",
) -> str:
    """
    Args:
        question: 发送给 Hermes 的完整问题。
        agent_profile: jarvis(语音主控/通用) / brainstorm(哲学思辨)
    """
    logger.info(f"[Hermes -> {agent_profile}] {question[:100]}")

    async with httpx.AsyncClient(timeout=60.0) as client:
        resp = await client.post(
            HERMES_URL,
            headers={
                "Content-Type": "application/json",
                "Authorization": f"Bearer {HERMES_KEY}",
            },
            json={
                "model": agent_profile,
                "messages": [{"role": "user", "content": question}],
                "temperature": 0.7,
                "max_tokens": 2048,
            },
        )
        resp.raise_for_status()
        answer = resp.json()["choices"][0]["message"]["content"]
        logger.info(f"[Hermes <-] {answer[:150]}")
        return answer


async def entrypoint(ctx: JobContext):
    logger.info(f"建立 WebRTC 连接: room={ctx.room.name}")
    await ctx.connect()

    model = RealtimeModel(
        model="gemini-3.1-flash-live-preview",
        instructions=(
            "你是贾维斯（Jarvis），一个运行在 Arch Linux 上的高级实时语音助手。"
            "你的声音沉稳、睿智、略带一分英伦绅士冷幽默。\n\n"
            "## 核心行为准则\n"
            "- 用精炼、口语化的中文交流。主人说中文时你必须用中文回复。\n"
            "- 答非所问、冗长啰嗦、机械重复皆是禁忌。\n"
            "- 随时准备被主人打断并迅速做出反应。\n\n"
            "## 调用 Hermes 大脑的时机\n"
            "- 遇到需要深度推理、哲学思辨、CS/编程/Linux/408 考研知识、"
            "或需要访问主人 Obsidian 知识库时，调用 query_hermes。\n"
            "- 日常寒暄、简单事实（天气/时间/常识）、闲聊不需要调用。\n"
            "- 拿到 Hermes 的回答后，用你自己的声音自然转述，可以适当精简重组。\n\n"
            "## Agent Profile 选择指南\n"
            "- 哲学、思辨、概念分析 -> brainstorm\n"
            "- 编程、Linux、408 考研、CS 技术、其他通用问题 -> jarvis"
        ),
        voice="Charon",
        temperature=1.1,
        api_key=os.getenv("GOOGLE_API_KEY"),
        vertexai=False,
    )

    agent = Agent(
        instructions="你是贾维斯，Arch Linux 上的 AI 语音助手。声音沉稳睿智，用精炼口语化中文交流。",
        llm=model,
        tools=[query_hermes],
    )

    session = AgentSession(llm=model, tools=[query_hermes])

    @ctx.room.on("data_received")
    def on_data_received(data_received_payload: bytes, participant, **kwargs):
        try:
            payload = json.loads(data_received_payload.decode("utf-8"))
            if payload.get("type") == "interrupt":
                logger.info("收到来自前端手动点击的打断信号！")
                session.interrupt(force=True)
        except Exception as e:
            logger.error(f"处理前端手动打断数据包失败: {e}")

    await session.start(agent=agent, room=ctx.room)
    logger.info("贾维斯 (Arch C: Gemini Voice + Hermes Brain) 已就绪。")


if __name__ == "__main__":
    cli.run_app(
        WorkerOptions(
            entrypoint_fnc=entrypoint,
            ws_url=os.getenv("LIVEKIT_URL", "ws://localhost:7880"),
            api_key=os.getenv("LIVEKIT_API_KEY", "devkey"),
            api_secret=os.getenv("LIVEKIT_API_SECRET", "secret"),
        )
    )
