#!/usr/bin/env bash
# mt - source this file

# Guard against being sourced multiple times during init
[[ -n "${_MT_SOURCING:-}" ]] && return 0

mt() {
  # Convert DEBUG=1 to MT_LOG_LEVEL=DEBUG
  if [[ -n "${DEBUG:-}" ]]; then
    export MT_LOG_LEVEL=DEBUG
  fi

  # Get path to script and root of project
  # Always calculate from BASH_SOURCE to handle symlinks correctly
  command -v realpath &>/dev/null || {
    echo "Error: 'realpath' is required but not found. Please install 'coreutils' (e.g. 'brew install coreutils' on macOS)." >&2
    return 1
  }
  SCRIPT_PATH="$(realpath "${BASH_SOURCE[0]}")"
  SCRIPT_DIR="$(dirname -- "${SCRIPT_PATH}")"
  # Only calculate MT_ROOT if not set or if set to a relative path (common bug)
  if [[ -z "${MT_ROOT:-}" ]] || [[ "${MT_ROOT}" != /* ]]; then
    export MT_ROOT="$(dirname -- "${SCRIPT_DIR}")"
  fi

  # Load core functions
  source "${MT_ROOT}/lib/functions.sh" # Must be loaded first (I think)

  source "${MT_ROOT}/lib/colors.sh"
  source "${MT_ROOT}/lib/edit.sh"
  source "${MT_ROOT}/lib/git.sh"
  source "${MT_ROOT}/lib/path.sh"
  source "${MT_ROOT}/lib/stow.sh"
  source "${MT_ROOT}/lib/deps.sh"
  source "${MT_ROOT}/lib/systemd.sh"
  source "${MT_ROOT}/lib/repos.sh"
  source "${MT_ROOT}/lib/package.sh"
  source "${MT_ROOT}/lib/working-set.sh" # MT-11 working set helpers
  source "${MT_ROOT}/lib/module.sh" # MT-11 module commands
  source "${MT_ROOT}/lib/service.sh" # MT-11 service commands
  # MT-12 system health diagnostics (requires bash 4+ for declare -g)
  if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
    source "${MT_ROOT}/lib/doctor.sh"
  fi

  # Initialise globals
  : ${XDG_LOCAL_BIN:="${HOME}/.local/bin"}

  # Dirs for pkg files/symlinks
  # Symlink or copy to here and then symlink to target
  # Provides single choke point for MT packages (rename dir to disable)
  : ${MT_PKG_DIR:="${HOME}/.metool"}
  export MT_PKG_DIR

  # Working set directories (MT-11)
  : ${MT_MODULES_DIR:="${MT_PKG_DIR}/modules"}
  : ${MT_PACKAGES_DIR:="${MT_PKG_DIR}/packages"}
  export MT_MODULES_DIR
  export MT_PACKAGES_DIR

  _mt_log DEBUG "SCRIPT_PATH=${SCRIPT_PATH}"
  _mt_log DEBUG "MT_ROOT=${MT_ROOT}"

  # Ensure pkg dirs exist
  command mkdir -p "${MT_PKG_DIR}/bin"
  # mkdir -p "${MT_PKG_DIR}/config" # Not used currently
  command mkdir -p "${MT_PKG_DIR}/shell"

  # Ensure working set dirs exist (MT-11)
  command mkdir -p "${MT_MODULES_DIR}"
  command mkdir -p "${MT_PACKAGES_DIR}"

  # Check for global debug flag before other argument processing
  if [[ "${1:-}" == "--debug" ]] || [[ "${1:-}" == "-d" ]]; then
    export MT_LOG_LEVEL=DEBUG
    shift  # Remove debug flag from arguments
  fi

  # Parse command
  if [[ $# -eq 0 ]]; then

    ## Ensure MT_BIN_DIR is in PATH
    _mt_path_prepend "${MT_PKG_DIR}/bin"

    # Source all files under MT_PKG_DIR/shell
    # Set guard to prevent recursive sourcing of this file
    export _MT_SOURCING=1
    if [[ -d "${MT_PKG_DIR}/shell" ]]; then
      # Detect current shell
      local current_shell=""
      if [[ -n "${BASH_VERSION}" ]]; then
        current_shell="bash"
      elif [[ -n "${ZSH_VERSION}" ]]; then
        current_shell="zsh"
      fi
      _mt_log DEBUG "Detected shell: $current_shell"

      while IFS= read -r -d '' file; do
        if [[ "$(realpath "$file")" == "${SCRIPT_PATH}" ]]; then
          #if [[ "$(realpath "$file")" =~ "${MT_ROOT}" ]]; then
          _mt_log DEBUG "Not sourcing myself ($SCRIPT_PATH): $file"
          continue
        fi

        # Check file extension for shell-specific sourcing
        local filename="$(basename "$file")"
        local ext=""
        if [[ "$filename" == *.* ]]; then
          ext="${filename##*.}"
        fi

        # Determine if file should be sourced
        local should_source=true

        case "$ext" in
          bash)
            # .bash files only in bash
            if [[ "$current_shell" != "bash" ]]; then
              should_source=false
            fi
            ;;
          zsh)
            # .zsh files only in zsh
            if [[ "$current_shell" != "zsh" ]]; then
              should_source=false
            fi
            ;;
          sh|"")
            # .sh files and files with no extension work in all shells
            should_source=true
            ;;
          *)
            # Other extensions (e.g., .py, .md) - source in all shells
            should_source=true
            ;;
        esac

        if [[ "$should_source" == "true" ]]; then
          _mt_log DEBUG "Sourcing $file"
          source "$file"
        else
          _mt_log DEBUG "Skipping $file (shell-specific: .$ext, current: $current_shell)"
        fi
      done < <(command find -L "${MT_PKG_DIR}/shell" -type f -not -name ".*" -print0 | command sort -z)
      # Setup bash completion for aliases (only if bash-completion is loaded)
      if type -t _complete_alias &>/dev/null; then
        complete -F _complete_alias "${!BASH_ALIASES[@]}"
      fi
    fi
    unset _MT_SOURCING

  else

    case $1 in
    -h | --help)
      echo "Usage: mt [-d|--debug] [command]"
      echo
      echo "Global Options:"
      echo "  -d, --debug            Enable debug output"
      echo
      echo "Core Commands:"
      echo "  cd [TARGET]            Change to MT_ROOT, module, package, or executable"
      echo "  deps [--install]       Check metool dependencies (--install to auto-install on macOS)"
      echo "  doctor [OPTIONS]       Run system health diagnostics"
      echo "  edit TARGET            Edit function, executable or file"
      echo "  git <subcommand>       Git repository management"
      echo "    add [REPO] [ALIAS]   Add repository to .repos.txt manifest"
      echo "    clone URL [PATH]     Clone a git repository to a canonical location"
      echo "    pull [DIR|FILE]      Pull repositories from repos.txt manifest file"
      echo "    push [DIR|FILE]      Push local commits for repositories in manifest"
      echo "    repos [OPTIONS]      List git repositories"
      echo "    trusted [PATH]       Check if repository is trusted"
      echo "  module <subcommand>    Module management"
      echo "    list                 List modules in working set"
      echo "    add MODULE           Add module to working set"
      echo "    remove MODULE        Remove module from working set"
      echo "    edit MODULE          Edit module"
      echo "    update [MODULE...]   Update module(s) from git remote"
      echo "  package <subcommand>   Package management"
      echo "    list                 List packages in working set"
      echo "    add MOD/PKG          Add package to working set"
      echo "    remove PKG           Remove package from working set"
      echo "    edit PKG             Edit package"
      echo "    install PKG [OPTS]   Install package components"
      echo "    uninstall PKG [OPTS] Uninstall package (remove symlinks)"
      echo "    new NAME [PATH]      Create new package from template"
      echo "    service CMD PKG      Manage package services"
      echo "  reload                 Reload metool"
      echo "  update                 Update metool from git"
      echo "  which TARGET           Show real path to module, package, function, or executable"
      echo "  -h, --help             Show this help message and exit"
      echo
      ;;
    cd)
      shift
      if [[ $# -eq 1 ]]; then
        _mt_log DEBUG "\$1=$1"
        _mt_cd "$1"
      else
        echo "Changing directory to: $MT_ROOT"
        cd "$MT_ROOT"
      fi
      ;;
    git)
      shift
      _mt_git "$@"
      ;;
    clone)
      # Keep for backwards compatibility
      shift
      _mt_clone "$@"
      ;;
    edit)
      shift
      _mt_edit "$@"
      ;;
    update)
      shift
      _mt_update
      ;;
    reload)
      shift
      _mt_source "${MT_ROOT}/shell/mt"
      ;;
    module)
      shift
      _mt_module "$@"
      ;;
    package)
      shift
      _mt_package "$@"
      ;;
    deps)
      shift
      _mt_deps "$@"
      ;;
    doctor)
      shift
      _mt_doctor "$@"
      ;;
    which)
      shift
      _mt_which "$@"
      ;;
    help)
      # Redirect help to -h/--help handler
      mt --help
      ;;
    *)
      _mt_error "Unknown command: $1"
      return 1
      ;;
    esac

  fi
}

mt "$@"
