"""
工具集模块 - 提供打开应用、整理文件等实用功能
"""
import subprocess
import os
import shutil
from pathlib import Path
from typing import List, Optional
import logging

logger = logging.getLogger(__name__)


class SystemTools:
    """系统工具集"""
    
    @staticmethod
    def open_application(app_name: str) -> bool:
        """
        打开 macOS 应用程序
        
        Args:
            app_name: 应用名称（如 "Safari", "Notes", "Calculator"）
        
        Returns:
            是否成功打开
        """
        try:
            # macOS 使用 open 命令打开应用
            subprocess.run(["open", "-a", app_name], check=True, timeout=5)
            logger.info(f"成功打开应用: {app_name}")
            return True
        except subprocess.TimeoutExpired:
            logger.warning(f"打开应用超时: {app_name}")
            return False
        except subprocess.CalledProcessError as e:
            logger.error(f"打开应用失败: {app_name}, 错误: {e}")
            return False
        except Exception as e:
            logger.error(f"打开应用异常: {app_name}, 错误: {e}")
            return False
    
    @staticmethod
    def open_url(url: str, browser: str = "Safari") -> bool:
        """
        在指定浏览器中打开 URL（默认使用 Safari）
        
        Args:
            url: 网址
            browser: 浏览器名称（默认 "Safari"）
        
        Returns:
            是否成功打开
        """
        try:
            # 使用指定浏览器打开 URL
            subprocess.run(["open", "-a", browser, url], check=True, timeout=5)
            logger.info(f"成功在 {browser} 中打开URL: {url}")
            return True
        except Exception as e:
            logger.error(f"在 {browser} 中打开URL失败: {url}, 错误: {e}")
            # 如果指定浏览器失败，尝试使用默认浏览器
            try:
                subprocess.run(["open", url], check=True, timeout=5)
                logger.info(f"使用默认浏览器打开URL: {url}")
                return True
            except Exception as e2:
                logger.error(f"使用默认浏览器打开URL失败: {url}, 错误: {e2}")
                return False
    
    @staticmethod
    def open_file(file_path: str) -> bool:
        """
        打开文件
        
        Args:
            file_path: 文件路径
        
        Returns:
            是否成功打开
        """
        try:
            if not os.path.exists(file_path):
                logger.error(f"文件不存在: {file_path}")
                return False
            subprocess.run(["open", file_path], check=True, timeout=5)
            logger.info(f"成功打开文件: {file_path}")
            return True
        except Exception as e:
            logger.error(f"打开文件失败: {file_path}, 错误: {e}")
            return False
    
    @staticmethod
    def get_clipboard() -> str:
        """
        获取剪贴板内容
        
        Returns:
            剪贴板文本内容
        """
        try:
            result = subprocess.run(
                ["pbpaste"],
                capture_output=True,
                text=True,
                timeout=2
            )
            return result.stdout.strip()
        except Exception as e:
            logger.error(f"获取剪贴板失败: {e}")
            return ""
    
    @staticmethod
    def set_clipboard(text: str) -> bool:
        """
        设置剪贴板内容
        
        Args:
            text: 要设置的文本
        
        Returns:
            是否成功设置
        """
        try:
            process = subprocess.Popen(
                ["pbcopy"],
                stdin=subprocess.PIPE,
                text=True
            )
            process.communicate(input=text, timeout=2)
            logger.debug(f"设置剪贴板: {text[:50]}...")
            return True
        except Exception as e:
            logger.error(f"设置剪贴板失败: {e}")
            return False
    
    @staticmethod
    def organize_files(directory: str, by_type: bool = True) -> dict:
        """
        整理文件（按类型分类）
        
        Args:
            directory: 要整理的目录路径
            by_type: 是否按文件类型分类
        
        Returns:
            整理结果统计
        """
        try:
            if not os.path.exists(directory):
                logger.error(f"目录不存在: {directory}")
                return {"success": False, "error": "目录不存在"}
            
            stats = {
                "success": True,
                "moved": 0,
                "errors": 0
            }
            
            # 文件类型映射
            type_folders = {
                "Images": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".webp"],
                "Documents": [".pdf", ".doc", ".docx", ".txt", ".rtf", ".pages"],
                "Videos": [".mp4", ".mov", ".avi", ".mkv", ".wmv"],
                "Audio": [".mp3", ".wav", ".m4a", ".flac", ".aac"],
                "Archives": [".zip", ".rar", ".7z", ".tar", ".gz"],
                "Code": [".py", ".js", ".html", ".css", ".java", ".cpp", ".c"]
            }
            
            for item in os.listdir(directory):
                item_path = os.path.join(directory, item)
                if os.path.isfile(item_path):
                    _, ext = os.path.splitext(item)
                    ext = ext.lower()
                    
                    # 找到对应的文件夹
                    target_folder = None
                    for folder, extensions in type_folders.items():
                        if ext in extensions:
                            target_folder = folder
                            break
                    
                    if target_folder:
                        target_path = os.path.join(directory, target_folder)
                        os.makedirs(target_path, exist_ok=True)
                        
                        try:
                            shutil.move(item_path, os.path.join(target_path, item))
                            stats["moved"] += 1
                        except Exception as e:
                            logger.error(f"移动文件失败: {item_path}, 错误: {e}")
                            stats["errors"] += 1
            
            logger.info(f"文件整理完成: 移动 {stats['moved']} 个文件")
            return stats
        except Exception as e:
            logger.error(f"整理文件失败: {e}")
            return {"success": False, "error": str(e)}
    
    @staticmethod
    def search_files(directory: str, pattern: str) -> List[str]:
        """
        搜索文件
        
        Args:
            directory: 搜索目录
            pattern: 文件名模式（支持通配符）
        
        Returns:
            匹配的文件路径列表
        """
        try:
            results = []
            for root, dirs, files in os.walk(directory):
                for file in files:
                    if pattern.lower() in file.lower():
                        results.append(os.path.join(root, file))
            return results
        except Exception as e:
            logger.error(f"搜索文件失败: {e}")
            return []
    
    @staticmethod
    def copy_file(source: str, destination: str) -> bool:
        """
        复制文件或目录
        
        Args:
            source: 源路径
            destination: 目标路径
        
        Returns:
            是否成功
        """
        try:
            if not os.path.exists(source):
                logger.error(f"源文件不存在: {source}")
                return False
            
            if os.path.isdir(source):
                shutil.copytree(source, destination, dirs_exist_ok=True)
            else:
                os.makedirs(os.path.dirname(destination), exist_ok=True)
                shutil.copy2(source, destination)
            
            logger.info(f"复制成功: {source} -> {destination}")
            return True
        except Exception as e:
            logger.error(f"复制文件失败: {e}")
            return False
    
    @staticmethod
    def move_file(source: str, destination: str) -> bool:
        """
        移动文件或目录
        
        Args:
            source: 源路径
            destination: 目标路径
        
        Returns:
            是否成功
        """
        try:
            if not os.path.exists(source):
                logger.error(f"源文件不存在: {source}")
                return False
            
            os.makedirs(os.path.dirname(destination), exist_ok=True)
            shutil.move(source, destination)
            logger.info(f"移动成功: {source} -> {destination}")
            return True
        except Exception as e:
            logger.error(f"移动文件失败: {e}")
            return False
    
    @staticmethod
    def delete_file(file_path: str) -> bool:
        """
        删除文件或目录
        
        Args:
            file_path: 文件路径
        
        Returns:
            是否成功
        """
        try:
            if not os.path.exists(file_path):
                logger.warning(f"文件不存在: {file_path}")
                return False
            
            if os.path.isdir(file_path):
                shutil.rmtree(file_path)
            else:
                os.remove(file_path)
            
            logger.info(f"删除成功: {file_path}")
            return True
        except Exception as e:
            logger.error(f"删除文件失败: {e}")
            return False
    
    @staticmethod
    def create_file(file_path: str, content: str = "") -> bool:
        """
        创建文件
        
        Args:
            file_path: 文件路径
            content: 文件内容
        
        Returns:
            是否成功
        """
        try:
            os.makedirs(os.path.dirname(file_path), exist_ok=True)
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content)
            logger.info(f"创建文件成功: {file_path}")
            return True
        except Exception as e:
            logger.error(f"创建文件失败: {e}")
            return False
    
    @staticmethod
    def read_file(file_path: str) -> str:
        """
        读取文件内容
        
        Args:
            file_path: 文件路径
        
        Returns:
            文件内容
        """
        try:
            if not os.path.exists(file_path):
                logger.error(f"文件不存在: {file_path}")
                return ""
            
            with open(file_path, 'r', encoding='utf-8') as f:
                return f.read()
        except Exception as e:
            logger.error(f"读取文件失败: {e}")
            return ""
    
    @staticmethod
    def get_system_info() -> dict:
        """
        获取系统信息
        
        Returns:
            系统信息字典
        """
        try:
            info = {}
            # 获取 macOS 版本
            result = subprocess.run(
                ["sw_vers"],
                capture_output=True,
                text=True,
                timeout=2
            )
            if result.returncode == 0:
                for line in result.stdout.split("\n"):
                    if ":" in line:
                        key, value = line.split(":", 1)
                        info[key.strip()] = value.strip()
            
            # 获取磁盘使用情况
            result = subprocess.run(
                ["df", "-h", os.path.expanduser("~")],
                capture_output=True,
                text=True,
                timeout=2
            )
            if result.returncode == 0:
                lines = result.stdout.strip().split("\n")
                if len(lines) > 1:
                    parts = lines[1].split()
                    if len(parts) >= 5:
                        info["disk_usage"] = {
                            "used": parts[2],
                            "available": parts[3],
                            "percent": parts[4]
                        }
            
            return info
        except Exception as e:
            logger.error(f"获取系统信息失败: {e}")
            return {}

