#!/usr/bin/env python3
"""
工作手机Agent - 语音控制版
运行在手机上，支持语音命令和自主执行任务
"""

import asyncio
import json
import logging
import argparse
import base64
import time
from datetime import datetime
from typing import Optional, Dict, Any, List

try:
    import websockets
    import uiautomator2 as u2
except ImportError:
    print("请安装依赖: pip install websockets uiautomator2")
    exit(1)

# 尝试导入语音识别
try:
    import speech_recognition as sr
    VOICE_ENABLED = True
except ImportError:
    VOICE_ENABLED = False
    print("语音功能未启用，安装: pip install SpeechRecognition")

logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s')
logger = logging.getLogger(__name__)


class VoiceAgent:
    """
    语音控制Agent
    
    功能：
    1. 手机本地运行，无需电脑
    2. 语音命令控制
    3. 自主执行任务队列
    4. 连接远程服务器接收命令
    """
    
    def __init__(
        self,
        device_id: str,
        server_url: str = None,
        voice_enabled: bool = True
    ):
        self.device_id = device_id
        self.server_url = server_url
        self.voice_enabled = voice_enabled and VOICE_ENABLED
        
        # 初始化uiautomator2
        self.d = u2.connect()
        self.d.implicitly_wait(10.0)
        
        # 任务队列
        self.task_queue: List[Dict] = []
        self.running = False
        
        # 语音识别器
        if self.voice_enabled:
            self.recognizer = sr.Recognizer()
        
        # 预设命令
        self.commands = {
            "打开微信": self._open_wechat,
            "打开豆包": self._open_doubao,
            "打开抖音": self._open_douyin,
            "打开设置": self._open_settings,
            "截图": self._screenshot,
            "返回": self._go_back,
            "回到桌面": self._go_home,
            "向上滑": self._swipe_up,
            "向下滑": self._swipe_down,
        }
        
        logger.info(f"VoiceAgent初始化完成: {device_id}")
        logger.info(f"语音控制: {'启用' if self.voice_enabled else '禁用'}")
    
    # ========== 基础操作 ==========
    
    def _open_wechat(self):
        """打开微信"""
        self.d.app_start("com.tencent.mm")
        return {"success": True, "message": "微信已打开"}
    
    def _open_doubao(self):
        """打开豆包"""
        self.d.app_start("com.larus.nova")
        return {"success": True, "message": "豆包已打开"}
    
    def _open_douyin(self):
        """打开抖音"""
        self.d.app_start("com.ss.android.ugc.aweme")
        return {"success": True, "message": "抖音已打开"}
    
    def _open_settings(self):
        """打开设置"""
        self.d.app_start("com.android.settings")
        return {"success": True, "message": "设置已打开"}
    
    def _screenshot(self):
        """截图"""
        img = self.d.screenshot(format='raw')
        # 保存到手机
        path = f"/sdcard/screenshot_{int(time.time())}.png"
        with open(path, 'wb') as f:
            f.write(img)
        return {"success": True, "message": f"截图已保存: {path}"}
    
    def _go_back(self):
        """返回"""
        self.d.press("back")
        return {"success": True, "message": "已返回"}
    
    def _go_home(self):
        """回到桌面"""
        self.d.press("home")
        return {"success": True, "message": "已回到桌面"}
    
    def _swipe_up(self):
        """向上滑动"""
        self.d.swipe_ext("up", scale=0.8)
        return {"success": True, "message": "已向上滑动"}
    
    def _swipe_down(self):
        """向下滑动"""
        self.d.swipe_ext("down", scale=0.8)
        return {"success": True, "message": "已向下滑动"}
    
    # ========== 语音识别 ==========
    
    def listen_voice(self, timeout: int = 5) -> Optional[str]:
        """监听语音命令"""
        if not self.voice_enabled:
            return None
        
        try:
            with sr.Microphone() as source:
                logger.info("请说话...")
                self.recognizer.adjust_for_ambient_noise(source, duration=0.5)
                audio = self.recognizer.listen(source, timeout=timeout)
            
            # 使用Google语音识别（中文）
            text = self.recognizer.recognize_google(audio, language="zh-CN")
            logger.info(f"识别到: {text}")
            return text
        except sr.WaitTimeoutError:
            return None
        except sr.UnknownValueError:
            logger.warning("无法识别语音")
            return None
        except Exception as e:
            logger.error(f"语音识别错误: {e}")
            return None
    
    def process_voice_command(self, text: str) -> Dict:
        """处理语音命令"""
        text = text.strip()
        
        # 精确匹配
        if text in self.commands:
            return self.commands[text]()
        
        # 模糊匹配
        for cmd, func in self.commands.items():
            if cmd in text or text in cmd:
                return func()
        
        # 发送消息命令: "给XXX发消息说XXX"
        if "发消息" in text or "发送" in text:
            return self._parse_send_message(text)
        
        # 打开APP命令: "打开XXX"
        if text.startswith("打开"):
            app_name = text[2:].strip()
            return self._open_app_by_name(app_name)
        
        return {"success": False, "message": f"未识别的命令: {text}"}
    
    def _parse_send_message(self, text: str) -> Dict:
        """解析发消息命令"""
        # 示例: "给张三发消息说你好"
        import re
        match = re.search(r'给(.+?)(发消息|发送)(.+)', text)
        if match:
            contact = match.group(1).strip()
            message = match.group(3).replace("说", "").strip()
            return self._send_wechat_message(contact, message)
        return {"success": False, "message": "无法解析发消息命令"}
    
    def _send_wechat_message(self, contact: str, message: str) -> Dict:
        """发送微信消息"""
        try:
            # 打开微信
            self.d.app_start("com.tencent.mm")
            time.sleep(2)
            
            # 搜索联系人
            if self.d(text="搜索").exists(timeout=3):
                self.d(text="搜索").click()
            time.sleep(0.5)
            
            self.d.send_keys(contact)
            time.sleep(1)
            
            if self.d(text=contact).exists(timeout=3):
                self.d(text=contact).click()
            time.sleep(1)
            
            # 发送消息
            self.d.send_keys(message)
            time.sleep(0.3)
            
            if self.d(text="发送").exists(timeout=3):
                self.d(text="发送").click()
            
            return {"success": True, "message": f"已发送给{contact}: {message}"}
        except Exception as e:
            return {"success": False, "message": str(e)}
    
    def _open_app_by_name(self, name: str) -> Dict:
        """根据名称打开APP"""
        app_map = {
            "微信": "com.tencent.mm",
            "豆包": "com.larus.nova",
            "抖音": "com.ss.android.ugc.aweme",
            "小红书": "com.xingin.xhs",
            "淘宝": "com.taobao.taobao",
            "支付宝": "com.eg.android.AlipayGphone",
            "设置": "com.android.settings",
            "相机": "com.android.camera",
            "浏览器": "com.android.chrome",
        }
        
        package = app_map.get(name)
        if package:
            self.d.app_start(package)
            return {"success": True, "message": f"{name}已打开"}
        
        return {"success": False, "message": f"未知APP: {name}"}
    
    # ========== 任务队列 ==========
    
    def add_task(self, task: Dict):
        """添加任务到队列"""
        task["id"] = f"task_{int(time.time() * 1000)}"
        task["status"] = "pending"
        task["created_at"] = datetime.now().isoformat()
        self.task_queue.append(task)
        logger.info(f"添加任务: {task}")
        return task["id"]
    
    async def process_task_queue(self):
        """处理任务队列"""
        while self.running:
            if self.task_queue:
                task = self.task_queue[0]
                if task["status"] == "pending":
                    task["status"] = "running"
                    logger.info(f"执行任务: {task['id']}")
                    
                    try:
                        result = await self._execute_task(task)
                        task["status"] = "completed"
                        task["result"] = result
                    except Exception as e:
                        task["status"] = "failed"
                        task["error"] = str(e)
                    
                    self.task_queue.pop(0)
            
            await asyncio.sleep(1)
    
    async def _execute_task(self, task: Dict) -> Dict:
        """执行单个任务"""
        task_type = task.get("type")
        params = task.get("params", {})
        
        if task_type == "voice_command":
            return self.process_voice_command(params.get("text", ""))
        
        elif task_type == "click":
            self.d.click(params["x"], params["y"])
            return {"success": True}
        
        elif task_type == "send_message":
            return self._send_wechat_message(
                params.get("contact"),
                params.get("message")
            )
        
        elif task_type == "open_app":
            return self._open_app_by_name(params.get("name"))
        
        return {"success": False, "message": f"未知任务类型: {task_type}"}
    
    # ========== 远程连接 ==========
    
    async def connect_server(self):
        """连接远程服务器"""
        if not self.server_url:
            return
        
        while self.running:
            try:
                logger.info(f"连接服务器: {self.server_url}")
                
                async with websockets.connect(self.server_url) as ws:
                    # 注册
                    await ws.send(json.dumps({
                        "type": "register",
                        "device_id": self.device_id,
                        "capabilities": ["voice", "ui_control"]
                    }))
                    
                    async for message in ws:
                        data = json.loads(message)
                        await self._handle_server_message(data, ws)
                        
            except Exception as e:
                logger.error(f"服务器连接错误: {e}")
                await asyncio.sleep(5)
    
    async def _handle_server_message(self, data: Dict, ws):
        """处理服务器消息"""
        msg_type = data.get("type")
        
        if msg_type == "execute":
            # 添加到任务队列
            task_id = self.add_task(data.get("task", {}))
            await ws.send(json.dumps({
                "type": "task_queued",
                "task_id": task_id
            }))
        
        elif msg_type == "voice_command":
            result = self.process_voice_command(data.get("text", ""))
            await ws.send(json.dumps({
                "type": "result",
                "command_id": data.get("command_id"),
                "result": result
            }))
    
    # ========== 主循环 ==========
    
    async def voice_loop(self):
        """语音监听循环"""
        if not self.voice_enabled:
            return
        
        logger.info("开始语音监听...")
        while self.running:
            text = self.listen_voice(timeout=3)
            if text:
                # 唤醒词检测
                if "小助手" in text or "你好" in text:
                    logger.info("唤醒成功，等待命令...")
                    command = self.listen_voice(timeout=5)
                    if command:
                        result = self.process_voice_command(command)
                        logger.info(f"执行结果: {result}")
            
            await asyncio.sleep(0.1)
    
    async def start(self):
        """启动Agent"""
        self.running = True
        logger.info("VoiceAgent启动")
        
        tasks = [
            self.process_task_queue(),
        ]
        
        if self.server_url:
            tasks.append(self.connect_server())
        
        if self.voice_enabled:
            tasks.append(self.voice_loop())
        
        await asyncio.gather(*tasks)
    
    def stop(self):
        """停止Agent"""
        self.running = False
        logger.info("VoiceAgent停止")


def main():
    parser = argparse.ArgumentParser(description='语音控制Agent')
    parser.add_argument('--device-id', default='voice-agent-001', help='设备ID')
    parser.add_argument('--server', help='远程服务器地址 (ws://xxx:8899/ws/device/xxx)')
    parser.add_argument('--no-voice', action='store_true', help='禁用语音控制')
    
    args = parser.parse_args()
    
    agent = VoiceAgent(
        device_id=args.device_id,
        server_url=args.server,
        voice_enabled=not args.no_voice
    )
    
    try:
        asyncio.run(agent.start())
    except KeyboardInterrupt:
        agent.stop()


if __name__ == "__main__":
    main()
