#!/bin/bash
# mcinstaller.sh
# Automated MeshCentral Agent Installer for macOS (Universal: Intel + Apple Silicon)
# Usage: curl -fsSL https://zh.com.pa/mcimac | bash
#    o:  bash <(curl -fsSL https://zh.com.pa/mcimac)

# ============================================
# CLIENT CONFIGURATION
# ============================================
# Formato: "ID|Nombre|URL"
MeshClients=(
    "3DL|3 Dots Logistics|https://mc.zhconsultores.com/meshagents?id=JCEe33rgNXozLdGlMFO08EDCodg\$AGNf@EyV7UGbVcYZ4xA@iP0pemwDt8wKAvYO&installflags=2&meshinstall=10005"
    "360CG|360 Consulting Group|https://mc.zhconsultores.com/meshagents?id=HFsBVemiNwVyfkPfV4KF8qS6BCMzF6rQov\$Xkazf5Iy2sEOZ1hf\$aJJC1wt9Lzlt&installflags=2&meshinstall=10005"
    "360STCG|360 Sterling Tax Consulting Group|https://mc.zhconsultores.com/meshagents?id=JRxNb7O8NpaZX@Zyz@Xk9WfbyvyZQGV62vsNu1lrNFSVUBD17Hq3RHvqQh6ZVTTw&installflags=2&meshinstall=10005"
    "AALN|Arias, Abrego, Lopez & Noriega|https://mc.zhconsultores.com/meshagents?id=FVNN9JTkfE\$B7YEXoCV85B4zTiyheRTFihLuTBfHRqHMvx66QdGP1EYemERNc1ky&installflags=2&meshinstall=10005"
    "ABL|Action Brands Latam|https://mc.zhconsultores.com/meshagents?id=UuRw2OYL2Kl9ahKl2hhnupeK0Lzyr@PvyxIkf0zWOH\$YF@piMSBSTTVomUmx@xnk&installflags=2&meshinstall=10005"
    "ACC|Accman Consulting|https://mc.zhconsultores.com/meshagents?id=b1E29Xu2CUmqFottXWPyCItNZgvpblLoWcBJ9PI0FowoyMJPumcfN2zXEqozDvQ1&installflags=2&meshinstall=10005"
    "AG|Asyr Group|https://mc.zhconsultores.com/meshagents?id=hCHlLZa2xBJhIATDF0tQUv7A\$TIw2UMEJpO8mAMiiWIhWpuQRXAi68ku@SlNUX1z&installflags=2&meshinstall=10005"
    "ATN|Aiming True North|https://mc.zhconsultores.com/meshagents?id=aZm5sYrLFx@rD13DWLwjlqwCsrbRfxVJOL3yBqpP\$LU9mR@3lijnEjXVJ0SlZ8Gt&installflags=2&meshinstall=10005"
    "BGM|Best GlobalMed|https://mc.zhconsultores.com/meshagents?id=vWUglrzeO7Ylfaxe7IrVnhInAIGyqi@HUJXmZ62h90Jnapgj7Z@NqsL6CxXHGvb6&installflags=2&meshinstall=10005"
    "BR|BeRepublic|https://mc.zhconsultores.com/meshagents?id=CCYgaial3eYhwJWCacEthy6\$omyjnaSqXXsRLNjn4aZ2qI\$dFSgZdI\$37@4xRS3r&installflags=2&meshinstall=10005"
    "CDH|Casa Del Helado|https://mc.zhconsultores.com/meshagents?id=UWdht4Kfbodtwts78iYVXVvN1MY5p9iMPNQa8@dkhjlsfU@EQBZhtEZCUlf0WNy8&installflags=2&meshinstall=10005"
    "CI|Clientes Individuales|https://mc.zhconsultores.com/meshagents?id=rY\$u9ynyq4M88AZ58mwv40HKcGGLKXtFqAMcFIKt\$MG8xPgg4iL5qj0dBizM0\$0s&installflags=2&meshinstall=10005"
    "GA|Grupo Andujar|https://mc.zhconsultores.com/meshagents?id=o7uLctTUgOgQ@1avyb24n5v1DwQXEtsHzB0B@isspoEZFTqEoJGNtrfpGGkJfiQS&installflags=2&meshinstall=10005"
    "GC|Globo Consulting|https://mc.zhconsultores.com/meshagents?id=CPsF8hn51w1L1K2Y96Uaj11LVX8EAR2dxM09CSji@J0wMFdV5QOOj5nk2oEZVJeh&installflags=2&meshinstall=10005"
    "GDI|Grupo Desarrollo del Itsmo|https://mc.zhconsultores.com/meshagents?id=7WYf@G9WfmuEqFKtk@o0AS2OGKuB21KRkEMhtQWZEv9n6wbVbhXqDAF@5p2\$Fr0i&installflags=2&meshinstall=10005"
    "FJ|Inter Global Trading / Fundacion Jambo|https://mc.zhconsultores.com/meshagents?id=XdtQzoLOrWgOYzfQktFDDW8xsg8J@EJLYY9JJOcDhsTopWsdike3b900tuvHWf8G&installflags=2&meshinstall=10005"
    "IS507|International Supply 507|https://mc.zhconsultores.com/meshagents?id=uQ2XChdQHBVrPyX6LZa4HmXp6wCBGF\$KnCHFb@MQo@ev4pzPGInnxQFQARbPvaTa&installflags=2&meshinstall=10005"
    "JVA|Jaime Vega Abogados|https://mc.zhconsultores.com/meshagents?id=ylLMY950Z8jmd3wq1T2DBY8l\$dtKV4fWrxi3tTiBxJkSiZebGrNxSTTK6VLiWdj2&installflags=2&meshinstall=10005"
    "KSI|Kol Shearith Israel|https://mc.zhconsultores.com/meshagents?id=cA7RMByrQZXccMrCZ0r3oFRfeETxfM6eXplQSM68mmFHG2eHUYXGFsWaURqwpslR&installflags=2&meshinstall=10005"
    "ND|Nordik Design|https://mc.zhconsultores.com/meshagents?id=BJEj88YWouKOsa50\$Iiv3U1WRBUu0M@qfkrZaS6j\$QqjxKvvJ4\$xTXQweKgrA90h&installflags=2&meshinstall=10005"
    "PGA|Panama Guns & Ammo|https://mc.zhconsultores.com/meshagents?id=lm7OIiVHf4s\$mVIKO@kV6LDoM5akMYvBe0DGkUehGweGEroahX@I3FU5zcrqG3kL&installflags=2&meshinstall=10005"
    "RTA|Reciclaje Total de America|https://mc.zhconsultores.com/meshagents?id=Ij1peqmBTVlUODND0529rKxp6Fu8Sdlmq7XsC\$W46KTJ6zXfV9Dc7IOnVhzPxr8c&installflags=2&meshinstall=10005"
    "STP|Sintec Pharma|https://mc.zhconsultores.com/meshagents?id=ksSldxvC0tQLYtotpG5KnqPUazFegceiwPRK2C9tyaqfYEF4QOGM2lCDMgMFLY1Z&installflags=2&meshinstall=10005"
    "THP|Transmisiones Automaticas PTY|https://mc.zhconsultores.com/meshagents?id=w1OqUEotJIsGxPNBiQ5PdUv@EKG1aQ2V8lug7f1u9KK5Yohw\$8wwy@WIibnwOzrl&installflags=2&meshinstall=10005"
    "TS|Trituracion y Servicios|https://mc.zhconsultores.com/meshagents?id=t8u76\$2QNQaxvObIEjY@@is03Gvi@mXQ475AxGAVZfIapNltvhLUzyuxJYds1nJt&installflags=2&meshinstall=10005"
    "VMC|VM Suppliers|https://mc.zhconsultores.com/meshagents?id=w3xsop9L6FoFspFr8tC06MRjWjvTNn@jdpR9FvpUabloJmg1gbHzUbEUeNcNtOnj&installflags=2&meshinstall=10005"
    "ZH|ZH Consultores|https://mc.zhconsultores.com/meshagents?id=yJiO6y3huGowDbMTQdj0CXXgIW\$O8PM@sD@YWCq2hL8t35m0BtSOHwKJrNuF@BLM&installflags=2&meshinstall=10005"
)

# Nombre del servicio MeshAgent en macOS (usado para detectar instalaciones previas)
SERVICENAME="ZH_Consultores_Remote_Agent"
INSTALL_PARENT="/usr/local/mesh_services"

# ============================================
# COLORES
# ============================================
CYAN='\033[0;36m'; GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'; WHITE='\033[0;37m'; NC='\033[0m'

# ============================================
# FUNCIONES AUXILIARES
# ============================================
get_field() { # $1=linea  $2=indice (1=ID,2=Name,3=URL)
    echo "$1" | cut -d'|' -f"$2"
}

list_clients() {
    echo -e "\n${YELLOW}Clientes disponibles:${NC}\n"
    for client in "${MeshClients[@]}"; do
        local id name
        id=$(get_field "$client" 1)
        name=$(get_field "$client" 2)
        printf "${WHITE}  %-8s - %s${NC}\n" "$id" "$name"
    done
    echo ""
}

find_client() { # $1=ID en mayusculas -> imprime la linea coincidente
    local search="$1"
    for client in "${MeshClients[@]}"; do
        local id
        id=$(echo "$(get_field "$client" 1)" | tr '[:lower:]' '[:upper:]')
        if [[ "$id" == "$search" ]]; then
            echo "$client"
            return 0
        fi
    done
    return 1
}

# Localiza el directorio de instalacion de un MeshAgent previo.
# Imprime la ruta INSTALL_DIR si la encuentra; retorna 1 si no hay nada.
find_existing_install() {
    [ -d "$INSTALL_PARENT" ] || return 1
    local d
    for d in "$INSTALL_PARENT"/*; do
        [ -d "$d/$SERVICENAME" ] && { echo "$d/$SERVICENAME"; return 0; }
    done
    return 1
}

# Determina si el plist instalado tiene formato VIEJO.
# Viejo = existe la instalacion pero el LaunchAgent no existe
#         o no contiene el argumento -kvmagent (formato nuevo).
# Retorna 0 si es viejo (necesita parche), 1 si ya esta al dia / no aplica.
plist_is_old() {
    local la_plist="/Library/LaunchAgents/${SERVICENAME}.plist"
    [ -f "$la_plist" ] || return 0
    if grep -q -- "-kvmagent" "$la_plist" 2>/dev/null; then
        return 1
    fi
    return 0
}

# Aplica el parche al LaunchAgent plist (formato nuevo) y recarga servicios.
# Requiere privilegios root (se invoca via sudo).
patch_plist() {
    local install_dir="$1"
    local company bin la_plist ld_plist ts cuid

    company="$(basename "$(dirname "$install_dir")")"
    bin="$(ls "$install_dir"/*Agent 2>/dev/null | head -1)"
    if [ ! -x "$bin" ]; then
        echo -e "${RED}ERROR: no encontre binario *Agent en $install_dir${NC}" >&2
        return 1
    fi

    la_plist="/Library/LaunchAgents/${SERVICENAME}.plist"
    ld_plist="/Library/LaunchDaemons/${SERVICENAME}.plist"

    echo "==> COMPANY = $company"
    echo "==> BIN     = $bin"

    ts=$(date +%Y%m%d_%H%M%S)
    [ -f "$la_plist" ] && cp "$la_plist" "${la_plist}.bak.$ts"

    cat > "$la_plist" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>${SERVICENAME}-launchagent</string>
    <key>ProgramArguments</key>
    <array>
      <string>${bin}</string>
      <string>-kvmagent</string>
    </array>
    <key>LimitLoadToSessionType</key>
    <array>
      <string>Aqua</string>
      <string>LoginWindow</string>
    </array>
    <key>WorkingDirectory</key>
    <string>${install_dir}/</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>ThrottleInterval</key>
    <integer>5</integer>
  </dict>
</plist>
PLIST
    chown root:wheel "$la_plist"
    chmod 644 "$la_plist"
    echo "OK: $la_plist escrito"

    cuid="$(stat -f %u /dev/console)"
    echo "==> Console UID=$cuid"

    launchctl bootout "gui/$cuid/${SERVICENAME}-launchagent" 2>&1 || true
    launchctl bootstrap "gui/$cuid" "$la_plist" 2>&1 || true
    if [ -f "$ld_plist" ]; then
        launchctl bootout "system/$SERVICENAME" 2>&1 || true
        sleep 3
        local i
        for i in 1 2 3; do
            launchctl bootstrap system "$ld_plist" 2>&1 && break
            sleep 3
        done
    fi
    sleep 2
    echo "OK: plist parchado al formato nuevo."
    return 0
}

# ============================================
# SCRIPT START
# ============================================
clear
echo -e "\n${CYAN}========================================${NC}"
echo -e "${CYAN}  MeshCentral Agent Installer - ZH${NC}"
echo -e "${CYAN}  macOS Universal (Intel + Apple Silicon)${NC}"
echo -e "${CYAN}========================================${NC}\n"

# Validar que se ejecute en macOS
if [[ "$(uname)" != "Darwin" ]]; then
    echo -e "${RED}ERROR: Este script solo funciona en macOS.${NC}"
    exit 1
fi

# Forzar entrada interactiva incluso cuando se ejecuta via pipe (curl | bash)
if [[ ! -t 0 ]]; then
    if [[ -e /dev/tty ]]; then
        exec < /dev/tty
    else
        echo -e "${RED}ERROR: No hay terminal interactiva disponible.${NC}"
        echo -e "${YELLOW}Descargue el script y ejecutelo localmente con: bash mcinstaller.sh${NC}"
        exit 1
    fi
fi

found=false
selectedClient=""

# Solicitar el ID del cliente
while [[ "$found" == false ]]; do
    read -r -p "Ingrese el Client ID, escriba 'list' para ver todos, o 'exit' para cancelar: " inputID
    inputID=$(echo "$inputID" | tr '[:lower:]' '[:upper:]' | xargs)

    if [[ "$inputID" == "EXIT" ]]; then
        echo -e "\n${YELLOW}Instalacion cancelada.${NC}\n"
        exit 0
    elif [[ "$inputID" == "LIST" ]]; then
        list_clients
    elif [[ -z "$inputID" ]]; then
        echo -e "${RED}La entrada no puede estar vacia.${NC}"
    else
        match=$(find_client "$inputID")
        if [[ -n "$match" ]]; then
            selectedClient="$match"
            found=true
        else
            echo -e "${RED}ID '$inputID' no encontrado. Escriba 'list' para ver los clientes disponibles.${NC}"
        fi
    fi
done

clientID=$(get_field "$selectedClient" 1)
clientName=$(get_field "$selectedClient" 2)
meshURL=$(get_field "$selectedClient" 3)

# Confirmar seleccion
echo -e "\n${CYAN}========================================${NC}"
echo -e "${GREEN}Cliente: $clientID - $clientName${NC}"
echo -e "${CYAN}========================================${NC}\n"

read -r -p "Proceder con la instalacion? (S/N): " confirm
if [[ ! "$confirm" =~ ^[YySs] ]]; then
    echo -e "\n${YELLOW}Instalacion cancelada.${NC}\n"
    exit 0
fi

# Solicitar la contrasena al usuario (una sola vez, usada para todo sudo)
echo -n "Password: "
read -r -s password
echo ""

# Cachear credenciales sudo (evita pipe-to-sudo que causa SIGTRAP en macOS 26 Tahoe)
if ! echo "$password" | sudo -S -v 2>/dev/null; then
    echo -e "${RED}ERROR: contrasena incorrecta o sudo no disponible.${NC}"
    unset password
    exit 1
fi
# Mantener el timestamp de sudo vivo en background mientras dura la instalacion
(while true; do sudo -n -v 2>/dev/null; sleep 30; done) &
SUDO_KEEPALIVE_PID=$!
trap "kill $SUDO_KEEPALIVE_PID 2>/dev/null" EXIT

# ============================================
# DETECCION DE INSTALACION PREVIA + PARCHE PLIST
# ============================================
existingDir="$(find_existing_install || true)"
if [[ -n "$existingDir" ]]; then
    echo -e "\n${YELLOW}Se detecto una instalacion previa de MeshCentral en:${NC}"
    echo -e "${WHITE}  $existingDir${NC}"
    if plist_is_old; then
        echo -e "${YELLOW}El LaunchAgent tiene formato VIEJO. Aplicando parche antes de instalar...${NC}\n"
        # Exportamos las variables/funciones necesarias y corremos patch_plist como root.
        export SERVICENAME INSTALL_PARENT RED GREEN YELLOW WHITE NC
        export -f patch_plist
        sudo bash -c "$(declare -f patch_plist); patch_plist \"$existingDir\""
        if [[ $? -eq 0 ]]; then
            echo -e "${GREEN}Parche aplicado correctamente.${NC}"
        else
            echo -e "${RED}ADVERTENCIA: el parche del plist no se completo. Se continuara con la instalacion.${NC}"
        fi
    else
        echo -e "${GREEN}El LaunchAgent ya esta en formato nuevo. No requiere parche.${NC}"
    fi
fi

# ============================================
# INSTALACION
# ============================================
installerPath="/tmp/ZH_MeshAgent_${clientID}"

echo -e "\n${YELLOW}Descargando agente para: $clientName...${NC}"

# Descargar el binario (comillas dobles para manejar caracteres especiales)
curl -L -o "$installerPath" "$meshURL"

if [[ $? -ne 0 || ! -f "$installerPath" ]]; then
    echo -e "${RED}Error al descargar el archivo. Verifique la URL e intente nuevamente.${NC}"
    unset password
    exit 1
fi

echo -e "${YELLOW}Descarga completa. Preparando instalador...${NC}"

# Sacar de cuarentena y limpiar atributos extendidos
xattr -cr "$installerPath" 2>/dev/null

# Remover firma vieja (el binario fue parchado en el servidor; firma quedo invalida)
# y aplicar firma ad-hoc nueva. Evita codigo 133 (SIGTRAP por firma corrupta).
codesign --remove-signature "$installerPath" 2>/dev/null || true
codesign --sign - --force "$installerPath" 2>/dev/null || true

# Verificar firma; si falla, advertir
if ! codesign --verify "$installerPath" 2>/dev/null; then
    echo -e "${YELLOW}AVISO: la firma del binario no se pudo aplicar. macOS podria bloquearlo.${NC}"
fi

# Convertir el archivo en ejecutable
chmod +x "$installerPath"

# Ejecutar el instalador
echo -e "${YELLOW}Instalando...${NC}"
sudo "$installerPath" -install
installResult=$?

# Limpieza
rm -rf "$installerPath"
unset password
rm -f ~/.userdata 2>/dev/null

# Resultado
if [[ $installResult -eq 0 ]]; then
    echo -e "\n${GREEN}========================================${NC}"
    echo -e "${GREEN}  INSTALACION EXITOSA: $clientID${NC}"
    echo -e "${GREEN}========================================${NC}\n"
else
    echo -e "\n${RED}ERROR: El instalador devolvio el codigo $installResult${NC}\n"
    exit 1
fi