"""
语音识别与合成模块 - 完全重写版，确保在macOS 12上正常工作
"""
import subprocess
import tempfile
import os
from typing import Optional
import logging
import time
import threading

logger = logging.getLogger(__name__)


class SpeechEngine:
    """语音识别与合成引擎 - 完全重写版"""
    
    def __init__(self, language: str = "zh-CN", rate: int = 150):
        """
        初始化语音引擎
        
        Args:
            language: 语言代码
            rate: 语音速率（默认150）
        """
        self.language = language
        self.rate = rate
        self._check_dictation_enabled()
        logger.info(f"语音引擎初始化，语言: {language}, 速率: {rate}")
    
    def _check_dictation_enabled(self) -> bool:
        """检查macOS听写功能是否已启用"""
        try:
            # 检查系统设置
            script = '''
            tell application "System Preferences"
                activate
                set current pane to pane id "com.apple.preference.universalaccess"
            end tell
            tell application "System Events"
                tell process "System Preferences"
                    try
                        click button "听写" of tab group 1 of window 1
                        return "enabled"
                    on error
                        return "disabled"
                    end try
                end tell
            end tell
            '''
            result = subprocess.run(
                ["osascript", "-e", script],
                capture_output=True,
                text=True,
                timeout=5
            )
            if "enabled" in result.stdout.lower():
                logger.info("✅ macOS听写功能已启用")
                return True
            else:
                logger.warning("⚠️ macOS听写功能可能未启用，请前往系统设置 > 键盘 > 听写 启用")
                return False
        except Exception as e:
            logger.warning(f"无法检查听写功能状态: {e}")
            return False
    
    def speak(self, text: str, rate: Optional[int] = None) -> bool:
        """
        文本转语音（使用 macOS say 命令）
        
        Args:
            text: 要朗读的文本
            rate: 语音速率（None使用默认值）
        
        Returns:
            是否成功
        """
        try:
            rate = rate or self.rate
            # macOS 使用 say 命令进行语音合成
            cmd = ["say", "-r", str(rate), text]
            subprocess.run(cmd, check=True, timeout=len(text) * 0.1 + 5)
            logger.debug(f"语音合成: {text[:50]}...")
            return True
        except subprocess.TimeoutExpired:
            logger.warning("语音合成超时")
            return False
        except subprocess.CalledProcessError as e:
            logger.error(f"语音合成失败: {e}")
            return False
        except Exception as e:
            logger.error(f"语音合成异常: {e}")
            return False
    
    def recognize_speech(self, timeout: float = 10.0) -> Optional[str]:
        """
        语音识别（完全重写版，确保在macOS 12上正常工作）
        
        Args:
            timeout: 超时时间（秒）
        
        Returns:
            识别的文本，失败返回 None
        """
        try:
            # 方法1：优先使用 macOS 系统听写功能（最可靠，适配macOS 12）
            logger.info("🎤 尝试使用 macOS 听写功能...")
            result = self._recognize_with_macos_dictation_improved()
            if result:
                logger.info(f"✅ macOS听写识别成功: {result}")
                return result
            
            # 方法2：使用 speech_recognition 库（如果可用）
            logger.info("🎤 尝试使用 speech_recognition 库...")
            try:
                import speech_recognition as sr
                result = self._recognize_with_speech_recognition(timeout)
                if result:
                    logger.info(f"✅ speech_recognition识别成功: {result}")
                    return result
            except ImportError:
                logger.warning("speech_recognition 库未安装，跳过")
            except Exception as e:
                logger.warning(f"speech_recognition 失败: {e}")
            
            # 所有方法都失败
            logger.warning("❌ 所有语音识别方法都失败")
            return None
            
        except Exception as e:
            logger.error(f"语音识别失败: {e}")
            import traceback
            traceback.print_exc()
            return None
    
    def _recognize_with_macos_dictation_improved(self) -> Optional[str]:
        """
        使用 macOS 听写功能（改进版，更可靠）
        
        Returns:
            识别的文本，失败返回 None
        """
        try:
            # 保存当前剪贴板
            old_clipboard = ""
            try:
                result = subprocess.run(
                    ["pbpaste"],
                    capture_output=True,
                    text=True,
                    timeout=1
                )
                old_clipboard = result.stdout
            except:
                pass
            
            logger.info("📋 已保存当前剪贴板内容")
            
            # 方法1：使用 Fn Fn 快捷键触发听写（最可靠）
            logger.info("🔧 尝试触发听写功能（Fn Fn）...")
            
            # 创建改进的AppleScript脚本
            script = '''
            tell application "System Events"
                -- 方法1：尝试使用 Fn Fn（key code 63）
                try
                    -- 第一次按Fn
                    key code 63
                    delay 0.2
                    -- 第二次按Fn（触发听写）
                    key code 63
                    delay 0.5
                    return "success"
                on error errMsg
                    -- 方法2：尝试使用 Command+Shift+X
                    try
                        keystroke "x" using {command down, shift down}
                        delay 0.5
                        return "success"
                    on error
                        return "failed"
                    end try
                end try
            end tell
            '''
            
            # 执行脚本
            result = subprocess.run(
                ["osascript", "-e", script],
                capture_output=True,
                text=True,
                timeout=3,
                check=False
            )
            
            if "success" not in result.stdout.lower():
                logger.warning("⚠️ 无法触发听写功能，请手动按 Fn Fn 或 Command+Shift+X")
                # 即使脚本失败，也继续尝试（用户可能手动触发）
            
            logger.info("✅ 听写功能已触发（或请手动按 Fn Fn）")
            logger.info("💡 请开始说话，说完后按 Fn 键或点击完成按钮")
            
            # 等待用户说话和完成（给足够时间）
            logger.info("⏳ 等待语音输入...")
            max_wait = 30  # 最多等待30秒
            check_interval = 0.5
            waited = 0
            
            while waited < max_wait:
                time.sleep(check_interval)
                waited += check_interval
                
                # 检查剪贴板是否改变
                try:
                    result = subprocess.run(
                        ["pbpaste"],
                        capture_output=True,
                        text=True,
                        timeout=1
                    )
                    new_clipboard = result.stdout.strip()
                    
                    # 如果剪贴板内容改变，且不是空的，可能是识别结果
                    if (new_clipboard and 
                        new_clipboard != old_clipboard and 
                        len(new_clipboard) > 0 and
                        len(new_clipboard) < 1000):  # 限制长度，避免误判
                        
                        # 进一步验证：如果内容看起来像语音识别结果
                        # （通常不会包含特殊字符或格式）
                        if not new_clipboard.startswith("http") and not new_clipboard.startswith("file://"):
                            logger.info(f"📋 检测到剪贴板变化: {new_clipboard[:50]}...")
                            
                            # 恢复原剪贴板
                            if old_clipboard:
                                try:
                                    subprocess.run(
                                        ["pbcopy"],
                                        input=old_clipboard,
                                        text=True,
                                        timeout=1,
                                        check=False
                                    )
                                except:
                                    pass
                            
                            logger.info(f"✅ 识别成功: {new_clipboard}")
                            return new_clipboard
                except:
                    pass
                
                # 每5秒提示一次
                if int(waited) % 5 == 0 and waited > 0:
                    logger.info(f"⏳ 仍在等待... ({int(waited)}秒)")
            
            logger.warning("⏱️ 等待超时，未检测到识别结果")
            logger.info("💡 提示：请确保：")
            logger.info("   1. 系统设置 > 键盘 > 听写 已启用")
            logger.info("   2. 说完后按 Fn 键或点击完成按钮")
            logger.info("   3. 麦克风权限已授予")
            
            return None
            
        except Exception as e:
            logger.error(f"macOS 听写失败: {e}")
            import traceback
            traceback.print_exc()
            return None
    
    def _recognize_with_speech_recognition(self, timeout: float) -> Optional[str]:
        """
        使用 speech_recognition 库进行语音识别
        
        Args:
            timeout: 超时时间
        
        Returns:
            识别的文本，失败返回 None
        """
        try:
            import speech_recognition as sr
            r = sr.Recognizer()
            
            # 优化配置（针对macOS 12和Intel Mac）
            r.energy_threshold = 300  # 降低阈值，更容易触发
            r.dynamic_energy_threshold = True
            r.pause_threshold = 0.5  # 停顿阈值
            r.phrase_threshold = 0.3
            r.non_speaking_duration = 0.5
            
            logger.info("🎤 正在监听语音输入...")
            
            with sr.Microphone() as source:
                # 调整环境噪音
                logger.info("🔧 正在调整环境噪音...")
                try:
                    r.adjust_for_ambient_noise(source, duration=0.5)
                except:
                    pass
                
                logger.info("✅ 准备就绪，请开始说话...")
                
                try:
                    # 监听语音
                    audio = r.listen(source, timeout=timeout, phrase_time_limit=15)
                    logger.info("🔍 正在识别语音...")
                except sr.WaitTimeoutError:
                    logger.warning("⏱️ 语音输入超时")
                    return None
                except Exception as e:
                    logger.error(f"❌ 监听失败: {e}")
                    return None
            
            # 尝试识别
            try:
                # 优先使用 Google（最快，免费）
                logger.info("🌐 使用 Google 语音识别服务...")
                text = r.recognize_google(audio, language='zh-CN', show_all=False)
                logger.info(f"✅ 识别成功: {text}")
                return text
            except sr.UnknownValueError:
                logger.warning("❌ 无法识别语音内容")
                return None
            except sr.RequestError as e:
                logger.error(f"❌ 语音识别服务错误: {e}")
                # 尝试备用服务
                try:
                    logger.info("🔄 尝试使用备用服务...")
                    text = r.recognize_sphinx(audio, language='zh-CN')
                    logger.info(f"✅ 备用服务识别成功: {text}")
                    return text
                except:
                    logger.error("❌ 所有语音识别服务都失败")
                    return None
                    
        except ImportError:
            logger.warning("speech_recognition 库未安装")
            return None
        except Exception as e:
            logger.error(f"speech_recognition 失败: {e}")
            import traceback
            traceback.print_exc()
            return None
    
    def save_speech_to_file(self, text: str, output_path: str, rate: Optional[int] = None) -> bool:
        """
        将语音保存到文件
        
        Args:
            text: 要转换的文本
            output_path: 输出文件路径（.aiff格式）
            rate: 语音速率
        
        Returns:
            是否成功
        """
        try:
            rate = rate or self.rate
            os.makedirs(os.path.dirname(output_path), exist_ok=True)
            cmd = ["say", "-r", str(rate), "-o", output_path, text]
            subprocess.run(cmd, check=True, timeout=len(text) * 0.1 + 5)
            logger.info(f"语音保存到文件: {output_path}")
            return True
        except Exception as e:
            logger.error(f"保存语音文件失败: {e}")
            return False
    
    def get_available_voices(self) -> list:
        """
        获取可用的语音列表
        
        Returns:
            语音名称列表
        """
        try:
            result = subprocess.run(
                ["say", "-v", "?"],
                capture_output=True,
                text=True,
                timeout=5
            )
            voices = []
            for line in result.stdout.split("\n"):
                if line.strip():
                    # 解析语音名称（格式：语言名称 语言代码）
                    parts = line.split()
                    if len(parts) >= 2:
                        voices.append(" ".join(parts[:-1]))
            return voices
        except Exception as e:
            logger.error(f"获取语音列表失败: {e}")
            return []
    
    def set_voice(self, voice_name: str) -> bool:
        """
        设置语音（需要在 speak 方法中使用）
        
        Args:
            voice_name: 语音名称
        
        Returns:
            是否成功
        """
        try:
            # 验证语音是否存在
            voices = self.get_available_voices()
            if any(voice_name.lower() in v.lower() for v in voices):
                self.voice = voice_name
                logger.info(f"设置语音: {voice_name}")
                return True
            else:
                logger.warning(f"语音不存在: {voice_name}")
                return False
        except Exception as e:
            logger.error(f"设置语音失败: {e}")
            return False
