# 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 -e

# 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

SENTRY_ROOT="$(
    cd "$(dirname "${BASH_SOURCE[0]}")"
    pwd -P
)"

source "${SENTRY_ROOT}/scripts/lib.sh"

# 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
# This is used to group issues on Sentry.io.
# If an issue does not call info() or die() it will be grouped under this
error_message="Unknown issue"
# This has to be the same value as what sentry-cli accepts
log_level="info"

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
    [ -z "${SENTRY_DEVENV_NO_REPORT+x}" ] && report_to_sentry
}

report_to_sentry() {
    if ! require sentry-cli; then
        curl -sL https://sentry.io/get-cli/ | bash
    fi
    # Report to sentry-dev-env project
    SENTRY_DSN="https://9bdb053cb8274ea69231834d1edeec4c@o1.ingest.sentry.io/5723503" \
        sentry-cli send-event -m "$error_message" --logfile "$_SENTRY_LOG_FILE" --level $log_level
    rm "$_SENTRY_LOG_FILE"
}

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

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

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

die() {
    echo -e "${red}${bold}FATAL: ${*}${reset}" >&2
    # When reporting to Sentry, this will allow grouping the errors differently
    # NOTE: The first line of the output is used to group issues
    error_message=("${@}")
    log_level="error"
    return 1
}

prompt_python_venv_creation() {
    echo -e "${yellow}You are missing a Python virtualenv and we ${bold}need${reset}${yellow} to run a bootstrapping script (it can take a few minutes)"
    info "About to create ${venv_name}..."
    echo -e "\nContinue (y/N)?"
    read -r resp
    case "$resp" in
    y | Y) echo "Okay, let's do this." ;;
    *)
        die "Aborted!"
        ;;
    esac
}

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

# don't check pypi for a potential new pip version; low-hanging fruit to save a bit of time
export PIP_DISABLE_PIP_VERSION_CHECK=on

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

# 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 "${SENTRY_ROOT}/.env" ]; then
    info "Loading variables from ${SENTRY_ROOT}/.env"
    dotenv "${SENTRY_ROOT}/.env"
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 || mktemp /tmp/sentry.envrc.XXXXXXXX.out)
    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."
    # This will allow `sentry devservices` errors to be reported
    export SENTRY_DEVSERVICES_DSN=https://23670f54c6254bfd9b7de106637808e9@o1.ingest.sentry.io/1492057
fi

# We can remove these lines in few months
if [ "$SHELL" == "/bin/zsh" ]; then
    zshrc_path="${HOME}/.zshrc"
    header="# Apple M1 environment variables"
    if grep -qF "${header}" "${zshrc_path}"; then
        echo -e "\n${red}Please delete from ${zshrc_path}, the following three lines:${reset}"
        echo -e "${header}
export CPATH=/opt/homebrew/Cellar/librdkafka/1.8.2/include
export LDFLAGS=-L/opt/homebrew/Cellar/gettext/0.21/lib"
        echo -e "\nWe have moved exporting of these variables to the right place."
        return 1
    fi
fi

### System ###

for pkg in \
    make \
    docker \
    chromedriver \
    pkg-config \
    pyenv \
    openssl; do
    if ! require "$pkg"; then
        die "You seem to be missing the system dependency: ${pkg}
Please install homebrew, and run brew bundle."
    fi
done

### Git ###

debug "Configuring git..."

make setup-git-config

### Python ###

venv_name=".venv"

if [ ! -f "${venv_name}/bin/activate" ]; then
    prompt_python_venv_creation
    # This is time consuming but it has to be done
    source "${SENTRY_ROOT}/scripts/bootstrap-py3-venv"
fi

# The user might be cd'ing into sentry with another non-direnv managed
# (in that it would be automatically deactivated) virtualenv active.
deactivate 2>/dev/null || true

# shellcheck disable=SC1091
source "${venv_name}/bin/activate"

# XXX: ideally, direnv is able to export PS1 as modified by sourcing venvs
#      but we'd have to patch direnv, and ".venv" isn't descriptive anyways
unset PS1

debug "Ensuring proper virtualenv..."
"${SENTRY_ROOT}/scripts/ensure-venv.sh"

if ! require sentry; then
    warn "Your virtualenv is activated, but sentry doesn't seem to be installed."
    commands_to_run+=("make install-py-dev")
fi

### pre-commit ###

debug "Checking pre-commit..."

if ! require pre-commit; then
    warn "Looks like you don't have pre-commit installed."
    commands_to_run+=("make setup-git")
fi

python3 -m tools.docker_memory_check

### Node ###

debug "Checking node..."

if ! require node; then
    die "You don't seem to have node installed. Install volta (a node version manager): https://develop.sentry.dev/environment/#javascript"
fi

make node-version-check

if [ ! -x "node_modules/.bin/webpack" ]; then
    warn "You don't seem to have yarn packages installed."
    commands_to_run+=("make install-js-dev")
fi

PATH_add node_modules/.bin

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

if [ "${log_level}" != "info" ]; 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"