"""
自动化控制模块 - 使用 pyautogui 实现鼠标和键盘自动化
"""
import pyautogui
import time
import os
from typing import Tuple, Optional, List
import logging

logger = logging.getLogger(__name__)

# 安全设置：防止鼠标移动到屏幕角落导致程序中断
pyautogui.FAILSAFE = True
pyautogui.PAUSE = 0.1  # 每个操作之间的默认延迟


class AutomationController:
    """自动化控制器"""
    
    def __init__(self, delay: float = 0.5):
        """
        初始化自动化控制器
        
        Args:
            delay: 操作之间的延迟时间（秒）
        """
        self.delay = delay
        self.screen_width, self.screen_height = pyautogui.size()
        logger.info(f"自动化控制器初始化，屏幕尺寸: {self.screen_width}x{self.screen_height}")
    
    def get_screen_size(self) -> Tuple[int, int]:
        """
        获取屏幕尺寸
        
        Returns:
            (宽度, 高度) 元组
        """
        return (self.screen_width, self.screen_height)
    
    def move_mouse(self, x: int, y: int, duration: float = 0.5):
        """
        移动鼠标到指定坐标
        
        Args:
            x: X坐标
            y: Y坐标
            duration: 移动持续时间（秒）
        """
        try:
            # 确保坐标在屏幕范围内
            x = max(0, min(x, self.screen_width - 1))
            y = max(0, min(y, self.screen_height - 1))
            pyautogui.moveTo(x, y, duration=duration)
            logger.debug(f"鼠标移动到: ({x}, {y})")
        except Exception as e:
            logger.error(f"移动鼠标失败: {e}")
    
    def click(self, x: Optional[int] = None, y: Optional[int] = None, button: str = 'left', clicks: int = 1):
        """
        点击鼠标
        
        Args:
            x: X坐标（None表示当前位置）
            y: Y坐标（None表示当前位置）
            button: 鼠标按钮 ('left', 'right', 'middle')
            clicks: 点击次数
        """
        try:
            if x is not None and y is not None:
                self.move_mouse(x, y)
            time.sleep(self.delay)
            pyautogui.click(x, y, button=button, clicks=clicks)
            logger.debug(f"点击: ({x}, {y}), 按钮: {button}, 次数: {clicks}")
        except Exception as e:
            logger.error(f"点击失败: {e}")
    
    def double_click(self, x: Optional[int] = None, y: Optional[int] = None):
        """双击"""
        self.click(x, y, clicks=2)
    
    def right_click(self, x: Optional[int] = None, y: Optional[int] = None):
        """右键点击"""
        self.click(x, y, button='right')
    
    def type_text(self, text: str, interval: float = 0.05):
        """
        输入文本
        
        Args:
            text: 要输入的文本
            interval: 每个字符之间的间隔（秒）
        """
        try:
            time.sleep(self.delay)
            pyautogui.typewrite(text, interval=interval)
            logger.debug(f"输入文本: {text[:50]}...")
        except Exception as e:
            logger.error(f"输入文本失败: {e}")
    
    def press_key(self, key: str, presses: int = 1, interval: float = 0.1):
        """
        按下键盘按键
        
        Args:
            key: 按键名称（如 'enter', 'tab', 'space'）
            presses: 按下次数
            interval: 多次按下之间的间隔
        """
        try:
            time.sleep(self.delay)
            pyautogui.press(key, presses=presses, interval=interval)
            logger.debug(f"按下按键: {key}, 次数: {presses}")
        except Exception as e:
            logger.error(f"按下按键失败: {e}")
    
    def hotkey(self, *keys):
        """
        组合键（如 Command+C）
        
        Args:
            *keys: 按键序列（如 'command', 'c'）
        """
        try:
            time.sleep(self.delay)
            pyautogui.hotkey(*keys)
            logger.debug(f"组合键: {'+'.join(keys)}")
        except Exception as e:
            logger.error(f"组合键失败: {e}")
    
    def scroll(self, clicks: int, x: Optional[int] = None, y: Optional[int] = None):
        """
        滚动鼠标滚轮
        
        Args:
            clicks: 滚动次数（正数向上，负数向下）
            x: X坐标（None表示当前位置）
            y: Y坐标（None表示当前位置）
        """
        try:
            if x is not None and y is not None:
                self.move_mouse(x, y)
            time.sleep(self.delay)
            pyautogui.scroll(clicks, x=x, y=y)
            logger.debug(f"滚动: {clicks} 次")
        except Exception as e:
            logger.error(f"滚动失败: {e}")
    
    def screenshot(self, save_path: Optional[str] = None) -> Optional[str]:
        """
        截取屏幕（安全模式，避免Intel Mac崩溃）
        
        Args:
            save_path: 保存路径（None表示不保存）
        
        Returns:
            截图文件路径
        """
        try:
            # 方法1：尝试使用pyautogui
            screenshot = pyautogui.screenshot()
            if save_path:
                os.makedirs(os.path.dirname(save_path), exist_ok=True)
                screenshot.save(save_path)
                logger.info(f"截图保存: {save_path}")
                return save_path
            return None
        except Exception as e:
            logger.warning(f"pyautogui截图失败: {e}，尝试备用方法")
            try:
                # 方法2：使用screencapture命令（更安全）
                import tempfile
                import subprocess
                
                if save_path:
                    target_path = save_path
                else:
                    temp_file = tempfile.NamedTemporaryFile(suffix='.png', delete=False)
                    temp_file.close()
                    target_path = temp_file.name
                
                os.makedirs(os.path.dirname(target_path), exist_ok=True)
                
                result = subprocess.run(
                    ['screencapture', '-x', target_path],
                    capture_output=True,
                    timeout=5
                )
                
                if result.returncode == 0 and os.path.exists(target_path):
                    logger.info(f"截图保存: {target_path}")
                    return target_path
                else:
                    logger.error("screencapture命令失败")
                    return None
            except Exception as e2:
                logger.error(f"所有截图方法都失败: {e2}")
                return None
    
    def locate_on_screen(self, image_path: str, confidence: float = 0.8) -> Optional[Tuple[int, int, int, int]]:
        """
        在屏幕上定位图像
        
        Args:
            image_path: 图像文件路径
            confidence: 匹配置信度（0-1）
        
        Returns:
            找到的位置 (left, top, width, height)，未找到返回 None
        """
        try:
            location = pyautogui.locateOnScreen(image_path, confidence=confidence)
            if location:
                logger.info(f"找到图像: {image_path}, 位置: {location}")
                return location
            return None
        except pyautogui.ImageNotFoundException:
            logger.debug(f"未找到图像: {image_path}")
            return None
        except Exception as e:
            logger.error(f"定位图像失败: {e}")
            return None
    
    def click_image(self, image_path: str, confidence: float = 0.8) -> bool:
        """
        找到图像并点击
        
        Args:
            image_path: 图像文件路径
            confidence: 匹配置信度
        
        Returns:
            是否成功点击
        """
        try:
            location = self.locate_on_screen(image_path, confidence)
            if location:
                center = pyautogui.center(location)
                self.click(center.x, center.y)
                return True
            return False
        except Exception as e:
            logger.error(f"点击图像失败: {e}")
            return False
    
    def drag(self, start_x: int, start_y: int, end_x: int, end_y: int, duration: float = 1.0):
        """
        拖拽操作
        
        Args:
            start_x: 起始X坐标
            start_y: 起始Y坐标
            end_x: 结束X坐标
            end_y: 结束Y坐标
            duration: 拖拽持续时间
        """
        try:
            self.move_mouse(start_x, start_y)
            time.sleep(self.delay)
            pyautogui.drag(end_x - start_x, end_y - start_y, duration=duration)
            logger.debug(f"拖拽: ({start_x}, {start_y}) -> ({end_x}, {end_y})")
        except Exception as e:
            logger.error(f"拖拽失败: {e}")
    
    def get_mouse_position(self) -> Tuple[int, int]:
        """获取当前鼠标位置"""
        return pyautogui.position()
    
    def wait_for_image(self, image_path: str, timeout: float = 10.0, confidence: float = 0.8) -> Optional[Tuple[int, int, int, int]]:
        """
        等待图像出现在屏幕上
        
        Args:
            image_path: 图像文件路径
            timeout: 超时时间（秒）
            confidence: 匹配置信度
        
        Returns:
            找到的位置，超时返回 None
        """
        start_time = time.time()
        while time.time() - start_time < timeout:
            location = self.locate_on_screen(image_path, confidence)
            if location:
                return location
            time.sleep(0.5)
        logger.warning(f"等待图像超时: {image_path}")
        return None

