#!/usr/bin/env bash
# Installs and starts Watcher in a dev container.

set -euo pipefail

readonly WATCHER_API_URL="${WATCHER_API_URL:-}"
readonly WATCHER_CLIENT_VERSION="${WATCHER_CLIENT_VERSION:-}"
readonly PORT="${WATCHER_BACKEND_PORT:-8228}"
readonly STATE_DIR="$HOME/.apollo_monitor"
readonly LOG_FILE="$STATE_DIR/logs/devcontainer.log"
readonly LOCAL_SETTINGS_SEED="${WATCHER_LOCAL_SETTINGS_SEED:-}"

if [ "$#" -eq 0 ]; then
    ACTION="start"
elif [ "$#" -eq 1 ] && [ "$1" = "--prepare-only" ]; then
    ACTION="$1"
else
    echo "Usage: $0 [--prepare-only]" >&2
    exit 2
fi
readonly ACTION

if [ "$ACTION" = "start" ] && [ -z "$WATCHER_API_URL" ]; then
    echo "WATCHER_API_URL is not set; set it in containerEnv in devcontainer.json." >&2
    exit 1
fi

export PATH="$HOME/.local/bin:$PATH"

# Volume mount points start out owned by root. Keep this here rather than in a
# lifecycle command: this script runs on create and on start, and a lifecycle
# command that fails skips every later one. Skip missing paths so dropping an
# agent's volume still starts Watcher, and never recurse, because the
# credentials directory below is a host bind mount and keeps the host's owner.
take_ownership() {
    local path
    for path in "$@"; do
        [ -d "$path" ] || continue
        [ -w "$path" ] && continue
        if command -v sudo >/dev/null 2>&1; then
            sudo -n chown "$(id -u):$(id -g)" "$path" || true
        fi
        [ -w "$path" ] && continue
        echo "Cannot make $path writable; working passwordless sudo is required." >&2
        return 1
    done
}

take_ownership "$STATE_DIR" "$HOME/.claude" "$HOME/.codex"

if [ -n "$LOCAL_SETTINGS_SEED" ] && [ ! -e "$STATE_DIR/settings.local.yaml" ]; then
    install -m 600 "$LOCAL_SETTINGS_SEED" "$STATE_DIR/settings.local.yaml"
fi

if [ "$ACTION" = "--prepare-only" ]; then
    exit 0
fi

is_healthy() {
    curl -fsS "http://127.0.0.1:${PORT}/api/health" >/dev/null 2>&1
}

# A healthy client can still be unreachable or signed out, and records nothing
# either way.
warn_if_unsigned() {
    if watcher doctor auth >/dev/null 2>&1; then
        return 0
    fi
    # This check also fails when the deployment is unreachable, so name no
    # cause here. The doctor output below says which it was.
    echo "Watcher is running but its sign-in check did not pass, so it may be" >&2
    echo "recording nothing. If it is not signed in, open the forwarded UI and" >&2
    echo "sign in to ${WATCHER_API_URL}. Details:" >&2
    watcher doctor auth >&2 || true
}

if is_healthy; then
    watcher hooks install --yes
    warn_if_unsigned
    echo "Watcher is already running on port ${PORT}."
    exit 0
fi

mkdir -p "$STATE_DIR/logs"

if ! command -v watcher >/dev/null 2>&1; then
    if [ -n "$WATCHER_CLIENT_VERSION" ]; then
        installer="https://github.com/ApolloResearch/watcher-bin/releases/download/v${WATCHER_CLIENT_VERSION}/install.sh"
    else
        installer="https://github.com/ApolloResearch/watcher-bin/releases/latest/download/install.sh"
    fi
    curl -fsSL "$installer" | bash -s -- --watcher-api-url "$WATCHER_API_URL"
fi

# Refresh hooks because agents can be installed after the container is created.
watcher hooks install --yes

# Detach from the TTY so Watcher survives after this script returns.
setsid watcher </dev/null >>"$LOG_FILE" 2>&1 &

for _ in $(seq 1 60); do
    if is_healthy; then
        healthy=1
        break
    fi
    sleep 1
done

if [ -z "${healthy:-}" ]; then
    echo "Watcher did not become healthy within 60s; see $LOG_FILE" >&2
    exit 1
fi

warn_if_unsigned
echo "Watcher is running. Review UI: port ${PORT} in the container."
