#!/usr/bin/env bash
set -euo pipefail
set -E

echo "Starting Migration Runner"

: "${APP_DIR:?APP_DIR is required}"
# shellcheck source=/dev/null
source "${APP_DIR}/src/init.sh"

trap 'code=$?; \
  src="${BASH_SOURCE[1]:-${BASH_SOURCE[0]}}"; \
  line="${BASH_LINENO[0]:-0}"; \
  cmd="${BASH_COMMAND:-}"; \
  printf "[error] exit %s at %s:%s: %s\\n" "$code" "$src" "$line" "$cmd" >&2' ERR


# Tool checks
try_cmd "git"
try_cmd "liquibase"

# --- Logging ---

[[ -n "${BUILD_ENV}" ]] && info "Deploying to ${BUILD_ENV}"
info "CONTEXTS=${CONTEXTS} SKIP_MAIN_DB=${SKIP_MAIN_DB} SKIP_TEST_DB=${SKIP_TEST_DB} SQLITE_ENABLE=${SQLITE_ENABLE}"
info "[GITHUB] REPO=${GITHUB_REPO} BRANCH=${GITHUB_BRANCH} DIR=${GITHUB_REPO_DIR}"

# --- Databases ---

db_vendors=("mysql")
[[ "${SQLITE_ENABLE}" == "true" ]] && db_vendors+=("sqlite")

for vendor in "${db_vendors[@]}"; do
  # Sanity check
  vendor_script="${APP_DIR}/src/vendors/${vendor}.sh"
  [[ -f "${vendor_script}" ]] || die "Missing vendor script: ${vendor_script}"

  # Load
  # shellcheck source=/dev/null
  source "${vendor_script}"

  # Initialize and wait
  "${vendor}_init"
  "${vendor}_wait_ready"

  # Create main DB
  if [[ "${SKIP_MAIN_DB}" != "true" ]]; then
    "${vendor}_create_db"
  fi

  # Create test DB
  if [[ "${SKIP_TEST_DB}" != "true" ]]; then
    "${vendor}_create_test_db"
  fi
done

# --- GitHub ---

# Create a temp askpass file
GIT_ASKPASS="$(mktemp)" || die "mktemp failed"
chmod 0700 "${GIT_ASKPASS}"

# Always delete the file
readonly _ASKPASS="${GIT_ASKPASS}"
trap 'rm -f -- "${_ASKPASS}"' EXIT

# Add the github credentials to the file.
# With a token, username can be anything.
cat > "${GIT_ASKPASS}" <<'EOF'
#!/usr/bin/env bash
case "$1" in
  *Username*) printf '%s' "user" ;;
  *Password*) printf '%s' "${GITHUB_DEPLOY_TOKEN}" ;;
  *) printf '' ;;
esac
EOF

# Configure git to use the askpass
export GIT_ASKPASS
export GIT_ASKPASS_REQUIRE=force
export GIT_TERMINAL_PROMPT=0

# Sparse clone the repo
info "Cloning '${GITHUB_USER}/${GITHUB_REPO}' on branch '${GITHUB_BRANCH}'"
rm -rf repo
git -c init.defaultBranch=master clone \
  --branch "${GITHUB_BRANCH}" \
  --depth=1 \
  --filter=blob:none \
  --no-tags \
  --single-branch \
  --sparse \
  "https://github.com/${GITHUB_USER}/${GITHUB_REPO}.git" \
  repo

# Sparse checkout and navigate to the given directory
info "Checking out path '${GITHUB_REPO_DIR}'"
git -C repo sparse-checkout set "${GITHUB_REPO_DIR}" \
  || die "Path '${GITHUB_REPO_DIR}' not found"

# Cleanup
git -C repo config credential.helper ""
unset GIT_ASKPASS GIT_ASKPASS_REQUIRE GIT_TERMINAL_PROMPT

# Navigate to the directory
cd "repo/${GITHUB_REPO_DIR}/build" || die "Missing build dir"

# --- Liquibase ---

_migrate_pair() {
  local mysql_db; mysql_db="$1"
  local sqlite_db; sqlite_db="$2"

  # Migrate into a mysql db
  : "${1:?mysql_db required}"
  mysql_migrate "${mysql_db}"

  # Check if sqlite enabled
  if [[ "${SQLITE_ENABLE}" != "true" ]]; then
    return 0
  fi

  # Migrate or clone into a sqlite db
  : "${sqlite_db:?sqlite_db required}"
  case "${SQLITE_SOURCE,,}" in
    liquibase) sqlite_migrate "${sqlite_db}" ;;
    mysql) sqlite_mysql_clone "${mysql_db}" "${sqlite_db}" ;;
    *) die "[sqlite] Invalid source '${SQLITE_SOURCE}'" ;;
  esac
}

# Main DB
if [[ "${SKIP_MAIN_DB}" == "true" ]]; then
  info "Skipping main database migration"
else
  _migrate_pair "${MYSQL_DB_NAME}" "${SQLITE_DB_NAME:-}"
fi

# Test DB
if [[ "${SKIP_TEST_DB}" == "true" ]]; then
  info "Skipping test database migration"
else
  _migrate_pair "${MYSQL_TEST_DB_NAME}" "${SQLITE_TEST_DB_NAME:-}"
fi
