#!/usr/bin/env bash
# https://direnv.net/man/direnv-stdlib.1.html

# for when i spawn a bunch of tabs
if command -v git-wait >/dev/null; then
  git() { git-wait "$@"; }
fi

# TODO:
# git config --local core.hooksPath "$PWD"/.githooks

flake_shell=.#envrc
if [[ -f .remote.toml ]]; then
  flake_shell+=-remotes
fi
if [[ ! -f /run/current-system/nixos-version ]]; then
  flake_shell+=-fhs
fi

# ensure (dirty) updated flake lock
# TODO: cache this on gitea? Run in background?
now="$(date +%Y-%m-%d)"
if [[ ! -d .direnv/tmp ]]; then
  mkdir -p .direnv/tmp
elif command -v find >/dev/null; then
  find .direnv/tmp/ -mindepth 1 -maxdepth 1 -type d -and ! -newermt "4 hours ago" -exec rm -rf {} \;
fi
if [[ ! -s .direnv/pull-date || "$now" != "$(cat .direnv/pull-date)" ]]; then
  tmp=$(mktemp -p .direnv/tmp -d)
  if ! git diff --exit-code --quiet HEAD -- flake.lock >&/dev/null; then
    cp flake.lock "$tmp"/dirty-flake.lock
    git reset -- flake.lock
    git restore -- flake.lock
    cp flake.lock "$tmp"/clean-flake.lock # we could instead preserve the current git rev
  fi
  git pull --rebase --autostash
  if grep -q "^=======" flake.lock; then
    # Can this happen anymore? Yes, if i forgot to push
    git reset -- flake.lock
    rm flake.lock # git restore?
    git checkout -- flake.lock
  elif [[ -s "$tmp"/clean-flake.lock ]] && ! diff -q "$tmp"/clean-flake.lock flake.lock >&/dev/null; then
    cp "$tmp"/flake-dirty.lock flake.lock
  fi
  direnv allow # :3

  # nix flake update
  ! declare -F update_flake >&/dev/null || ! echo >&2 "ERROR: update_flake() already declared!"
  update_flake() (
    set -euo pipefail
    declare -a update_args=()
    readarray -td $'\n' update_args <<<"$(
      nix eval --file flake.nix --apply 'x: builtins.attrNames x.inputs' --json |
        jq '.[]' -r |
        grep -v '^nixpkgs-expensive$'
    )"
    # update_args+=(--output-lock-file "$tmp"/new-flake.lock)
    set -x
    nix flake update "${update_args[@]}" ||
      nix flake update "${update_args[@]}" --option access-tokens ""
  )
  if command -v pueue >/dev/null && pueue status >&/dev/null; then
    # update and build shell in background
    echo >&2 "+ pueue add --immediate nix flake update ..."
    pueue add --immediate "$(declare -f update_flake); update_flake \"\$@\"; set -x; nix print-dev-env \"$flake_shell\" >/dev/null"
  else
    # update while blocking
    update_flake
  fi
  unset -f update_flake

  # TODO: move to pueue job?
  printf "%s\n" "$now" >.direnv/pull-date
fi

# source env
use flake "$flake_shell"

printf "\n"
just motd
printf "\n"

unset -f git

export QEMU_NET_OPTS="hostfwd=tcp::10022-:22,hostfwd=tcp::10080-:80,hostfwd=tcp::10443-:443"
