from config.logger import setup_logging
import random
import uuid
import tempfile
import os
import time
import requests
from plugins_func.register import register_function, ToolType, ActionResponse, Action
from core.handle.sendAudioHandle import send_stt_message
from core.utils.dialogue import Message
from core.providers.tts.dto.dto import TTSMessageDTO, SentenceType, ContentType
from config.manage_api_client import get_device_stories

TAG = __name__

play_story_function_desc = {
    "type": "function",
    "function": {
        "name": "play_story",
        "description": "播放故事、讲故事的功能。当用户说：讲故事、播放故事、听故事、来个故事、给我讲个故事、我想听故事等时调用此功能。",
        "parameters": {
            "type": "object",
            "properties": {
                "story_name": {
                    "type": "string",
                    "description": "故事名称，如果用户没有指定具体故事名则为'random', 明确指定的时返回故事名字 示例: ```用户:讲下王子与公主的故事\n参数：王子与公主``` ```用户:讲个故事 \n参数：random ```",
                }
            },
            "required": ["story_name"],
        },
    },
}


def _get_random_play_prompt(story_title):
    """生成随机播放引导语"""
    prompts = [
        f"正在为您播放，{story_title}",
        f"请欣赏故事，{story_title}",
        f"即将为您播放，{story_title}",
        f"为您带来，{story_title}",
        f"让我们聆听，{story_title}",
        f"接下来请欣赏，{story_title}",
        f"为您献上，{story_title}",
    ]
    return random.choice(prompts)


def _download_audio_from_url(logger, audio_url: str):
    """从URL下载音频文件到临时目录"""
    try:
        # 创建临时文件
        temp_dir = tempfile.gettempdir()
        temp_filename = f"function_story_{int(time.time())}.mp3"
        temp_path = os.path.join(temp_dir, temp_filename)

        logger.bind(tag=TAG).info(f"开始下载音频: {audio_url} -> {temp_path}")

        # 下载音频文件
        response = requests.get(audio_url, stream=True, timeout=60)
        response.raise_for_status()

        with open(temp_path, 'wb') as f:
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)

        # 验证文件大小
        file_size = os.path.getsize(temp_path)
        if file_size == 0:
            logger.bind(tag=TAG).error("下载的音频文件大小为0")
            os.remove(temp_path)
            return None

        logger.bind(tag=TAG).info(f"音频下载完成: {temp_path}, 大小: {file_size} 字节")
        return temp_path

    except requests.exceptions.RequestException as e:
        logger.bind(tag=TAG).error(f"下载音频失败: {str(e)}")
        return None
    except Exception as e:
        logger.bind(tag=TAG).error(f"下载音频时发生未知错误: {str(e)}")
        return None


@register_function("play_story", play_story_function_desc, ToolType.SYSTEM_CTL)
def play_story(conn, story_name: str):
    """播放故事函数"""
    try:
        conn.logger.bind(tag=TAG).info(f"play_story 被调用: story_name={story_name}, device_id={conn.device_id}")

        # 获取设备ID
        device_id = conn.device_id
        if not device_id:
            conn.logger.bind(tag=TAG).error("设备ID不存在，无法播放故事")
            return ActionResponse(
                action=Action.RESPONSE,
                result="设备ID不存在",
                response="抱歉，无法播放故事"
            )

        # 检查事件循环状态
        if not hasattr(conn, 'loop') or not conn.loop.is_running():
            conn.logger.bind(tag=TAG).error("事件循环未运行，无法提交任务")
            return ActionResponse(
                action=Action.RESPONSE,
                result="系统繁忙",
                response="请稍后再试"
            )

        # 默认故事信息（作为兜底）
        default_story_name = "侦探与龙：宝石的秘密"
        default_audio_url = "https://toy-storage.airlabs.art/audio/volcano_tts/permanent/20250904/story_7369183431743246336_cfd71314.mp3"
        default_story_title = "侦探与龙：宝石的秘密"

        # 调用API获取设备故事信息
        conn.logger.bind(tag=TAG).info(f"开始调用API获取设备故事，device_id: {device_id}")
        stories_data = get_device_stories(device_id)
        conn.logger.bind(tag=TAG).info(f"API返回的stories_data: {stories_data}")

        final_story_name = default_story_name
        final_audio_url = default_audio_url
        final_story_title = default_story_title

        if stories_data:
            # 从API响应中提取故事信息
            story_info = None

            # 检查API返回格式：{"success": true, "data": {"title": "...", "audio_url": "..."}}
            if isinstance(stories_data, dict) and stories_data.get("success") and "data" in stories_data:
                data = stories_data["data"]
                # 新格式：data直接包含故事信息
                if isinstance(data, dict) and "title" in data and "audio_url" in data:
                    story_info = data
                    conn.logger.bind(tag=TAG).info(f"从API获取到直接故事数据: {story_info.get('title')}")
                # 原格式：data包含stories数组
                else:
                    story_list = data.get("stories", [])
                    if len(story_list) > 0:
                        # 随机选择一个故事
                        story_info = random.choice(story_list)
                        conn.logger.bind(tag=TAG).info(f"从API获取到{len(story_list)}个故事，随机选择其中一个")
            # 兼容其他格式
            elif isinstance(stories_data, list) and len(stories_data) > 0:
                story_info = random.choice(stories_data)
            elif isinstance(stories_data, dict) and 'stories' in stories_data:
                story_list = stories_data['stories']
                if len(story_list) > 0:
                    story_info = random.choice(story_list)

            if story_info:
                final_story_name = story_info.get("title", default_story_name)
                final_audio_url = story_info.get("audio_url", default_audio_url)
                final_story_title = story_info.get("title", default_story_title)
                conn.logger.bind(tag=TAG).info(f"使用API获取的故事: {final_story_title}")
            else:
                conn.logger.bind(tag=TAG).warning("API返回数据格式不正确，使用默认故事信息")
        else:
            conn.logger.bind(tag=TAG).warning("无法获取设备故事信息，使用默认故事信息")

        # 下载音频文件
        conn.logger.bind(tag=TAG).info(f"开始下载音频文件: {final_audio_url}")
        temp_file_path = _download_audio_from_url(conn.logger, final_audio_url)

        if not temp_file_path:
            conn.logger.bind(tag=TAG).error("下载音频文件失败")
            return ActionResponse(
                action=Action.RESPONSE,
                result="下载失败",
                response="抱歉，无法播放故事"
            )

        # 生成播放提示语
        play_prompt = _get_random_play_prompt(final_story_title)
        conn.logger.bind(tag=TAG).info(f"播放提示语: {play_prompt}")

        # 发送消息到对话
        import asyncio
        asyncio.run_coroutine_threadsafe(
            send_stt_message(conn, play_prompt),
            conn.loop
        )
        conn.dialogue.put(Message(role="assistant", content=play_prompt))

        # 生成新的sentence_id并重置TTS状态
        conn.sentence_id = str(uuid.uuid4())
        conn.tts.tts_audio_first_sentence = True

        # 重置播放状态
        conn.client_abort = False
        conn.llm_finish_task = False

        # 将音频加入TTS队列
        conn.tts.tts_text_queue.put(
            TTSMessageDTO(
                sentence_id=conn.sentence_id,
                sentence_type=SentenceType.FIRST,
                content_type=ContentType.ACTION,
            )
        )
        conn.tts.tts_text_queue.put(
            TTSMessageDTO(
                sentence_id=conn.sentence_id,
                sentence_type=SentenceType.MIDDLE,
                content_type=ContentType.TEXT,
                content_detail=play_prompt,
            )
        )
        conn.tts.tts_text_queue.put(
            TTSMessageDTO(
                sentence_id=conn.sentence_id,
                sentence_type=SentenceType.MIDDLE,
                content_type=ContentType.FILE,
                content_file=temp_file_path,
                content_detail=final_story_title,
            )
        )
        conn.tts.tts_text_queue.put(
            TTSMessageDTO(
                sentence_id=conn.sentence_id,
                sentence_type=SentenceType.LAST,
                content_type=ContentType.ACTION,
            )
        )

        conn.logger.bind(tag=TAG).info(f"故事播放任务已加入队列: {final_story_title}")

        # 返回成功响应
        return ActionResponse(
            action=Action.NONE,
            result="播放成功",
            response=play_prompt
        )

    except Exception as e:
        conn.logger.bind(tag=TAG).error(f"播放故事失败: {str(e)}")
        import traceback
        conn.logger.bind(tag=TAG).error(f"详细错误: {traceback.format_exc()}")
        return ActionResponse(
            action=Action.RESPONSE,
            result=str(e),
            response="播放故事时出错了"
        )


async def handle_story_command(conn, text="播放随机故事"):
    """
    向后兼容函数，供 story_handler.py 调用
    将异步调用转换为同步的 play_story 函数调用
    """
    try:
        conn.logger.bind(tag=TAG).info(f"handle_story_command 被调用: {text}")

        # 从 text 中提取故事名称
        story_name = "random"
        if "讲故事" in text and text != "随机播放故事":
            # 提取故事名称，例如 "讲故事 小红帽" -> "小红帽"
            parts = text.split("讲故事", 1)
            if len(parts) > 1:
                story_name = parts[1].strip()

        # 调用同步的 play_story 函数
        result = play_story(conn, story_name)

        conn.logger.bind(tag=TAG).info(f"handle_story_command 完成: {result}")
        return True

    except Exception as e:
        conn.logger.bind(tag=TAG).error(f"handle_story_command 失败: {str(e)}")
        import traceback
        conn.logger.bind(tag=TAG).error(f"详细错误: {traceback.format_exc()}")
        return False
