#!/not/executable/bash
# This is the .envrc for sentry, for use with direnv.
# It's responsible for enforcing a standard dev environment by checking as much state as possible, and either performing
# initialization (e.g. activating the venv) or giving recommendations on how to reach the desired state.
# It also sets useful environment variables.
# If you'd like to override or set any custom environment variables, this .envrc will read a .env file at the end.
set -eu

# Upgrading Mac can uninstall the Command Line Tools, thus, removing our access to git
# The message talks about xcrun, however, we can use the lack of git as a way to know that we need this
# xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools),
# missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
if [ "$(uname -s)" == "Darwin" ] && [ ! -f "/Library/Developer/CommandLineTools/usr/bin/git" ]; then
    echo -e "$(tput setaf 1)\nERROR: Complete the interactive installation (10+ mins) of the Command Line Tools.$(tput sgr0)"
    xcode-select --install
    return 1
fi

source "scripts/lib.sh"

bold="$(tput bold)"
red="$(tput setaf 1)"
green="$(tput setaf 2)"
yellow="$(tput setaf 3)"
reset="$(tput sgr0)"

# XXX: we can't trap bash EXIT, because it'll override direnv's finalizing routines.
#      consequently, using "exit" anywhere will skip this notice from showing.
#      so need to use set -e, and return 1.
trap notice ERR

complete_success="yup"



help_message() {
    cat <<EOF
For more help run: make direnv-help
EOF
}

failure_message() {
    cat <<EOF

${red}${bold}direnv wasn't able to complete execution.
You may have been given some recommendations in the error message.
Follow them, and then you'll need to re-run direnv by running "direnv allow".${reset}
EOF
    help_message
}

notice() {
    [ $? -eq 0 ] && return
    failure_message
}

debug() {
    if [ "${SENTRY_DIRENV_DEBUG-}" ]; then
        echo -e "${@}"
    fi
}

info() {
    echo -e "${bold}${*}${reset}"
}

warn() {
    echo -e "${yellow}${*}${reset}" >&2
    complete_success="nope"
}

die() {
    echo -e "${red}${bold}FATAL: ${*}${reset}" >&2
    return 1
}

show_commands_info() {
    echo -e "\n${red}Run the following commands to bring your environment up-to-date:"
    for cmd in "${commands_to_run[@]}"; do
        warn "    ${red}$cmd"
    done
    echo ""
}

### Environment ###

commands_to_run=()

# Always write stdout immediately. Very helpful for debugging
export PYTHONUNBUFFERED=1

# make sure we don't have any conflicting PYTHONPATH
unset PYTHONPATH

# increase node's memory limit, required for our webpacking
export NODE_OPTIONS="--max-old-space-size=5120"

# Frontend hot module reloader using `react-refresh`
# Enable this by default for development envs (CI/deploys do not use envrc)
export SENTRY_UI_HOT_RELOAD=1

### You can override the exported variables with a .env file
# All exports should happen before here unless they're safeguarded (see devenv error reporting below)
if [ -f ".env" ]; then
    info "Loading variables from .env"
    dotenv
fi

## Notify of reporting to Sentry
if [ -n "${SENTRY_DEVENV_NO_REPORT+x}" ]; then
    debug "No development environment errors will be reported (since you've defined SENTRY_DEVENV_NO_REPORT)."
    _SENTRY_LOG_FILE=''
else
    # Since direnv traps the EXIT signal we place the temp file under /tmp for the odd time
    # the script will use the EXIT path
    _SENTRY_LOG_FILE=$(mktemp /tmp/sentry.envrc.out.$$.XXXXXX)
    exec > >(tee "$_SENTRY_LOG_FILE")
    exec 2>&1
    debug "Development errors will be reported to Sentry.io. If you wish to opt-out, set SENTRY_DEVENV_NO_REPORT as an env variable."
    export SENTRY_DEVSERVICES_DSN=https://23670f54c6254bfd9b7de106637808e9@o1.ingest.sentry.io/1492057
fi

# for deduplicating
PATH_rm "/opt/homebrew/bin"

# homebrew must not be searched first, we need venv and devenv to take precedence
PATH_add "/opt/homebrew/bin"

# PATH_add prepends, so entries listed earlier rank lower. npm ships a binary
# named `sentry`, which must not shadow the venv's.
PATH_add node_modules/.bin

### Python ###

export VIRTUAL_ENV="${PWD}/.venv"
PATH_add "${VIRTUAL_ENV}/bin"

if [ -f "${VIRTUAL_ENV}/bin/devenv" ]; then
    DEVENV="${VIRTUAL_ENV}/bin/devenv"
else
    DEVENV=devenv
fi

export SENTRY_DEVENV_HOME="${SENTRY_DEVENV_HOME:-$XDG_DATA_HOME/sentry-devenv}"
PATH_add "${SENTRY_DEVENV_HOME}/bin"
if ! command -v "$DEVENV" >/dev/null; then
  die '
Please install the devenv tool:
https://github.com/getsentry/devenv#install
'
fi

if ! [ -x "${VIRTUAL_ENV}/bin/sentry" ]; then
    warn "Your virtualenv is activated, but sentry doesn't seem to be installed."
    commands_to_run+=("devenv sync")
fi

# this is the standard repo-local bin root
PATH_add "${PWD}/.devenv/bin"

# gcloud and friends
PATH_add "/opt/homebrew/share/google-cloud-sdk/bin"

# pnpm prepends node_modules/.bin to PATH, even when the venv comes first here.
rm -f node_modules/.bin/sentry
hash -r

# Only remove shadowing executables once the expected command is installed.
if [ -x "${VIRTUAL_ENV}/bin/sentry" ]; then
    while [ "$(command -v sentry)" != "${VIRTUAL_ENV}/bin/sentry" ]; do
        sentry_path="$(command -v sentry || true)"
        if [ "$(type -t sentry)" != "file" ] || [ ! -f "$sentry_path" ] || [ "$sentry_path" -ef "${VIRTUAL_ENV}/bin/sentry" ]; then
            die "Expected sentry to resolve to ${VIRTUAL_ENV}/bin/sentry, got: ${sentry_path:-not found}"
        fi
        # Resolve parent directories, not the executable: unlinking a local shim
        # is safe, but following a directory symlink could delete a global tool.
        sentry_dir="$(cd -- "$(dirname -- "$sentry_path")" && pwd -P)"
        case "$sentry_dir/" in
            "$(pwd -P)/"*) ;;
            *) die "Refusing to remove $sentry_path outside this checkout. Adjust PATH so ${VIRTUAL_ENV}/bin/sentry takes precedence." ;;
        esac
        info "Removing $sentry_path: it shadows ${VIRTUAL_ENV}/bin/sentry"
        rm -f -- "$sentry_path"
        hash -r
    done
fi

### prek ###

debug "Checking prek..."

if ! require prek; then
    warn "Looks like you don't have prek installed."
    commands_to_run+=("devenv sync")
fi

### dotagents ###

if [ -f "agents.toml" ] && { [ ! -s "agents.lock" ] || [ ! -d ".agents/skills" ] || [ -z "$(ls -A ".agents/skills" 2>/dev/null)" ]; }; then
    warn "Agent skills not installed."
    commands_to_run+=("devenv sync")
fi

### Node ###

if [ -f ".node-version" ]; then
    debug "Checking node..."

    if [ "${SENTRY_DEVENV_SKIP_FRONTEND:-}" != "1" ]; then
        if ! require node; then
            die "You don't seem to have node installed. Please run devenv sync."
        fi

        read -r node_version < ".node-version"
        if [ "v${node_version}" != "$(node --version)" ]; then
            die "Unexpected $(command -v node) version. Please run devenv sync."
        fi

        if [ ! -d "node_modules" ]; then
            die "You don't seem to have pnpm packages installed. Please run devenv sync."
        fi
    fi
fi

# These are commands that can take a significant amount of time
if [ ${#commands_to_run[@]} -ne 0 ]; then
    show_commands_info
fi

if [ "${complete_success}" != "yup" ]; then
    help_message
    warn "\nPartial success. The virtualenv is active, however, you're not fully up-to-date (see messages above)."
else
    echo "${green}${bold}SUCCESS!${reset}"
fi

# Since we can't use an EXIT routine we need to guarantee we delete the file here
[ -z "$_SENTRY_LOG_FILE" ] || rm -f "$_SENTRY_LOG_FILE"
