#!/usr/bin/env bash
# ===============================================================
# apps.sh - Instalación de aplicaciones esenciales
# ===============================================================
#
# Este módulo se encarga de instalar y configurar una amplia gama
# de aplicaciones y herramientas de sistema.
#
# Funciones principales:
#   - Instala Homebrew (Linuxbrew) para gestionar paquetes adicionales.
#   - Instala paquetes desde los repositorios de Arch (pacman) y desde AUR.
#   - Organiza los paquetes por categorías (base, multimedia, red, etc.).
#   - Configura drivers para gráficos Intel Iris Xe.
#   - Configura GNOME Keyring para la gestión de contraseñas y claves SSH.
#   - Habilita servicios del sistema para aplicaciones como keyd, logiops y TeamViewer.
#
# ===============================================================

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/common.sh"

# ---------------------------------------------------------------
# ensure_homebrew_env()
# ---------------------------------------------------------------
# Asegura que el entorno de Homebrew esté configurado correctamente.
#
# Esta función realiza dos tareas principales:
#   1. Carga Homebrew en la sesión de shell actual para que el comando `brew`
#      esté disponible inmediatamente después de la instalación.
#   2. Añade la línea de inicialización de Homebrew a los ficheros de
#      perfil del usuario (`.profile` y `.zprofile`) para que `brew`
#      esté disponible en futuras sesiones de terminal.
#
# Parámetros:
#   $1 - Ruta al ejecutable de brew.
# ---------------------------------------------------------------
ensure_homebrew_env() {
    local brew_bin="$1"
    if [[ ! -x "$brew_bin" ]]; then
        return 1
    fi

    # Evalúa `shellenv` para que el resto del módulo pueda usar `brew`
    # sin necesidad de reiniciar la shell.
    eval "$("$brew_bin" shellenv)" || return 1

    local shell_snippet='eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'
    local -a appended=()
    local -a rc_targets=("${HOME}/.profile")

    # Si el usuario utiliza Zsh, añade también la configuración a .zprofile.
    if [[ -n "${SHELL:-}" && "$(basename "${SHELL}")" == "zsh" ]]; then
        rc_targets+=("${HOME}/.zprofile")
    fi

    for rc_file in "${rc_targets[@]}"; do
        if [[ -f "$rc_file" ]] && grep -Fq "$shell_snippet" "$rc_file"; then
            continue
        fi
        {
            echo ""
            echo "# Configuración añadida por Omarchy Setup para inicializar Homebrew"
            echo "$shell_snippet"
        } >> "$rc_file"
        appended+=("$rc_file")
    done

    if [[ ${#appended[@]} -gt 0 ]]; then
        log_info "Se añadió la inicialización de Homebrew a: ${appended[*]}."
    fi

    return 0
}

# ---------------------------------------------------------------
# install_homebrew()
# ---------------------------------------------------------------
# Instala Homebrew (conocido como Linuxbrew en Linux).
#
# Comprueba si Homebrew ya está instalado. Si no lo está, descarga y
# ejecuta el script de instalación oficial de forma no interactiva.
# Después de la instalación, llama a `ensure_homebrew_env` para
# configurar el entorno de shell.
# ---------------------------------------------------------------
install_homebrew() {
    log_step "Instalación de Homebrew (Linuxbrew)"
    
    local brew_path="/home/linuxbrew/.linuxbrew/bin/brew"
    if command_exists brew; then
        brew_path="$(command -v brew)"
    fi

    if command_exists brew || [[ -x "$brew_path" ]]; then
        log_success "Homebrew ya está instalado."
        ensure_homebrew_env "${brew_path}" || true
        return 0
    fi
    
    log_info "Instalando Homebrew..."
    # Instala de forma no interactiva para evitar prompts.
    if NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"; then
        log_success "Homebrew instalado correctamente."
        ensure_homebrew_env "${brew_path}" || log_warning "Homebrew se instaló pero no se pudo configurar la shell automáticamente."
    else
        log_error "Falló la instalación de Homebrew."
        return 1
    fi
}

# ---------------------------------------------------------------
# install_nvm()
# ---------------------------------------------------------------
# Instala NVM (Node Version Manager).
#
# Descarga y ejecuta el script de instalación oficial de NVM.
# Se asegura de que el directorio de instalación exista antes de
# ejecutar el script para evitar errores si $NVM_DIR está predefinido.
# ---------------------------------------------------------------
install_nvm() {
    log_step "Instalación de NVM (Node Version Manager)"

    # Define y exporta NVM_DIR para asegurar consistencia.
    export NVM_DIR="$HOME/.nvm"

    if [[ -d "$NVM_DIR" ]]; then
        log_success "NVM ya está instalado."
        return 0
    fi

    log_info "Instalando NVM..."
    # Crea el directorio de instalación para evitar el error "directory does not exist".
    mkdir -p "$NVM_DIR"

    # El script de nvm espera que NVM_DIR esté exportado.
    if curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash; then
        log_success "NVM instalado correctamente."
        log_info "Para usar NVM, reinicia tu terminal o ejecuta: source ${NVM_DIR}/nvm.sh"
    else
        log_error "Falló la instalación de NVM."
        # Limpia el directorio si la instalación falló para no dejar un estado inconsistente.
        rm -rf "$NVM_DIR"
        return 1
    fi
}

# ---------------------------------------------------------------
# run_module_main()
# ---------------------------------------------------------------
# Función principal del módulo de instalación de aplicaciones.
#
# Ejecuta una secuencia de tareas para instalar y configurar
# aplicaciones esenciales del sistema.
# ---------------------------------------------------------------
run_module_main() {
    log_step "Instalación de Aplicaciones"

    # --- Definición de Paquetes ---
    # Paquetes base para el sistema y desarrollo.
    local PACMAN_BASE=(
        git curl wget base-devel unzip htop fastfetch btop
        vim nano tmux xdg-utils xdg-user-dirs stow
        gnome-keyring libsecret seahorse openssh rsync usbutils
        tlp
    )
    # Paquetes para desarrollo de software.
    local PACMAN_DEV=(
        python python-pip nodejs npm uv arduino-cli
    )
    # Paquetes para reproducción y edición multimedia.
    local PACMAN_MULTIMEDIA=(
        vlc vlc-plugins-all libdvdcss audacity inkscape
        ffmpeg gstreamer gst-plugins-good gst-plugins-bad gst-plugins-ugly
        yt-dlp alsa-utils pavucontrol
    )
    # Aplicaciones de red y conectividad.
    local PACMAN_NETWORK=(
        filezilla telegram-desktop scrcpy speedtest-cli
    )
    # Drivers para gráficos Intel (Mesa y Vulkan).
    local PACMAN_INTEL_GFX=(
        mesa vulkan-intel lib32-mesa lib32-vulkan-intel
    )
    # Drivers para aceleración de vídeo por hardware en Intel (VA-API).
    local PACMAN_INTEL_VIDEO=(
        intel-media-driver libva-utils libvdpau-va-gl libva-mesa-driver
        libva-intel-driver onevpl-intel-gpu
    )
    # Soporte para computación GPGPU con OpenCL.
    local PACMAN_OPENCL=(
        ocl-icd libclc clinfo
    )
    # Paquetes a instalar desde el Arch User Repository (AUR).
    local AUR_PACKAGES=(
        "visual-studio-code-bin" "cursor-bin" "keyd" "fragments"
        "logiops" "ltunify" "teamviewer" "intel-compute-runtime"
        "antigravity" "opencode"
    )

    # --- Instalación de Paquetes ---
    log_info "Instalando herramientas base..."
    sudo pacman -S --noconfirm --needed "${PACMAN_BASE[@]}" || {
        log_error "Error al instalar herramientas base"
        return 1
    }

    log_info "Instalando herramientas de desarrollo..."
    sudo pacman -S --noconfirm --needed "${PACMAN_DEV[@]}" || {
        log_warning "Algunas herramientas de desarrollo no se pudieron instalar"
    }

    # Instalar NVM
    install_nvm

    # Instalar Homebrew
    install_homebrew

    log_info "Instalando aplicaciones multimedia..."
    sudo pacman -S --noconfirm --needed "${PACMAN_MULTIMEDIA[@]}" || {
        log_warning "Algunos paquetes multimedia no se pudieron instalar"
    }

    # Configura VLC como el reproductor por defecto para los tipos de archivo más comunes.
    log_info "Configurando VLC como reproductor predeterminado..."
    local mime_types=("audio/mpeg" "audio/mp4" "audio/x-wav" "video/mp4" "video/x-matroska" "video/x-msvideo" "video/x-ms-wmv" "video/webm")
    for type in "${mime_types[@]}"; do
        xdg-mime default vlc.desktop "$type" 2>/dev/null || true
    done

    log_info "Instalando aplicaciones de red..."
    sudo pacman -S --noconfirm --needed "${PACMAN_NETWORK[@]}" || {
        log_warning "Algunos paquetes de red no se pudieron instalar"
    }
    
    log_info "Instalando Flatpak..."
    sudo pacman -S --noconfirm --needed flatpak || {
        log_warning "Flatpak no se pudo instalar"
    }

    # --- Configuración de Drivers Intel ---
    log_info "Instalando drivers y codecs para Intel Iris Xe..."

    # Instala los headers del kernel si son necesarios para compilar módulos.
    KVER="$(uname -r)"
    if [[ ! -d "/usr/lib/modules/${KVER}/build" ]]; then
        log_info "Instalando headers de kernel..."
        sudo pacman -S --noconfirm --needed linux-headers || {
            log_warning "No se pudieron instalar headers de kernel"
        }
    fi

    log_info "Instalando drivers de gráficos Intel..."
    sudo pacman -S --noconfirm --needed "${PACMAN_INTEL_GFX[@]}" || {
        log_warning "Algunos drivers de gráficos no se pudieron instalar"
    }

    log_info "Instalando drivers de video Intel (VA-API/VDPAU)..."
    sudo pacman -S --noconfirm --needed "${PACMAN_INTEL_VIDEO[@]}" || {
        log_warning "Algunos drivers de video no se pudieron instalar"
    }

    log_info "Instalando soporte OpenCL para Intel..."
    sudo pacman -S --noconfirm --needed "${PACMAN_OPENCL[@]}" || {
        log_warning "Algunos paquetes OpenCL no se pudieron instalar"
    }

    # Crea el fichero de configuración de OpenCL para los drivers de Intel.
    if [[ ! -f /etc/OpenCL/vendors/intel.icd ]] && [[ -f /usr/lib/intel-opencl/libigdrcl.so ]]; then
        log_info "Configurando OpenCL para Intel..."
        sudo mkdir -p /etc/OpenCL/vendors
        echo "/usr/lib/intel-opencl/libigdrcl.so" | sudo tee /etc/OpenCL/vendors/intel.icd >/dev/null
    fi

    # Actualiza la caché de librerías compartidas.
    sudo ldconfig || true
    
    # --- Verificación de Drivers ---
    log_info "Verificando drivers Intel instalados..."
    if command_exists vainfo; then
        log_info "Información de VA-API:"
        vainfo 2>/dev/null | head -5 || true
    fi
    
    if command_exists clinfo; then
        log_info "Información de OpenCL:"
        clinfo 2>/dev/null | grep -E "Platform Name|Device Name" || true
    fi
    
    # --- Instalación desde AUR ---
    log_info "Instalando aplicaciones desde AUR..."
    log_warning "Este paso puede tardar varios minutos; qt5-webengine y teamviewer descargan y compilan bastante."
    if ! aur_install_packages "${AUR_PACKAGES[@]}"; then
        log_warning "Algunas aplicaciones de AUR no se pudieron instalar automáticamente."
    fi
    
    # --- Configuración de Servicios ---
    log_info "Configurando servicios del sistema..."

    # Configura GNOME Keyring para que actúe como agente de credenciales.
    log_info "Configurando GNOME Keyring como agente de credenciales..."
    # Habilita el servicio de GNOME Keyring para el usuario actual.
    if systemctl --user enable --now gnome-keyring-daemon.socket >/dev/null 2>&1; then
        log_success "GNOME Keyring listo para gestionar contraseñas."
    else
        log_warning "No se pudo habilitar gnome-keyring-daemon en systemd de usuario. Verifica que tu sesión use systemd (--user)."
    fi

    log_info "Las claves SSH se gestionarán con el módulo 'K' (gcr-ssh-agent)."
    
    # Habilita los servicios de las aplicaciones instaladas.
    if command_exists keyd; then
        if systemctl is-enabled keyd.service &>/dev/null; then
            log_info "keyd.service ya está habilitado."
        else
            sudo systemctl enable --now keyd.service 2>/dev/null || true
            log_success "keyd.service habilitado."
        fi
    fi

    if command_exists logiops; then
        if systemctl is-enabled logiops.service &>/dev/null; then
            log_info "logiops.service ya está habilitado."
        else
            sudo systemctl enable --now logiops.service 2>/dev/null || true
            log_success "logiops.service habilitado."
        fi
    fi

    if command_exists teamviewer; then
        if systemctl is-enabled teamviewerd.service &>/dev/null; then
            log_info "teamviewerd.service ya está habilitado."
        else
            sudo systemctl enable --now teamviewerd.service 2>/dev/null || true
            log_success "teamviewerd.service habilitado."
        fi
        if sudo teamviewer --daemon start >/dev/null 2>&1; then
            log_success "TeamViewer daemon iniciado"
        else
            log_warning "No se pudo iniciar el daemon de TeamViewer con 'teamviewer --daemon start'"
        fi
        sudo teamviewer --daemon enable >/dev/null 2>&1 || true
    fi

    if command_exists tlp; then
        if systemctl is-enabled tlp.service &>/dev/null; then
            log_info "tlp.service ya está habilitado."
        else
            sudo systemctl enable tlp.service 2>/dev/null || true
            log_success "tlp.service habilitado."
        fi
        if ! systemctl is-active tlp.service &>/dev/null; then
            sudo systemctl start tlp.service 2>/dev/null || true
            log_success "tlp.service iniciado."
        fi
    fi
    
    log_success "Aplicaciones instaladas correctamente"
    return 0
}

# Ejecutar si se llama directamente al script.
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    run_module_main "$@"
fi
