#!/bin/bash

# NUPST Setup Script
# Downloads the appropriate Node.js binary for the current platform
# and installs production dependencies

# Parse command line arguments
FORCE_UPDATE=0

for arg in "$@"; do
  case $arg in
    --force|-f)
      FORCE_UPDATE=1
      shift
      ;;
    *)
      # Unknown option
      ;;
  esac
done

# Find the directory where this script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

# Create vendor directory if it doesn't exist
mkdir -p "$SCRIPT_DIR/vendor"

# Get the latest LTS Node.js version
echo "Determining latest LTS Node.js version..."
NODE_VERSIONS_JSON=$(curl -s https://nodejs.org/dist/index.json)
if [ $? -ne 0 ]; then
  echo "Warning: Could not fetch latest Node.js versions. Using fallback version."
  NODE_VERSION="20.11.1"  # Fallback to a recent LTS version
else
  # Extract the latest LTS version (those marked with lts field)
  NODE_VERSION=$(echo "$NODE_VERSIONS_JSON" | grep -o '"version":"v[0-9.]*".*"lts":[^,]*' | grep -v '"lts":false' | grep -o 'v[0-9.]*' | head -1 | cut -c 2-)
  
  if [ -z "$NODE_VERSION" ]; then
    echo "Warning: Could not determine latest LTS version. Using fallback version."
    NODE_VERSION="20.11.1"  # Fallback to a recent LTS version
  else
    echo "Latest Node.js LTS version: $NODE_VERSION"
  fi
fi

# Detect architecture
ARCH=$(uname -m)
OS=$(uname -s)

# Map architecture and OS to Node.js download URL
NODE_URL=""
NODE_DIR=""
case "$OS" in
  Linux)
    case "$ARCH" in
      x86_64)
        NODE_URL="https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz"
        NODE_DIR="node-linux-x64"
        ;;
      aarch64|arm64)
        NODE_URL="https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-arm64.tar.gz"
        NODE_DIR="node-linux-arm64"
        ;;
      *)
        echo "Unsupported architecture: $ARCH. Please install Node.js manually."
        exit 1
        ;;
    esac
    ;;
  Darwin)
    case "$ARCH" in
      x86_64)
        NODE_URL="https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-darwin-x64.tar.gz"
        NODE_DIR="node-darwin-x64"
        ;;
      arm64)
        NODE_URL="https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-darwin-arm64.tar.gz"
        NODE_DIR="node-darwin-arm64"
        ;;
      *)
        echo "Unsupported architecture: $ARCH. Please install Node.js manually."
        exit 1
        ;;
    esac
    ;;
  *)
    echo "Unsupported operating system: $OS. Please install Node.js manually."
    exit 1
    ;;
esac

# Check if we already have the Node.js binary
if [ -f "$SCRIPT_DIR/vendor/$NODE_DIR/bin/node" ] && [ $FORCE_UPDATE -eq 0 ]; then
  echo "Node.js binary already exists for $OS-$ARCH. Skipping download."
  echo "Use --force or -f to force update Node.js."
else
  echo "Downloading Node.js v$NODE_VERSION for $OS-$ARCH..."
  
  # Download and extract Node.js
  TMP_FILE="$SCRIPT_DIR/vendor/node.tar.gz"
  curl -L "$NODE_URL" -o "$TMP_FILE"
  
  if [ $? -ne 0 ]; then
    echo "Error downloading Node.js. Please check your internet connection and try again."
    exit 1
  fi
  
  # Create target directory
  mkdir -p "$SCRIPT_DIR/vendor/$NODE_DIR"
  
  # Extract Node.js
  tar -xzf "$TMP_FILE" -C "$SCRIPT_DIR/vendor"
  
  # Move extracted files to the target directory
  NODE_EXTRACT_DIR=$(find "$SCRIPT_DIR/vendor" -maxdepth 1 -name "node-v*" -type d | head -n 1)
  if [ -d "$NODE_EXTRACT_DIR" ]; then
    cp -R "$NODE_EXTRACT_DIR"/* "$SCRIPT_DIR/vendor/$NODE_DIR/"
    rm -rf "$NODE_EXTRACT_DIR"
  else
    echo "Error extracting Node.js. Please try again."
    exit 1
  fi
  
  # Clean up
  rm "$TMP_FILE"
  
  echo "Node.js v$NODE_VERSION for $OS-$ARCH has been downloaded and extracted."
fi

# Remove any existing dist_ts directory
if [ -d "$SCRIPT_DIR/dist_ts" ]; then
  echo "Removing existing dist_ts directory..."
  rm -rf "$SCRIPT_DIR/dist_ts"
fi

# Download dist_ts from npm registry
echo "Downloading dist_ts from npm registry..."

# Create temp directory
TEMP_DIR=$(mktemp -d)

# Get version from package.json
if [ -f "$SCRIPT_DIR/package.json" ]; then
  echo "Reading version from package.json..."
  # Extract version using grep and cut
  VERSION=$(grep -o '"version": "[^"]*"' "$SCRIPT_DIR/package.json" | cut -d'"' -f4)
  
  if [ -z "$VERSION" ]; then
    echo "Error: Could not determine version from package.json."
    rm -rf "$TEMP_DIR"
    exit 1
  fi
  
  echo "Package version is $VERSION. Downloading matching package tarball..."
else
  echo "Warning: package.json not found. Getting latest version from npm registry..."
  VERSION=$(curl -s https://registry.npmjs.org/@serve.zone/nupst | grep -o '"latest":"[^"]*"' | cut -d'"' -f4)
  
  if [ -z "$VERSION" ]; then
    echo "Error: Could not determine version from npm registry."
    rm -rf "$TEMP_DIR"
    exit 1
  fi
  
  echo "Latest version is $VERSION. Using as fallback."
fi

# First try to download with the version from package.json
TARBALL_URL="https://registry.npmjs.org/@serve.zone/nupst/-/nupst-$VERSION.tgz"
TARBALL_PATH="$TEMP_DIR/nupst.tgz"

echo "Attempting to download version $VERSION from $TARBALL_URL..."
curl -sL "$TARBALL_URL" -o "$TARBALL_PATH"

# If download fails or file is empty, try to get the latest version from npm
if [ $? -ne 0 ] || [ ! -s "$TARBALL_PATH" ]; then
  echo "Package version $VERSION not found on npm registry."
  echo "Fetching latest version information from npm registry..."
  
  # Get latest version from npm registry
  NPM_REGISTRY_INFO=$(curl -s https://registry.npmjs.org/@serve.zone/nupst)
  
  if [ $? -ne 0 ]; then
    echo "Error: Could not connect to npm registry."
    echo "Will attempt to build from source instead."
    rm -rf "$TEMP_DIR"
    mkdir -p "$SCRIPT_DIR/dist_ts"
    BUILD_FROM_SOURCE=1
    return 0
  fi
  
  # Extract latest version
  LATEST_VERSION=$(echo "$NPM_REGISTRY_INFO" | grep -o '"latest":"[^"]*"' | cut -d'"' -f4)
  
  if [ -z "$LATEST_VERSION" ]; then
    echo "Error: Could not determine latest version from npm registry."
    echo "Will attempt to build from source instead."
    rm -rf "$TEMP_DIR"
    mkdir -p "$SCRIPT_DIR/dist_ts"
    BUILD_FROM_SOURCE=1
    return 0
  fi
  
  echo "Found latest version: $LATEST_VERSION. Downloading..."
  
  TARBALL_URL="https://registry.npmjs.org/@serve.zone/nupst/-/nupst-$LATEST_VERSION.tgz"
  TARBALL_PATH="$TEMP_DIR/nupst.tgz"
  
  curl -sL "$TARBALL_URL" -o "$TARBALL_PATH"
  
  if [ $? -ne 0 ] || [ ! -s "$TARBALL_PATH" ]; then
    echo "Error: Failed to download any package version from npm registry."
    echo "Installation cannot continue without the dist_ts directory."
    rm -rf "$TEMP_DIR"
    exit 1
  fi
fi

# Extract the tarball
mkdir -p "$TEMP_DIR/extract"
tar -xzf "$TARBALL_PATH" -C "$TEMP_DIR/extract"

# Copy dist_ts to the installation directory
if [ -d "$TEMP_DIR/extract/package/dist_ts" ]; then
  echo "Copying dist_ts directory to installation..."
  mkdir -p "$SCRIPT_DIR/dist_ts"
  cp -R "$TEMP_DIR/extract/package/dist_ts/"* "$SCRIPT_DIR/dist_ts/"
else
  echo "Error: dist_ts directory not found in the downloaded npm package."
  rm -rf "$TEMP_DIR"
  exit 1
fi

# Clean up
rm -rf "$TEMP_DIR"

echo "dist_ts directory successfully downloaded from npm registry."

# Make launcher script executable
chmod +x "$SCRIPT_DIR/bin/nupst"

# Set up Node.js binary path
NODE_BIN_DIR="$SCRIPT_DIR/vendor/$NODE_DIR/bin"
NODE_BIN="$NODE_BIN_DIR/node"
NPM_CLI_JS="$NODE_BIN_DIR/../lib/node_modules/npm/bin/npm-cli.js"

# Ensure we have executable permissions
chmod +x "$NODE_BIN"

# Make sure the npm-cli.js exists
if [ ! -f "$NPM_CLI_JS" ]; then
  # Try to find npm-cli.js
  NPM_CLI_JS=$(find "$NODE_BIN_DIR/.." -name "npm-cli.js" | head -1)
  
  if [ -z "$NPM_CLI_JS" ]; then
    echo "Warning: Could not find npm-cli.js, npm commands may fail"
    # Set to a fallback value so code can continue
    NPM_CLI_JS="$NODE_BIN_DIR/npm"
  else
    echo "Found npm-cli.js at: $NPM_CLI_JS"
  fi
fi

# Display which binaries we're using
echo "Using Node binary: $NODE_BIN"
echo "Using NPM CLI JS: $NPM_CLI_JS"

# Remove existing node_modules directory and package files
echo "Cleaning up existing installation..."
rm -rf "$SCRIPT_DIR/node_modules"
rm -f "$SCRIPT_DIR/package-lock.json"

# Back up existing package.json if it exists
if [ -f "$SCRIPT_DIR/package.json" ]; then
  echo "Backing up existing package.json..."
  cp "$SCRIPT_DIR/package.json" "$SCRIPT_DIR/package.json.bak"
fi

# Create a clean minimal package.json with ONLY net-snmp dependency
echo "Creating minimal package.json with only net-snmp dependency..."
VERSION=$(grep -o '"version": "[^"]*"' "$SCRIPT_DIR/package.json.bak" | head -1 | cut -d'"' -f4 || echo "2.6.3")
echo '{
  "name": "@serve.zone/nupst",
  "version": "'$VERSION'",
  "description": "Node.js UPS Shutdown Tool for SNMP-enabled UPS devices",
  "main": "dist_ts/index.js",
  "type": "module",
  "bin": {
    "nupst": "bin/nupst"
  },
  "dependencies": {
    "net-snmp": "3.20.0"
  },
  "engines": {
    "node": ">=16.0.0"
  },
  "private": true
}' > "$SCRIPT_DIR/package.json"

# Install ONLY net-snmp
echo "Installing ONLY net-snmp dependency (+ 2 subdependencies)..."
echo "Node version: $("$NODE_BIN" --version)"
echo "Executing NPM directly with Node.js"

# Execute npm-cli.js directly with our Node.js binary
"$NODE_BIN" "$NPM_CLI_JS" --prefix "$SCRIPT_DIR" install --no-audit --no-fund

INSTALL_STATUS=$?
if [ $INSTALL_STATUS -ne 0 ]; then
  echo "Error: Failed to install net-snmp dependency. NUPST may not function correctly."
  echo "Restoring original package.json..."
  mv "$SCRIPT_DIR/package.json.bak" "$SCRIPT_DIR/package.json"
  exit 1
else
  echo "net-snmp dependency installed successfully."
  # Show what's actually installed
  echo "Installed modules:"
  find "$SCRIPT_DIR/node_modules" -maxdepth 1 -type d | grep -v "^$SCRIPT_DIR/node_modules$" | sort
  
  # Remove backup if successful
  rm -f "$SCRIPT_DIR/package.json.bak"
fi

# No temporary files to clean up

echo "NUPST setup completed successfully."
echo "You can now run NUPST using: $SCRIPT_DIR/bin/nupst"
echo "To install NUPST globally, run: sudo ln -s $SCRIPT_DIR/bin/nupst /usr/local/bin/nupst"