#!/usr/bin/env bash
# ==============================================================================
# Script de Instalación Automatizada de Nodo Worker (Linux)
# Trading Software Cluster - PersonalTrade
#
# Uso:
#   curl -fsSL https://files.personaltrade.online/install-node.sh | bash
# ==============================================================================
set -eo pipefail

CENTRAL_TAILSCALE_IP="100.88.45.110"
CENTRAL_CH_HTTP="http://${CENTRAL_TAILSCALE_IP}:8123"
CENTRAL_CH_TCP="${CENTRAL_TAILSCALE_IP}:9000"
CENTRAL_REDIS_HOST="${CENTRAL_TAILSCALE_IP}"
CENTRAL_REDIS_PORT="6379"

# Estilos de salida
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color

log_info() { echo -e "${CYAN}[INFO]${NC} $1"; }
log_ok()   { echo -e "${GREEN}[OK]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_err()  { echo -e "${RED}[ERROR]${NC} $1"; }

clear_term() {
    echo -e "${BOLD}${BLUE}==================================================================${NC}"
    echo -e "${BOLD}${CYAN}   Trading Software - Instalación de Nodo Worker (Linux)${NC}"
    echo -e "${BOLD}${BLUE}==================================================================${NC}\n"
}

clear_term

# ------------------------------------------------------------------------------
# 1. VALIDACIÓN DE PRE-REQUISITOS
# ------------------------------------------------------------------------------
log_info "Validando pre-requisitos del sistema..."

# A. Verificar Docker
if ! command -v docker >/dev/null 2>&1; then
    log_err "Docker no está instalado en este sistema."
    echo -e "${YELLOW}Por favor instala Docker Engine antes de continuar:${NC}"
    echo -e "  curl -fsSL https://get.docker.com | sh\n"
    exit 1
fi

if ! docker info >/dev/null 2>&1; then
    log_err "El daemon de Docker no está en ejecución o no tienes permisos de acceso."
    echo -e "${YELLOW}Asegúrate de que el servicio esté iniciado:${NC}"
    echo -e "  sudo systemctl start docker\n"
    exit 1
fi
log_ok "Docker está instalado y en ejecución."

# B. Verificar Login en el Registro r.ricardou.com
log_info "Verificando acceso al registro de imágenes r.ricardou.com..."
if ! docker pull r.ricardou.com/ts-attribute-worker:latest >/dev/null 2>&1; then
    log_err "No se pudo autenticar o descargar imágenes desde r.ricardou.com"
    echo -e "${YELLOW}Por favor ejecuta el login antes de iniciar la instalación:${NC}"
    echo -e "  docker login r.ricardou.com\n"
    exit 1
fi
log_ok "Autenticación en r.ricardou.com verificada exitosamente."

# C. Verificar Tailscale
log_info "Verificando conexión Tailscale..."
if ! command -v tailscale >/dev/null 2>&1; then
    log_err "Tailscale no está instalado en este sistema."
    echo -e "${YELLOW}Por favor instala Tailscale y únete a la red privada:${NC}"
    echo -e "  curl -fsSL https://tailscale.com/install.sh | sh\n"
    exit 1
fi

LOCAL_TAILSCALE_IP=$(tailscale ip -4 2>/dev/null || true)
if [ -z "$LOCAL_TAILSCALE_IP" ]; then
    log_err "Tailscale no tiene una IP asignada en la red privada."
    echo -e "${YELLOW}Ejecuta: tailscale up para autenticar el dispositivo.${NC}\n"
    exit 1
fi
log_ok "Tailscale activo. IP Local del Nodo: ${LOCAL_TAILSCALE_IP}"

# Verificar conectividad con el nodo central
log_info "Comprobando comunicación con el servidor central (${CENTRAL_TAILSCALE_IP})..."
if ! curl -s --connect-timeout 5 "${CENTRAL_CH_HTTP}/ping" | grep -q "Ok"; then
    log_err "No se pudo conectar a ClickHouse en ${CENTRAL_CH_HTTP}"
    echo -e "${YELLOW}Verifica que este nodo esté autorizado en la red Tailscale.${NC}\n"
    exit 1
fi
log_ok "Conectividad con ClickHouse Central confirmada."

# ------------------------------------------------------------------------------
# 2. PREGUNTAS INTERACTIVAS (Leídas desde /dev/tty para soporte pipe curl | bash)
# ------------------------------------------------------------------------------
DEFAULT_HOSTNAME=$(hostname -s 2>/dev/null || hostname)
echo ""
echo -e "${BOLD}${CYAN}--- Configuración del Nodo ---${NC}"

if [ -t 0 ]; then
    INPUT_SRC="/dev/stdin"
else
    INPUT_SRC="/dev/tty"
fi

read -rp "1. Ingresa el nombre para este nodo [default: ${DEFAULT_HOSTNAME}]: " NODE_NAME < "$INPUT_SRC"
NODE_NAME="${NODE_NAME:-$DEFAULT_HOSTNAME}"

DEFAULT_DATA_DIR="/var/lib/clickhouse_data"
read -rp "2. Directorio para la base de datos ClickHouse [default: ${DEFAULT_DATA_DIR}]: " DATA_DIR < "$INPUT_SRC"
DATA_DIR="${DATA_DIR:-$DEFAULT_DATA_DIR}"

log_info "Configuración seleccionada:"
echo -e "  - Nombre del Nodo : ${BOLD}${NODE_NAME}${NC}"
echo -e "  - Directorio BD   : ${BOLD}${DATA_DIR}${NC}"
echo ""

# ------------------------------------------------------------------------------
# 3. VERIFICACIÓN DE ESPACIO EN DISCO (+20% DE HOLGURA)
# ------------------------------------------------------------------------------
log_info "Calculando tamaño actual de la base de datos central..."
DB_SIZE_BYTES=$(curl -s "${CENTRAL_CH_HTTP}/?query=SELECT%20sum(bytes_on_disk)%20FROM%20system.parts%20WHERE%20active%20AND%20database%3D'default'")

if [ -z "$DB_SIZE_BYTES" ] || [ "$DB_SIZE_BYTES" = "0" ]; then
    # Tamaño por defecto estimado de seguridad: 4 GB
    DB_SIZE_BYTES=4294967296
fi

# Requerido = Tamaño * 1.20 (20% holgura)
REQUIRED_BYTES=$(awk "BEGIN {print int($DB_SIZE_BYTES * 1.20)}")
REQUIRED_GB=$(awk "BEGIN {printf \"%.2f\", $REQUIRED_BYTES / 1073741824}")
DB_SIZE_GB=$(awk "BEGIN {printf \"%.2f\", $DB_SIZE_BYTES / 1073741824}")

# Asegurar directorio de datos
mkdir -p "$DATA_DIR" 2>/dev/null || sudo mkdir -p "$DATA_DIR"

AVAIL_BYTES=$(df -B1 "$DATA_DIR" | tail -n 1 | awk '{print $4}')
AVAIL_GB=$(awk "BEGIN {printf \"%.2f\", $AVAIL_BYTES / 1073741824}")

log_info "Espacio de almacenamiento:"
echo -e "  - Tamaño actual DB central : ${DB_SIZE_GB} GB"
echo -e "  - Requerido (+20% holgura) : ${BOLD}${REQUIRED_GB} GB${NC}"
echo -e "  - Disponible en partición  : ${BOLD}${AVAIL_GB} GB${NC}"

if [ "$AVAIL_BYTES" -lt "$REQUIRED_BYTES" ]; then
    log_err "Espacio en disco insuficiente en ${DATA_DIR}"
    echo -e "${RED}Se requieren al menos ${REQUIRED_GB} GB pero solo hay ${AVAIL_GB} GB disponibles.${NC}\n"
    exit 1
fi
log_ok "Espacio en disco verificado correctamente."

# ------------------------------------------------------------------------------
# 4. DESPLIEGUE DE CLICKHOUSE LOCAL EN EL NODO
# ------------------------------------------------------------------------------
log_info "Desplegando contenedor ClickHouse local (fxdb-ch-node)..."

docker stop fxdb-ch-node >/dev/null 2>&1 || true
docker rm fxdb-ch-node >/dev/null 2>&1 || true

docker run -d \
    --name fxdb-ch-node \
    --restart unless-stopped \
    -p 9000:9000 \
    -p 8123:8123 \
    -v "${DATA_DIR}:/var/lib/clickhouse" \
    --ulimit nofile=262144:262144 \
    clickhouse/clickhouse-server:latest >/dev/null

log_info "Esperando a que ClickHouse local esté listo..."
for i in {1..30}; do
    if curl -s "http://localhost:8123/ping" | grep -q "Ok"; then
        break
    fi
    sleep 1
done
log_ok "ClickHouse local en ejecución."

# ------------------------------------------------------------------------------
# 5. SINCRONIZACIÓN DE ESQUEMA Y RÉPLICA DE DATOS
# ------------------------------------------------------------------------------
log_info "Sincronizando esquemas de tablas desde el servidor central..."

TABLES_QUERY="SELECT name FROM system.tables WHERE database = 'default' AND engine NOT LIKE '%View%' AND is_temporary = 0"
TABLES=$(curl -s "${CENTRAL_CH_HTTP}/?query=$(echo "$TABLES_QUERY" | tr ' ' '+')")

for TABLE in $TABLES; do
    log_info "Replicando estructura y datos de la tabla: ${TABLE}..."
    
    # Obtener CREATE TABLE del servidor central
    CREATE_SQL=$(curl -s "${CENTRAL_CH_HTTP}/?query=SHOW%20CREATE%20TABLE%20default.${TABLE}")
    
    # Crear tabla local si no existe
    docker exec fxdb-ch-node clickhouse-client --query "$CREATE_SQL" >/dev/null 2>&1 || true
    
    # Sincronizar datos usando remote() nativo de ClickHouse
    docker exec fxdb-ch-node clickhouse-client --query "INSERT INTO default.${TABLE} SELECT * FROM remote('${CENTRAL_TAILSCALE_IP}:9000', 'default', '${TABLE}', 'default', '')" >/dev/null 2>&1 || true
    
    COUNT_LOCAL=$(docker exec fxdb-ch-node clickhouse-client --query "SELECT count() FROM default.${TABLE}")
    log_ok "Tabla ${TABLE} sincronizada (${COUNT_LOCAL} registros locales)."
done

# ------------------------------------------------------------------------------
# 6. DESPLIEGUE DEL CONTENEDOR WORKER
# ------------------------------------------------------------------------------
CPU_CORES=$(nproc 2>/dev/null || echo 2)
RAM_GB=$(free -g 2>/dev/null | awk '/^Mem:/{print $2}' || echo 4)
MAX_WORKERS=$(( CPU_CORES > 2 ? CPU_CORES - 1 : 1 ))

log_info "Hardware detectado: ${CPU_CORES} Cores, ${RAM_GB} GB RAM. Concurrencia configurada: ${MAX_WORKERS} workers."
log_info "Desplegando contenedor ts-attribute-worker..."

docker stop ts-attribute-worker >/dev/null 2>&1 || true
docker rm ts-attribute-worker >/dev/null 2>&1 || true

docker run -d \
    --name ts-attribute-worker \
    --restart unless-stopped \
    --net host \
    -e CLICKHOUSE_HOST=127.0.0.1 \
    -e CLICKHOUSE_PORT=9000 \
    -e CLICKHOUSE_USER=default \
    -e CLICKHOUSE_PASSWORD="" \
    -e CLICKHOUSE_DB=default \
    -e REDIS_HOST="${CENTRAL_REDIS_HOST}" \
    -e REDIS_PORT="${CENTRAL_REDIS_PORT}" \
    -e NODE_NAME="${NODE_NAME}" \
    -e MAX_CONCURRENT_BACKFILLS="${MAX_WORKERS}" \
    r.ricardou.com/ts-attribute-worker:latest >/dev/null

log_ok "ts-attribute-worker iniciado correctamente."

# ------------------------------------------------------------------------------
# 7. AUTO-REGISTRO EN CLICKHOUSE Y REDIS CENTRAL
# ------------------------------------------------------------------------------
log_info "Registrando nodo en el cluster central..."

NODE_ID="node-${LOCAL_TAILSCALE_IP//./-}"
REGISTER_SQL="INSERT INTO default.cluster_node (node_id, node_name, tailscale_ip, os_type, cpu_cores, ram_gb, max_concurrent_tasks, data_path, status, registered_at, last_heartbeat) VALUES ('${NODE_ID}', '${NODE_NAME}', '${LOCAL_TAILSCALE_IP}', 'Linux', ${CPU_CORES}, ${RAM_GB}, ${MAX_WORKERS}, '${DATA_DIR}', 'ONLINE', now(), now());"

curl -s "${CENTRAL_CH_HTTP}/" --data-binary "$REGISTER_SQL" >/dev/null

echo ""
echo -e "${BOLD}${GREEN}==================================================================${NC}"
echo -e "${BOLD}${GREEN}   ¡Nodo Worker Instalado y Registrado Exitosamente!${NC}"
echo -e "${BOLD}${GREEN}==================================================================${NC}"
echo -e "  - ID del Nodo    : ${BOLD}${NODE_ID}${NC}"
echo -e "  - Nombre         : ${BOLD}${NODE_NAME}${NC}"
echo -e "  - IP Tailscale   : ${BOLD}${LOCAL_TAILSCALE_IP}${NC}"
echo -e "  - ClickHouse BD  : ${BOLD}${DATA_DIR}${NC}"
echo -e "  - Capacidad      : ${BOLD}${MAX_WORKERS} backfills concurrentes${NC}"
echo -e "  - Estado Clúster : ${BOLD}ONLINE${NC}\n"
