#!/usr/bin/env bash
#
# VS Code extension installer for macOS and Linux (Ubuntu).
#
# Usage:
#   ./install.sh                                  # looks for .vscode/extensions.json
#   ./install.sh -f extensions.json               # specify a local JSON file
#   ./install.sh -f https://link-to-your/ext.json # specify a remote URL directly
#   ./install.sh -p "MyProfile" -f <source>       # install into a named profile

set -euo pipefail
IFS=$'\n\t'

EXTENSIONS=(
  "docker.docker"
  "github.github-vscode-theme"
  "GitHub.vscode-github-actions"
  "ms-azuretools.vscode-containers"
  "ms-vscode-remote.vscode-remote-extensionpack"
  "pkief.material-icon-theme"
)
PROFILE=""
SOURCE=""

usage() {
  cat <<EOF
Usage: $(basename "$0") [--profile "ProfileName"] [--file "extensions.json" | "https://..."]

Installs a curated list of VS Code extensions on macOS or Linux from a local JSON file or URL.

Options:
  -p, --profile <name>   Install into the named VS Code profile.
  -f, --file <path/url>  Path or URL to the JSON file containing recommendations.
                         Defaults to .vscode/extensions.json if it exists.
  -h, --help             Show this help and exit.
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    -p|--profile)
      if [[ $# -lt 2 || -z "${2:-}" ]]; then
        echo "Error: --profile requires a non-empty value." >&2
        exit 2
      fi
      PROFILE="$2"
      shift 2
      ;;
    -f|--file)
      if [[ $# -lt 2 || -z "${2:-}" ]]; then
        echo "Error: --file requires a non-empty value." >&2
        exit 2
      fi
      SOURCE="$2"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Error: unknown argument '$1'." >&2
      usage >&2
      exit 2
      ;;
  esac
done

OS="$(uname -s)"
case "$OS" in
  Darwin|Linux) ;;
  *)
    echo "Error: unsupported OS '$OS'. Use install.ps1 on Windows." >&2
    exit 1
    ;;
esac

# 1. Check for 'code' command
if ! command -v code >/dev/null 2>&1; then
  cat >&2 <<'EOF'
Error: the 'code' command is not on your PATH.
EOF
  exit 1
fi

# 2. Check for 'jq' command
if ! command -v jq >/dev/null 2>&1; then
  echo "Error: 'jq' is not installed. (Ubuntu: sudo apt-get install jq)" >&2
  exit 1
fi

# 3. Resolve JSON Source (Local File vs URL)
JSON_FILE=""
TEMP_JSON_FILE=""
USE_HARDCODED=false

if [[ -z "$SOURCE" ]]; then
  if [[ -f ".vscode/extensions.json" ]]; then
    JSON_FILE=".vscode/extensions.json"
  else
    echo "Info: No JSON file specified and .vscode/extensions.json not found. Using hardcoded extensions." >&2
    USE_HARDCODED=true
  fi
elif [[ "$SOURCE" =~ ^https?:// ]]; then
  if ! command -v curl >/dev/null 2>&1; then
    echo "Error: 'curl' is required to download remote JSON files." >&2
    exit 1
  fi
  echo "Downloading JSON from URL..."
  JSON_FILE="$(mktemp -t vscode-json.XXXXXX)"
  TEMP_JSON_FILE="$JSON_FILE"
  curl -sSL "$SOURCE" -o "$JSON_FILE"
else
  JSON_FILE="$SOURCE"
  if [[ ! -f "$JSON_FILE" ]]; then
    echo "Error: File '$JSON_FILE' does not exist." >&2
    exit 1
  fi
fi

# 4. Extract extensions from JSON using jq (if not using hardcoded array)
if [[ "$USE_HARDCODED" == false ]]; then
  mapfile -t EXTENSIONS < <(jq -r '.recommendations[]?' "$JSON_FILE")
  
  if [[ ${#EXTENSIONS[@]} -eq 0 ]]; then
    echo "Error: No extensions found under the 'recommendations' key." >&2
    exit 1
  fi
fi

declare -a CODE_ARGS=()
if [[ -n "$PROFILE" ]]; then
  CODE_ARGS+=("--profile" "$PROFILE")
fi

# Trap to clean up logs and temporary downloaded JSON files
LOG_FILE="$(mktemp -t vscode-install.XXXXXX)"
trap 'rm -f "$LOG_FILE" $TEMP_JSON_FILE' EXIT

header="Installing ${#EXTENSIONS[@]} extension(s)"
[[ -n "$PROFILE" ]] && header+=" into profile '$PROFILE'"
echo "$header..."
echo

installed=0
failed=0
declare -a FAILED_LIST=()

for ext in "${EXTENSIONS[@]}"; do
  [[ -z "$ext" ]] && continue 

  printf '  -> %-55s ' "$ext"
  if code "${CODE_ARGS[@]}" --install-extension "$ext" --force >"$LOG_FILE" 2>&1; then
    echo "ok"
    installed=$((installed + 1))
  else
    echo "FAILED"
    failed=$((failed + 1))
    FAILED_LIST+=("$ext")
    sed 's/^/       /' "$LOG_FILE" >&2 || true
  fi
done

echo
echo "Done. Installed: ${installed}, Failed: ${failed}"

if (( failed > 0 )); then
  echo "Failed extensions:" >&2
  for f in "${FAILED_LIST[@]}"; do
    echo "  - $f" >&2
  done
  exit 1
fi