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

export PATH="/run/current-system/sw/bin:/usr/bin:/bin:${PATH}"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
LOG_DIR="${1:-${ULTRACLOUD_KVM_PUBLISHABLE_LOG_DIR:-${REPO_ROOT}/work/publishable-kvm-suite}}"

mkdir -p "${LOG_DIR}"

log() {
  printf '[publishable-kvm-suite] %s\n' "$*"
}

choose_runtime_root() {
  local candidate avail best="" best_avail=-1

  for candidate in /nix/var/tmp /var/tmp /tmp "${HOME}"; do
    mkdir -p "${candidate}" 2>/dev/null || continue
    avail="$(df -Pk "${candidate}" 2>/dev/null | awk 'NR==2 { print $4 }')"
    [[ -n "${avail}" ]] || continue
    if (( avail > best_avail )); then
      best="${candidate}"
      best_avail="${avail}"
    fi
  done

  [[ -n "${best}" ]] || {
    log "no writable runtime root found"
    return 1
  }

  printf '%s\n' "${best}/ultracloud-publishable-kvm-suite"
}

get_hostname() {
  if command -v hostname >/dev/null 2>&1; then
    hostname
  else
    uname -n
  fi
}

prepare_runtime_dirs() {
  local runtime_root

  runtime_root="$(choose_runtime_root)"
  export ULTRACLOUD_KVM_RUNTIME_ROOT="${runtime_root}"
  export TMPDIR="${runtime_root}/tmp"
  export XDG_CACHE_HOME="${runtime_root}/xdg-cache"
  mkdir -p "${TMPDIR}" "${XDG_CACHE_HOME}"
}

capture_environment() {
  {
    printf 'started_at=%s\n' "$(date -Is)"
    printf 'hostname=%s\n' "$(get_hostname)"
    printf 'kernel=%s\n' "$(uname -a)"
    printf 'pwd=%s\n' "$(pwd)"
    printf 'user=%s\n' "$(id -un)"
    printf 'uid=%s\n' "$(id -u)"
    printf 'gid=%s\n' "$(id -g)"
    printf 'branch=%s\n' "$(git -C "${REPO_ROOT}" branch --show-current)"
    printf 'commit=%s\n' "$(git -C "${REPO_ROOT}" rev-parse HEAD)"
    printf 'nix_version=%s\n' "$(nix --version)"
    printf 'runtime_root=%s\n' "${ULTRACLOUD_KVM_RUNTIME_ROOT:-}"
    printf 'tmpdir=%s\n' "${TMPDIR:-}"
    printf 'xdg_cache_home=%s\n' "${XDG_CACHE_HOME:-}"
    printf 'kvm_present=%s\n' "$([[ -e /dev/kvm ]] && echo yes || echo no)"
    if [[ -e /dev/kvm ]]; then
      printf 'kvm_stat=%s\n' "$(stat -c '%A %U %G %t:%T' /dev/kvm)"
    fi
    if [[ -f /sys/module/kvm_intel/parameters/nested ]]; then
      printf 'kvm_intel_nested=%s\n' "$(cat /sys/module/kvm_intel/parameters/nested)"
    fi
    if [[ -f /sys/module/kvm_amd/parameters/nested ]]; then
      printf 'kvm_amd_nested=%s\n' "$(cat /sys/module/kvm_amd/parameters/nested)"
    fi
  } >"${LOG_DIR}/environment.txt"
}

run_case() {
  local name="$1"
  shift
  local logfile="${LOG_DIR}/${name}.log"
  local metafile="${LOG_DIR}/${name}.meta"
  local started_at ended_at rc

  started_at="$(date -Is)"
  printf 'command=%s\n' "$*" >"${metafile}"
  printf 'started_at=%s\n' "${started_at}" >>"${metafile}"

  log "running ${name}: $*"
  set +e
  (
    cd "${REPO_ROOT}"
    "$@"
  ) 2>&1 | tee "${logfile}"
  rc=${PIPESTATUS[0]}
  set -e

  ended_at="$(date -Is)"
  printf 'ended_at=%s\n' "${ended_at}" >>"${metafile}"
  printf 'exit_code=%s\n' "${rc}" >>"${metafile}"

  if (( rc != 0 )); then
    log "${name} failed; see ${logfile}"
    return "${rc}"
  fi

  log "${name} passed"
}

main() {
  prepare_runtime_dirs
  capture_environment

  [[ -e /dev/kvm ]] || {
    log "/dev/kvm is missing"
    return 1
  }

  run_case fresh-smoke nix run ./nix/test-cluster#cluster -- fresh-smoke
  run_case fresh-demo-vm-webapp nix run ./nix/test-cluster#cluster -- fresh-demo-vm-webapp
  run_case fresh-matrix nix run ./nix/test-cluster#cluster -- fresh-matrix

  printf 'finished_at=%s\n' "$(date -Is)" >>"${LOG_DIR}/environment.txt"
  log "publishable KVM suite passed; logs in ${LOG_DIR}"
}

main "$@"
