#!/bin/bash
set -Eeuo pipefail

trap 'echo "❌ ERROR at line $LINENO. Command: $BASH_COMMAND"' ERR

########################################
# REQUIRED BASE PATHS
########################################
APP_DIR="/opt/openclaw"
DATA_DIR="$APP_DIR/data"
WORKSPACE_DIR="$DATA_DIR/workspace"
ACME_DIR="$APP_DIR/traefik/acme"

export DEBIAN_FRONTEND=noninteractive

########################################
# Read values from cloud-init seed (optional)
########################################
echo "💾 Reading cloud-init seed values..."
mount /dev/sr0 /mnt || true

DOMAIN="$(grep -m1 '^hostname:' /mnt/user-data 2>/dev/null | sed 's/hostname:[[:space:]]*//')" || true
password="$(grep -m1 '^password:' /mnt/user-data 2>/dev/null | sed 's/password:[[:space:]]*//')" || true

# Read WHMCS-injected API tokens from cloud-init user-data
OPENAI_TOKEN="$(grep -m1 '^openai_token:' /mnt/user-data 2>/dev/null | sed 's/openai_token:[[:space:]]*//')" || true
ANTHROPIC_TOKEN="$(grep -m1 '^anthropic_token:' /mnt/user-data 2>/dev/null | sed 's/anthropic_token:[[:space:]]*//')" || true

umount /dev/sr0 || true

# Fallback defaults if cloud-init properties are empty
DOMAIN="${DOMAIN}"
OPENAI_TOKEN="${OPENAI_TOKEN:-}"
ANTHROPIC_TOKEN="${ANTHROPIC_TOKEN:-}"

########################################
# SAFE APT LOCK HANDLING
########################################
echo "🔍 Checking for apt/dpkg locks..."
APT_PROCS=$(pgrep -af "apt|apt-get|dpkg" || true)

if [[ -n "$APT_PROCS" ]]; then
  echo "⚠️ Found active apt/dpkg processes:"
  echo "$APT_PROCS"

  if pgrep -af "dpkg --configure" >/dev/null; then
    echo "❌ dpkg is actively configuring packages. Exiting to avoid corruption."
    exit 1
  fi

  echo "🧹 Stopping safe stuck apt processes..."
  pkill -f "apt.systemd.daily" || true
  pkill -f "unattended-upgrade" || true
  pkill -f "apt-get" || true
  pkill -f "apt" || true
  sleep 3
fi
echo "✅ apt/dpkg state OK"

########################################
# SYSTEM PREP & DOCKER INSTALL
########################################
apt-get update -y
apt-get install -y ca-certificates curl gnupg lsb-release ufw unzip openssl
update-ca-certificates || true

if ! command -v docker >/dev/null 2>&1; then
  echo "🐳 Installing Docker Engine..."
  curl -fsSL https://get.docker.com | sh
fi
systemctl enable --now docker

########################################
# DIRECTORY STRUCTURE INITIALIZATION
########################################
echo "📁 Building directory structure under $APP_DIR..."
mkdir -p "$DATA_DIR" "$WORKSPACE_DIR" "$ACME_DIR"
chown -R 1000:1000 $DATA_DIR
chmod 775 -R $DATA_DIR

touch "$ACME_DIR/acme.json"
chmod 600 "$ACME_DIR/acme.json"

########################################
# SAFE TOKEN GENERATION
########################################
if [[ -z "${OPENCLAW_GATEWAY_TOKEN:-}" ]]; then
  OPENCLAW_GATEWAY_TOKEN="$(openssl rand -hex 24)"
fi

########################################
# GENERATE ENVIRONMENT CONFIG (.env)
########################################
echo "📝 Generating runtime .env..."
cat > "$APP_DIR/.env" <<EOF
OPENCLAW_CONFIG_DIR=$DATA_DIR
OPENCLAW_WORKSPACE_DIR=$WORKSPACE_DIR

# Network & Security
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_BRIDGE_PORT=18790
OPENCLAW_GATEWAY_BIND=lan

# Image Version
OPENCLAW_IMAGE=ghcr.io/openclaw/openclaw:latest

# Extras
OPENCLAW_EXTRA_MOUNTS=
OPENCLAW_HOME_VOLUME=
OPENCLAW_DOCKER_APT_PACKAGES=
OPENCLAW_EXTENSIONS=
OPENCLAW_SANDBOX=
OPENCLAW_DOCKER_SOCKET=/var/run/docker.sock
DOCKER_GID=
OPENCLAW_INSTALL_DOCKER_CLI=
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=
OPENCLAW_TZ=Europe/Berlin

# Performance Tuning
OPENCLAW_CONCURRENCY=4
NODE_COMPILE_CACHE=1

# Tokens
OPENCLAW_GATEWAY_TOKEN=$OPENCLAW_GATEWAY_TOKEN
OPENAI_TOKEN=$OPENAI_TOKEN
ANTHROPIC_TOKEN=$ANTHROPIC_TOKEN

DOMAIN=$DOMAIN
LETSENCRYPT_EMAIL=admin@$DOMAIN
EOF

########################################
# GENERATE DOCKER COMPOSE MANIFEST
########################################
echo "📝 Generating docker-compose.yml..."
cat > "$APP_DIR/docker-compose.yml" <<EOF
networks:
  openclaw-net:
    driver: bridge

services:
  traefik:
    image: traefik:v3.6.1
    container_name: openclaw-traefik
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/acme:/acme
    command:
      - "--api.dashboard=false"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=openclaw-net"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@\${DOMAIN}"
      - "--certificatesresolvers.letsencrypt.acme.storage=/acme/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "--log.level=INFO"
    networks:
      - openclaw-net

  openclaw-gateway:
    image: \${OPENCLAW_IMAGE:-openclaw:local}
    shm_size: '2gb'
    sysctls:
      - net.core.somaxconn=65535
    dns:
      - 1.1.1.1
      - 8.8.8.8
    oom_score_adj: -500 
    mem_swappiness: 0 
    environment:
      HOME: /home/node
      TERM: xterm-256color
      OPENCLAW_GATEWAY_MODE: local
      OPENCLAW_GATEWAY_TOKEN: \${OPENCLAW_GATEWAY_TOKEN:-}
      OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: \${OPENCLAW_ALLOW_INSECURE_PRIVATE_WS:-}
      CLAUDE_AI_SESSION_KEY: \${CLAUDE_AI_SESSION_KEY:-}
      CLAUDE_WEB_SESSION_KEY: \${CLAUDE_WEB_SESSION_KEY:-}
      CLAUDE_WEB_COOKIE: \${CLAUDE_WEB_COOKIE:-}
      TZ: \${OPENCLAW_TZ:-UTC}
      NODE_COMPILE_CACHE: 1
      OPENCLAW_CONCURRENCY: 4
      NODE_OPTIONS: --max-old-space-size=8192
    volumes:
      - $DATA_DIR:/home/node/.openclaw
      - $WORKSPACE_DIR:/home/node/.openclaw/workspace
    ports:
      - "127.0.0.1:\${OPENCLAW_GATEWAY_PORT:-18789}:18789"
      - "127.0.0.1:\${OPENCLAW_BRIDGE_PORT:-18790}:18790"
    init: true
    restart: unless-stopped
    command:
      [
        "node",
        "dist/index.js",
        "gateway",
        "--bind",
        "\${OPENCLAW_GATEWAY_BIND:-lan}",
        "--port",
        "18789",
        "--allow-unconfigured",
      ]
    healthcheck:
      test:
        [
          "CMD",
          "node",
          "-e",
          "fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
        ]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 20s
    networks:
      - openclaw-net
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.openclaw-gateway.rule=Host(\`\${DOMAIN}\`)" 
      - "traefik.http.routers.openclaw-gateway.entrypoints=websecure"
      - "traefik.http.routers.openclaw-gateway.tls=true"
      - "traefik.http.routers.openclaw-gateway.tls.certresolver=letsencrypt"
      - "traefik.http.services.openclaw-gateway.loadbalancer.server.port=18789"

  openclaw-cli:
    image: \${OPENCLAW_IMAGE:-openclaw:local}
    cap_drop:
      - NET_RAW
      - NET_ADMIN
    security_opt:
      - no-new-privileges:true
    environment:
      HOME: /home/node
      TERM: xterm-256color
      OPENCLAW_GATEWAY_TOKEN: \${OPENCLAW_GATEWAY_TOKEN:-}
      OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: \${OPENCLAW_ALLOW_INSECURE_PRIVATE_WS:-}
      BROWSER: echo
      CLAUDE_AI_SESSION_KEY: \${CLAUDE_AI_SESSION_KEY:-}
      CLAUDE_WEB_SESSION_KEY: \${CLAUDE_WEB_SESSION_KEY:-}
      CLAUDE_WEB_COOKIE: \${CLAUDE_WEB_COOKIE:-}
      TZ: \${OPENCLAW_TZ:-UTC}
    volumes:
      - \${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
      - \${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
    stdin_open: true
    tty: true
    init: true
    entrypoint: ["node", "dist/index.js"]
    depends_on:
      - openclaw-gateway
    networks:
      - openclaw-net
EOF

########################################
# FIREWALL
########################################
echo "🛡️ Configuring Firewall..."
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable

########################################
# DEPLOYMENT ENGINE START
########################################
echo "🚀 Booting stack via Docker Compose..."
cd "$APP_DIR"
docker compose up -d

echo ""
echo "✅ OpenClaw pure compose setup successful."
echo "🌐 Proxy route active at: https://$DOMAIN"
