#!/usr/bin/env bash
set -euo pipefail

SOCKET_DIR="${SOCKET_DIR:-/var/www/html/superlegis-socket-bridge}"
LARAVEL_DIR="${LARAVEL_DIR:-/var/www/html/superlegis_atualizado}"
DOMAIN="${DOMAIN:-teste.superlegis.com.br}"
SERVER_IP="${SERVER_IP:-179.95.236.139}"
PORT="${PORT:-4000}"
HOST="${HOST:-127.0.0.1}"
NODE_USER="${NODE_USER:-www-data}"
NODE_GROUP="${NODE_GROUP:-www-data}"
SERVICE_NAME="${SERVICE_NAME:-superlegis-socket-bridge}"
APACHE_CONF="/etc/apache2/conf-available/${SERVICE_NAME}.conf"
START_SCRIPT="/usr/local/bin/${SERVICE_NAME}-start"

log() {
  printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
}

need_root() {
  if [[ "${EUID}" -ne 0 ]]; then
    echo "Rode como root: sudo bash $0"
    exit 1
  fi
}

backup_file() {
  local file="$1"
  if [[ -f "$file" ]]; then
    cp -a "$file" "${file}.bak.$(date '+%Y%m%d%H%M%S')"
  fi
}

set_env_value() {
  local file="$1"
  local key="$2"
  local value="$3"

  touch "$file"
  if grep -qE "^${key}=" "$file"; then
    sed -i "s|^${key}=.*|${key}=${value}|" "$file"
  else
    printf '%s=%s\n' "$key" "$value" >> "$file"
  fi
}

require_command() {
  local command_name="$1"
  local package_name="${2:-$1}"

  if ! command -v "$command_name" >/dev/null 2>&1; then
    log "Instalando pacote necessario: ${package_name}"
    apt-get update
    apt-get install -y "$package_name"
  fi
}

need_root

log "Conferindo diretorios"
if [[ ! -d "$SOCKET_DIR" ]]; then
  echo "Diretorio do socket nao encontrado: ${SOCKET_DIR}"
  exit 1
fi

if [[ ! -d "$LARAVEL_DIR" ]]; then
  echo "Diretorio do Laravel nao encontrado: ${LARAVEL_DIR}"
  exit 1
fi

require_command node nodejs
require_command npm npm
require_command curl curl
require_command openssl openssl

if [[ -z "${SOCKET_IO_BRIDGE_TOKEN:-}" ]]; then
  SOCKET_IO_BRIDGE_TOKEN="$(openssl rand -hex 32)"
fi

log "Configurando .env do socket bridge"
cd "$SOCKET_DIR"
if [[ ! -f .env && -f .env.example ]]; then
  cp .env.example .env
fi
backup_file "${SOCKET_DIR}/.env"
set_env_value "${SOCKET_DIR}/.env" "PORT" "$PORT"
set_env_value "${SOCKET_DIR}/.env" "HOST" "$HOST"
set_env_value "${SOCKET_DIR}/.env" "SOCKET_IO_CORS_ORIGIN" "https://${DOMAIN}"
set_env_value "${SOCKET_DIR}/.env" "SOCKET_IO_BRIDGE_TOKEN" "$SOCKET_IO_BRIDGE_TOKEN"

log "Instalando dependencias Node"
if [[ -f package-lock.json ]]; then
  npm ci --omit=dev
else
  npm install --omit=dev
fi

log "Ajustando permissoes do socket"
chown -R "${NODE_USER}:${NODE_GROUP}" "$SOCKET_DIR"

log "Criando start script do socket"
cat > "$START_SCRIPT" <<EOF
#!/usr/bin/env bash
set -euo pipefail
cd "$SOCKET_DIR"
exec /usr/bin/node src/server.js
EOF
chmod 0755 "$START_SCRIPT"

log "Criando servico systemd: ${SERVICE_NAME}"
cat > "/etc/systemd/system/${SERVICE_NAME}.service" <<EOF
[Unit]
Description=SuperLegis Socket.IO Voting Bridge
After=network.target

[Service]
Type=simple
WorkingDirectory=$SOCKET_DIR
EnvironmentFile=$SOCKET_DIR/.env
ExecStart=$START_SCRIPT
Restart=always
RestartSec=5
User=$NODE_USER
Group=$NODE_GROUP
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
systemctl restart "$SERVICE_NAME"

log "Configurando variaveis do Laravel"
if [[ ! -f "${LARAVEL_DIR}/.env" ]]; then
  echo "Laravel .env nao encontrado em ${LARAVEL_DIR}/.env"
  exit 1
fi
backup_file "${LARAVEL_DIR}/.env"
set_env_value "${LARAVEL_DIR}/.env" "SOCKET_IO_BRIDGE_ENABLED" "true"
set_env_value "${LARAVEL_DIR}/.env" "SOCKET_IO_BRIDGE_ENDPOINT" "http://${HOST}:${PORT}/events/voting-panel-update"
set_env_value "${LARAVEL_DIR}/.env" "SOCKET_IO_BRIDGE_TOKEN" "$SOCKET_IO_BRIDGE_TOKEN"
set_env_value "${LARAVEL_DIR}/.env" "SOCKET_IO_BRIDGE_TIMEOUT" "3"
set_env_value "${LARAVEL_DIR}/.env" "SOCKET_IO_CLIENT_URL" "https://${DOMAIN}"

cd "$LARAVEL_DIR"
if [[ -f artisan ]]; then
  php artisan config:clear || true
  php artisan cache:clear || true
fi

log "Configurando proxy Apache para Socket.IO"
a2enmod proxy proxy_http proxy_wstunnel rewrite headers >/dev/null
backup_file "$APACHE_CONF"
cat > "$APACHE_CONF" <<EOF
# Proxy reverso do Socket.IO da votacao.
# O cliente acessa https://${DOMAIN}/socket.io/ e o Apache encaminha para o Node local.
ProxyPreserveHost On
ProxyPass "/socket.io/" "http://${HOST}:${PORT}/socket.io/" retry=0
ProxyPassReverse "/socket.io/" "http://${HOST}:${PORT}/socket.io/"

<Location "/socket.io/">
    Require all granted
    Header always set X-SuperLegis-Socket-Bridge "enabled"
</Location>
EOF
a2enconf "$SERVICE_NAME" >/dev/null
apache2ctl configtest
systemctl reload apache2

log "Validando socket local"
for _ in {1..30}; do
  if curl -fsS "http://${HOST}:${PORT}/health" >/dev/null 2>&1; then
    break
  fi
  sleep 1
done

curl -fsS "http://${HOST}:${PORT}/health" >/dev/null

log "Resumo"
echo "Servico: $(systemctl is-active "$SERVICE_NAME")"
echo "Health local: http://${HOST}:${PORT}/health"
echo "URL cliente Laravel: https://${DOMAIN}"
echo "Proxy Socket.IO: https://${DOMAIN}/socket.io/"
echo "IP esperado do servidor: ${SERVER_IP}"
echo
echo "Para acompanhar logs:"
echo "  journalctl -u ${SERVICE_NAME} -f"
echo
echo "Token gerado/aplicado nos dois .env:"
echo "  ${SOCKET_IO_BRIDGE_TOKEN}"
