#!/usr/bin/env bash
# GoClaw Docker setup — generates .env and docker-compose command for your chosen variant.
#
# Usage:
#   ./scripts/setup-docker.sh              # Interactive mode
#   ./scripts/setup-docker.sh --variant full --with-ui
#   ./scripts/setup-docker.sh --variant alpine --dev
#
# Variants:
#   alpine   — Base image (~50 MB), no runtimes
#   node     — Alpine + Node.js pre-installed
#   python   — Alpine + Python pre-installed
#   full     — Alpine + Node.js + Python + all skill dependencies
#
# Flags:
#   --dev        Mount local source for development (live reload)
#   --with-ui    Include web dashboard
#   --port N     Gateway port (default: 18790)
#   --ui-port N  Dashboard port (default: 3000)
#   --pg-port N  PostgreSQL port (default: 5432)

set -euo pipefail

# ── Defaults ──
VARIANT=""
DEV_MODE=false
WITH_UI=false
PORT="${GOCLAW_PORT:-18790}"
UI_PORT="${GOCLAW_UI_PORT:-3000}"
PG_PORT="${POSTGRES_PORT:-5432}"
DATA_DIR="${GOCLAW_DATA_DIR:-./goclaw-data}"

# ── Parse args ──
while [[ $# -gt 0 ]]; do
  case "$1" in
    --variant)  VARIANT="$2"; shift 2 ;;
    --dev)      DEV_MODE=true; shift ;;
    --with-ui)  WITH_UI=true; shift ;;
    --port)     PORT="$2"; shift 2 ;;
    --ui-port)  UI_PORT="$2"; shift 2 ;;
    --pg-port)  PG_PORT="$2"; shift 2 ;;
    --data-dir) DATA_DIR="$2"; shift 2 ;;
    --help|-h)
      head -20 "$0" | grep '^#' | sed 's/^# \?//'
      exit 0
      ;;
    *) echo "Unknown option: $1"; exit 1 ;;
  esac
done

# ── Interactive variant selection ──
if [ -z "$VARIANT" ]; then
  echo "Select GoClaw Docker variant:"
  echo ""
  echo "  1) alpine  — Base image (~50 MB), no runtimes"
  echo "  2) node    — + Node.js (for JS/TS skills)"
  echo "  3) python  — + Python (for Python skills)"
  echo "  4) full    — + Node.js + Python + all skill deps"
  echo ""
  read -rp "Choice [1-4, default=1]: " choice
  case "${choice:-1}" in
    1|alpine)  VARIANT="alpine" ;;
    2|node)    VARIANT="node" ;;
    3|python)  VARIANT="python" ;;
    4|full)    VARIANT="full" ;;
    *) echo "Invalid choice"; exit 1 ;;
  esac
fi

# ── Resolve Docker image tag ──
DOCKER_IMAGE="digitop/goclaw"
case "$VARIANT" in
  alpine)  IMAGE_TAG="latest" ;;
  node)    IMAGE_TAG="node" ;;
  python)  IMAGE_TAG="python" ;;
  full)    IMAGE_TAG="full" ;;
  *) echo "Unknown variant: $VARIANT"; exit 1 ;;
esac

echo ""
echo "Setting up GoClaw (${VARIANT})..."

# ── Create data directories ──
mkdir -p "${DATA_DIR}"/{config,data,workspace,skills,storage}

# ── Generate secrets if not present ──
ENV_FILE="${DATA_DIR}/.env"
if [ ! -f "$ENV_FILE" ]; then
  GATEWAY_TOKEN="$(openssl rand -hex 32 2>/dev/null || head -c 64 /dev/urandom | od -An -tx1 | tr -d ' \n')"
  ENCRYPTION_KEY="$(openssl rand -hex 16 2>/dev/null || head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n')"
  PG_PASSWORD="$(openssl rand -hex 12 2>/dev/null || head -c 24 /dev/urandom | od -An -tx1 | tr -d ' \n')"

  cat > "$ENV_FILE" <<EOF
# GoClaw environment — generated by setup-docker.sh
# Variant: ${VARIANT}

# Gateway
GOCLAW_GATEWAY_TOKEN=${GATEWAY_TOKEN}
GOCLAW_ENCRYPTION_KEY=${ENCRYPTION_KEY}

# Ports
GOCLAW_PORT=${PORT}
GOCLAW_UI_PORT=${UI_PORT}
POSTGRES_PORT=${PG_PORT}

# PostgreSQL
POSTGRES_USER=goclaw
POSTGRES_PASSWORD=${PG_PASSWORD}
POSTGRES_DB=goclaw
EOF
  echo "Generated ${ENV_FILE} with random secrets."
else
  echo "Using existing ${ENV_FILE}"
fi

# ── Generate docker-compose.yaml ──
COMPOSE_FILE="${DATA_DIR}/docker-compose.yaml"

cat > "$COMPOSE_FILE" <<YAML
# GoClaw Docker Compose — variant: ${VARIANT}
# Generated by setup-docker.sh. Edit as needed.

services:
  postgres:
    image: pgvector/pgvector:pg18
    ports:
      - "\${POSTGRES_PORT:-5432}:5432"
    environment:
      POSTGRES_USER: \${POSTGRES_USER:-goclaw}
      POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:-goclaw}
      POSTGRES_DB: \${POSTGRES_DB:-goclaw}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U \${POSTGRES_USER:-goclaw}"]
      interval: 5s
      timeout: 5s
      retries: 10
    restart: unless-stopped

  goclaw:
YAML

# Dev mode: build from source; Production: use pre-built image
if [ "$DEV_MODE" = true ]; then
  cat >> "$COMPOSE_FILE" <<YAML
    build:
      context: $(pwd)
      dockerfile: Dockerfile
      args:
        ENABLE_PYTHON: "$([ "$VARIANT" = "python" ] || [ "$VARIANT" = "full" ] && echo true || echo false)"
        ENABLE_NODE: "$([ "$VARIANT" = "node" ] || [ "$VARIANT" = "full" ] && echo true || echo false)"
        ENABLE_FULL_SKILLS: "$([ "$VARIANT" = "full" ] && echo true || echo false)"
YAML
else
  cat >> "$COMPOSE_FILE" <<YAML
    image: ${DOCKER_IMAGE}:${IMAGE_TAG}
YAML
fi

cat >> "$COMPOSE_FILE" <<YAML
    ports:
      - "\${GOCLAW_PORT:-18790}:18790"
    env_file:
      - .env
    environment:
      - GOCLAW_HOST=0.0.0.0
      - GOCLAW_PORT=18790
      - GOCLAW_CONFIG=/app/data/config.json
      - GOCLAW_SKILLS_DIR=/app/data/skills
      - GOCLAW_WORKSPACE=/app/workspace
      - GOCLAW_POSTGRES_DSN=postgres://\${POSTGRES_USER:-goclaw}:\${POSTGRES_PASSWORD:-goclaw}@postgres:5432/\${POSTGRES_DB:-goclaw}?sslmode=disable
    volumes:
      # Persistent data: config, agent files, runtime packages (pip/npm)
      - goclaw-data:/app/data
      # Workspace: agent working directory for file operations
      - goclaw-workspace:/app/workspace
      # Custom skills: user-installed skills persist across restarts
      - goclaw-skills:/app/skills
      # Storage: uploaded media, documents
      - goclaw-storage:/app/storage
    depends_on:
      postgres:
        condition: service_healthy
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    read_only: true
    tmpfs:
      - /tmp:rw,noexec,nosuid,size=256m
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: "2.0"
          pids: 200
    restart: unless-stopped
YAML

# Add web UI service if requested
if [ "$WITH_UI" = true ]; then
  cat >> "$COMPOSE_FILE" <<YAML

  goclaw-ui:
    image: ${DOCKER_IMAGE}-web:latest
    ports:
      - "\${GOCLAW_UI_PORT:-3000}:80"
    depends_on:
      - goclaw
    restart: unless-stopped
YAML
fi

cat >> "$COMPOSE_FILE" <<YAML

volumes:
  postgres-data:
  goclaw-data:
  goclaw-workspace:
  goclaw-skills:
  goclaw-storage:
YAML

echo ""
echo "Generated ${COMPOSE_FILE}"
echo ""
echo "── Quick start ──"
echo ""
echo "  cd ${DATA_DIR}"
echo "  docker compose up -d"
echo ""
if [ "$WITH_UI" = true ]; then
  echo "  Gateway:   http://localhost:${PORT}"
  echo "  Dashboard: http://localhost:${UI_PORT}"
else
  echo "  Gateway: http://localhost:${PORT}"
  echo "  Add --with-ui flag to include the web dashboard."
fi
echo ""
echo "── Volumes ──"
echo ""
echo "  goclaw-data      → /app/data       Config, runtime packages (pip/npm cache)"
echo "  goclaw-workspace → /app/workspace  Agent file operations"
echo "  goclaw-skills    → /app/skills     Custom installed skills"
echo "  goclaw-storage   → /app/storage    Uploaded media & documents"
echo "  postgres-data    → PostgreSQL data"
echo ""
echo "── Useful commands ──"
echo ""
echo "  docker compose logs -f goclaw      # View logs"
echo "  docker compose exec goclaw goclaw version   # Check version"
echo "  docker compose down                # Stop"
echo "  docker compose down -v             # Stop + delete all data"
