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

declare -r BASHUNIT_MIN_BASH_VERSION="3.2"

function _check_bash_version() {
  local current_version
  if [[ -n ${BASHUNIT_TEST_BASH_VERSION:-} ]]; then
    # Checks if BASHUNIT_TEST_BASH_VERSION is set (typically for testing purposes)
    current_version="${BASHUNIT_TEST_BASH_VERSION}"
  elif [[ -n ${BASH_VERSINFO+set} ]]; then
    # Checks if the special Bash array BASH_VERSINFO exists. This array is only defined in Bash.
    current_version="${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}"
  else
    # If not in Bash (e.g., running from Zsh). The pipeline extracts just the major.minor version (e.g., 3.2).
    current_version="$(bash --version | head -n1 | cut -d' ' -f4 | cut -d. -f1,2)"
  fi

  local major minor
  IFS=. read -r major minor _ <<< "$current_version"

  if (( major < 3 )) || { (( major == 3 )) && (( minor < 2 )); }; then
    printf 'Bashunit requires Bash >= %s. Current version: %s\n' "$BASHUNIT_MIN_BASH_VERSION" "$current_version" >&2
    exit 1
  fi
}

_check_bash_version

# shellcheck disable=SC2034
declare -r BASHUNIT_VERSION="0.29.0"

# shellcheck disable=SC2155
declare -r BASHUNIT_ROOT_DIR="$(dirname "${BASH_SOURCE[0]}")"
export BASHUNIT_ROOT_DIR

# Capture working directory at startup (before any test changes it)
declare -r BASHUNIT_WORKING_DIR="$PWD"
export BASHUNIT_WORKING_DIR

# Early scan for flags that must be set before loading env.sh
for arg in "$@"; do
  case "$arg" in
    --preserve-env)
      export BASHUNIT_PRESERVE_ENV=true
      ;;
    -l|--login)
      export BASHUNIT_LOGIN_SHELL=true
      ;;
  esac
done

source "$BASHUNIT_ROOT_DIR/src/dev/debug.sh"
source "$BASHUNIT_ROOT_DIR/src/check_os.sh"
source "$BASHUNIT_ROOT_DIR/src/str.sh"
source "$BASHUNIT_ROOT_DIR/src/globals.sh"
source "$BASHUNIT_ROOT_DIR/src/dependencies.sh"
source "$BASHUNIT_ROOT_DIR/src/io.sh"
source "$BASHUNIT_ROOT_DIR/src/math.sh"
source "$BASHUNIT_ROOT_DIR/src/parallel.sh"
source "$BASHUNIT_ROOT_DIR/src/env.sh"
source "$BASHUNIT_ROOT_DIR/src/clock.sh"
source "$BASHUNIT_ROOT_DIR/src/state.sh"
source "$BASHUNIT_ROOT_DIR/src/colors.sh"
source "$BASHUNIT_ROOT_DIR/src/console_header.sh"
source "$BASHUNIT_ROOT_DIR/src/console_results.sh"
source "$BASHUNIT_ROOT_DIR/src/helpers.sh"
source "$BASHUNIT_ROOT_DIR/src/test_title.sh"
source "$BASHUNIT_ROOT_DIR/src/upgrade.sh"
source "$BASHUNIT_ROOT_DIR/src/assertions.sh"
source "$BASHUNIT_ROOT_DIR/src/doc.sh"
source "$BASHUNIT_ROOT_DIR/src/reports.sh"
source "$BASHUNIT_ROOT_DIR/src/runner.sh"
source "$BASHUNIT_ROOT_DIR/src/bashunit.sh"
source "$BASHUNIT_ROOT_DIR/src/init.sh"
source "$BASHUNIT_ROOT_DIR/src/learn.sh"
source "$BASHUNIT_ROOT_DIR/src/main.sh"

bashunit::check_os::init
bashunit::clock::init

# Subcommand detection
_SUBCOMMAND=""

case "${1:-}" in
  test|bench|doc|init|learn|upgrade|assert)
    _SUBCOMMAND="$1"
    shift
    ;;
  -v|--version)
    bashunit::console_header::print_version
    exit 0
    ;;
  -h|--help)
    bashunit::console_header::print_help
    exit 0
    ;;
  -*)
    # Flag without subcommand → assume "test"
    _SUBCOMMAND="test"
    ;;
  "")
    # No arguments → assume "test" (uses BASHUNIT_DEFAULT_PATH)
    _SUBCOMMAND="test"
    ;;
  *)
    # Path argument → assume "test"
    _SUBCOMMAND="test"
    ;;
esac

# Route to subcommand handler
case "$_SUBCOMMAND" in
  test)    bashunit::main::cmd_test "$@" ;;
  bench)   bashunit::main::cmd_bench "$@" ;;
  doc)     bashunit::main::cmd_doc "$@" ;;
  init)    bashunit::main::cmd_init "$@" ;;
  learn)   bashunit::main::cmd_learn "$@" ;;
  upgrade) bashunit::main::cmd_upgrade "$@" ;;
  assert)  bashunit::main::cmd_assert "$@" ;;
esac
