"""
@RAG_CONTEXT
{
  "archivo": "src/rag_indexer/tmux_manager.py",
  "lineas": 0,
  "tokens_estimados": 0,
  "hash_contenido": "",
  "creacion": "2026-03-17",
  "modificacion": "2026-03-17",
  "tags": [],
  "descripcion_corta": "",
  "descripcion_larga": ""
}
"""
import os
import shutil
import subprocess
from pathlib import Path
from .logger import get_logger

logger = get_logger("rag_indexer_tmux")

# ──────────────────────────────────────────────
#  Detección de tmux en el sistema
# ──────────────────────────────────────────────

def is_tmux_available() -> bool:
    return shutil.which("tmux") is not None


def get_tmux_version() -> str:
    """Retorna la versión de tmux instalada, ej. 'tmux 3.3a'. '' si no está."""
    try:
        result = subprocess.run(
            ["tmux", "-V"], capture_output=True, text=True, timeout=5
        )
        return result.stdout.strip()
    except Exception:
        return ""


def is_inside_tmux() -> bool:
    """Devuelve True si la sesión actual ya corre dentro de tmux."""
    return bool(os.environ.get("TMUX"))


# ──────────────────────────────────────────────
#  Detección de gestores de paquetes
# ──────────────────────────────────────────────

_PKG_INSTALL = {
    "apt":     ["apt",     "install", "-y", "tmux"],
    "apt-get": ["apt-get", "install", "-y", "tmux"],
    "dnf":     ["dnf",     "install", "-y", "tmux"],
    "yum":     ["yum",     "install", "-y", "tmux"],
    "pacman":  ["pacman",  "-S", "--noconfirm", "tmux"],
    "brew":    ["brew",    "install", "tmux"],
}

_PKG_UPDATE = {
    "apt":     ["apt",     "install", "--only-upgrade", "-y", "tmux"],
    "apt-get": ["apt-get", "install", "--only-upgrade", "-y", "tmux"],
    "dnf":     ["dnf",     "upgrade",  "-y", "tmux"],
    "yum":     ["yum",     "update",   "-y", "tmux"],
    "pacman":  ["pacman",  "-Syu", "--noconfirm", "tmux"],
    "brew":    ["brew",    "upgrade", "tmux"],
}


def _detect_pkg_cmd(table: dict) -> list:
    for mgr, cmd in table.items():
        if shutil.which(mgr):
            return cmd
    return []


def _run_pkg_cmd(cmd: list) -> bool:
    """Ejecuta un comando de gestor de paquetes. Retorna True si tuvo éxito."""
    if not cmd:
        return False
    logger.info("Ejecutando: %s", " ".join(cmd))
    try:
        result = subprocess.run(cmd, timeout=120)
        return result.returncode == 0
    except Exception as exc:
        logger.error("Error ejecutando gestor de paquetes: %s", exc)
        return False


def install_tmux_interactive() -> bool:
    """
    Detecta gestor de paquetes e instala tmux con confirmación del usuario.
    Retorna True si tmux quedó disponible al final.
    """
    cmd = _detect_pkg_cmd(_PKG_INSTALL)
    if not cmd:
        print(
            "\n  No se detectó un gestor de paquetes compatible (apt/dnf/yum/pacman/brew)."
        )
        print("  Instala tmux manualmente: https://github.com/tmux/tmux/wiki/Installing")
        return False

    print(f"\n  Gestor detectado: {cmd[0]}")
    print(f"  Comando a ejecutar: sudo {' '.join(cmd)}")
    confirm = input("  ¿Confirmas la instalación? [S/n]: ").strip().lower()
    if confirm == "n":
        print("  Instalación cancelada.")
        return False

    # Intentar con sudo si es necesario
    full_cmd = ["sudo"] + cmd if cmd[0] != "brew" else cmd
    ok = _run_pkg_cmd(full_cmd)
    if ok and is_tmux_available():
        logger.info("tmux instalado correctamente: %s", get_tmux_version())
        return True
    logger.error("La instalación de tmux falló o no se detectó después de instalar.")
    return False


def update_tmux_interactive() -> None:
    """Detecta gestor de paquetes y actualiza tmux con confirmación del usuario."""
    cmd = _detect_pkg_cmd(_PKG_UPDATE)
    if not cmd:
        print(
            "\n  No se detectó un gestor de paquetes compatible para actualizar tmux."
        )
        return

    print(f"\n  Gestor detectado: {cmd[0]}")
    print(f"  Comando a ejecutar: sudo {' '.join(cmd)}")
    confirm = input("  ¿Confirmas la actualización? [S/n]: ").strip().lower()
    if confirm == "n":
        print("  Actualización cancelada.")
        return

    full_cmd = ["sudo"] + cmd if cmd[0] != "brew" else cmd
    ok = _run_pkg_cmd(full_cmd)
    if ok:
        logger.info("tmux actualizado: %s", get_tmux_version())
    else:
        logger.error("La actualización de tmux falló.")


# ──────────────────────────────────────────────
#  Nombres y estado de sesiones
# ──────────────────────────────────────────────

def get_session_name(cwd: str = None) -> str:
    """Retorna el nombre de sesión para el proyecto actual: {basename}___rag-indexer."""
    base = os.path.basename(cwd or os.getcwd()) or "proyecto"
    return f"{base}___rag-indexer"


def session_exists(name: str) -> bool:
    """Retorna True si existe una sesión tmux con ese nombre."""
    try:
        result = subprocess.run(
            ["tmux", "has-session", "-t", name],
            capture_output=True, timeout=5
        )
        return result.returncode == 0
    except Exception:
        return False


# ──────────────────────────────────────────────
#  Creación y gestión de sesiones
# ──────────────────────────────────────────────

def create_session(name: str, ai_cmd: str = "") -> bool:
    """
    Crea una sesión tmux con 2 ventanas:
      Window 0: AI  — lanza ai_cmd si está definido
      Window 1: Shell — bash limpio
    Retorna True si se creó correctamente.
    """
    try:
        # Crear sesión con ventana "AI" (modo detached)
        subprocess.run(
            ["tmux", "new-session", "-d", "-s", name, "-n", "AI"],
            check=True, timeout=10
        )
        # Crear ventana "Shell"
        subprocess.run(
            ["tmux", "new-window", "-t", f"{name}:", "-n", "Shell"],
            check=True, timeout=10
        )
        # Lanzar AI CLI en ventana 0 si está configurado
        if ai_cmd:
            subprocess.run(
                ["tmux", "send-keys", "-t", f"{name}:AI", ai_cmd, "Enter"],
                timeout=5
            )
        # Seleccionar ventana AI como activa
        subprocess.run(
            ["tmux", "select-window", "-t", f"{name}:AI"],
            timeout=5
        )
        return True
    except subprocess.CalledProcessError as exc:
        logger.error("Error creando sesión tmux '%s': %s", name, exc)
        return False


def attach_session(name: str) -> None:
    """Entra a la sesión tmux. Bloquea hasta que el usuario salga (Ctrl+B D)."""
    os.execlp("tmux", "tmux", "attach-session", "-t", name)


def kill_session(name: str) -> bool:
    """Elimina la sesión tmux. Retorna True si se eliminó."""
    try:
        subprocess.run(
            ["tmux", "kill-session", "-t", name],
            check=True, capture_output=True, timeout=5
        )
        return True
    except subprocess.CalledProcessError:
        return False


# ──────────────────────────────────────────────
#  Configuración en .env
# ──────────────────────────────────────────────

def save_tmux_config(enabled: bool, ai_cmd: str, session_name: str = "") -> None:
    """Escribe las variables RAG_TMUX_* en el .env del proyecto."""
    try:
        from dotenv import set_key
        env_path = os.path.join(os.getcwd(), ".env")
        # Crear .env si no existe
        if not os.path.exists(env_path):
            Path(env_path).touch()
        set_key(env_path, "RAG_TMUX_ENABLED", "true" if enabled else "false")
        if ai_cmd:
            set_key(env_path, "RAG_AI_CMD", ai_cmd)
        if session_name:
            set_key(env_path, "RAG_TMUX_SESSION", session_name)
        logger.info("Configuración tmux guardada en .env")
    except Exception as exc:
        logger.error("Error guardando configuración tmux: %s", exc)


def load_tmux_config() -> dict:
    """Carga la configuración tmux desde .env. Retorna defaults si no existe."""
    try:
        from dotenv import load_dotenv
        load_dotenv(os.path.join(os.getcwd(), ".env"))
    except Exception:
        pass
    return {
        "enabled":  os.environ.get("RAG_TMUX_ENABLED", "false").lower() == "true",
        "ai_cmd":   os.environ.get("RAG_AI_CMD", "claude"),
        "session":  os.environ.get("RAG_TMUX_SESSION", "") or get_session_name(),
    }


# ──────────────────────────────────────────────
#  Script helper .ai/scripts/session.sh
# ──────────────────────────────────────────────

def write_session_script(session_name: str) -> None:
    """Genera .ai/scripts/session.sh — shortcut de reconexión desde cualquier terminal."""
    scripts_dir = os.path.join(os.getcwd(), ".ai", "scripts")
    os.makedirs(scripts_dir, exist_ok=True)
    script_path = os.path.join(scripts_dir, "session.sh")
    content = f"""#!/bin/bash
# Generado por rag-indexer tmux-init
# Reconecta a la sesión persistente del proyecto desde cualquier terminal.
rag-indexer tmux-attach
"""
    with open(script_path, "w", encoding="utf-8") as f:
        f.write(content)
    os.chmod(script_path, 0o755)
    logger.info("Script helper generado: %s", script_path)


# ──────────────────────────────────────────────
#  Comandos CLI públicos
# ──────────────────────────────────────────────

def cmd_init() -> None:
    """
    rag-indexer tmux-init
    Flujo completo:
      1. Verificar/instalar/actualizar tmux
      2. Configurar RAG_AI_CMD
      3. Guardar config en .env
      4. Generar .ai/scripts/session.sh
      5. Ofrecer crear y entrar a la sesión ahora
    """
    print("\n═══════════════════════════════════════════════")
    print("  rag-indexer tmux — Configuración de sesión persistente")
    print("═══════════════════════════════════════════════\n")

    # ── 1. Verificar tmux ──────────────────────────
    if is_tmux_available():
        version = get_tmux_version()
        print(f"  ✅ tmux detectado: {version}")
        update = input("  ¿Deseas actualizar tmux a la última versión? [s/N]: ").strip().lower()
        if update == "s":
            update_tmux_interactive()
    else:
        print("  ⚠️  tmux no está instalado en este sistema.")
        print("  tmux mantiene sesiones activas aunque se cierre la terminal,")
        print("  ahorrando tokens al no tener que re-explicar el contexto a la IA.\n")
        install = input("  ¿Deseas instalar tmux ahora? [S/n]: ").strip().lower()
        if install != "n":
            ok = install_tmux_interactive()
            if not ok:
                print("\n  ❌ No se pudo instalar tmux. Configura el paquete manualmente y vuelve a correr tmux-init.")
                return
        else:
            print("  Instalación omitida. Puedes correr 'rag-indexer tmux-init' cuando lo instales.")
            return

    # ── 2. Configurar AI CLI ───────────────────────
    print()
    ai_cmd = input("  Comando de tu AI CLI (ej. claude, cursor, aider) [claude]: ").strip()
    if not ai_cmd:
        ai_cmd = "claude"

    # ── 3. Nombre de sesión ────────────────────────
    session_name = get_session_name()
    print(f"\n  Nombre de sesión: {session_name}")
    custom = input("  ¿Deseas usar un nombre diferente? [dejar vacío para mantener]: ").strip()
    if custom:
        session_name = custom

    # ── 4. Guardar en .env ─────────────────────────
    save_tmux_config(enabled=True, ai_cmd=ai_cmd, session_name=session_name)

    # ── 5. Generar script helper ───────────────────
    write_session_script(session_name)

    print(f"\n  ✅ Configuración guardada en .env")
    print(f"  ✅ Script helper: .ai/scripts/session.sh")
    print(f"\n  ⚠️  Nota: las sesiones tmux NO persisten reboots.")
    print(f"      Tras reiniciar el servidor, ejecuta 'rag-indexer tmux-attach' para recrear la sesión.\n")

    # ── 6. Ofrecer crear sesión ahora ──────────────
    crear = input("  ¿Deseas crear la sesión y entrar ahora? [S/n]: ").strip().lower()
    if crear != "n":
        if session_exists(session_name):
            print(f"\n  Sesión '{session_name}' ya existe — reconectando...")
        else:
            print(f"\n  Creando sesión '{session_name}' con ventanas [AI] y [Shell]...")
            create_session(session_name, ai_cmd)
        print("  (Para salir de tmux sin cerrar la sesión: Ctrl+B → D)\n")
        attach_session(session_name)  # bloquea hasta que el usuario salga


def cmd_attach() -> None:
    """
    rag-indexer tmux-attach
    Conecta a la sesión del proyecto. Si no existe, la recrea automáticamente.
    """
    if not is_tmux_available():
        logger.error("tmux no está instalado. Ejecuta 'rag-indexer tmux-init' primero.")
        return

    cfg = load_tmux_config()
    session_name = cfg["session"]
    ai_cmd = cfg["ai_cmd"]

    # Advertir anidamiento
    if is_inside_tmux():
        print(f"\n  ⚠️  Ya estás dentro de una sesión tmux.")
        print(f"  Anidar sesiones puede causar conflictos de atajos de teclado (Ctrl+B).")
        confirm = input("  ¿Deseas continuar de todos modos? [s/N]: ").strip().lower()
        if confirm != "s":
            print("  Operación cancelada.")
            return

    if session_exists(session_name):
        print(f"\n  Reconectando a sesión existente: {session_name}")
        print("  (Para salir sin cerrar la sesión: Ctrl+B → D)\n")
    else:
        print(f"\n  Sesión '{session_name}' no encontrada — creando nueva...")
        create_session(session_name, ai_cmd)
        print(f"  Ventanas disponibles: [AI] ({ai_cmd}) | [Shell]")
        print("  (Para salir sin cerrar la sesión: Ctrl+B → D)\n")

    attach_session(session_name)  # bloquea hasta que el usuario salga


def cmd_del_session() -> None:
    """
    rag-indexer tmux-del-session
    Elimina la sesión tmux del proyecto actual con confirmación.
    """
    if not is_tmux_available():
        logger.error("tmux no está instalado.")
        return

    cfg = load_tmux_config()
    session_name = cfg["session"]

    if not session_exists(session_name):
        print(f"\n  No existe ninguna sesión tmux activa con el nombre '{session_name}'.")
        return

    print(f"\n  Sesión a eliminar: {session_name}")
    print("  ⚠️  Cualquier proceso corriendo dentro (AI CLI, shells) será terminado.")
    confirm = input("  ¿Confirmas la eliminación? [s/N]: ").strip().lower()
    if confirm != "s":
        print("  Operación cancelada.")
        return

    if kill_session(session_name):
        print(f"\n  ✅ Sesión '{session_name}' eliminada.")
        print("  Para crear una nueva sesión: rag-indexer tmux-attach\n")
    else:
        logger.error("No se pudo eliminar la sesión '%s'.", session_name)


def cmd_status() -> None:
    """
    rag-indexer tmux-status
    Muestra el estado de la sesión tmux del proyecto actual.
    """
    if not is_tmux_available():
        print("\n  ❌ tmux no está instalado.")
        return

    cfg = load_tmux_config()
    session_name = cfg["session"]
    print(f"\n  Proyecto: {os.path.basename(os.getcwd())}")
    print(f"  Sesión  : {session_name}")

    if not session_exists(session_name):
        print("  Estado  : ❌ Sin sesión activa")
        print("\n  Tip: ejecuta 'rag-indexer tmux-attach' para crear una nueva.\n")
        return

    # Obtener info de la sesión
    try:
        result = subprocess.run(
            [
                "tmux", "display-message", "-p", "-t", session_name,
                "created=#{session_created}|windows=#{session_windows}|activity=#{session_activity}"
            ],
            capture_output=True, text=True, timeout=5
        )
        info = {}
        for pair in result.stdout.strip().split("|"):
            if "=" in pair:
                k, v = pair.split("=", 1)
                info[k] = v

        # Listar ventanas
        wins_result = subprocess.run(
            ["tmux", "list-windows", "-t", session_name, "-F", "  [#{window_index}] #{window_name}#{?window_active, ← activa,}"],
            capture_output=True, text=True, timeout=5
        )
        windows_str = wins_result.stdout.strip()
    except Exception:
        windows_str = ""

    print("  Estado  : ✅ Activa")
    if windows_str:
        print(f"  Ventanas:")
        for line in windows_str.splitlines():
            print(f"  {line}")
    print(f"  AI CMD  : {cfg['ai_cmd']}")
    print()


def cmd_list() -> None:
    """
    rag-indexer tmux-list
    Lista todas las sesiones ___rag-indexer activas en el sistema.
    """
    if not is_tmux_available():
        print("\n  ❌ tmux no está instalado.")
        return

    try:
        result = subprocess.run(
            ["tmux", "list-sessions", "-F", "#{session_name}"],
            capture_output=True, text=True, timeout=5
        )
        if result.returncode != 0:
            print("\n  No hay sesiones tmux activas en el sistema.\n")
            return

        all_sessions = result.stdout.strip().splitlines()
        rag_sessions = [s for s in all_sessions if s.endswith("___rag-indexer")]

        if not rag_sessions:
            print("\n  No hay sesiones rag-indexer activas en este sistema.\n")
            return

        current = get_session_name()
        print(f"\n  Sesiones rag-indexer activas ({len(rag_sessions)}):\n")
        for s in rag_sessions:
            marker = " ← proyecto actual" if s == current else ""
            print(f"    {s}{marker}")
        print()
    except Exception as exc:
        logger.error("Error listando sesiones tmux: %s", exc)
