import os
import shutil
import platform
from pathlib import Path
from datetime import datetime
import pyautogui


class FileManager:
    """Менеджер файлов и системы для Jarvis AI"""
    
    def __init__(self):
        self.current_directory = Path.cwd()
        
        # Настройки безопасности для pyautogui (только для скриншотов)
        pyautogui.FAILSAFE = True
        pyautogui.PAUSE = 0.1
    
    def get_current_directory(self) -> str:
        """Получить текущую рабочую директорию"""
        return str(self.current_directory)
    
    def change_directory(self, path: str) -> str:
        """Сменить текущую директорию"""
        try:
            new_path = Path(path)
            if not new_path.is_absolute():
                new_path = self.current_directory / new_path
            
            if new_path.is_dir():
                self.current_directory = new_path.resolve()
                return str(self.current_directory)
            else:
                raise Exception(f"Директория не существует: {path}")
        except Exception as e:
            raise Exception(f"Ошибка смены директории: {e}")
    
    def list_directory(self, path: str = None, show_hidden: bool = False) -> list:
        """Получить список файлов и директорий"""
        try:
            target_path = Path(path) if path else self.current_directory
            if not target_path.is_absolute():
                target_path = self.current_directory / target_path
            
            items = []
            for item in target_path.iterdir():
                if not show_hidden and item.name.startswith('.'):
                    continue
                
                item_info = {
                    'name': item.name,
                    'type': 'directory' if item.is_dir() else 'file',
                    'size': item.stat().st_size if item.is_file() else 0,
                    'modified': datetime.fromtimestamp(item.stat().st_mtime)
                }
                items.append(item_info)
            
            return sorted(items, key=lambda x: (x['type'] != 'directory', x['name']))
        except Exception as e:
            raise Exception(f"Ошибка чтения директории: {e}")
    
    def create_directory(self, name: str, path: str = None) -> str:
        """Создать новую директорию"""
        try:
            base_path = Path(path) if path else self.current_directory
            if not base_path.is_absolute():
                base_path = self.current_directory / base_path
            
            new_dir = base_path / name
            new_dir.mkdir(parents=True, exist_ok=False)
            return str(new_dir)
        except Exception as e:
            raise Exception(f"Ошибка создания директории: {e}")
    
    def create_file(self, name: str, content: str = "", path: str = None) -> str:
        """Создать новый файл"""
        try:
            base_path = Path(path) if path else self.current_directory
            if not base_path.is_absolute():
                base_path = self.current_directory / base_path
            
            new_file = base_path / name
            with open(new_file, 'w', encoding='utf-8') as f:
                f.write(content)
            return str(new_file)
        except Exception as e:
            raise Exception(f"Ошибка создания файла: {e}")
    
    def delete_path(self, path: str, recursive: bool = False) -> bool:
        """Удалить файл или директорию"""
        try:
            target_path = Path(path)
            if not target_path.is_absolute():
                target_path = self.current_directory / target_path
            
            if target_path.is_file():
                target_path.unlink()
            elif target_path.is_dir():
                if recursive:
                    shutil.rmtree(target_path)
                else:
                    target_path.rmdir()
            else:
                raise Exception(f"Путь не существует: {path}")
            
            return True
        except Exception as e:
            raise Exception(f"Ошибка удаления: {e}")
    
    def copy_path(self, source: str, destination: str) -> str:
        """Копировать файл или директорию"""
        try:
            source_path = Path(source)
            if not source_path.is_absolute():
                source_path = self.current_directory / source_path
            
            dest_path = Path(destination)
            if not dest_path.is_absolute():
                dest_path = self.current_directory / dest_path
            
            if source_path.is_file():
                shutil.copy2(source_path, dest_path)
            elif source_path.is_dir():
                shutil.copytree(source_path, dest_path)
            else:
                raise Exception(f"Источник не существует: {source}")
            
            return str(dest_path)
        except Exception as e:
            raise Exception(f"Ошибка копирования: {e}")
    
    def move_path(self, source: str, destination: str) -> str:
        """Переместить файл или директорию"""
        try:
            source_path = Path(source)
            if not source_path.is_absolute():
                source_path = self.current_directory / source_path
            
            dest_path = Path(destination)
            if not dest_path.is_absolute():
                dest_path = self.current_directory / dest_path
            
            shutil.move(str(source_path), str(dest_path))
            return str(dest_path)
        except Exception as e:
            raise Exception(f"Ошибка перемещения: {e}")
    
    def search_files(self, pattern: str, search_dir: str = None, recursive: bool = True) -> list:
        """Поиск файлов по шаблону"""
        try:
            base_dir = Path(search_dir) if search_dir else self.current_directory
            if not base_dir.is_absolute():
                base_dir = self.current_directory / base_dir
            
            results = []
            if recursive:
                search_pattern = f"**/{pattern}"
            else:
                search_pattern = pattern
            
            for match in base_dir.glob(search_pattern):
                if match.is_file() or match.is_dir():
                    results.append({
                        'name': match.name,
                        'path': str(match),
                        'type': 'directory' if match.is_dir() else 'file'
                    })
            
            return results
        except Exception as e:
            raise Exception(f"Ошибка поиска: {e}")
    
    def get_file_info(self, path: str) -> dict:
        """Получить детальную информацию о файле или директории"""
        try:
            target_path = Path(path)
            if not target_path.is_absolute():
                target_path = self.current_directory / target_path
            
            if not target_path.exists():
                raise Exception(f"Путь не существует: {path}")
            
            stat = target_path.stat()
            return {
                'name': target_path.name,
                'absolute_path': str(target_path.resolve()),
                'type': 'directory' if target_path.is_dir() else 'file',
                'size': stat.st_size,
                'size_human': self._human_readable_size(stat.st_size),
                'created': datetime.fromtimestamp(stat.st_ctime),
                'modified': datetime.fromtimestamp(stat.st_mtime),
                'permissions': oct(stat.st_mode)[-3:]
            }
        except Exception as e:
            raise Exception(f"Ошибка получения информации: {e}")
    
    def get_disk_usage(self) -> dict:
        """Получить информацию об использовании диска"""
        try:
            total, used, free = shutil.disk_usage(self.current_directory)
            return {
                'path': str(self.current_directory),
                'total': total,
                'total_human': self._human_readable_size(total),
                'used': used,
                'used_human': self._human_readable_size(used),
                'free': free,
                'free_human': self._human_readable_size(free),
                'usage_percent': (used / total) * 100
            }
        except Exception as e:
            raise Exception(f"Ошибка получения информации о диске: {e}")
    
    def read_file_content(self, path: str) -> str:
        """Прочитать содержимое файла"""
        try:
            target_path = Path(path)
            if not target_path.is_absolute():
                target_path = self.current_directory / target_path
            
            if not target_path.is_file():
                raise Exception(f"Файл не существует: {path}")
            
            with open(target_path, 'r', encoding='utf-8') as f:
                return f.read()
        except Exception as e:
            raise Exception(f"Ошибка чтения файла: {e}")
    
    def capture_screenshot(self, save_path: str = None):
        """Сделать скриншот экрана"""
        try:
            screenshot = pyautogui.screenshot()
            if save_path:
                screenshot.save(save_path)
            return screenshot
        except Exception as e:
            raise Exception(f"Ошибка при создании скриншота: {e}")
    
    def _human_readable_size(self, size_bytes: int) -> str:
        """Конвертировать размер в читаемый формат"""
        if size_bytes == 0:
            return "0B"
        
        units = ["B", "KB", "MB", "GB", "TB"]
        import math
        i = int(math.floor(math.log(size_bytes, 1024)))
        p = math.pow(1024, i)
        s = round(size_bytes / p, 2)
        return f"{s} {units[i]}"