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

declare -r BASHUNIT_MIN_BASH_VERSION="3.0"

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.0).
    current_version="$(bash --version | head -n1 | cut -d' ' -f4 | cut -d. -f1,2)"
  fi

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

  if ((major < 3)); 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.34.1"

# 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
  --skip-env-file)
    export BASHUNIT_SKIP_ENV_FILE=true
    ;;
  -l | --login)
    export BASHUNIT_LOGIN_SHELL=true
    ;;
  --no-color)
    # shellcheck disable=SC2034
    BASHUNIT_NO_COLOR=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/coverage.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/watch.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 | watch)
    _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 "$@" ;;
  watch) bashunit::main::cmd_watch "$@" ;;
esac
