#!/bin/sh
# Boosthis project scanner — https://www.boosthis.com/scan
#
# What this does: walks THIS project (monorepos included), looks at manifest
# file NAMES and manifest contents only — package.json, go.mod, pom.xml,
# build.gradle(.kts), requirements.txt, pyproject.toml, composer.json,
# wp-config.php, *.csproj/*.sln, Gemfile/config.ru/*.gemspec, Cargo.toml/
# src/main.rs, mix.exs — and prints which
# Boosthis kits the project needs.
#
# Privacy: everything runs locally. It never reads your source code and it
# uploads NOTHING — there is no network call in this script.
#
# Usage: run from your project root — two steps, nothing piped into a shell:
#          curl -fsSL https://www.boosthis.com/scan -o boosthis-scan.sh
#          sh boosthis-scan.sh
#        (optional: pass a directory:  sh boosthis-scan.sh /path/to/project)
#
# This is the inventory view. Fetched with your Boosthis project key, the same
# scanner also prints each kit's install commands — see the end of the output.

ROOT="${1:-.}"

found_rn=""; found_web=""; found_node=""; found_python=""; found_go=""; found_java=""
found_php=""; found_dotnet=""; found_ruby=""; found_rust=""; found_elixir=""
found_kotlin=""

add() {
  eval "cur=\$found_$1"
  case " $cur " in
    *" $2 "*) ;;
    *) eval "found_$1=\"$cur $2\"" ;;
  esac
}

# Manifest walk — prunes dependency/build/vendor directories so a monorepo
# scan stays fast and never wanders into third-party code.
MANIFESTS=$(find "$ROOT" \
  \( -name node_modules -o -name vendor -o -name .git -o -name build \
     -o -name dist -o -name out -o -name target -o -name Pods \
     -o -name .venv -o -name venv -o -name __pycache__ -o -name .next \
     -o -name .expo -o -name .gradle -o -name .idea \) -prune -o \
  -type f \( -name package.json -o -name go.mod -o -name pom.xml \
     -o -name build.gradle -o -name build.gradle.kts \
     -o -name requirements.txt -o -name pyproject.toml \
     -o -name composer.json -o -name wp-config.php \
     -o -name "*.csproj" -o -name "*.sln" \
     -o -name Gemfile -o -name config.ru -o -name "*.gemspec" \
     -o -name Cargo.toml -o -name main.rs -o -name mix.exs \
     -o -name AndroidManifest.xml \) -print 2>/dev/null)

while IFS= read -r f; do
  [ -n "$f" ] || continue
  d=$(dirname "$f")
  case $(basename "$f") in
    go.mod) add go "$d" ;;
    composer.json|wp-config.php) add php "$d" ;;
    Gemfile|config.ru|*.gemspec) add ruby "$d" ;;
    Cargo.toml) add rust "$d" ;;
    main.rs)
      # Only src/main.rs marks a Rust crate root; a stray main.rs elsewhere
      # does not. Attribute it to the crate dir (the parent of src/), matching
      # where Cargo.toml lives, so both signals collapse to one entry.
      if [ "$(basename "$d")" = "src" ]; then add rust "$(dirname "$d")"; fi
      ;;
    mix.exs) add elixir "$d" ;;
    *.csproj|*.sln) add dotnet "$d" ;;
    # An AndroidManifest.xml is the unambiguous mark of a native Android app —
    # the Kotlin (device) kit, NOT the Java server kit. Attribute it to the
    # module root (the parent of src/main where the manifest lives) so it
    # collapses onto the same directory as that module's build.gradle.
    AndroidManifest.xml)
      md="$d"
      [ "$(basename "$md")" = "main" ] && md="$(dirname "$md")"
      [ "$(basename "$md")" = "src" ] && md="$(dirname "$md")"
      add kotlin "$md"
      ;;
    pom.xml|build.gradle|build.gradle.kts)
      # Gradle builds BOTH native Android apps (Kotlin kit) and JVM servers
      # (Java kit). Only the Android Gradle plugin marks an app; a Ktor/Spring
      # server keeps the java runtime. pom.xml is always a JVM server.
      if [ "$(basename "$f")" != "pom.xml" ] && \
         grep -Eq "com\.android\.(application|library)" "$f"; then
        add kotlin "$d"
      else
        add java "$d"
      fi
      ;;
    requirements.txt|pyproject.toml) add python "$d" ;;
    package.json)
      if grep -Eq '"(expo|react-native)"[[:space:]]*:' "$f"; then
        add rn "$d"
      elif grep -Eq '"(react|react-dom|next|vite|vue|nuxt|svelte|@angular/core|astro|solid-js|preact)"[[:space:]]*:' "$f"; then
        add web "$d"
      else
        add node "$d"
      fi
      ;;
  esac
done <<BOOSTHIS_EOF
$MANIFESTS
BOOSTHIS_EOF

echo ""
echo "Boosthis project scanner"
echo "Scanned: $ROOT  (manifest files only — no source code read, nothing uploaded)"
echo ""

any=""

report() {
  rt="$1"; label="$2"; dirs="$3"
  [ -n "$dirs" ] || return 0
  any=1
  echo "  • $label kit  (runtime: $rt)"
  for d in $dirs; do
    echo "      detected in: $d"
  done
  if [ -n "$4" ]; then
    echo "      install (run from that directory, same project key for every kit;"
    echo "      the middle step lists the archive without unpacking it):"
    echo "      $4"
  fi
  echo ""
}

if [ -n "$found_rn$found_web$found_node$found_python$found_go$found_java$found_php$found_dotnet$found_ruby$found_rust$found_elixir$found_kotlin" ]; then
  echo "Detected runtimes — install one Boosthis kit per runtime:"
  echo ""
fi
report rn     "Mobile app (React Native / Expo)" "$found_rn"     ''
report web    "Website (browser)"                "$found_web"    ''
report node   "Node.js backend"                  "$found_node"   ''
report python "Python backend"                   "$found_python" ''
report go     "Go backend"                       "$found_go"     ''
report java   "Java backend"                     "$found_java"   ''
report php    "PHP backend"                      "$found_php"    ''
report dotnet "C# / .NET backend"                "$found_dotnet" ''
report ruby   "Ruby backend (Rails / Rack)"      "$found_ruby"   ''
report rust   "Rust backend"                     "$found_rust"   ''
report elixir "Elixir backend (Phoenix / OTP)"   "$found_elixir" ''
report kotlin "Android app (Kotlin)"             "$found_kotlin" ''

# Plain HTML pages — a project with .html files but no bundler manifest has
# no way to install a module kit. It is still a browser, so it can still be
# measured: the one-line hosted script needs no build step at all. Only
# suggested when no bundled web app was detected (a Vite/Next project also
# has .html files, and it should use the module kit instead).
HTML_DIRS=$(find "$ROOT" \
  \( -name node_modules -o -name vendor -o -name .git -o -name build \
     -o -name dist -o -name out -o -name target -o -name Pods \
     -o -name .venv -o -name venv -o -name __pycache__ -o -name .next \
     -o -name .expo -o -name .gradle -o -name .idea \) -prune -o \
  -type f -name '*.html' -print 2>/dev/null | sed 's|/[^/]*$||' | sort -u | head -5)

if [ -z "$found_web" ] && [ -n "$HTML_DIRS" ]; then
  if [ -z "$any" ]; then
    echo "Detected plain HTML pages — no build step needed:"
    echo ""
  fi
  any=1
  echo "  • Plain HTML / no-code pages  (one-line install, nothing to compile)"
  for d in $HTML_DIRS; do
    echo "      detected in: $d"
  done
  echo "      nothing to compile — the one-line snippet for these pages is"
  echo "      on your Setup page (see below)."
  echo ""
fi

if [ -z "$any" ]; then
  echo "Nothing detected — no recognizable manifest files found under $ROOT."
  echo "If this is a plain HTML site, or you would rather pick your runtime(s)"
  echo "manually (rn | web | node | python | go | java | php | dotnet | ruby | kotlin | rust | elixir),"
  echo "the Setup page for your project key has copy-paste instructions: https://www.boosthis.com/dashboard."
else
  echo "That is the inventory: one Boosthis kit per runtime listed above."
  echo ""
  echo "Install steps are not published on the open web. Two ways to get them:"
  echo "  • Sign in at https://www.boosthis.com/dashboard — the Setup page for your project key"
  echo "    carries the exact command for each kit, key already filled in."
  echo "  • Re-run this scanner with that key and it prints them here:"
  echo ""
  echo '      curl -fsSL -H "Authorization: Bearer <your project key>" https://www.boosthis.com/scan -o boosthis-scan.sh'
  echo '      sh boosthis-scan.sh'
fi
echo ""
