"""
Mount Quantum FS - Script dedicado para montar el sistema de archivos cuántico
usando WinFSP directamente sin depender de Python FUSE bindings.

Ejecutar como administrador para mejores resultados.
"""

import os
import sys
import ctypes
import platform
import time
import subprocess
import logging
import shutil
from pathlib import Path
from module_utils import prepare_mountpoint

# Configurar logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("quantum_mount.log"),
        logging.StreamHandler()
    ]
)

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

def ensure_winfsp_loaded():
    """Carga la DLL de WinFSP y verifica su disponibilidad."""
    try:
        # Intentar cargar la DLL de WinFSP desde posibles rutas
        possible_paths = [
            os.environ.get('ProgramFiles(x86)', 'C:\\Program Files (x86)') + "\\WinFsp 2023\\bin\\winfsp-x64.dll",
            os.environ.get('ProgramFiles(x86)', 'C:\\Program Files (x86)') + "\\WinFsp\\bin\\winfsp-x64.dll"
        ]
        
        for path in possible_paths:
            if os.path.exists(path):
                winfsp = ctypes.cdll.LoadLibrary(path)
                print(f"✓ WinFSP cargado correctamente desde {path}")
                return True
        
        print("❌ No se encontró la DLL de WinFSP en las rutas esperadas.")
        return False
    except Exception as e:
        print(f"❌ Error al cargar WinFSP: {e}")
        return False

def mount_with_launcher(mountpoint, source_dir):
    """
    Monta el sistema de archivos usando WinFSP Launcher directamente.
    Esta aproximación utiliza el launcher propio de WinFSP que es más estable que
    el binding de Python para FUSE.
    """
    try:
        # Construir la ruta al ejecutable del controlador quantum
        quantum_driver = str(Path(__file__).parent / ".venv" / "src" / "driver_core.exe")
        winfsp_launcher = os.environ.get('ProgramFiles(x86)', 'C:\\Program Files (x86)') + "\\WinFsp\\bin\\launchctl-x64.exe"
        
        if not os.path.exists(winfsp_launcher):
            logging.error(f"WinFSP Launcher no encontrado en {winfsp_launcher}")
            return False
        
        # Crear un parámetro de configuración para el sistema de archivos
        fs_config = {
            "source": source_dir,
            "mountpoint": mountpoint,
            "FileInfoTimeout": "-1",
            "VolumeInfoTimeout": "-1",
            "DirInfoTimeout": "-1",
            "SecurityTimeout": "-1",
        }
        
        # Crear una lista de parámetros para el launcher
        cmd = [
            winfsp_launcher, 
            "start",
            "-d", quantum_driver,  # Path al driver
            "-i", "QuantumFS",     # ID del driver
            "-u", mountpoint,      # Punto de montaje
            "-o", f"source={source_dir}"  # Directorio fuente
        ]
        
        # Ejecutar el comando
        logging.info(f"Ejecutando comando: {' '.join(cmd)}")
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        if result.returncode != 0:
            logging.error(f"Error al montar: {result.stderr}")
            return False
        
        # Verificar si el montaje fue exitoso esperando y comprobando
        for i in range(10):  # Intentar por 10 segundos
            if os.path.ismount(mountpoint):
                logging.info(f"Montaje FUSE exitoso en {mountpoint}")
                return True
            time.sleep(1)
        
        # Última verificación: intentar listar el directorio
        try:
            files = os.listdir(mountpoint)
            logging.info(f"Montaje FUSE verificado. Contenido: {files[:5] if files else 'Vacío'}")
            return True
        except Exception as e:
            logging.error(f"Error al verificar el montaje: {e}")
            return False
    except Exception as e:
        logging.error(f"Error en el proceso de montaje: {e}")
        return False

def mount_with_python_fuse(mountpoint, source_dir):
    """
    Alternativa usando Python FUSE bindings directamente.
    Esto es un fallback si el método con el launcher de WinFSP falla.
    """
    try:
        # Construir el comando para ejecutar el script quantum_fs.py
        python_exe = sys.executable
        quantum_fs_script = str(Path(__file__).parent / ".venv" / "src" / "quantum_fs.py")
        
        cmd = [
            python_exe,
            quantum_fs_script,
            mountpoint,
            "-o", f"source={source_dir},allow_other,direct_io"
        ]
        
        logging.info(f"Ejecutando comando FUSE: {' '.join(cmd)}")
        
        # Iniciar el proceso en modo separado
        process = subprocess.Popen(
            cmd, 
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0
        )
        
        # Esperar a que el montaje ocurra
        for i in range(10):  # Intentar por 10 segundos
            if os.path.ismount(mountpoint):
                logging.info(f"Montaje FUSE con Python exitoso en {mountpoint}")
                return True
            time.sleep(1)
        
        # Verificar si el proceso está en ejecución
        if process.poll() is None:
            logging.info("El proceso FUSE está en ejecución, pero no se detecta el montaje")
            
            # Verificar si hay output del proceso
            output, error = process.communicate(timeout=1)
            if output:
                logging.info(f"Salida del proceso: {output.decode()[:200]}")
            if error:
                logging.warning(f"Error del proceso: {error.decode()[:200]}")
            
            # Intentar verificar listando el directorio
            try:
                files = os.listdir(mountpoint)
                logging.info(f"Contenido del punto de montaje: {files[:5] if files else 'Vacío'}")
                return True
            except Exception as e:
                logging.error(f"No se puede listar el contenido del punto de montaje: {e}")
        else:
            logging.error("El proceso FUSE terminó prematuramente")
            output, error = process.communicate()
            if output:
                logging.info(f"Salida del proceso: {output.decode()[:200]}")
            if error:
                logging.error(f"Error del proceso: {error.decode()[:200]}")
        
        return False
    except Exception as e:
        logging.error(f"Error al montar con Python FUSE: {e}")
        return False

def mount_quantum_fs(source_dir=None):
    """
    Función principal para montar el sistema de archivos cuántico.
    Intenta con diferentes métodos en caso de que alguno falle.
    """
    # Verificar permisos de administrador
    if not is_admin():
        logging.warning("No se está ejecutando como administrador. Esto puede causar problemas de permisos.")
    
    # Verificar si WinFSP está instalado
    if not ensure_winfsp_loaded():
        logging.error("WinFSP no está correctamente instalado o configurado.")
        print("RECOMENDACIÓN: Instale WinFSP desde https://github.com/winfsp/winfsp/releases")
        return False
    
    # Definir el punto de montaje
    mountpoint = str(Path(__file__).parent / ".venv" / "mountpoint")
    logging.info(f"Usando punto de montaje: {mountpoint}")
    
    # Verificar el directorio fuente
    if source_dir is None:
        # Buscar directorio de documentos o usar CCaaa como fallback
        try:
            documents_dir = os.path.join(os.path.expanduser("~"), "Documents")
            if os.path.exists(documents_dir):
                source_dir = documents_dir
            else:
                source_dir = "C:\\CCaaa"  # Directorio por defecto si no se encuentra otro
        except:
            source_dir = "C:\\CCaaa"  # Fallback en caso de error
    
    if not os.path.isdir(source_dir):
        logging.error(f"El directorio fuente no existe: {source_dir}")
        return False
    
    logging.info(f"Usando directorio fuente: {source_dir}")
    
    # Preparar el punto de montaje
    if not prepare_mountpoint(mountpoint):  # Usar prepare_mountpoint
        logging.error("No se pudo preparar el punto de montaje.")
        return False
    
    # Intentar montar con el launcher de WinFSP
    logging.info("Intentando montar con WinFSP Launcher...")
    if mount_with_launcher(mountpoint, source_dir):
        logging.info("Montaje exitoso con WinFSP Launcher")
        return True
    
    # Si falla el primer método, intentar con Python FUSE
    logging.info("Intentando montar con Python FUSE...")
    if mount_with_python_fuse(mountpoint, source_dir):
        logging.info("Montaje exitoso con Python FUSE")
        return True
    
    # Si ambos métodos fallan, intentar un enfoque de subproceso directo
    logging.info("Intentando montar con método alternativo...")
    try:
        # Este método inicia un proceso separado para ejecutar quantum_driver.py
        # con un flag especial que le indica que debe intentar solo el montaje
        python_exe = sys.executable
        driver_script = str(Path(__file__).parent / ".venv" / "src" / "quantum_driver.py")
        
        cmd = [
            python_exe,
            driver_script,
            source_dir,
            "--mount-only"  # Flag especial para solo intentar el montaje
        ]
        
        # Ejecutar el comando en un proceso separado
        subprocess.Popen(
            cmd,
            creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0
        )
        
        # Esperar a ver si el montaje ocurre
        for i in range(15):  # Esperar hasta 15 segundos
            if os.path.ismount(mountpoint):
                logging.info(f"Montaje exitoso con método alternativo")
                return True
            time.sleep(1)
        
        logging.error("El método alternativo de montaje también falló")
        return False
    except Exception as e:
        logging.error(f"Error en el método alternativo: {e}")
        return False

if __name__ == "__main__":
    # Obtener el directorio fuente de los argumentos
    source_dir = sys.argv[1] if len(sys.argv) > 1 else None
    
    print("=== MONTAJE DE SISTEMA DE ARCHIVOS CUÁNTICO ===")
    print(f"Directorio fuente: {source_dir if source_dir else 'No especificado, usando C:\\CCaaa'}")
    print("Log detallado: quantum_mount.log\n")
    
    if mount_quantum_fs(source_dir):
        print("\n✅ Sistema de archivos montado correctamente")
        print("Puede acceder a sus archivos a través de:")
        print(f"  {os.path.abspath(os.path.join(os.path.dirname(__file__), '.venv', 'mountpoint'))}")
        print("\nEjecute el visualizador de archivos con:")
        print(f"  python .venv/src/quantum_metadata_manager.py")
    else:
        print("\n❌ No se pudo montar el sistema de archivos")
        print("Revise el archivo quantum_mount.log para ver detalles del error")
        print("Si el problema persiste, intente ejecutar:")
        print("  python fix_fuse_mount.py")
