#!/bin/bash
# unraid-api-handler

# shellcheck source=/dev/null
source /etc/profile

flash="/boot/config/plugins/dynamix.my.servers"
[[ ! -d "${flash}" ]] && echo "Please reinstall the Unraid Connect plugin" && exit 1
[[ ! -f "${flash}/env" ]] && echo 'env=production' >"${flash}/env"
unraid_binary_path="/usr/local/bin/unraid-api"
pnpm_store_dir="/usr/.pnpm-store"

# Placeholder functions for plugin installation/uninstallation
install() {
  true
}
uninstall() {
  true
}

# Creates a backup of the global pnpm store directory
# Args:
#   $1 - Path to the backup file (tar.xz format)
# Returns:
#   0 on success, 1 on failure
backup_pnpm_store() {
  # Check if backup file path is provided
  if [ -z "$1" ]; then
    echo "Error: Backup file path is required"
    return 1
  fi

  local backup_file="$1"

  # Check if pnpm command exists
  if ! command -v pnpm >/dev/null 2>&1; then
    echo "pnpm is not installed. Skipping backup."
    return 1
  fi

  # Determine the global pnpm store directory
  mkdir -p "$pnpm_store_dir"

  echo "Backing up pnpm store from '$pnpm_store_dir' to '$backup_file'"

  # Create a tar.gz archive of the global pnpm store
  if tar -cJf "$backup_file" -C "$(dirname "$pnpm_store_dir")" "$(basename "$pnpm_store_dir")"; then
    echo "pnpm store backup completed successfully."
  else
    echo "Error: Failed to create pnpm store backup."
    return 1
  fi
}

# Restores the pnpm store from a backup file
# Args:
#   $1 - Path to the backup file (tar.xz format)
# Returns:
#   0 on success, 1 on failure
# Note: Requires 1.5x the backup size in free space for safe extraction
restore_pnpm_store() {
  # Check if pnpm command exists
  if ! command -v pnpm >/dev/null 2>&1; then
    echo "pnpm is not installed. Cannot restore store."
    return 1
  fi

  local backup_file="$1"
  # Check if backup file exists
  if [ ! -f "$backup_file" ]; then
    echo "Backup file not found at '$backup_file'. Skipping restore."
    return 0
  fi

  # Check available disk space in destination
  local backup_size
  backup_size=$(stat -c%s "$backup_file")
  local dest_space
  dest_space=$(df --output=avail "$(dirname "$pnpm_store_dir")" | tail -n1)
  dest_space=$((dest_space * 1024)) # Convert KB to bytes

  # Require 1.5x the backup size for safe extraction
  local required_space=$((backup_size + (backup_size / 2)))

  if [ "$dest_space" -lt "$required_space" ]; then
    echo "Error: Insufficient disk space in destination. Need at least $((required_space / 1024 / 1024))MB, have $((dest_space / 1024 / 1024))MB"
    return 1
  fi

  echo "Restoring pnpm store from '$backup_file' to '$pnpm_store_dir'"
  # Remove existing store directory if it exists and ensure its parent directory exists
  rm -rf "$pnpm_store_dir"
  mkdir -p "$(dirname "$pnpm_store_dir")"

  # Extract directly to final location
  if ! tar -xJf "$backup_file" -C "$(dirname "$pnpm_store_dir")" --preserve-permissions; then
    echo "Error: Failed to extract backup to final location."
    rm -rf "$pnpm_store_dir"
    return 1
  fi

  echo "pnpm store restored successfully."
}

# Executes pnpm install with production dependencies and offline preference
# Captures and logs build script warnings to a dedicated log file at /var/log/unraid-api/build-scripts.log
# Args: none
# Output: Streams install progress and logs build script warnings
run_pnpm_install() {
  local log_file="/var/log/unraid-api/build-scripts.log"
  stdbuf -oL pnpm install --prod --prefer-offline --reporter=append-only 2>&1 | sed -e "/^╭ Warning/,/^╰/w $log_file" -e "/^╭ Warning/,/^╰/c\Build scripts completed. See $log_file for details."
  echo "Note: This warning is expected. Build scripts are intentionally ignored for security and performance reasons." >> "$log_file"
}

# Installs production dependencies for the unraid-api using pnpm. Prefers offline mode.
# Uses the api_base_directory variable or defaults to /usr/local/unraid-api
# Returns:
#   0 on success, 1 on failure
pnpm_install_unraid_api() {
  # Check if pnpm command exists
  if ! command -v pnpm >/dev/null 2>&1; then
    echo "Error: pnpm command not found. Cannot install dependencies."
    return 1
  fi

  # Use the api_base_directory variable if set, otherwise default to /usr/local/unraid-api
  local unraid_api_dir="${api_base_directory:-/usr/local/unraid-api}"
  if [ ! -d "$unraid_api_dir" ]; then
    echo "Error: unraid API directory '$unraid_api_dir' does not exist."
    return 1
  fi

  echo "Executing 'pnpm install' in $unraid_api_dir"
  rm -rf /usr/local/unraid-api/node_modules
  # Run pnpm install in a subshell to prevent changing the current working directory of the script
  (cd "$unraid_api_dir" && run_pnpm_install)
}

case "$1" in
'install')
  install "$2"
  ;;
'reload')
  restart
  ;;
'uninstall')
  uninstall
  ;;
'pnpm-install')
  pnpm_install_unraid_api
  ;;
'backup-dependencies')
  backup_pnpm_store "$2"
  ;;
'restore-dependencies')
  restore_pnpm_store "$2"
  ;;
*)
  # Pass all other commands to unraid-api
  "${unraid_binary_path}" "$@"
  ;;
esac
