#!/command/with-contenv bash
set -euo pipefail

# ── Data directories ────────────────────────────────────────
export GRACKLE_HOME="${GRACKLE_HOME:-/data}"
GRACKLE_DATA="${GRACKLE_HOME}/.grackle"
mkdir -p "$GRACKLE_DATA"
chown node:node "$GRACKLE_DATA"

# ── Volume migration: old layout → new layout ───────────────
# Old compose mounted grackle-data:/grackle-home/.grackle → files at volume root.
# New compose mounts grackle-data:/data → app expects files at /data/.grackle/.
# Detect old layout and migrate.
if [ -f "/data/grackle.db" ] && [ ! -f "$GRACKLE_DATA/grackle.db" ]; then
  echo "Migrating data from old volume layout..."
  migrate_error=0
  for f in /data/*; do
    name="$(basename "$f")"
    case "$name" in .grackle|neo4j|.hf-cache|.claude-sdk) continue ;; esac
    if ! mv "$f" "$GRACKLE_DATA/$name"; then
      echo "WARN: Failed to migrate '$f' to '$GRACKLE_DATA/$name'" >&2
      migrate_error=1
    fi
  done
  chown -R node:node "$GRACKLE_DATA"
  if [ "$migrate_error" -eq 0 ]; then
    echo "Volume migration complete"
  else
    echo "Volume migration completed with errors; see warnings above." >&2
  fi
fi

# Neo4j data directories (created unconditionally — harmless if Neo4j is disabled)
mkdir -p /data/neo4j/data /data/neo4j/logs /data/neo4j/run
chown -R node:node /data/neo4j

# ── Docker socket access ────────────────────────────────────
# On Linux hosts the socket GID may differ from any in-container group;
# on Docker Desktop (macOS / Windows) permissions are typically open.
DOCKER_SOCK="/var/run/docker.sock"
if [ -S "$DOCKER_SOCK" ]; then
  SOCK_GID="$(stat -c '%g' "$DOCKER_SOCK")"
  # Find an existing group with that GID, or create one.
  GROUP_NAME="$(awk -F: -v gid="$SOCK_GID" '$3 == gid { print $1; exit }' /etc/group)"
  if [ -z "$GROUP_NAME" ]; then
    groupadd -g "$SOCK_GID" dockerhost
    GROUP_NAME="dockerhost"
  fi
  usermod -aG "$GROUP_NAME" node
fi

# ── Writable Claude SDK config ──────────────────────────────
# The host's ~/.claude is mounted read-only (for credentials + settings).
# The Claude Agent SDK needs to write session files to ~/.claude/projects/,
# so we create a writable copy in the persistent volume and point the SDK
# there via CLAUDE_CONFIG_DIR.
CLAUDE_RO="/home/node/.claude"
CLAUDE_RW="${GRACKLE_HOME}/.claude-sdk"
if [ -d "$CLAUDE_RO" ] && ! gosu node touch "$CLAUDE_RO/.write-test" 2>/dev/null; then
  mkdir -p "$CLAUDE_RW/projects"
  # Sync credential/config files from the RO mount (skip directories —
  # they'll be created fresh in the writable dir by the SDK as needed).
  for f in .credentials.json settings.json settings.local.json CLAUDE.md; do
    if [ -f "$CLAUDE_RO/$f" ]; then
      cp -pu "$CLAUDE_RO/$f" "$CLAUDE_RW/$f" 2>/dev/null || true
      if [ "$f" = ".credentials.json" ]; then
        chmod 600 "$CLAUDE_RW/$f" 2>/dev/null || true
      fi
    fi
  done
  chown -R node:node "$CLAUDE_RW"
  # Export CLAUDE_CONFIG_DIR for all s6-supervised services
  echo "$CLAUDE_RW" > /run/s6/container_environment/CLAUDE_CONFIG_DIR
else
  rm -f "$CLAUDE_RO/.write-test" 2>/dev/null || true
fi

# ── Codex / Copilot writable check ───────────────────────────
# Unlike Claude (which has CLAUDE_CONFIG_DIR), Codex and Copilot have no
# config dir override. Their CLIs write directly to ~/.codex/ and ~/.copilot/.
# These MUST be mounted writable (no :ro flag) or auth/session state will fail.
for sdk_dir in /home/node/.codex /home/node/.copilot; do
  if [ -d "$sdk_dir" ] && ! gosu node test -w "$sdk_dir"; then
    echo "ERROR: $sdk_dir is mounted read-only but must be writable." >&2
    echo "       Change the mount from ':ro' to writable in docker-compose.yml." >&2
  fi
done

# ── Credential mount warnings ───────────────────────────────
# For the local adapter, file tokens are NOT pushed via gRPC
# (excludeFileTokens: true). Runtimes read credential files directly
# from the filesystem. Missing mounts cause silent auth failure.
warn_missing() {
  local path="$1" name="$2" primary_envalt="$3"
  shift 3

  # If any of the provided env vars (primary + optional fallbacks) is set,
  # skip the warning — credentials are already configured via env.
  local envalt
  for envalt in "$primary_envalt" "$@"; do
    if [ -n "${!envalt:-}" ]; then
      return 0
    fi
  done

  # Check for the specific credential file so that an empty bind-mounted
  # directory still triggers a warning.
  if [ ! -f "$path" ]; then
    echo "WARN: $name not found at $path — mount via -v or set $primary_envalt"
  fi
}

warn_missing "/home/node/.claude/.credentials.json" "Claude credentials" "ANTHROPIC_API_KEY"
warn_missing "/home/node/.copilot/config.json" "Copilot credentials" "COPILOT_GITHUB_TOKEN" "GH_TOKEN" "GITHUB_TOKEN"
warn_missing "/home/node/.codex/auth.json" "Codex credentials" "OPENAI_API_KEY"
