#!/usr/bin/env bash

set -euo pipefail

die() {
  echo "postrelease: $*" >&2
  exit 1
}

require_clean_tracked_tree() {
  git diff --quiet || die "tracked worktree changes are present"
  git diff --cached --quiet || die "staged changes are present"
}

make_next_update() {
  local extname="$1"
  local update_dir="$2"
  local cmake_file="$3"
  local version="$4"
  local release_file next_file release_name next_name tmp

  shopt -s nullglob
  local matches=("${update_dir}/${extname}--"*--"${version}.sql")
  shopt -u nullglob

  if [[ ${#matches[@]} -ne 1 ]]; then
    die "expected exactly one released ${update_dir}/${extname}--*--${version}.sql, found ${#matches[@]}"
  fi

  release_file="${matches[0]}"
  next_file="${update_dir}/${extname}--${version}--unreleased.sql"
  release_name="$(basename "$release_file")"
  next_name="$(basename "$next_file")"

  [[ ! -e "$next_file" ]] || die "${next_file} already exists"
  grep -qF "$release_name" "$cmake_file" || die "${cmake_file} does not reference ${release_name}"

  sed -n '1,/^\\echo /p' "$release_file" |
    sed "s/UPDATE TO '${version}'/UPDATE TO 'unreleased'/" > "$next_file"

  tmp="$(mktemp)"
  awk -v needle="    sql/updates/${release_name}" -v addition="    sql/updates/${next_name}" '
    {
      print
      if ($0 == needle) {
        print addition
        hits++
      }
    }
    END {
      if (hits != 1) {
        exit 42
      }
    }
  ' "$cmake_file" > "$tmp" || {
    rm -f "$tmp"
    rm -f "$next_file"
    die "${cmake_file} must contain exactly one sql/updates/${release_name} entry"
  }
  mv "$tmp" "$cmake_file"
}

verify_update_references() {
  local cmake_file update_path

  for cmake_file in h3/CMakeLists.txt h3_postgis/CMakeLists.txt; do
    while IFS= read -r update_path; do
      [[ -f "$(dirname "$cmake_file")/${update_path}" ]] ||
        die "${cmake_file} references missing ${update_path}"
    done < <(grep -oE 'sql/updates/[A-Za-z0-9_.-]+\.sql' "$cmake_file")
  done
}

main() {
  local repo_root version

  repo_root="$(git rev-parse --show-toplevel)"
  cd "$repo_root"

  version="$(sed -rnE 's/^  VERSION ([0-9]+\.[0-9]+\.[0-9]+)/\1/p' CMakeLists.txt)"
  [[ -n "$version" ]] || die "could not parse project version from CMakeLists.txt"

  require_clean_tracked_tree

  sed -i '/set(INSTALL_VERSION "unreleased/s/^#//g' CMakeLists.txt
  sed -i "/set(INSTALL_VERSION \"\${PROJECT_VERSION}\")/s/^/#/g" CMakeLists.txt

  make_next_update h3 h3/sql/updates h3/CMakeLists.txt "$version"
  make_next_update h3_postgis h3_postgis/sql/updates h3_postgis/CMakeLists.txt "$version"
  sed -i "s/ALTER EXTENSION h3 UPDATE TO '${version}'/ALTER EXTENSION h3 UPDATE TO 'unreleased'/g" \
    h3/test/sql/extension.sql h3/test/expected/extension.out
  for test_file in h3/test/sql/extension.sql h3/test/expected/extension.out; do
    grep -q "ALTER EXTENSION h3 UPDATE TO 'unreleased'" "$test_file" ||
      die "${test_file} extension regression target was not restored to unreleased"
  done

  verify_update_references
  scripts/check-metadata
  git diff --check

  echo "Post-release development files for ${version} -> unreleased are prepared."
}

main "$@"
