#!/usr/bin/env bash
#
# install-deps.sh — Install EMDS-Workbench Python dependencies into the
# QGIS-bundled Python on macOS.
#
# EMDS-Workbench needs pandas and pyarrow in the SAME Python that QGIS runs.
# The official QGIS macOS bundle ships pandas (e.g. 2.3.3) but NOT pyarrow, so
# the plugin fails on initialization. This script locates the bundled Python
# inside /Applications/QGIS*.app and installs only what is missing.
#
# Behaviour:
#   * pandas is installed (pinned <3) ONLY if it is not already importable.
#     An existing bundled pandas is left untouched.
#   * pyarrow is installed ONLY if it is not already importable.
#   * Recent QGIS macOS bundles ship without a usable pip3, so pip is
#     bootstrapped via ensurepip / get-pip.py when needed.
#   * If the bundle site-packages is not writable, falls back to --user.
#
# Usage:
#   bash scripts/macos/install-deps.sh
#   QGIS_APP="/Applications/QGIS_Final-4.0.2.app" bash scripts/macos/install-deps.sh
#
set -euo pipefail

echo "EMDS-Workbench macOS dependency installer"
echo "========================================="

# --- 1. Locate QGIS app bundle(s) ---------------------------------------
# Bundle names vary: QGIS.app, QGIS-LTR.app, QGIS_Final-4.0.2.app,
# QGIS-final-4.0.0.app, etc. Match case-insensitively.
declare -a APPS=()
if [[ -n "${QGIS_APP:-}" ]]; then
  APPS+=("$QGIS_APP")
else
  shopt -s nullglob
  for dir in /Applications "$HOME/Applications"; do
    for app in "$dir"/*.app; do
      base="$(basename "$app")"
      shopt -s nocasematch
      if [[ "$base" == qgis* ]]; then
        APPS+=("$app")
      fi
      shopt -u nocasematch
    done
  done
  shopt -u nullglob
fi

if [[ ${#APPS[@]} -eq 0 ]]; then
  echo "ERROR: No QGIS*.app bundle found in /Applications or ~/Applications." >&2
  echo "Install QGIS from https://qgis.org/download/ and re-run," >&2
  echo "or set QGIS_APP=/path/to/QGIS.app and re-run." >&2
  exit 1
fi

if [[ ${#APPS[@]} -gt 1 ]]; then
  echo "Multiple QGIS bundles found:"
  printf '  %s\n' "${APPS[@]}"
fi
# Prefer the highest-sorting name (usually the highest version).
QGIS_APP_SELECTED="$(printf '%s\n' "${APPS[@]}" | sort | tail -n 1)"
echo "Using: $QGIS_APP_SELECTED"

# --- 2. Locate the bundled python3 --------------------------------------
PY="$QGIS_APP_SELECTED/Contents/MacOS/python3"
if [[ ! -x "$PY" ]]; then
  # Fall back to a versioned interpreter (e.g. python3.12) in the same dir.
  PY="$(ls "$QGIS_APP_SELECTED"/Contents/MacOS/python3.* 2>/dev/null | sort -V | tail -n 1 || true)"
fi
if [[ -z "${PY:-}" || ! -x "$PY" ]]; then
  echo "ERROR: Could not find the QGIS bundled python3 in" >&2
  echo "  $QGIS_APP_SELECTED/Contents/MacOS" >&2
  exit 1
fi
echo "Python: $PY"
"$PY" --version

# --- 3. Ensure pip is available -----------------------------------------
if ! "$PY" -m pip --version >/dev/null 2>&1; then
  echo "pip not found in the QGIS python; bootstrapping with ensurepip..."
  if ! "$PY" -m ensurepip --upgrade >/dev/null 2>&1; then
    echo "ensurepip unavailable; fetching get-pip.py..."
    TMP_GETPIP="$(mktemp -t getpip).py"
    trap 'rm -f "$TMP_GETPIP"' EXIT
    curl -fsSL https://bootstrap.pypa.io/get-pip.py -o "$TMP_GETPIP"
    "$PY" "$TMP_GETPIP"
  fi
fi
echo "pip: $("$PY" -m pip --version)"

# --- 4. Decide install target -------------------------------------------
# /Applications is generally not SIP-protected, but the .app may be
# admin-owned and read-only for the current user. Test writability of the
# bundle's site-packages; if not writable, fall back to --user, which the
# bundled QGIS python keeps on sys.path by default.
SITE_DIR="$("$PY" -c 'import site; ps = site.getsitepackages() if hasattr(site,"getsitepackages") else []; print(ps[0] if ps else "")' 2>/dev/null || echo "")"
PIP_FLAGS=(--no-input --disable-pip-version-check)
if [[ -z "$SITE_DIR" || ! -w "$SITE_DIR" ]]; then
  echo "Bundle site-packages not writable (${SITE_DIR:-unknown}); using --user install."
  PIP_FLAGS+=(--user)
fi
# PEP 668: allow augmenting a possibly externally-managed environment. This is
# a no-op on pythons without the EXTERNALLY-MANAGED marker.
PIP_FLAGS+=(--break-system-packages)

# --- 5. Install only what is missing ------------------------------------
ensure_pkg() {
  local import_name="$1" spec="$2"
  if "$PY" -c "import $import_name" >/dev/null 2>&1; then
    local ver
    ver="$("$PY" -c "import $import_name as m; print(getattr(m,'__version__','?'))" 2>/dev/null || echo '?')"
    echo "  OK: '$import_name' already present ($ver) — leaving it unchanged."
  else
    echo "  Installing $spec ..."
    "$PY" -m pip install "${PIP_FLAGS[@]}" "$spec"
  fi
}

echo "Checking/installing dependencies..."
ensure_pkg pandas  "pandas>=2.0,<3"
ensure_pkg pyarrow "pyarrow>=14.0.0"

# --- 6. Verify -----------------------------------------------------------
echo "Verifying imports in the QGIS python..."
"$PY" - <<'PYEOF'
import importlib, sys
ok = True
for name in ("pandas", "pyarrow"):
    try:
        m = importlib.import_module(name)
        print(f"  {name} {getattr(m, '__version__', '?')} -> {m.__file__}")
    except Exception as exc:  # noqa: BLE001
        ok = False
        print(f"  FAILED to import {name}: {exc}", file=sys.stderr)
sys.exit(0 if ok else 1)
PYEOF

echo
echo "Done. Restart QGIS so the plugin picks up the new packages."
