"""
Script reparador completo para el montaje FUSE del Contenedor Cuántico.
Ejecutar como administrador para resolver todos los problemas de montaje.
"""

import os
import sys
import subprocess
import ctypes
import time
import shutil
import winreg
import platform

from setup_paths import configure_paths
from winfsp_utils import check_winfsp_installation, restart_winfsp_service
from mount_utils import prepare_mountpoint

# Intentar importar psutil, pero manejar el caso en que no esté instalado
try:
    import psutil
    PSUTIL_AVAILABLE = True
except ImportError:
    PSUTIL_AVAILABLE = False
    print("ADVERTENCIA: El módulo 'psutil' no está instalado.")
    print("Para instalarlo, ejecute: pip install psutil")
    print("Continuando con funcionalidad limitada...\n")

def is_admin():
    """Verifica si el script se está ejecutando con privilegios de administrador."""
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False

def kill_processes_using_path(path):
    """Mata todos los procesos que tengan abierto un archivo en la ruta especificada."""
    killed = []
    
    if not PSUTIL_AVAILABLE:
        print("No se pueden detectar procesos usando el punto de montaje (psutil no disponible).")
        return killed
    
    for proc in psutil.process_iter(['pid', 'name', 'open_files']):
        try:
            for file in proc.open_files() or []:
                if path.lower() in file.path.lower():
                    print(f"Cerrando proceso {proc.name()} (PID: {proc.pid}) que usa {file.path}")
                    proc.kill()
                    killed.append(proc.name())
                    break
        except (psutil.AccessDenied, psutil.NoSuchProcess):
            continue
    return killed

def fix_dependencies():
    """Instala todas las dependencias de Python necesarias."""
    print("\n[1/5] Instalando dependencias de Python...")
    
    modules = ["fusepy", "zstd", "numpy", "Pillow", "anytree", "psutil"]
    missing = []
    
    # Verificar qué módulos faltan
    for module in modules:
        try:
            __import__(module)
            print(f"✓ {module} ya instalado")
        except ImportError:
            print(f"✗ {module} NO instalado - se instalará")
            missing.append(module)
    
    if not missing:
        print("✅ Todas las dependencias de Python ya están instaladas")
        return True
    
    # Instalar los módulos faltantes
    try:
        print(f"Instalando módulos faltantes: {', '.join(missing)}")
        subprocess.run([sys.executable, "-m", "pip", "install"] + missing, check=True)
        print("✅ Módulos instalados correctamente")
        return True
    except Exception as e:
        print(f"❌ Error al instalar módulos: {e}")
        return False

# Configurar rutas necesarias
configure_paths()

def fix_winfsp():
    """Repara la instalación y registro de WinFSP."""
    if not check_winfsp_installation():
        print("ERROR: WinFSP no está instalado correctamente.")
        return False
    if not restart_winfsp_service():
        print("ERROR: No se pudo reiniciar el servicio WinFSP.")
        return False
    return True

def fix_mountpoint():
    """Limpia y prepara el punto de montaje."""
    mountpoint = os.path.abspath(os.path.join(os.path.dirname(__file__), ".venv", "mountpoint"))
    return prepare_mountpoint(mountpoint)

def fix_fuse_path():
    """Corrige la ruta para el DLL de WinFSP en el módulo FUSE."""
    print("\n[4/5] Corrigiendo rutas de FUSE...")
    
    try:
        # Verificar la ruta correcta del DLL de WinFSP
        winfsp_dir = os.environ.get('ProgramFiles(x86)', 'C:\\Program Files (x86)') + "\\WinFsp"
        correct_dll_path = os.path.join(winfsp_dir, "bin", "winfsp-x64.dll")
        
        if os.path.exists(correct_dll_path):
            print(f"✓ DLL de WinFSP encontrado en: {correct_dll_path}")
            
            # Crear un patch simple en el entorno
            os.environ["WINFSPDLL"] = correct_dll_path
            print("✅ Variable de entorno WINFSPDLL configurada")
            
            # Intentar cargar la DLL directamente
            try:
                import ctypes
                winfsp = ctypes.cdll.LoadLibrary(correct_dll_path)
                print("✅ DLL de WinFSP cargada correctamente")
            except Exception as e:
                print(f"⚠️ Error al cargar DLL directamente: {e}")
            
            return True
        else:
            print(f"❌ No se encontró el DLL de WinFSP en {correct_dll_path}")
            return False
    except Exception as e:
        print(f"❌ Error al configurar ruta de WinFSP: {e}")
        return False

def test_fuse():
    """Realiza una prueba básica de funcionamiento de FUSE."""
    print("\n[5/5] Probando funcionamiento de FUSE...")
    
    try:
        # Intentar importar el módulo fusepy
        try:
            import fuse
            print("✓ Módulo fusepy importado correctamente")
        except ImportError:
            print("❌ No se pudo importar el módulo fusepy")
            return False
        
        # Verificar si podemos crear una instancia básica de Operations
        try:
            class TestFS(fuse.Operations):
                def getattr(self, path, fh=None):
                    return dict(st_mode=0o755, st_nlink=2, st_size=0,
                                st_ctime=time.time(), st_mtime=time.time(),
                                st_atime=time.time())
            
            test_instance = TestFS()
            print("✓ Se pudo crear una instancia de Operations")
            
            # No intentamos montar aquí, solo verificamos que podamos instanciar
            print("✅ Verificación básica de FUSE completada")
            return True
        except Exception as e:
            print(f"❌ Error al crear instancia de Operations: {e}")
            return False
    except Exception as e:
        print(f"❌ Error en la prueba de FUSE: {e}")
        return False

def clean_stale_files():
    """Limpia archivos temporales o residuales que puedan causar problemas."""
    print("\nLimpiando archivos temporales...")
    
    try:
        # Limpiar archivos de caché en la carpeta del proyecto
        cache_dirs = [
            os.path.join(os.path.dirname(__file__), "__pycache__"),
            os.path.join(os.path.dirname(__file__), ".venv", "src", "__pycache__")
        ]
        
        for cache_dir in cache_dirs:
            if os.path.exists(cache_dir):
                try:
                    shutil.rmtree(cache_dir)
                    print(f"✓ Carpeta de caché eliminada: {cache_dir}")
                except Exception as e:
                    print(f"⚠️ No se pudo eliminar caché {cache_dir}: {e}")
        
        # Limpiar archivos .pyc que puedan causar problemas
        for root, dirs, files in os.walk(os.path.dirname(__file__)):
            for file in files:
                if file.endswith(".pyc") or file.endswith(".pyo"):
                    try:
                        os.unlink(os.path.join(root, file))
                        print(f"✓ Archivo eliminado: {file}")
                    except Exception:
                        pass
        
        print("✅ Limpieza de archivos completada")
        return True
    except Exception as e:
        print(f"⚠️ Error durante la limpieza de archivos: {e}")
        return False

def main():
    """Función principal que ejecuta todas las reparaciones."""
    print("=== REPARACIÓN COMPLETA DEL SISTEMA FUSE PARA CONTENEDOR CUÁNTICO ===\n")
    
    if not is_admin():
        print("⚠️ Este script debe ejecutarse como administrador.")
        print("Por favor, cierre esta ventana y vuelva a ejecutar como administrador.")
        return False
    
    # Ejecutar todos los pasos de reparación
    deps_ok = fix_dependencies()
    winfsp_ok = fix_winfsp()
    mountpoint_ok = fix_mountpoint()
    fuse_path_ok = fix_fuse_path()
    fuse_test_ok = test_fuse()
    
    # Limpiar archivos temporales al final
    clean_stale_files()
    
    # Mostrar resumen
    print("\n=== RESUMEN DE REPARACIÓN ===")
    print(f"1. Dependencias Python: {'✅' if deps_ok else '❌'}")
    print(f"2. Configuración WinFSP: {'✅' if winfsp_ok else '❌'}")
    print(f"3. Punto de montaje: {'✅' if mountpoint_ok else '❌'}")
    print(f"4. Ruta FUSE: {'✅' if fuse_path_ok else '❌'}")
    print(f"5. Prueba FUSE: {'✅' if fuse_test_ok else '❌'}")
    
    all_ok = deps_ok and winfsp_ok and mountpoint_ok and fuse_path_ok and fuse_test_ok
    
    if all_ok:
        print("\n✅ REPARACIÓN COMPLETADA CON ÉXITO")
        print("\nPara usar el Contenedor Cuántico:")
        print("1. Reinicie su computadora")
        print("2. Ejecute el sistema con:")
        print(f"   python .venv/src/quantum_driver.py \"C:\\ruta\\a\\archivos\"")
        return True
    else:
        print("\n⚠️ Algunos problemas no pudieron ser reparados.")
        print("Acciones recomendadas:")
        
        if not deps_ok:
            print("- Instale manualmente los módulos de Python: pip install fusepy zstd numpy Pillow anytree psutil")
        
        if not winfsp_ok:
            print("- Instale/reinstale WinFSP desde: https://github.com/winfsp/winfsp/releases")
            print("- Reinicie el equipo después de la instalación")
        
        if not mountpoint_ok:
            print("- Cierre todas las aplicaciones que estén usando el punto de montaje")
            print("- Verifique permisos de carpeta en el punto de montaje")
        
        if not fuse_path_ok or not fuse_test_ok:
            print("- Intente ejecutar: python -m pip uninstall fusepy")
            print("- Luego: python -m pip install fusepy --force-reinstall")
        
        print("\nSi los problemas persisten:")
        print("1. Ejecute el script como administrador")
        print("2. Reinicie su computadora y vuelva a intentar")
        print("3. Considere reinstalar Python y todas las dependencias")
        
        return False

if __name__ == "__main__":
    success = main()
    input("\nPresione Enter para salir...")
    sys.exit(0 if success else 1)
