#!/usr/bin/env bash
# Workspace and project classification.

node_workspace_root() {
  local dir="$1" parent
  while [[ "$dir" == "$ROOT" || "$dir" == "$ROOT"/* ]]; do
    [[ -f "$dir/pnpm-workspace.yaml" ]] && { printf '%s\n' "$dir"; return; }
    if [[ -f "$dir/package.json" ]] && node -e 'const p=require(process.argv[1]);process.exit(p.workspaces?0:1)' "$dir/package.json" 2>/dev/null; then
      printf '%s\n' "$dir"; return
    fi
    [[ "$dir" == "$ROOT" ]] && break
    parent="$(dirname "$dir")"; [[ "$parent" == "$dir" ]] && break; dir="$parent"
  done
  printf '%s\n' "$1"
}

discover() {
  local manifest dir type root
  while IFS= read -r -d '' manifest; do
    dir="$(dirname "$manifest")"
    matches_filter "$manifest" || continue
    type="shared-package"
    node -e 'const p=require(process.argv[1]);const d={...(p.dependencies||{}),...(p.devDependencies||{}),...(p.optionalDependencies||{})};process.exit(d.next?0:1)' "$manifest" 2>/dev/null && type="nextjs-app"
    NODE_PROJECTS+=("$manifest"); NODE_TYPES+=("$type")
    [[ "$type" == shared-package ]] && SHARED_PACKAGES+=("$dir")
    root="$(node_workspace_root "$dir")"; unique_append NODE_ROOTS "$root"
  done < <(find "$ROOT" -type d \( -name .git -o -name node_modules -o -name .next -o -name bin -o -name obj -o -name .maintenance \) -prune -o -type f -name package.json -print0)

  while IFS= read -r -d '' manifest; do
    matches_filter "$manifest" || continue
    type="dotnet-lib"
    grep -Eqi '<OutputType>[^<]*(Exe|WinExe)' "$manifest" && type="dotnet-app"
    if grep -Eqi 'PackageReference[^>]+Include="Avalonia|Avalonia\.(Desktop|Controls|Themes)' "$manifest" || find "$(dirname "$manifest")" -maxdepth 3 -type f \( -name '*.axaml' -o -name 'App.xaml' \) -print -quit | grep -q .; then
      type="avalonia-app"
    fi
    DOTNET_PROJECTS+=("$manifest"); DOTNET_TYPES+=("$type")
  done < <(find "$ROOT" -type d \( -name .git -o -name node_modules -o -name bin -o -name obj -o -name .maintenance \) -prune -o -type f \( -name '*.csproj' -o -name '*.fsproj' -o -name '*.vbproj' \) -print0)
}

print_inventory() {
  printf '%sDep Upgrader %s%s\n' "$C_BOLD$C_CYAN" "$VERSION" "$C_RESET"
  printf 'Root: %s\n\n' "$ROOT"
  local i
  if [[ "$ECOSYSTEMS" != dotnet ]]; then
    printf '%sNode / pnpm%s\n' "$C_BOLD" "$C_RESET"
    for i in "${!NODE_PROJECTS[@]}"; do printf '  %-16s %s\n' "${NODE_TYPES[$i]}" "${NODE_PROJECTS[$i]#$ROOT/}"; done
  fi
  if [[ "$ECOSYSTEMS" != node ]]; then
    printf '%s.NET / Avalonia%s\n' "$C_BOLD" "$C_RESET"
    for i in "${!DOTNET_PROJECTS[@]}"; do printf '  %-16s %s\n' "${DOTNET_TYPES[$i]}" "${DOTNET_PROJECTS[$i]#$ROOT/}"; done
  fi
  printf '\nNode projects: %s · .NET projects: %s\n' "${#NODE_PROJECTS[@]}" "${#DOTNET_PROJECTS[@]}"
}
