#!/bin/bash

#   BAREOS® - Backup Archiving REcovery Open Sourced
#
#   Copyright (C) 2026 Bareos GmbH & Co. KG
#
#   This program is Free Software; you can redistribute it and/or
#   modify it under the terms of version three of the GNU Affero General Public
#   License as published by the Free Software Foundation and included
#   in the file LICENSE.
#
#   This program is distributed in the hope that it will be useful, but
#   WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#   Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
#   02110-1301, USA.

set -e
set -o pipefail
set -u

TestName="$(basename "$(pwd)")"
export TestName

. ./environment
. "${BAREOS_SCRIPTS_DIR}/functions"

proxy_port="${BAREOS_WEBUI_PROXY_PORT}"
bundle_dir="${current_test_directory}/webui-vue-dist"
proxy_log="${tmp}/webui-vue-proxy.out"
frontend_log="${tmp}/webui-vue-frontend.out"
proxy_config="${tmp}/bareos-webui-proxy.ini"
proxy_pid_file="${tmp}/webui-vue-proxy.pid"
frontend_pid_file="${tmp}/webui-vue-frontend.pid"
required_node_major=20
PROXY_PID=""
FRONTEND_PID=""

function run_logged_command()
{
  local log_file="$1"
  local description="$2"
  shift 2

  if ! "$@" >"${log_file}" 2>&1; then
    echo "${description} failed:" >&2
    cat "${log_file}" >&2
    exit 1
  fi
}

function cleanup_on_error()
{
  local rc=$?
  if [[ $rc -eq 0 ]]; then
    return 0
  fi

  if [[ -n "${FRONTEND_PID}" ]] && kill -0 "${FRONTEND_PID}" >/dev/null 2>&1; then
    kill "${FRONTEND_PID}" || true
    wait "${FRONTEND_PID}" || true
  fi
  if [[ -n "${PROXY_PID}" ]] && kill -0 "${PROXY_PID}" >/dev/null 2>&1; then
    kill "${PROXY_PID}" || true
    wait "${PROXY_PID}" || true
  fi
  rm -f "${frontend_pid_file}" "${proxy_pid_file}"
  stop_bareos || true
}

function check_node_version()
{
  local version
  local major

  version="$("${NODE_EXECUTABLE}" --version 2>/dev/null)" || {
    echo "Failed to run Node executable: ${NODE_EXECUTABLE}" >&2
    exit 1
  }

  if [[ ! "${version}" =~ ^v([0-9]+)\.[0-9]+\.[0-9]+$ ]]; then
    echo "Could not parse Node version from: ${version}" >&2
    exit 1
  fi

  major="${BASH_REMATCH[1]}"
  if ((major < required_node_major)); then
    echo \
      "webui-vue tests require Node >= ${required_node_major}, but found ${version} (${NODE_EXECUTABLE})." >&2
    exit 1
  fi
}

function wait_for_http()
{
  local url="$1"
  local attempt
  for attempt in $(seq 1 100); do
    if curl --silent --fail "$url" >/dev/null; then
      return 0
    fi
    sleep 0.2
  done
  return 1
}

function wait_for_tcp()
{
  local host="$1"
  local port="$2"
  local attempt
  for attempt in $(seq 1 100); do
    if (echo >/dev/tcp/"$host"/"$port") >/dev/null 2>&1; then
      return 0
    fi
    sleep 0.2
  done
  return 1
}

trap cleanup_on_error EXIT

${BAREOS_SCRIPTS_DIR}/cleanup
${BAREOS_SCRIPTS_DIR}/setup

setup_data

bin/bareos start
bin/bareos status
print_debug "$(bin/bconsole <<<"status dir")"

proxy_tls_psk_disable=no
if [[ "${BAREOS_WEBUI_PROXY_DISABLE_TLS_PSK}" = "1" ]]; then
  proxy_tls_psk_disable=yes
fi

cat >"${proxy_config}" <<END_OF_PROXY_CONFIG
[listen]
address = 127.0.0.1
port = ${proxy_port}

[bareos-dir]
address = 127.0.0.1
port = ${BAREOS_DIRECTOR_PORT}
tls_psk_disable = ${proxy_tls_psk_disable}

[bareos-dir-2]
address = 127.0.0.1
port = ${BAREOS_DIRECTOR_PORT}
tls_psk_disable = ${proxy_tls_psk_disable}
END_OF_PROXY_CONFIG

check_node_version

pushd "${CMAKE_SOURCE_DIR}/webui-vue" >/dev/null
if [[ "${BAREOS_WEBUI_VUE_USE_DIST_FIRST}" = "TRUE" &&
  -n "${BAREOS_WEBUI_VUE_DIST_DIR}" &&
  -f "${BAREOS_WEBUI_VUE_DIST_DIR}/index.html" ]]; then
  bundle_dir="${BAREOS_WEBUI_VUE_DIST_DIR}"
  echo "Using prebuilt webui-vue dist: ${bundle_dir}"
elif [ -x "${WEBUI_VUE_VITE_EXECUTABLE}" ]; then
  run_logged_command \
    "${tmp}/webui-vue-generate-version.out" \
    "generate-bareos-version.mjs" \
    "${NODE_EXECUTABLE}" scripts/generate-bareos-version.mjs

  run_logged_command \
    "${tmp}/webui-vue-build.out" \
    "vite build" \
    "${WEBUI_VUE_VITE_EXECUTABLE}" build --outDir "${bundle_dir}"
  echo "Using generated webui-vue test bundle: ${bundle_dir}"
elif [[ -n "${BAREOS_WEBUI_VUE_DIST_DIR}" &&
  -f "${BAREOS_WEBUI_VUE_DIST_DIR}/index.html" ]]; then
  bundle_dir="${BAREOS_WEBUI_VUE_DIST_DIR}"
  echo "Using prebuilt webui-vue dist: ${bundle_dir}"
else
  echo "Missing prepared webui-vue dist and Vite executable. Install them before configuring and running the Playwright systemtests." >&2
  exit 1
fi
popd >/dev/null

"${BAREOS_WEBUI_PROXY_BINARY}" --config "${proxy_config}" >"${proxy_log}" 2>&1 &
PROXY_PID=$!
printf '%s\n' "${PROXY_PID}" >"${proxy_pid_file}"

"${NODE_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/webui-vue/scripts/serve-spa.mjs" \
  --host 127.0.0.1 \
  --port "${BAREOS_WEBUI_PORT}" \
  --root "${bundle_dir}" \
  --ws-proxy-host 127.0.0.1 \
  --ws-proxy-port "${proxy_port}" \
  >"${frontend_log}" 2>&1 &
FRONTEND_PID=$!
printf '%s\n' "${FRONTEND_PID}" >"${frontend_pid_file}"

if ! wait_for_tcp 127.0.0.1 "${proxy_port}"; then
  echo "bareos-webui-proxy did not start:" >&2
  cat "${proxy_log}" >&2
  exit 1
fi

if ! wait_for_http "${BAREOS_WEBUI_BASE_URL}"; then
  echo "webui-vue frontend did not start:" >&2
  cat "${frontend_log}" >&2
  exit 1
fi

echo "webui-vue proxy listening on ws://127.0.0.1:${proxy_port}"
echo "webui-vue frontend listening on ${BAREOS_WEBUI_BASE_URL}"
