#!/usr/bin/env bash
# MetaLens skill installer for Claude Code / OpenClaw
#
# Usage (review the script, then run):
#   curl -fsSL https://metalens.it/install/metalens.sh -o metalens.sh
#   less metalens.sh
#   bash metalens.sh --token mlns_xxx
#
# Installs:
#   ~/.claude/utils/metalens.js              — CLI helper
#   ~/.claude/skills/metalens/SKILL.md       — Skill definition for Claude Code
#   ~/.claude/metalens-config.json           — API token config
#
# Requires: bash, curl, node (v18+)

set -eu

BASE_URL="${METALENS_BASE_URL:-https://metalens.it}"
TOKEN="${METALENS_TOKEN:-}"
CONNECTION_ID="${METALENS_CONNECTION_ID:-}"
CLAUDE_DIR="${CLAUDE_DIR:-$HOME/.claude}"

# Parse --token / --connection-id / --base from args
while [ $# -gt 0 ]; do
  case "$1" in
    --token)          TOKEN="$2"; shift 2 ;;
    --token=*)        TOKEN="${1#*=}"; shift ;;
    --connection-id)  CONNECTION_ID="$2"; shift 2 ;;
    --base)           BASE_URL="$2"; shift 2 ;;
    --claude-dir)     CLAUDE_DIR="$2"; shift 2 ;;
    --help|-h)
      sed -n '2,20p' "$0" | sed 's/^# //; s/^#//'
      exit 0 ;;
    *) echo "Unknown flag: $1" >&2; exit 1 ;;
  esac
done

echo "==> MetaLens skill installer"
echo "    Base URL:     $BASE_URL"
echo "    Claude dir:   $CLAUDE_DIR"

# ─── Check dependencies ────────────────────────────────────────────────
for bin in curl node; do
  if ! command -v "$bin" >/dev/null 2>&1; then
    echo "✗ Missing dependency: $bin" >&2
    exit 1
  fi
done

node_major=$(node -e "console.log(process.versions.node.split('.')[0])")
if [ "$node_major" -lt 18 ]; then
  echo "✗ Node.js 18+ required (found $(node -v))" >&2
  exit 1
fi

# ─── Prompt for token if not supplied ──────────────────────────────────
if [ -z "$TOKEN" ]; then
  echo ""
  echo "No API token provided. Create one at:"
  echo "  $BASE_URL/dashboard/settings  →  API Tokens  →  New Token"
  echo ""
  printf "Paste token (mlns_...): "
  read -r TOKEN
fi

if [ -z "$TOKEN" ]; then
  echo "✗ Token required" >&2
  exit 1
fi

case "$TOKEN" in
  mlns_*) ;;
  *) echo "⚠  Token doesn't start with 'mlns_' — continuing anyway" ;;
esac

# ─── Verify token works ────────────────────────────────────────────────
echo "==> Verifying token..."
verify=$(curl -fsS -w '\n%{http_code}' "$BASE_URL/api/connections" \
  -H "Authorization: Bearer $TOKEN" 2>&1) || {
    echo "✗ Token verification failed:" >&2
    echo "$verify" >&2
    exit 1
  }
status_code=$(printf '%s' "$verify" | tail -n 1)
if [ "$status_code" != "200" ]; then
  echo "✗ Token rejected (HTTP $status_code)" >&2
  exit 1
fi
echo "    ✓ Token valid"

# ─── Auto-pick connection if none set ──────────────────────────────────
if [ -z "$CONNECTION_ID" ]; then
  body=$(printf '%s' "$verify" | sed '$d')
  count=$(node -e "try{const d=JSON.parse(process.argv[1]);console.log((d.connections||[]).length)}catch{console.log(0)}" "$body")
  if [ "$count" = "1" ]; then
    CONNECTION_ID=$(node -e "console.log(JSON.parse(process.argv[1]).connections[0].id)" "$body")
    echo "    ✓ Default connection: auto-selected (only one available)"
  elif [ "$count" = "0" ]; then
    echo "    ⚠  No connections found — add one in the MetaLens UI first"
  else
    echo "    i  $count connections found — you can set defaultConnectionId in the config later"
  fi
fi

# ─── Install files ─────────────────────────────────────────────────────
mkdir -p "$CLAUDE_DIR/utils" "$CLAUDE_DIR/skills/metalens"

echo "==> Downloading helper..."
curl -fsSL "$BASE_URL/install/metalens.js" -o "$CLAUDE_DIR/utils/metalens.js"
chmod +x "$CLAUDE_DIR/utils/metalens.js"
echo "    ✓ $CLAUDE_DIR/utils/metalens.js"

echo "==> Downloading skill..."
curl -fsSL "$BASE_URL/install/SKILL.md" -o "$CLAUDE_DIR/skills/metalens/SKILL.md"
echo "    ✓ $CLAUDE_DIR/skills/metalens/SKILL.md"

echo "==> Writing config..."
config_path="$CLAUDE_DIR/metalens-config.json"
if [ -f "$config_path" ]; then
  echo "    ⚠  $config_path exists — backing up to ${config_path}.bak"
  cp "$config_path" "${config_path}.bak"
fi

if [ -n "$CONNECTION_ID" ]; then
  node -e "
    const fs = require('fs');
    fs.writeFileSync(process.argv[1], JSON.stringify({
      apiToken: process.argv[2],
      baseUrl: process.argv[3],
      defaultConnectionId: process.argv[4],
    }, null, 2) + '\n');
  " "$config_path" "$TOKEN" "$BASE_URL" "$CONNECTION_ID"
else
  node -e "
    const fs = require('fs');
    fs.writeFileSync(process.argv[1], JSON.stringify({
      apiToken: process.argv[2],
      baseUrl: process.argv[3],
    }, null, 2) + '\n');
  " "$config_path" "$TOKEN" "$BASE_URL"
fi
chmod 600 "$config_path"
# If running as root on behalf of another user (e.g. inside Docker via runuser/su),
# transfer ownership to the process owner of the parent shell so they can read the file.
if [ "$(id -u)" = "0" ]; then
  target_user="${SUDO_USER:-}"
  if [ -z "$target_user" ]; then
    # Try to detect the non-root user from the process tree
    target_user=$(ps -o user= -p "$PPID" 2>/dev/null | tr -d '[:space:]') || true
  fi
  if [ -n "$target_user" ] && [ "$target_user" != "root" ]; then
    chown "$target_user" "$config_path" 2>/dev/null || true
    echo "    ✓ $config_path (permissions 600, owner: $target_user)"
  else
    echo "    ✓ $config_path (permissions 600)"
  fi
else
  echo "    ✓ $config_path (permissions 600)"
fi

# ─── Smoke test ────────────────────────────────────────────────────────
echo ""
echo "==> Smoke test: listing connections..."
node "$CLAUDE_DIR/utils/metalens.js" connections

echo ""
echo "✓ MetaLens skill installed."
echo ""
echo "Try it:"
echo "  node $CLAUDE_DIR/utils/metalens.js search 'revenue by month'"
echo "  node $CLAUDE_DIR/utils/metalens.js xray latest"
echo "  node $CLAUDE_DIR/utils/metalens.js tree list"
echo ""
echo "The skill is loaded automatically by Claude Code on next session."
