ron.psm1

# --------------------------------------------
# Run on Node (ron)
# v1.0.0
# Author: Aaron Carneiro <@euaaron>
# Email: ron@aaroncarneiro.com
# GitHub: https://github.com/euaaron
# This File: https://gist.github.com/euaaron/8b0a2497244b3711e65ad798bdc5873f
# --------------------------------------------
$ronVersion = "v1.0.4"
$silentInit = $true

# Configuration
$configFileName = ".ronrc"
$ronrc = "$PSScriptRoot\$configFileName"

# ============ UTILITY FUNCTIONS ============

# Logging function - centralized console output
function Write-Log {
  param(
    [string] $Message = "",
    [string] $ForegroundColor = "White",
    [switch] $IsError
  )
  if ($IsError) {
    Write-Host $Message -ForegroundColor Red
  } else {
    Write-Host $Message -ForegroundColor $ForegroundColor
  }
}

# Load configuration from JSON file
function Get-Config {
  if (Test-Path $ronrc) {
    $config = Get-Content $ronrc | ConvertFrom-Json
    # Add default properties if missing
    if (-Not $config.PSObject.Properties['autoUpdate']) {
      $config | Add-Member -NotePropertyName autoUpdate -NotePropertyValue $true -Force
    }
    if (-Not $config.PSObject.Properties['lastUpdateCheck']) {
      $config | Add-Member -NotePropertyName lastUpdateCheck -NotePropertyValue "" -Force
    }
    return $config
  }
  
  # Return default config if file doesn't exist
  return @{
    nodeDirectory = $HOME + "\.ron\node\"
    defaultVersion = "24"
    architecture = "win-x64"
    autoUpdate = $true
    lastUpdateCheck = ""
  }
}

# Save configuration to JSON file
function Set-Config {
  param(
    [PSCustomObject] $Config
  )
  
  try {
    $Config | ConvertTo-Json | Set-Content -Path $ronrc -Force
    Write-Log "Configuration saved to $ronrc" -ForegroundColor Green
  }
  catch {
    Write-Log "Error saving configuration: $_" -IsError
  }
}

# Initialize configuration file with defaults if missing
function Initialize-Config {
  param(
    [bool] $Force = $false
  )
  
  if ($Force -and (Test-Path $ronrc)) {
    Write-Log "Force flag detected. Removing existing configuration..." -ForegroundColor Yellow
    Remove-Item $ronrc -Force
    Write-Log "Existing configuration removed." -ForegroundColor Green
  }
  
  if (-Not (Test-Path $ronrc)) {
    Write-Log "Initializing ron configuration..." -ForegroundColor Cyan
    
    # Determine system architecture
    $systemArch = (Get-CimInstance Win32_OperatingSystem).OSArchitecture
    $architecture = switch -Regex ($systemArch) {
      "64.*bit|x64|AMD64" { "win-x64" }
      "32.*bit|x86" { "win-x86" }
      "ARM.*64|aarch64" { "win-arm64" }
      default { "win-x64" }
    }
    Write-Log "Detected architecture: $architecture" -ForegroundColor Green
    
    # Fetch LTS version from nodejs.org
    Write-Log "Fetching current Node.js LTS version..." -ForegroundColor Cyan
    try {
      $indexJson = Invoke-RestMethod -Uri "https://nodejs.org/dist/index.json" -UseBasicParsing
      $ltsVersion = ($indexJson | Where-Object { $_.lts -ne $false } | Select-Object -First 1).version
      $defaultVersion = $ltsVersion -replace "v(\d+)\..*", '$1'
      Write-Log "Current LTS version: v$defaultVersion" -ForegroundColor Green
    }
    catch {
      Write-Log "Warning: Unable to fetch LTS version from nodejs.org. Using fallback version 24" -ForegroundColor Yellow
      $defaultVersion = "24"
    }
    
    # Prompt user for node directory
    $defaultPath = "$HOME\.ron"
    Write-Log ""
    Write-Log "Please provide the desired Node.js installation directory." -ForegroundColor Cyan
    Write-Log "Default path: $defaultPath (or ~/.ron)" -ForegroundColor Gray
    Write-Host -NoNewline "Enter path (press Enter for default): "
    $userInput = Read-Host
    
    if ([string]::IsNullOrWhiteSpace($userInput)) {
      $nodeDirectory = $defaultPath + "\node\"
      Write-Log "Using default path: $nodeDirectory" -ForegroundColor Green
    }
    else {
      # Clean up user input and ensure it ends properly
      $userInput = $userInput.Trim().TrimEnd('\\')
      $nodeDirectory = $userInput + "\node\"
      Write-Log "Using custom path: $nodeDirectory" -ForegroundColor Green
    }
    
    $defaultConfig = @{
      nodeDirectory = $nodeDirectory
      defaultVersion = $defaultVersion
      architecture = $architecture
      autoUpdate = $true
      lastUpdateCheck = ""
    }
    Set-Config $defaultConfig
    Write-Log "Configuration file created at $ronrc" -ForegroundColor Green
    Write-Log ""
    Write-Log "This tool checks daily for Node.js LTS updates so you never fall behind." -ForegroundColor Cyan
    Write-Log "If you don't want automatic update checks, run 'ron -autoupdate false'" -ForegroundColor Gray
  }
}

function CreateDir {
  param(
    [string] $Dir = ""
  )

  if (-Not $Dir -Contains "*:\") {
    $tempDir = $Dir;
    $Dir = ([System.Environment]::CurrentDirectory)
    $Dir += "\"
    $Dir += $tempDir;
  }

  if (-Not (Test-Path $Dir)) {
    $dirPath = $Dir.Split("\");
    $currentPath = ""
    $count = 0;
    $dirPath | ForEach-Object {
      if (-Not ($dirPath[$count] -Eq "") -Or -Not ($dirPath[$count] -Eq "\")) {
        $currentPath += $dirPath[$count]
        $currentPath += "\"
        $currentPath = $currentPath.Replace("\\", "\");
        if (-Not (Test-Path $currentPath) -And -Not ($currentPath -Eq "")) {
          mkdir $currentPath | Out-Null
        }
      }
      if (-Not ($dirPath.Length - 1 -Eq $count)) {
        $count += 1;
      } else {
          Write-Log "Directory '$currentPath' has been created successfully!"
        return;
      }
    }
  } else {
    Write-Log "Error! '$dir' already exists!" -IsError
  }
}

Function Test-CommandExists {
  Param (
    [string] $Command, 
    [switch] $Silent
  )
  $oldPreference = $ErrorActionPreference
  $ErrorActionPreference = 'stop'
  $exists = $false;

  try {
    if(Get-Command $Command) {
      $exists = $true
      if (-Not $Silent) {
        Write-Log "Command '$Command' exists!"
      }
    }
  }
  Catch {
    $exists = $false
    if (-Not $Silent) {
      Write-Log "Command '$Command' was not found!" -IsError
    }
  }

  $ErrorActionPreference = $oldPreference
  return $exists;
}

# Ensure directory exists, create if needed
function Test-Directory {
  param(
    [string] $Path
  )
  
  if (-Not (Test-Path $Path)) {
    CreateDir -Dir $Path
  }
}

# Get LTS version information from nodejs.org
function Get-LtsVersions {
  try {
    $indexJson = Invoke-RestMethod -Uri "https://nodejs.org/dist/index.json" -UseBasicParsing
    $ltsVersions = $indexJson | Where-Object { $_.lts -ne $false }
    $latestLts = $ltsVersions | Select-Object -First 1
    $latestLtsShort = $latestLts.version -replace "v(\d+)\..*", '$1'
    
    $allLtsVersionsShort = $ltsVersions | ForEach-Object { 
      $_.version -replace "v(\d+)\..*", '$1' 
    } | Select-Object -Unique
    
    return @{
      latestLtsFull = $latestLts.version
      latestLtsShort = $latestLtsShort
      allLtsVersions = $allLtsVersionsShort
    }
  }
  catch {
    return $null
  }
}

# Check for LTS updates and prompt user
function Check-LtsUpdate {
  param(
    [PSCustomObject] $Config
  )
  
  if (-Not $Config.autoUpdate) {
    return
  }
  
  $today = Get-Date -Format "yyyy-MM-dd"
  
  # Check if we already checked today
  if ($Config.lastUpdateCheck -eq $today) {
    return
  }
  
  Write-Log "Checking for Node.js LTS updates..." -ForegroundColor Cyan
  $ltsInfo = Get-LtsVersions
  
  if (-Not $ltsInfo) {
    Write-Log "Could not check for updates." -ForegroundColor Yellow
    return
  }
  
  $Config.lastUpdateCheck = $today
  Set-Config $Config
  
  if ($ltsInfo.latestLtsShort -ne $Config.defaultVersion) {
    Write-Log ""
    Write-Host "Node.js " -NoNewline
    Write-Host $ltsInfo.latestLtsFull -NoNewline -ForegroundColor Green
    Write-Host " is the new latest LTS version! Do you want to upgrade? [y/N]: " -NoNewline
    $response = Read-Host
    
    if ($response -eq 'y' -or $response -eq 'Y') {
      $Config.defaultVersion = $ltsInfo.latestLtsShort
      Set-Config $Config
      Write-Log "Default version updated to $($ltsInfo.latestLtsShort)" -ForegroundColor Green
    } else {
      Write-Log "Alright, I'll let you know again tomorrow." -ForegroundColor Cyan
      Write-Log "If you don't want me to bother you again, set 'ron -autoupdate false'" -ForegroundColor Gray
    }
    Write-Log ""
  }
}

# Calculate Levenshtein distance between two strings for fuzzy matching
function Get-StringDistance {
  param(
    [string] $String1,
    [string] $String2
  )
  
  $len1 = $String1.Length
  $len2 = $String2.Length
  $matrix = New-Object 'int[,]' ($len1 + 1), ($len2 + 1)
  
  for ($i = 0; $i -le $len1; $i++) { $matrix[$i, 0] = $i }
  for ($j = 0; $j -le $len2; $j++) { $matrix[0, $j] = $j }
  
  for ($i = 1; $i -le $len1; $i++) {
    for ($j = 1; $j -le $len2; $j++) {
      $cost = if ($String1[$i - 1] -eq $String2[$j - 1]) { 0 } else { 1 }
      $matrix[$i, $j] = [Math]::Min(
        [Math]::Min($matrix[$i - 1, $j] + 1, $matrix[$i, $j - 1] + 1),
        $matrix[$i - 1, $j - 1] + $cost
      )
    }
  }
  
  return $matrix[$len1, $len2]
}

# Find the closest matching command
function Find-ClosestCommand {
  param(
    [string] $Input
  )
  
  $validCommands = @(
    @{name="init"; aliases=@("i")},
    @{name="version"; aliases=@("v")},
    @{name="list"; aliases=@("l")},
    @{name="change"; aliases=@("c")},
    @{name="dir"; aliases=@()},
    @{name="default"; aliases=@("d")},
    @{name="help"; aliases=@("h")},
    @{name="remote"; aliases=@("r")},
    @{name="arch"; aliases=@("a")},
    @{name="force"; aliases=@("F")}
  )
  
  $cleanInput = $Input.ToLower().TrimStart('-')
  $bestMatch = $null
  $bestDistance = [int]::MaxValue
  
  foreach ($cmd in $validCommands) {
    $distance = Get-StringDistance -String1 $cleanInput -String2 $cmd.name
    if ($distance -lt $bestDistance -and $distance -le 3) {
      $bestDistance = $distance
      $bestMatch = $cmd.name
    }
    
    foreach ($alias in $cmd.aliases) {
      $distance = Get-StringDistance -String1 $cleanInput -String2 $alias
      if ($distance -lt $bestDistance -and $distance -le 2) {
        $bestDistance = $distance
        $bestMatch = $cmd.name
      }
    }
  }
  
  return $bestMatch
}

# Add or update PATH entry for Node directory
function Set-NodePathEntry {
  param(
    [string] $NodeDirectory
  )
  
  if ($env:Path -notlike "*$NodeDirectory*") {
    $env:Path = "$NodeDirectory;" + $env:Path
  } else {
    # Remove old entry and add new one at the beginning
    $env:Path = ($env:Path -split ';' | Where-Object { $_ -notlike "*node*" }) -join ';'
    $env:Path = "$NodeDirectory;" + $env:Path
  }
}

# ============ MAIN RON FUNCTION ============

function ron {
  [CmdletBinding()]
  param(
    [Alias('c')]
    [string] $Change = "",    
    [Alias('i')]
    [switch] $Init,
    [Alias('v')]
    [switch] $Version,
    [Alias('f')]
    [switch] $Force,
    [Alias('l')]
    [switch] $List,
    [Alias('r')]
    [switch] $Remote,
    [Alias('h')]
    [switch] $Help,
    [Alias('a')]
    [string] $Arch = "",
    [switch] $Dir,
    [Alias('d')]
    [switch] $Default,
    [switch] $AutoUpdate
  )

  # Load configuration
  $config = Get-Config

  # Handle special case: if -Dir or -AutoUpdate is present, $Change contains their value
  $dirArg = $null
  $autoUpdateArg = $null
  
  if ($Dir.IsPresent -and -Not [string]::IsNullOrWhiteSpace($Change)) {
    $dirArg = $Change
    $Change = ""
  }
  
  if ($AutoUpdate.IsPresent -and -Not [string]::IsNullOrWhiteSpace($Change)) {
    $autoUpdateArg = $Change
    $Change = ""
  }

  # Validate that $Change is not a command name (user forgot the dash)
  $commandNames = @("init", "version", "list", "change", "dir", "default", "help", "remote", "arch", "force")
  if (-Not [string]::IsNullOrEmpty($Change) -and $commandNames -contains $Change.ToLower()) {
    Write-Log "Invalid command: '$Change'. Did you mean '-$Change'?" -IsError
    return
  }

  # Validate architecture parameter
  $validArchitectures = @("win-x64", "win-x86", "win-arm64")
  if (-Not [string]::IsNullOrEmpty($Arch)) {
    if ($validArchitectures -notcontains $Arch) {
      # Check if it looks like a version number (likely user error)
      if ($Arch -match '^\d+$') {
        Write-Log "Invalid command usage. Did you mean 'ron -change $Arch'?" -IsError
        return
      }
      Write-Log "Invalid architecture: '$Arch'. Valid options are: $($validArchitectures -join ', ')" -IsError
      return
    }
    $config.architecture = $Arch
    Set-Config $config
  }

  $nodeDir = $config.nodeDirectory
  $defaultVersion = $config.defaultVersion
  $arch = if ([string]::IsNullOrEmpty($Arch)) { $config.architecture } else { $Arch }

  # -------- INNER FUNCTIONS --------
  
  function nInit {
    Test-Directory -Path $nodeDir

    $defaultNodeDir = Join-Path $nodeDir $defaultVersion
    
    if (-Not (Test-Path $defaultNodeDir)) {
      Write-Log "Default Node version $defaultVersion not found. Installing..." -ForegroundColor Yellow
      try {
        nChange -Version $defaultVersion -Arch $arch -Force $false
      }
      catch {
        Write-Log "Error installing Node version $defaultVersion : $_" -IsError
      }
    }

    if ((Test-Path $defaultNodeDir) -And (Test-Path "$defaultNodeDir\node.exe")) {
      Set-NodePathEntry -NodeDirectory $defaultNodeDir
    }
  }

  function nChange {
    param (
      [string] $Version = '',
      [string] $Arch = "win-x64",
      [bool] $Force = $false
    )
    
    if ($Version -eq '') {
      Write-Log "Please specify a version. Example: ron -change 18" -IsError
      return
    }

    $versionDir = Join-Path $nodeDir $Version
    
    if ((Test-Path $versionDir) -And -Not $Force) {
      Write-Log "Changed to Node.js $Version"
      Set-NodePathEntry -NodeDirectory $versionDir
      return
    }

    # Download and install
    try {
      $remoteNodeVersions = (Invoke-WebRequest -Uri "https://nodejs.org/dist/" -UseBasicParsing).Links.Href

      $versionExists = $remoteNodeVersions | Where-Object { $_ -like "latest-v$Version.x/*" }
      
      if (-Not $versionExists) {
        throw "Version $Version is invalid! Run 'ron -list -remote' to see available versions."
      }

      # Clean up old installation if force is true
      if (Test-Path $versionDir) {
        Remove-Item -Path $versionDir -Recurse -Force | Out-Null
      }

      $tempDir = Join-Path $nodeDir "temp"
      if (Test-Path $tempDir) {
        Remove-Item -Path $tempDir -Recurse -Force | Out-Null
      }

      New-Item -ItemType Directory -Path $tempDir | Out-Null
      
      # Get download URL
      $downloadUrl = "https://nodejs.org/dist/latest-v$Version.x/"
      $response = Invoke-WebRequest -Uri $downloadUrl -UseBasicParsing
      $fullPath = ($response.Links.Href | Where-Object { $_ -like "*node-v$Version.*-$Arch.zip" } | Select-Object -First 1)
      
      if ([string]::IsNullOrEmpty($fullPath)) {
        throw "No matching Node.js file found for version $Version and architecture $Arch"
      }

      # Extract just the filename from the full path
      $fileName = Split-Path -Leaf $fullPath
      $downloadUrl = $downloadUrl + $fileName
      Write-Log "Downloading Node.js $Version from $downloadUrl" -ForegroundColor Cyan
      
      Invoke-WebRequest -Uri $downloadUrl -OutFile "$tempDir\$Version.zip" -UseBasicParsing
      Write-Log "Downloaded successfully" -ForegroundColor Green
      
      Start-Sleep -Milliseconds 500

      Write-Log "Extracting to $versionDir" -ForegroundColor Cyan
      Expand-Archive -Path "$tempDir\$Version.zip" -DestinationPath $versionDir -Force
      
      # Move extracted files up one directory
      Get-ChildItem -Path "$versionDir\node-v*" -Directory | ForEach-Object {
        Get-ChildItem -Path $_.FullName | Move-Item -Destination $versionDir -Force
      }
      Remove-Item -Path "$versionDir\node-v*" -Recurse -Force -ErrorAction SilentlyContinue

      Remove-Item -Path $tempDir -Recurse -Force | Out-Null
      Write-Log "Installation complete" -ForegroundColor Green

      # Update PATH
      Set-NodePathEntry -NodeDirectory $versionDir
      
      if (Test-CommandExists -Command node -Silent) {
        node -v
      } else {
        Write-Log "Node installed but not yet accessible. Please restart your terminal." -ForegroundColor Yellow
      }
    }
    catch {
      Write-Log "Error during installation: $_" -IsError
    }
  }

  function nList {
    param ([switch] $Remote)
    
    if ($Remote.IsPresent) {
      Write-Log "Fetching available Node.js versions..." -ForegroundColor Cyan
      (Invoke-WebRequest -Uri "https://nodejs.org/dist/" -UseBasicParsing).Links.Href | 
        Where-Object { $_ -like "latest-v*" -and $_ -notlike "latest-v0*" } | 
        ForEach-Object {
          $_.Replace('latest-', '').Replace('.x/', '')
        }
      Write-Log "These are current available Node.js versions (latest)" -ForegroundColor Green
    } else {
      if (Test-Path $nodeDir) {
        Write-Log "Installed Node.js versions:" -ForegroundColor Green
        Get-ChildItem -Path $nodeDir -Directory | Where-Object { $_.Name -notlike "temp" } | ForEach-Object { Write-Host $_.Name }
      } else {
        Write-Log "Node directory does not exist: $nodeDir" -IsError
      }
    }
  }

  function Show-NodeVersion {
    Write-Host "ron " -ForegroundColor Cyan -NoNewline
    Write-Log $ronVersion
    Write-Log "-----------------------------------------------"
    
    # Get the current node version in use
    $nodeInUse = "Not installed"
    $nodeInUseVersion = $null
    if (Test-CommandExists -Command node -Silent) {
      $nodeInUseVersion = node -v
      $nodeInUse = $nodeInUseVersion
    } else {
      Write-Log "Node.js is not installed! Run 'ron -help' for installation options." -ForegroundColor Yellow
    }
    
    # Show default and in-use versions with color coding
    if ($config) {
      $defaultVersion = $config.defaultVersion
      $defaultNodeDir = Join-Path $nodeDir $defaultVersion
      
      # Try to get the actual version number for the default version
      $defaultFullVersion = "v$defaultVersion.x.x"
      if (Test-Path "$defaultNodeDir\node.exe") {
        try {
          $defaultFullVersion = & "$defaultNodeDir\node.exe" -v
        } catch {
          $defaultFullVersion = "v$defaultVersion.x.x"
        }
      }
      
      # Get LTS version info for color coding
      $ltsInfo = Get-LtsVersions
      
      Write-Host "Node.js (Default) " -NoNewline
      
      # Color code default version
      if ($ltsInfo) {
        if ($defaultVersion -eq $ltsInfo.latestLtsShort) {
          # Latest LTS - Green
          Write-Host $defaultFullVersion -NoNewline -ForegroundColor Green
        } elseif ($ltsInfo.allLtsVersions -contains $defaultVersion) {
          # Is LTS but not latest - Cyan
          Write-Host $defaultFullVersion -NoNewline -ForegroundColor Cyan
        } else {
          # Not an LTS - Red
          Write-Host $defaultFullVersion -NoNewline -ForegroundColor Red
        }
      } else {
        Write-Host $defaultFullVersion -NoNewline -ForegroundColor Cyan
      }
      
      Write-Host " | (In Use) " -NoNewline
      
      # Color code in-use version
      if ($nodeInUseVersion) {
        # Extract major version numbers for comparison
        $inUseMajor = [int]($nodeInUseVersion -replace 'v(\d+)\..*', '$1')
        $defaultMajor = [int]$defaultVersion
        
        if ($inUseMajor -lt $defaultMajor) {
          Write-Host $nodeInUseVersion -ForegroundColor Red
        } else {
          Write-Host $nodeInUseVersion -ForegroundColor Green
        }
      } else {
        Write-Host $nodeInUse -ForegroundColor Yellow
      }
    }
  }

  function Show-Help {
    Write-Log "Run on Node - Help" -ForegroundColor Cyan
    Write-Log ""
    Write-Host "-init" -NoNewline -ForegroundColor White
    Write-Host " (-i)" -NoNewline -ForegroundColor DarkGray
    Write-Host " | Initialize ron with config file and install default version."
    Write-Host " -force" -NoNewline -ForegroundColor Yellow
    Write-Host " (-f)" -NoNewline -ForegroundColor DarkGray
    Write-Host " | (with -init) Force recreate configuration file."
    
    Write-Host "-version" -NoNewline -ForegroundColor White
    Write-Host " (-v)" -NoNewline -ForegroundColor DarkGray
    Write-Host " | Display current ron and node versions."
    
    Write-Host "-list" -NoNewline -ForegroundColor White
    Write-Host " (-l)" -NoNewline -ForegroundColor DarkGray
    Write-Host " | List all installed Node.js versions."
    
    Write-Host " -remote" -NoNewline -ForegroundColor White
    Write-Host " (-r)" -NoNewline -ForegroundColor DarkGray
    Write-Host " | List all available Node.js versions for installation."
    
    Write-Host "-change" -NoNewline -ForegroundColor White
    Write-Host " (-c)" -NoNewline -ForegroundColor DarkGray
    Write-Host " <version> | Switch to a Node.js version (auto-installs if needed)."
    Write-Log " Ex: ron -change 22 (installs latest v22.x.x)" -ForegroundColor Cyan
    
    Write-Host " -default" -NoNewline -ForegroundColor Yellow
    Write-Host " (-d)" -NoNewline -ForegroundColor DarkGray
    Write-Host " | (with version) Also set as default version in .ronrc."
    Write-Log " Ex: ron 22 -default or ron -change 22 -default" -ForegroundColor Cyan
    
    Write-Host "-autoupdate [val]" -NoNewline -ForegroundColor White
    Write-Host " | Show or set auto-update (true/false). Checks daily for LTS updates."
    
    Write-Host "-help" -NoNewline -ForegroundColor White
    Write-Host " (-h)" -NoNewline -ForegroundColor DarkGray
    Write-Host " | Display this help page."
  }

  # -------- COMMAND ROUTING --------
  
  if ($Help.IsPresent) {
    Show-Help
  } elseif ($List.IsPresent) {
    nList -Remote:$Remote.IsPresent
  } elseif ($Change -ne "" -and -Not $Dir.IsPresent) {
    nChange -Version $Change -Arch $arch -Force $Force.IsPresent
    if ($Default.IsPresent) {
      $config = Get-Config
      $config.defaultVersion = $Change
      Set-Config $config
      Write-Log "Default Node.js version set to $Change" -ForegroundColor Green
    }
  } elseif ($Dir.IsPresent) {
    if (-Not [string]::IsNullOrWhiteSpace($dirArg)) {
      # Clean up user input and ensure it ends with \node\
      $dirArg = $dirArg.Trim().TrimEnd('\')
      $nodeDirectory = $dirArg + "\node\"
      $config.nodeDirectory = $nodeDirectory
      Set-Config $config
      Write-Log "Node.js installation directory set to $nodeDirectory" -ForegroundColor Green
    } else {
      Write-Log "Node.js installation directory: $($config.nodeDirectory)" -ForegroundColor Green
    }
  } elseif ($AutoUpdate.IsPresent) {
    if (-Not [string]::IsNullOrWhiteSpace($autoUpdateArg)) {
      $boolValue = $autoUpdateArg -eq "true" -or $autoUpdateArg -eq "1" -or $autoUpdateArg -eq "yes" -or $autoUpdateArg -eq "y"
      $config.autoUpdate = $boolValue
      Set-Config $config
      if ($boolValue) {
        Write-Log "Auto-update enabled. Ron will check daily for Node.js LTS updates." -ForegroundColor Green
      } else {
        Write-Log "Auto-update disabled. Ron will not check for updates automatically." -ForegroundColor Yellow
      }
    } else {
      $status = if ($config.autoUpdate) { "enabled" } else { "disabled" }
      Write-Log "Auto-update is currently $status" -ForegroundColor Cyan
    }
  } elseif ($Version.IsPresent) {
    Show-NodeVersion
  } elseif ($Init.IsPresent) {
    try {
      if ($Force.IsPresent) {
        # Force initialization - delete and recreate config
        Initialize-Config -Force $true
        # Reload config after recreation
        $config = Get-Config
        $nodeDir = $config.nodeDirectory
        $defaultVersion = $config.defaultVersion
        $arch = $config.architecture
      }
      nInit
      if (-Not $silentInit) {
        Show-NodeVersion
      }
    }
    catch {
      Write-Log "Error during initialization: $_" -IsError
    }
  } else {
    # Default behavior - check if .ronrc exists
    if (Test-Path $ronrc) {
      # Config exists, show version
      Show-NodeVersion
    } else {
      # Config doesn't exist, initialize
      Write-Log "Configuration not found. Initializing ron..." -ForegroundColor Yellow
      try {
        $silentInit = $false
        nInit
        Show-NodeVersion
      }
      catch {
        Write-Log "Error during initialization: $_" -IsError
      }
    }
  }
}

# ============ INITIALIZATION ============

# Initialize configuration file
Initialize-Config

# Auto-initialize on module import
ron -init

# Check for LTS updates (once per day)
$config = Get-Config
Check-LtsUpdate -Config $config

Export-ModuleMember -Function ron -Variable ronrc