"""
语音会话工具 - 实时语音交互问答

功能：
1. 开启语音会话（类似唤醒智能音箱）
2. 用户说话 → AI识别 → AI语音回复
3. 循环交互，直到结束会话
4. 类似Siri、小爱同学的语音助手体验
"""
import json
from typing import Optional, Dict
from langchain.tools import tool
from coze_coding_dev_sdk import ASRClient, TTSClient
from coze_coding_utils.runtime_ctx.context import new_context
import logging
from datetime import datetime

logger = logging.getLogger(__name__)


class VoiceSessionManager:
    """语音会话管理器 - 管理实时语音交互会话"""
    
    _instance = None
    _sessions: Dict[str, Dict] = {}  # 存储活跃的语音会话
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def start_session(self, session_id: str, user_id: Optional[str] = None) -> Dict:
        """开启语音会话"""
        session = {
            "session_id": session_id,
            "user_id": user_id or "anonymous",
            "status": "active",  # active/ended
            "start_time": datetime.now(),
            "turns": [],  # 对话轮次
            "context": {}  # 会话上下文
        }
        self._sessions[session_id] = session
        logger.info(f"开启语音会话: {session_id}")
        return session
    
    def get_session(self, session_id: str) -> Optional[Dict]:
        """获取语音会话"""
        return self._sessions.get(session_id)
    
    def add_turn(self, session_id: str, user_input: str, assistant_response: str, audio_url: str):
        """添加一轮对话"""
        if session_id in self._sessions:
            turn = {
                "timestamp": datetime.now().isoformat(),
                "user_input": user_input,
                "assistant_response": assistant_response,
                "audio_url": audio_url
            }
            self._sessions[session_id]["turns"].append(turn)
    
    def end_session(self, session_id: str):
        """结束语音会话"""
        if session_id in self._sessions:
            session = self._sessions[session_id]
            session["status"] = "ended"
            session["end_time"] = datetime.now()
            duration = (session["end_time"] - session["start_time"]).total_seconds()
            logger.info(f"结束语音会话 {session_id}, 持续时间: {duration:.1f}秒, 对话轮次: {len(session['turns'])}")
            return session
    
    def get_active_sessions(self) -> list:
        """获取所有活跃会话"""
        return [
            session for session in self._sessions.values()
            if session["status"] == "active"
        ]


# 全局会话管理器
voice_session_manager = VoiceSessionManager()


@tool
def start_voice_session(
    user_id: Optional[str] = None,
    greeting: Optional[str] = None
) -> str:
    """
    开启语音会话，类似于唤醒智能音箱（Siri、小爱同学）。
    
    参数:
        user_id: 用户ID（可选）
        greeting: 开场白（可选），如果不提供将使用默认问候语
    
    返回:
        会话ID和欢迎语音URL
    
    示例:
        start_voice_session(user_id="user123", greeting="您好，我是物业管家小何")
    """
    try:
        # 生成会话ID
        import uuid
        session_id = f"voice_{uuid.uuid4().hex[:12]}"
        
        # 创建会话
        session = voice_session_manager.start_session(
            session_id=session_id,
            user_id=user_id
        )
        
        # 默认欢迎语
        default_greeting = "您好，我是物业智能管家小何，有什么可以帮您的吗？"
        greeting_text = greeting or default_greeting
        
        # 生成欢迎语音
        ctx = new_context(method="voice.session.start")
        tts_client = TTSClient(ctx=ctx)
        greeting_audio_url, _ = tts_client.synthesize(
            uid=session_id,
            text=greeting_text,
            speaker="zh_female_xiaohe_uranus_bigtts",
            audio_format="mp3"
        )
        
        logger.info(f"语音会话已开启: {session_id}")
        
        return json.dumps({
            "success": True,
            "session_id": session_id,
            "status": "active",
            "greeting": greeting_text,
            "greeting_audio_url": greeting_audio_url,
            "message": "语音会话已开启，您可以开始说话了"
        }, ensure_ascii=False)
        
    except Exception as e:
        error_msg = f"开启语音会话失败: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return json.dumps({
            "success": False,
            "error": error_msg
        }, ensure_ascii=False)


@tool
def voice_chat(
    session_id: str,
    audio_url: str,
    speaker: str = "zh_female_xiaohe_uranus_bigtts"
) -> str:
    """
    在语音会话中进行交互：识别用户语音，AI处理并返回语音回复。
    
    这是核心的语音交互工具，实现"用户说话 → AI识别 → AI回复语音"的完整流程。
    
    参数:
        session_id: 语音会话ID（通过start_voice_session获取）
        audio_url: 用户语音的URL地址
        speaker: 语音角色（可选）
    
    返回:
        识别的文字、AI回复文字、回复语音URL
    
    示例:
        voice_chat(session_id="voice_xxx", audio_url="https://example.com/user_voice.mp3")
    """
    try:
        # 获取会话
        session = voice_session_manager.get_session(session_id)
        if not session:
            return json.dumps({
                "success": False,
                "error": f"语音会话 {session_id} 不存在，请先调用 start_voice_session 开启会话"
            }, ensure_ascii=False)
        
        if session["status"] != "active":
            return json.dumps({
                "success": False,
                "error": f"语音会话 {session_id} 已结束"
            }, ensure_ascii=False)
        
        # ===== 步骤1: 语音识别（ASR） =====
        ctx_asr = new_context(method="voice.asr")
        asr_client = ASRClient(ctx=ctx_asr)
        recognized_text, _ = asr_client.recognize(
            uid=session_id,
            url=audio_url
        )
        
        logger.info(f"语音识别结果: {recognized_text}")
        
        # ===== 步骤2: AI理解并生成回复 =====
        # 注意：这里的AI回复实际上是由主Agent的LLM生成的
        # 这个工具只负责"语音识别"和"语音合成"
        # 在实际调用时，Agent会先调用此工具识别文字，然后自己生成回复文字
        # 所以这里我们返回识别的文字，让Agent继续处理
        
        # ===== 步骤3: 语音合成（TTS） =====
        # 注意：语音合成会在Agent生成回复文字后，调用speak_to_user工具完成
        # 或者可以在这里提供一个示例回复（用于演示）
        
        # 记录用户输入
        voice_session_manager.add_turn(
            session_id=session_id,
            user_input=recognized_text,
            assistant_response="",  # 稍后由Agent填充
            audio_url=""
        )
        
        return json.dumps({
            "success": True,
            "session_id": session_id,
            "recognized_text": recognized_text,
            "message": "语音识别成功，请继续处理用户需求并生成回复"
        }, ensure_ascii=False)
        
    except Exception as e:
        error_msg = f"语音交互失败: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return json.dumps({
            "success": False,
            "error": error_msg
        }, ensure_ascii=False)


@tool
def end_voice_session(
    session_id: str,
    farewell: Optional[str] = None
) -> str:
    """
    结束语音会话。
    
    参数:
        session_id: 语音会话ID
        farewell: 结束语（可选）
    
    返回:
        会话统计信息
    
    示例:
        end_voice_session(session_id="voice_xxx", farewell="感谢使用，再见")
    """
    try:
        # 获取会话
        session = voice_session_manager.get_session(session_id)
        if not session:
            return json.dumps({
                "success": False,
                "error": f"语音会话 {session_id} 不存在"
            }, ensure_ascii=False)
        
        # 默认结束语
        default_farewell = "感谢您的使用，祝您生活愉快，再见！"
        farewell_text = farewell or default_farewell
        
        # 生成结束语语音
        ctx = new_context(method="voice.session.end")
        tts_client = TTSClient(ctx=ctx)
        farewell_audio_url, _ = tts_client.synthesize(
            uid=session_id,
            text=farewell_text,
            speaker="zh_female_xiaohe_uranus_bigtts",
            audio_format="mp3"
        )
        
        # 结束会话
        ended_session = voice_session_manager.end_session(session_id)
        
        # 计算会话时长
        duration = (ended_session["end_time"] - ended_session["start_time"]).total_seconds()
        
        logger.info(f"语音会话已结束: {session_id}")
        
        return json.dumps({
            "success": True,
            "session_id": session_id,
            "status": "ended",
            "farewell": farewell_text,
            "farewell_audio_url": farewell_audio_url,
            "duration_seconds": duration,
            "turn_count": len(ended_session["turns"]),
            "message": "语音会话已结束"
        }, ensure_ascii=False)
        
    except Exception as e:
        error_msg = f"结束语音会话失败: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return json.dumps({
            "success": False,
            "error": error_msg
        }, ensure_ascii=False)


@tool
def get_voice_session_status(
    session_id: str
) -> str:
    """
    查询语音会话状态。
    
    参数:
        session_id: 语音会话ID
    
    返回:
        会话详细信息
    
    示例:
        get_voice_session_status(session_id="voice_xxx")
    """
    try:
        session = voice_session_manager.get_session(session_id)
        if not session:
            return json.dumps({
                "success": False,
                "error": f"语音会话 {session_id} 不存在"
            }, ensure_ascii=False)
        
        # 计算会话时长
        if "end_time" in session:
            duration = (session["end_time"] - session["start_time"]).total_seconds()
        else:
            duration = (datetime.now() - session["start_time"]).total_seconds()
        
        return json.dumps({
            "success": True,
            "session": {
                "session_id": session["session_id"],
                "user_id": session["user_id"],
                "status": session["status"],
                "duration_seconds": duration,
                "turn_count": len(session["turns"]),
                "start_time": session["start_time"].isoformat(),
                "end_time": session.get("end_time", "").isoformat() if "end_time" in session else None
            }
        }, ensure_ascii=False)
        
    except Exception as e:
        error_msg = f"查询语音会话状态失败: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return json.dumps({
            "success": False,
            "error": error_msg
        }, ensure_ascii=False)
