# SellStar GUI Installer
# Professional Windows installer with user choices

$script:GuiAvailable = $true
try {
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing
    [System.Windows.Forms.Application]::EnableVisualStyles()
} catch {
    $script:GuiAvailable = $false
}

function Show-BlockingMessage {
    param(
        [string]$Title,
        [string]$Message
    )
    if ($script:GuiAvailable) {
        [System.Windows.Forms.MessageBox]::Show($Message, $Title, [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null
    } else {
        Write-Host $Message
        Read-Host "Press Enter to exit"
    }
}

function Show-WarningMessage {
    param(
        [string]$Title,
        [string]$Message
    )
    if ($script:GuiAvailable) {
        [System.Windows.Forms.MessageBox]::Show($Message, $Title, [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning) | Out-Null
    } else {
        Write-Host $Message
    }
}

function Test-VCRuntime {
    $RuntimePaths = @(
        "HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64",
        "HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64",
        "HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\ARM64"
    )
    foreach ($Path in $RuntimePaths) {
        if (Test-Path $Path) {
            $Data = Get-ItemProperty -Path $Path -ErrorAction SilentlyContinue
            if ($Data -and $Data.Installed -eq 1) {
                return $true
            }
        }
    }
    return $false
}

function Invoke-PreflightChecks {
    param(
        [string]$AppSourceDir,
        [string]$AppName
    )

    if (-not $script:GuiAvailable) {
        Show-BlockingMessage -Title "$AppName Installer" -Message "GUI components are not available on this system.`n`nUse portable mode: Launch.cmd or run _internal\SellStar\main.exe."
        exit 1
    }

    if ($PSVersionTable.PSVersion.Major -lt 5) {
        Show-BlockingMessage -Title "$AppName Installer" -Message "PowerShell 5.1 or newer is required for the GUI installer.`n`nUse portable mode instead."
        exit 1
    }

    if ($ExecutionContext.SessionState.LanguageMode -ne "FullLanguage") {
        Show-BlockingMessage -Title "$AppName Installer" -Message "PowerShell is restricted by policy (LanguageMode: $($ExecutionContext.SessionState.LanguageMode)).`n`nUse portable mode: Launch.cmd or run _internal\SellStar\main.exe."
        exit 1
    }

    if (-not [Environment]::Is64BitOperatingSystem) {
        Show-BlockingMessage -Title "$AppName Installer" -Message "A 64-bit version of Windows is required."
        exit 1
    }

    $Arch = $env:PROCESSOR_ARCHITECTURE
    if ($Arch -ne "AMD64" -and $Arch -ne "ARM64") {
        Show-BlockingMessage -Title "$AppName Installer" -Message "Unsupported CPU architecture: $Arch"
        exit 1
    }

    $OsVersion = [System.Environment]::OSVersion.Version
    if ($OsVersion.Major -lt 10) {
        Show-BlockingMessage -Title "$AppName Installer" -Message "Windows 10 (22H2) or Windows 11 is required."
        exit 1
    }
    if ($OsVersion.Major -eq 10 -and $OsVersion.Build -lt 19045) {
        Show-BlockingMessage -Title "$AppName Installer" -Message "Windows 10 22H2 (build 19045) or newer is required."
        exit 1
    }

    if ($Arch -eq "ARM64") {
        Show-WarningMessage -Title "$AppName Installer" -Message "Windows on ARM detected. This build is x64 and may run under emulation."
    }

    if (-not (Test-Path "$AppSourceDir\main.exe")) {
        Show-BlockingMessage -Title "$AppName Installer" -Message "Installer files are missing or incomplete.`n`nMake sure all files are extracted."
        exit 1
    }

    if (-not (Test-VCRuntime)) {
        Show-WarningMessage -Title "$AppName Installer" -Message "Microsoft Visual C++ 2015-2022 Redistributable (x64) was not detected.`n`nIf the app fails to start, install it from Microsoft."
    }
}

# ===== INSTALLATION DETECTION FUNCTIONS =====

function Test-SellStarInstallation {
    param([string]$Path)
    if (-not (Test-Path $Path)) { return $false }
    if (-not (Test-Path "$Path\main.exe")) { return $false }
    
    # Additional validation - check for _internal folder (OneDIR structure)
    if (Test-Path "$Path\_internal") {
        # OneDIR structure detected (silent mode)
        return $true
    }
    
    # Fallback - just main.exe existence
    return $true
}

function Get-InstallationVersion {
    param([string]$Path)
    
    try {
        # Try to get version from main.exe
        $VersionInfo = [System.Diagnostics.FileVersionInfo]::GetVersionInfo("$Path\main.exe")
        if ($VersionInfo.FileVersion) {
            return $VersionInfo.FileVersion
        }
        if ($VersionInfo.ProductVersion) {
            return $VersionInfo.ProductVersion
        }
    } catch {
                    # Could not read version from main.exe (silent mode)
    }
    
    return "Unknown"
}

function Find-InstallationFromRegistry {
    # STAGE 1: Scanning Windows Registry (silent mode)
    
    $RegPaths = @(
        "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar",
        "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar"
    )
    
    foreach ($RegPath in $RegPaths) {
        # Checking registry path (silent mode)
        if (Test-Path $RegPath) {
            $RegData = Get-ItemProperty -Path $RegPath -ErrorAction SilentlyContinue
            if ($RegData -and $RegData.InstallLocation) {
                $InstallPath = $RegData.InstallLocation.TrimEnd('\')
                # Registry points to installation path (silent mode)
                
                if (Test-SellStarInstallation -Path $InstallPath) {
                    $Version = if ($RegData.DisplayVersion) { $RegData.DisplayVersion } else { Get-InstallationVersion -Path $InstallPath }
                    # FOUND via Registry (silent mode)
                    return @{ Found = $true; Path = $InstallPath; Version = $Version; Source = "Registry" }
                } else {
                    # Registry entry exists but installation not found (silent mode)
                }
            }
        }
    }
    return @{ Found = $false }
}

function Find-InstallationFromStandardPaths {
    # STAGE 2: Scanning Standard Installation Paths (silent mode)
    
    $StandardPaths = @(
        "$env:PROGRAMFILES\SellStar",
        "${env:PROGRAMFILES(x86)}\SellStar",
        "$env:LOCALAPPDATA\SellStar",
        "$env:APPDATA\SellStar",
        "$env:USERPROFILE\Desktop\SellStar",
        "C:\SellStar"
    )
    
    foreach ($Path in $StandardPaths) {
        # Checking standard path (silent mode)
        if (Test-SellStarInstallation -Path $Path) {
            $Version = Get-InstallationVersion -Path $Path
            # FOUND via Standard Path (silent mode)
            return @{ Found = $true; Path = $Path; Version = $Version; Source = "Standard Path" }
        }
    }
    return @{ Found = $false }
}




function Find-ExistingInstallation {
    # ENHANCED INSTALLATION DETECTION (silent mode)
    # 2-stage detection system for existing SellStar installation
    
    # STAGE 1: Registry (fastest - 0.1s)
    $Result = Find-InstallationFromRegistry
    if ($Result.Found) { return $Result }
    
    # STAGE 2: Standard Paths (fast - 0.5s)  
    $Result = Find-InstallationFromStandardPaths
    if ($Result.Found) { return $Result }
    
    # No existing SellStar installation found (silent mode)
    return @{ Found = $false }
}

# Application info
$AppName = "SellStar"
$AppVersion = "1.1.1"
$AppPublisher = "SellStar"
$AppDescription = "Professional e-commerce automation tools with AI-powered file processing"

# Get script directory - we're in _internal folder
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$AppSourceDir = Join-Path $ScriptDir "SellStar"

# ===== PREFLIGHT CHECKS =====
Invoke-PreflightChecks -AppSourceDir $AppSourceDir -AppName $AppName

# ===== PERFORM INSTALLATION DETECTION =====
# Starting SellStar Enhanced Installer (silent mode)
$ExistingInstall = Find-ExistingInstallation

# Determine mode
if ($ExistingInstall.Found) {
    $IsUpdateMode = $true
    $FormTitle = "$AppName $AppVersion - Update"
    $MainTitle = "Update $AppName from $($ExistingInstall.Version) to $AppVersion"
    # UPDATE MODE: Found existing installation (silent)
} else {
    $IsUpdateMode = $false
    $FormTitle = "$AppName $AppVersion - Installation"
    $MainTitle = "Welcome to $AppName $AppVersion Setup"
    # INSTALL MODE: No existing installation found (silent)
}

# Default installation paths
$DefaultProgramFiles = "$env:PROGRAMFILES\SellStar"

# Create main form
$Form = New-Object System.Windows.Forms.Form
$Form.Text = $FormTitle
$Form.Size = New-Object System.Drawing.Size(600, 620)
$Form.StartPosition = "CenterScreen"
$Form.FormBorderStyle = "FixedDialog"
$Form.MaximizeBox = $false
$Form.MinimizeBox = $false

# Title label
$TitleLabel = New-Object System.Windows.Forms.Label
$TitleLabel.Location = New-Object System.Drawing.Point(20, 20)
$TitleLabel.Size = New-Object System.Drawing.Size(560, 30)
$TitleLabel.Text = $MainTitle
$TitleLabel.Font = New-Object System.Drawing.Font("Segoe UI", 14, [System.Drawing.FontStyle]::Bold)
$TitleLabel.ForeColor = [System.Drawing.Color]::Black
$Form.Controls.Add($TitleLabel)

# Description label
$DescLabel = New-Object System.Windows.Forms.Label
$DescLabel.Location = New-Object System.Drawing.Point(20, 60)
$DescLabel.Size = New-Object System.Drawing.Size(560, 40)
$DescLabel.Text = $AppDescription
$DescLabel.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$Form.Controls.Add($DescLabel)

$NextYPos = 120

# Current installation info (UPDATE MODE ONLY)
if ($IsUpdateMode) {
    $CurrentInstallFrame = New-Object System.Windows.Forms.GroupBox
    $CurrentInstallFrame.Location = New-Object System.Drawing.Point(20, $NextYPos)
    $CurrentInstallFrame.Size = New-Object System.Drawing.Size(560, 70)
    $CurrentInstallFrame.Text = "Current Installation"
    $CurrentInstallFrame.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
    $CurrentInstallFrame.ForeColor = [System.Drawing.Color]::Black
    $Form.Controls.Add($CurrentInstallFrame)
    
    $CurrentInstallLabel = New-Object System.Windows.Forms.Label
    $CurrentInstallLabel.Location = New-Object System.Drawing.Point(15, 25)
    $CurrentInstallLabel.Size = New-Object System.Drawing.Size(540, 35)
    $CurrentInstallLabel.Text = "Location: $($ExistingInstall.Path)`nVersion: $($ExistingInstall.Version) (detected via $($ExistingInstall.Source))"
    $CurrentInstallLabel.Font = New-Object System.Drawing.Font("Consolas", 8)
    $CurrentInstallFrame.Controls.Add($CurrentInstallLabel)
    
    $NextYPos += 90
}

# Installation path group (INSTALL MODE ONLY)
if (-not $IsUpdateMode) {
    $PathGroupBox = New-Object System.Windows.Forms.GroupBox
    $PathGroupBox.Location = New-Object System.Drawing.Point(20, $NextYPos)
    $PathGroupBox.Size = New-Object System.Drawing.Size(560, 95)
    $PathGroupBox.Text = "Installation Location"
    $PathGroupBox.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
    $PathGroupBox.ForeColor = [System.Drawing.Color]::Black
    $Form.Controls.Add($PathGroupBox)

    # Program Files radio (default for admin installer)
    $ProgramFilesRadio = New-Object System.Windows.Forms.RadioButton
    $ProgramFilesRadio.Location = New-Object System.Drawing.Point(20, 25)
    $ProgramFilesRadio.Size = New-Object System.Drawing.Size(520, 20)
    $ProgramFilesRadio.Text = "Program Files (system-wide installation) - $DefaultProgramFiles"
    $ProgramFilesRadio.Checked = $true
    $PathGroupBox.Controls.Add($ProgramFilesRadio)

    # Custom path radio
    $CustomRadio = New-Object System.Windows.Forms.RadioButton
    $CustomRadio.Location = New-Object System.Drawing.Point(20, 50)
    $CustomRadio.Size = New-Object System.Drawing.Size(100, 20)
    $CustomRadio.Text = "Custom:"
    $PathGroupBox.Controls.Add($CustomRadio)

    # Custom path textbox
    $CustomPathBox = New-Object System.Windows.Forms.TextBox
    $CustomPathBox.Location = New-Object System.Drawing.Point(130, 48)
    $CustomPathBox.Size = New-Object System.Drawing.Size(320, 20)
    $CustomPathBox.Text = "C:\SellStar"
    $CustomPathBox.Enabled = $false
    $PathGroupBox.Controls.Add($CustomPathBox)

    # Browse button
    $BrowseButton = New-Object System.Windows.Forms.Button
    $BrowseButton.Location = New-Object System.Drawing.Point(460, 46)
    $BrowseButton.Size = New-Object System.Drawing.Size(80, 25)
    $BrowseButton.Text = "Browse..."
    $BrowseButton.Enabled = $false
    $PathGroupBox.Controls.Add($BrowseButton)
    
    $NextYPos += 115
}

# Options group
$OptionsGroupBox = New-Object System.Windows.Forms.GroupBox
$OptionsGroupBox.Location = New-Object System.Drawing.Point(20, $NextYPos)
$OptionsGroupBox.Size = New-Object System.Drawing.Size(560, 100)
$OptionsGroupBox.Text = $(if ($IsUpdateMode) { "Update Options" } else { "Installation Options" })
$OptionsGroupBox.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$OptionsGroupBox.ForeColor = [System.Drawing.Color]::Black
$Form.Controls.Add($OptionsGroupBox)

if ($IsUpdateMode) {
    # Update-specific options
    # Backup checkbox
    $BackupCheckbox = New-Object System.Windows.Forms.CheckBox
    $BackupCheckbox.Location = New-Object System.Drawing.Point(20, 25)
    $BackupCheckbox.Size = New-Object System.Drawing.Size(260, 20)
    $BackupCheckbox.Text = "Backup current version (recommended)"
    $BackupCheckbox.Checked = $true
    $OptionsGroupBox.Controls.Add($BackupCheckbox)
    
    # Auto close app checkbox
    $AutoCloseCheckbox = New-Object System.Windows.Forms.CheckBox
    $AutoCloseCheckbox.Location = New-Object System.Drawing.Point(300, 25)
    $AutoCloseCheckbox.Size = New-Object System.Drawing.Size(250, 20)
    $AutoCloseCheckbox.Text = "Automatically close application"
    $AutoCloseCheckbox.Checked = $true
    $OptionsGroupBox.Controls.Add($AutoCloseCheckbox)
    
    # Preserve settings checkbox
    $PreserveSettingsCheckbox = New-Object System.Windows.Forms.CheckBox
    $PreserveSettingsCheckbox.Location = New-Object System.Drawing.Point(20, 55)
    $PreserveSettingsCheckbox.Size = New-Object System.Drawing.Size(260, 20)
    $PreserveSettingsCheckbox.Text = "Preserve user settings"
    $PreserveSettingsCheckbox.Checked = $true
    $OptionsGroupBox.Controls.Add($PreserveSettingsCheckbox)
    
    # Launch after update
    $AutoStartCheckbox = New-Object System.Windows.Forms.CheckBox
    $AutoStartCheckbox.Location = New-Object System.Drawing.Point(300, 55)
    $AutoStartCheckbox.Size = New-Object System.Drawing.Size(250, 20)
    $AutoStartCheckbox.Text = "Launch after update"
    $AutoStartCheckbox.Checked = $true
    $OptionsGroupBox.Controls.Add($AutoStartCheckbox)
} else {
    # Install-specific options
    # Desktop shortcut checkbox
    $DesktopCheckbox = New-Object System.Windows.Forms.CheckBox
    $DesktopCheckbox.Location = New-Object System.Drawing.Point(20, 30)
    $DesktopCheckbox.Size = New-Object System.Drawing.Size(200, 20)
    $DesktopCheckbox.Text = "Create desktop shortcut"
    $DesktopCheckbox.Checked = $true
    $OptionsGroupBox.Controls.Add($DesktopCheckbox)

    # Start menu checkbox
    $StartMenuCheckbox = New-Object System.Windows.Forms.CheckBox
    $StartMenuCheckbox.Location = New-Object System.Drawing.Point(20, 55)
    $StartMenuCheckbox.Size = New-Object System.Drawing.Size(200, 20)
    $StartMenuCheckbox.Text = "Create Start Menu shortcut"
    $StartMenuCheckbox.Checked = $true
    $OptionsGroupBox.Controls.Add($StartMenuCheckbox)

    # Auto-start checkbox
    $AutoStartCheckbox = New-Object System.Windows.Forms.CheckBox
    $AutoStartCheckbox.Location = New-Object System.Drawing.Point(250, 30)
    $AutoStartCheckbox.Size = New-Object System.Drawing.Size(200, 20)
    $AutoStartCheckbox.Text = "Launch after installation"
    $AutoStartCheckbox.Checked = $true
    $OptionsGroupBox.Controls.Add($AutoStartCheckbox)
}

$NextYPos += 120

# Language Selection group (INSTALL MODE ONLY)
if (-not $IsUpdateMode) {
    $LanguageGroupBox = New-Object System.Windows.Forms.GroupBox
    $LanguageGroupBox.Location = New-Object System.Drawing.Point(20, $NextYPos)
    $LanguageGroupBox.Size = New-Object System.Drawing.Size(560, 80)
    $LanguageGroupBox.Text = "Default Application Language"
    $LanguageGroupBox.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
    $LanguageGroupBox.ForeColor = [System.Drawing.Color]::Black
    $Form.Controls.Add($LanguageGroupBox)

    # Language selection label
    $LanguageLabel = New-Object System.Windows.Forms.Label
    $LanguageLabel.Location = New-Object System.Drawing.Point(20, 25)
    $LanguageLabel.Size = New-Object System.Drawing.Size(150, 20)
    $LanguageLabel.Text = "Choose language:"
    $LanguageLabel.Font = New-Object System.Drawing.Font("Segoe UI", 9)
    $LanguageGroupBox.Controls.Add($LanguageLabel)

    # Language ComboBox
    $LanguageCombo = New-Object System.Windows.Forms.ComboBox
    $LanguageCombo.Location = New-Object System.Drawing.Point(180, 23)
    $LanguageCombo.Size = New-Object System.Drawing.Size(350, 25)
    $LanguageCombo.DropDownStyle = "DropDownList"
    $LanguageCombo.Font = New-Object System.Drawing.Font("Segoe UI", 9)

    # Define available languages with display names (English only)
    $Languages = @(
        @{Code="en"; Name="English"},
        @{Code="pl"; Name="Polish"},
        @{Code="de"; Name="German"},
        @{Code="fr"; Name="French"},
        @{Code="es"; Name="Spanish"},
        @{Code="it"; Name="Italian"},
        @{Code="uk"; Name="Ukrainian"}
    )

    # Add languages to combo box
    foreach ($Lang in $Languages) {
        $LanguageCombo.Items.Add("$($Lang.Name)") | Out-Null
    }

    # Set default to Polish (index 1)
    $LanguageCombo.SelectedIndex = 1

    $LanguageGroupBox.Controls.Add($LanguageCombo)

    # Language info label
    $LanguageInfoLabel = New-Object System.Windows.Forms.Label
    $LanguageInfoLabel.Location = New-Object System.Drawing.Point(20, 50)
    $LanguageInfoLabel.Size = New-Object System.Drawing.Size(520, 20)
    $LanguageInfoLabel.Text = "This will set the default language for the application. You can change it later in Settings."
    $LanguageInfoLabel.Font = New-Object System.Drawing.Font("Segoe UI", 8)
    $LanguageInfoLabel.ForeColor = [System.Drawing.Color]::Gray
    $LanguageGroupBox.Controls.Add($LanguageInfoLabel)
    
    $NextYPos += 100
}

# Progress bar (hidden initially)
$ProgressBar = New-Object System.Windows.Forms.ProgressBar
$ProgressBar.Location = New-Object System.Drawing.Point(20, $NextYPos)
$ProgressBar.Size = New-Object System.Drawing.Size(560, 20)
$ProgressBar.Visible = $false
$Form.Controls.Add($ProgressBar)

# Status label
$StatusLabel = New-Object System.Windows.Forms.Label
$StatusLabel.Location = New-Object System.Drawing.Point(20, $($NextYPos + 30))
$StatusLabel.Size = New-Object System.Drawing.Size(400, 20)
$StatusLabel.Text = $(if ($IsUpdateMode) { "Ready to update" } else { "Ready to install" })
$StatusLabel.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$Form.Controls.Add($StatusLabel)

# Install/Update button
$InstallButton = New-Object System.Windows.Forms.Button
$InstallButton.Location = New-Object System.Drawing.Point(420, $($NextYPos + 30))
$InstallButton.Size = New-Object System.Drawing.Size(80, 30)
$InstallButton.Text = $(if ($IsUpdateMode) { "Update" } else { "Install" })
$InstallButton.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold)
$InstallButton.BackColor = [System.Drawing.Color]::DodgerBlue
$InstallButton.ForeColor = [System.Drawing.Color]::White
$Form.Controls.Add($InstallButton)

# Cancel button
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(510, $($NextYPos + 30))
$CancelButton.Size = New-Object System.Drawing.Size(70, 30)
$CancelButton.Text = "Cancel"
$CancelButton.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$CancelButton.BackColor = [System.Drawing.Color]::LightGray
$Form.Controls.Add($CancelButton)

# Event handlers (only for install mode)
if (-not $IsUpdateMode) {
    $CustomRadio.Add_CheckedChanged({
        $CustomPathBox.Enabled = $CustomRadio.Checked
        $BrowseButton.Enabled = $CustomRadio.Checked
    })

    $BrowseButton.Add_Click({
        $FolderDialog = New-Object System.Windows.Forms.FolderBrowserDialog
        $FolderDialog.Description = "Select installation folder"
        if ($FolderDialog.ShowDialog() -eq "OK") {
            $CustomPathBox.Text = $FolderDialog.SelectedPath + "\SellStar"
        }
    })
}

$CancelButton.Add_Click({
    $Form.Close()
})

# ===== ENHANCED UPDATE FUNCTION WITH ROLLBACK =====
function Perform-Update {
    param([string]$ExistingPath, [string]$ExistingVersion)
    
    $InstallButton.Enabled = $false
    $CancelButton.Enabled = $false
    $ProgressBar.Visible = $true
    $StatusLabel.Text = "Starting update..."
    $ProgressBar.Value = 5
    
    $BackupPath = $null
    $UserSettingsBackup = $null
    $UpdateSuccess = $false
    
    try {
        # Starting Enhanced Update Process (silent mode)
        # From: $ExistingVersion → To: $AppVersion  
        # Path: $ExistingPath
        
        # Close application if running (only if auto-close is enabled)
        if ($AutoCloseCheckbox.Checked) {
            $StatusLabel.Text = "Closing running instances..."
            # Closing running SellStar instances (silent mode)
            $RunningProcesses = Get-Process -Name "main" -ErrorAction SilentlyContinue
            if ($RunningProcesses) {
                $RunningProcesses | Stop-Process -Force -ErrorAction SilentlyContinue
                # Stopped running instances (silent mode)
                Start-Sleep -Seconds 3  # Give more time for graceful shutdown
            } else {
                # No running instances found (silent mode)
            }
        } else {
            # Skipping automatic application closure (user preference)
        }
        $ProgressBar.Value = 10
        
        # Backup user settings BEFORE main backup (only if preserve settings is enabled)
        if ($PreserveSettingsCheckbox.Checked) {
            $StatusLabel.Text = "Backing up user settings..."
            # Backing up user settings (silent mode)
            $SettingsPaths = @(
                "$ExistingPath\config.json",
                "$ExistingPath\settings.json", 
                "$ExistingPath\user_preferences.json",
                "$ExistingPath\auth_token.json"
            )
            
            $UserSettingsBackup = @{}
            foreach ($SettingsFile in $SettingsPaths) {
                if (Test-Path $SettingsFile) {
                    $UserSettingsBackup[$SettingsFile] = Get-Content $SettingsFile -Raw -ErrorAction SilentlyContinue
                    # Backed up settings file (silent mode)
                }
            }
        } else {
            # Skipping user settings backup (user preference)
            $UserSettingsBackup = @{}
        }
        $ProgressBar.Value = 15
        
        # Create full backup if requested
        if ($BackupCheckbox.Checked) {
            $StatusLabel.Text = "Creating full backup..."
            # Creating full installation backup (silent mode)
            $BackupPath = "$ExistingPath.backup_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
            Copy-Item -Path $ExistingPath -Destination $BackupPath -Recurse -Force
            # Full backup created (silent mode)
        }
        $ProgressBar.Value = 35
        
        # Verify source files exist
        $StatusLabel.Text = "Verifying update files..."
        # Verifying update source files (silent mode)
        if (-not (Test-Path "$AppSourceDir\main.exe")) {
            throw "Update source files not found: $AppSourceDir\main.exe"
        }
        if (-not (Test-Path "$AppSourceDir\_internal")) {
            throw "Update source structure invalid: missing _internal folder"
        }
        # Source files verified (silent mode)
        $ProgressBar.Value = 45
        
        # Update files (with verification)
        $StatusLabel.Text = "Updating application files..."
        # Updating application files (silent mode)
        
        # Remove old files (conditionally preserve settings)
        if ($PreserveSettingsCheckbox.Checked) {
            $ItemsToKeep = @("config.json", "settings.json", "user_preferences.json", "auth_token.json", "*.log")
            Get-ChildItem -Path $ExistingPath | Where-Object { 
                $_.Name -notin $ItemsToKeep -and $_.Name -notlike "*.log"
            } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
            # Settings files preserved during update (silent mode)
        } else {
            Get-ChildItem -Path $ExistingPath | Where-Object { 
                $_.Name -notlike "*.log"
            } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
            # All old files removed including settings (silent mode)
        }
        
        # Copy new files
        Copy-Item -Path "$AppSourceDir\*" -Destination $ExistingPath -Recurse -Force
        
        # Remove Python sources from plugins to discourage copy/paste
        $PluginSourcePath = Join-Path $ExistingPath "_internal\plugins"
        if (Test-Path $PluginSourcePath) {
            Get-ChildItem -Path $PluginSourcePath -Recurse -Filter *.py -ErrorAction SilentlyContinue |
                Remove-Item -Force -ErrorAction SilentlyContinue
        }
        # Files updated successfully (silent mode)
        $ProgressBar.Value = 70
        
        # Restore user settings (only if preserve settings is enabled and we have backups)
        if ($PreserveSettingsCheckbox.Checked -and $UserSettingsBackup.Count -gt 0) {
            $StatusLabel.Text = "Restoring user settings..."
            # Restoring user settings (silent mode)
            foreach ($SettingsFile in $UserSettingsBackup.Keys) {
                try {
                    $UserSettingsBackup[$SettingsFile] | Out-File -FilePath $SettingsFile -Encoding UTF8 -ErrorAction SilentlyContinue
                    # Restored settings file (silent mode)
                } catch {
                    # Could not restore settings file (silent mode)
                }
            }
        } else {
            # Skipping user settings restore (user preference or no backups) 
        }
        $ProgressBar.Value = 80
        
        # Verify installation integrity
        $StatusLabel.Text = "Verifying installation..."
        # Verifying updated installation (silent mode)
        if (-not (Test-SellStarInstallation -Path $ExistingPath)) {
            throw "Installation verification failed - main.exe not found or corrupted"
        }
        
        # Use the version we're installing (from build)
        $NewVersion = $AppVersion
        # Installation verified (silent mode)
        $ProgressBar.Value = 85
        
        # Update registry
        $StatusLabel.Text = "Updating registry..."
        # Updating registry (silent mode) - find existing registry entry location first
        $RegPathHKLM = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar"
        $RegPathHKCU = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar"
        
        # Find existing registry entry location
        $RegPath = $null
        if (Test-Path $RegPathHKLM) {
            $RegPath = $RegPathHKLM
            $RegLocation = "HKLM"
        } elseif (Test-Path $RegPathHKCU) {
            $RegPath = $RegPathHKCU
            $RegLocation = "HKCU"
        } else {
            # No registry entry found - create based on install location
            if ($ExistingPath.StartsWith($env:PROGRAMFILES)) {
                $RegPath = $RegPathHKLM
                $RegLocation = "HKLM"
            } else {
                $RegPath = $RegPathHKCU
                $RegLocation = "HKCU"
            }
            # Create new registry entry
            New-Item -Path $RegPath -Force | Out-Null
        }
        
        # Update registry entry with correct information
        Set-ItemProperty -Path $RegPath -Name "DisplayName" -Value "$AppName $AppVersion" -ErrorAction SilentlyContinue
        Set-ItemProperty -Path $RegPath -Name "DisplayVersion" -Value $AppVersion -ErrorAction SilentlyContinue
        Set-ItemProperty -Path $RegPath -Name "Publisher" -Value $AppPublisher -ErrorAction SilentlyContinue
        Set-ItemProperty -Path $RegPath -Name "InstallLocation" -Value $ExistingPath -ErrorAction SilentlyContinue
        Set-ItemProperty -Path $RegPath -Name "UninstallString" -Value "wscript.exe `"$ExistingPath\Uninstall.vbs`"" -ErrorAction SilentlyContinue
        Set-ItemProperty -Path $RegPath -Name "DisplayIcon" -Value "$ExistingPath\main.exe" -ErrorAction SilentlyContinue
        Set-ItemProperty -Path $RegPath -Name "NoModify" -Value 1 -ErrorAction SilentlyContinue
        Set-ItemProperty -Path $RegPath -Name "NoRepair" -Value 1 -ErrorAction SilentlyContinue
        # Registry updated (silent mode)
        
        # Create/Update uninstaller (ensure VBScript uninstaller exists)
        $StatusLabel.Text = "Creating uninstaller..."
        # $RegLocation is already set from registry detection above
        
        $UpdateUninstallScript = @'
' SellStar Silent Uninstaller
' This VBScript removes SellStar without showing console windows

Dim objShell, objFSO, scriptDir, appDir, result
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

' Show confirmation dialog
result = MsgBox("This will remove SellStar from your computer." & vbCrLf & vbCrLf & _
                "Are you sure you want to uninstall SellStar?", _
                vbYesNo + vbQuestion + vbDefaultButton2, "SellStar - Uninstall")

If result = vbYes Then
    ' Get directories
    scriptDir = objFSO.GetParentFolderName(WScript.ScriptFullName)
    appDir = scriptDir
    
    ' Remove shortcuts silently
    On Error Resume Next
    objFSO.DeleteFile objShell.SpecialFolders("Desktop") & "\SellStar.lnk", True
    objFSO.DeleteFile objShell.SpecialFolders("StartMenu") & "\Programs\SellStar.lnk", True
    On Error GoTo 0
    
    ' Remove registry entry
    On Error Resume Next
    If "REG_LOCATION_PLACEHOLDER" = "HKLM" Then
        objShell.RegDelete "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar\"
    Else
        objShell.RegDelete "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar\"
    End If
    On Error GoTo 0
    
    ' Remove application directory (delayed deletion for safety)
    ' Create batch file for delayed deletion
    Dim tempBat, tempPath
    tempPath = objShell.ExpandEnvironmentStrings("%TEMP%") & "\SellStarUninstall_" & Int(Rnd * 10000) & ".bat"
    Set tempBat = objFSO.CreateTextFile(tempPath, True)
    tempBat.WriteLine "@echo off"
    tempBat.WriteLine "timeout /t 2 /nobreak >nul"
    tempBat.WriteLine "rmdir /s /q """ & appDir & """"
    tempBat.WriteLine "del /q """ & tempPath & """"
    tempBat.Close
    
    ' Execute delayed deletion
    objShell.Run """" & tempPath & """", 0, False
    
    ' Show completion message
    MsgBox "SellStar has been successfully uninstalled." & vbCrLf & _
           "Thank you for using SellStar!", _
           vbInformation, "SellStar - Uninstall Complete"
Else
    ' User cancelled
    MsgBox "Uninstall cancelled.", vbInformation, "SellStar"
End If
'@
        
        # Replace placeholders and create uninstaller
        $UpdateUninstallScript = $UpdateUninstallScript.Replace("REG_LOCATION_PLACEHOLDER", $RegLocation)
        $UninstallerPath = "$ExistingPath\Uninstall.vbs"
        $UpdateUninstallScript | Out-File -FilePath $UninstallerPath -Encoding ASCII
        
        # Verify uninstaller was created successfully
        if (-not (Test-Path $UninstallerPath)) {
            throw "Failed to create uninstaller file: $UninstallerPath"
        }
        
        # Double-check UninstallString points to existing file
        $ActualUninstallString = "wscript.exe `"$UninstallerPath`""
        Set-ItemProperty -Path $RegPath -Name "UninstallString" -Value $ActualUninstallString -ErrorAction SilentlyContinue
        $ProgressBar.Value = 95
        
        # Success!
        $UpdateSuccess = $true
        $StatusLabel.Text = "Update completed successfully!"
        $ProgressBar.Value = 100
        
        # UPDATE COMPLETED SUCCESSFULLY! (silent mode)
        # From: $ExistingVersion → To: $NewVersion
        
        $SettingsMessage = if ($PreserveSettingsCheckbox.Checked) { "User settings have been preserved." } else { "User settings were not preserved (as requested)." }
        [System.Windows.Forms.MessageBox]::Show("SellStar has been successfully updated!`n`nFrom: $ExistingVersion`nTo: $NewVersion`n`n$SettingsMessage", "Update Complete", "OK", "Information")
        
        if ($AutoStartCheckbox.Checked) {
            # Launching updated application (silent mode)
            Start-Process -FilePath "$ExistingPath\main.exe"
        }
        
        $Form.Close()
        
    } catch {
        $ErrorMessage = $_.Exception.Message
        # UPDATE FAILED (silent mode)
        
        # ROLLBACK LOGIC
        if (-not $UpdateSuccess) {
            # Attempting rollback (silent mode)
            $StatusLabel.Text = "Update failed - attempting rollback..."
            
            try {
                if ($BackupPath -and (Test-Path $BackupPath)) {
                    # Restoring from full backup (silent mode)
                    
                    # Remove failed update
                    Remove-Item -Path $ExistingPath -Recurse -Force -ErrorAction SilentlyContinue
                    
                    # Restore from backup
                    Copy-Item -Path $BackupPath -Destination $ExistingPath -Recurse -Force
                    
                    # Rollback successful - previous version restored (silent mode)
                    $StatusLabel.Text = "Update failed - previous version restored"
                    [System.Windows.Forms.MessageBox]::Show("Update failed but previous version has been restored successfully.`n`nError: $ErrorMessage`n`nYour installation is back to: $ExistingVersion", "Update Failed - Rollback Successful", "OK", "Warning")
                    
                } elseif ($UserSettingsBackup.Count -gt 0) {
                    # Partial rollback - restore settings only
                    # Restoring user settings from memory backup (silent mode)
                    foreach ($SettingsFile in $UserSettingsBackup.Keys) {
                        try {
                            $UserSettingsBackup[$SettingsFile] | Out-File -FilePath $SettingsFile -Encoding UTF8 -ErrorAction SilentlyContinue
                        } catch {
                            # Ignore individual setting restore failures
                        }
                    }
                    # Partial rollback - settings restored (silent mode)
                    [System.Windows.Forms.MessageBox]::Show("Update failed. User settings have been restored where possible.`n`nError: $ErrorMessage`n`nYou may need to reinstall manually.", "Update Failed - Partial Recovery", "OK", "Error")
                } else {
                    # No backup available for rollback (silent mode)
                    [System.Windows.Forms.MessageBox]::Show("Update failed and no backup is available.`n`nError: $ErrorMessage`n`nPlease reinstall SellStar manually.", "Update Failed - No Backup", "OK", "Error")
                }
                
            } catch {
                # Rollback also failed (silent mode)
                [System.Windows.Forms.MessageBox]::Show("Update failed and rollback was unsuccessful.`n`nOriginal Error: $ErrorMessage`nRollback Error: $($_.Exception.Message)`n`nPlease reinstall SellStar manually.", "Critical Update Failure", "OK", "Error")
            }
        }
        
        $InstallButton.Enabled = $true
        $CancelButton.Enabled = $true
        $ProgressBar.Visible = $false
    }
}

# Installation/Update logic
$InstallButton.Add_Click({
    if ($IsUpdateMode) {
        Perform-Update -ExistingPath $ExistingInstall.Path -ExistingVersion $ExistingInstall.Version
        return
    }
    # Determine installation path
    if ($ProgramFilesRadio.Checked) {
        $InstallPath = $DefaultProgramFiles
    } else {
        $InstallPath = $CustomPathBox.Text
    }
    
    # Validate path
    if ([string]::IsNullOrWhiteSpace($InstallPath)) {
        [System.Windows.Forms.MessageBox]::Show("Please select a valid installation path.", "Error", "OK", "Error")
        return
    }
    
    # Since we're running as admin, proceed with installation
    $InstallButton.Enabled = $false
    $CancelButton.Enabled = $false
    $ProgressBar.Visible = $true
    $StatusLabel.Text = "Installing..."
    $ProgressBar.Value = 10
    
    try {
        # Create installation directory
        $StatusLabel.Text = "Creating installation directory..."
        if (!(Test-Path $InstallPath)) {
            New-Item -ItemType Directory -Path $InstallPath -Force | Out-Null
        }
        $ProgressBar.Value = 30
        
        # Copy application files
        $StatusLabel.Text = "Copying application files..."
        Copy-Item -Path "$AppSourceDir\*" -Destination $InstallPath -Recurse -Force
        
        # Remove Python sources from plugins to discourage copy/paste
        $PluginSourcePath = Join-Path $InstallPath "_internal\plugins"
        if (Test-Path $PluginSourcePath) {
            Get-ChildItem -Path $PluginSourcePath -Recurse -Filter *.py -ErrorAction SilentlyContinue |
                Remove-Item -Force -ErrorAction SilentlyContinue
        }
        $ProgressBar.Value = 60
        
        # Save language preference
        $StatusLabel.Text = "Saving language preference..."
        try {
            # Get selected language code
            $SelectedLanguageIndex = $LanguageCombo.SelectedIndex
            $SelectedLanguageCode = $Languages[$SelectedLanguageIndex].Code
            
            # Create user configuration directory (must match application's expected path)
            $AppDataDir = "$env:APPDATA\SellStar"
            if (!(Test-Path $AppDataDir)) {
                New-Item -ItemType Directory -Path $AppDataDir -Force | Out-Null
            }
            
            # Create basic configuration file with selected language
            $ConfigFile = "$AppDataDir\user_config.json"
            
            # Create JSON in exact format that matches Python json.dump(indent=2)
            $JsonContent = @"
{
  "ui": {
    "default_language": "$SelectedLanguageCode"
  }
}
"@
            
            # Save configuration with UTF-8 encoding (without BOM)
            $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
            [System.IO.File]::WriteAllText($ConfigFile, $JsonContent, $Utf8NoBomEncoding)
            
            # Language preference saved successfully
        } catch {
            # Language preference saving failed - not critical, continue installation
            # Error ignored to prevent installation failure
        }
        $ProgressBar.Value = 65
        
        # Create shortcuts
        if ($DesktopCheckbox.Checked) {
            $StatusLabel.Text = "Creating desktop shortcut..."
            $WshShell = New-Object -ComObject WScript.Shell
            $DesktopPath = [Environment]::GetFolderPath('Desktop')
            $Shortcut = $WshShell.CreateShortcut("$DesktopPath\SellStar.lnk")
            $Shortcut.TargetPath = "$InstallPath\main.exe"
            $Shortcut.WorkingDirectory = $InstallPath
            $Shortcut.Description = $AppDescription
            $Shortcut.IconLocation = "$InstallPath\main.exe,0"
            $Shortcut.Save()
        }
        $ProgressBar.Value = 75
        
        if ($StartMenuCheckbox.Checked) {
            $StatusLabel.Text = "Creating Start Menu shortcut..."
            $StartMenuPath = [Environment]::GetFolderPath('StartMenu')
            $WshShell = New-Object -ComObject WScript.Shell
            $Shortcut = $WshShell.CreateShortcut("$StartMenuPath\Programs\SellStar.lnk")
            $Shortcut.TargetPath = "$InstallPath\main.exe"
            $Shortcut.WorkingDirectory = $InstallPath
            $Shortcut.Description = $AppDescription
            $Shortcut.IconLocation = "$InstallPath\main.exe,0"
            $Shortcut.Save()
        }
        $ProgressBar.Value = 85
        
        # Register in Windows (Add/Remove Programs)
        $StatusLabel.Text = "Registering application..."
        if ($InstallPath.StartsWith($env:PROGRAMFILES)) {
            # System-wide installation - use HKLM
            $RegPath = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar"
        } else {
            # User installation - use HKCU
            $RegPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar"
        }
        New-Item -Path $RegPath -Force | Out-Null
        Set-ItemProperty -Path $RegPath -Name "DisplayName" -Value "$AppName $AppVersion"
        Set-ItemProperty -Path $RegPath -Name "DisplayVersion" -Value $AppVersion
        Set-ItemProperty -Path $RegPath -Name "Publisher" -Value $AppPublisher
        Set-ItemProperty -Path $RegPath -Name "InstallLocation" -Value $InstallPath
        Set-ItemProperty -Path $RegPath -Name "UninstallString" -Value "wscript.exe `"$InstallPath\Uninstall.vbs`""
        Set-ItemProperty -Path $RegPath -Name "DisplayIcon" -Value "$InstallPath\main.exe"
        Set-ItemProperty -Path $RegPath -Name "NoModify" -Value 1
        Set-ItemProperty -Path $RegPath -Name "NoRepair" -Value 1
        
        # Create uninstaller
        if ($InstallPath.StartsWith($env:PROGRAMFILES)) {
            $RegLocation = "HKLM"
        } else {
            $RegLocation = "HKCU"
        }
        
        $UninstallScript = @'
' SellStar Silent Uninstaller
' This VBScript removes SellStar without showing console windows

Dim objShell, objFSO, scriptDir, appDir, result
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

' Show confirmation dialog
result = MsgBox("This will remove SellStar from your computer." & vbCrLf & vbCrLf & _
                "Are you sure you want to uninstall SellStar?", _
                vbYesNo + vbQuestion + vbDefaultButton2, "SellStar - Uninstall")

If result = vbYes Then
    ' Get directories
    scriptDir = objFSO.GetParentFolderName(WScript.ScriptFullName)
    appDir = scriptDir
    
    ' Remove shortcuts silently
    On Error Resume Next
    objFSO.DeleteFile objShell.SpecialFolders("Desktop") & "\SellStar.lnk", True
    objFSO.DeleteFile objShell.SpecialFolders("StartMenu") & "\Programs\SellStar.lnk", True
    On Error GoTo 0
    
    ' Remove registry entry
    On Error Resume Next
    If "REG_LOCATION_PLACEHOLDER" = "HKLM" Then
        objShell.RegDelete "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar\"
    Else
        objShell.RegDelete "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall\SellStar\"
    End If
    On Error GoTo 0
    
    ' Remove application directory (delayed deletion for safety)
    ' Create batch file for delayed deletion
    Dim tempBat, tempPath
    tempPath = objShell.ExpandEnvironmentStrings("%TEMP%") & "\SellStarUninstall_" & Int(Rnd * 10000) & ".bat"
    Set tempBat = objFSO.CreateTextFile(tempPath, True)
    tempBat.WriteLine "@echo off"
    tempBat.WriteLine "timeout /t 2 /nobreak >nul"
    tempBat.WriteLine "rmdir /s /q """ & appDir & """"
    tempBat.WriteLine "del /q """ & tempPath & """"
    tempBat.Close
    
    ' Execute delayed deletion
    objShell.Run """" & tempPath & """", 0, False
    
    ' Show completion message
    MsgBox "SellStar has been successfully uninstalled." & vbCrLf & _
           "Thank you for using SellStar!", _
           vbInformation, "SellStar - Uninstall Complete"
Else
    ' User cancelled
    MsgBox "Uninstall cancelled.", vbInformation, "SellStar"
End If
'@

        # Replace placeholders with actual values
        $UninstallScript = $UninstallScript.Replace("REG_LOCATION_PLACEHOLDER", $RegLocation)
        $UninstallScript | Out-File -FilePath "$InstallPath\Uninstall.vbs" -Encoding ASCII
        $ProgressBar.Value = 95
        
        # Complete
        $StatusLabel.Text = "Installation completed successfully!"
        $ProgressBar.Value = 100
        
        [System.Windows.Forms.MessageBox]::Show("$AppName has been installed successfully!`n`nInstallation path: $InstallPath", "Installation Complete", "OK", "Information")
        
        # Launch application if requested
        if ($AutoStartCheckbox.Checked) {
            Start-Process "$InstallPath\main.exe"
        }
        
        $Form.Close()
        
    } catch {
        [System.Windows.Forms.MessageBox]::Show("Installation failed: $($_.Exception.Message)", "Error", "OK", "Error")
        $InstallButton.Enabled = $true
        $CancelButton.Enabled = $true
        $ProgressBar.Visible = $false
        $StatusLabel.Text = "Installation failed"
    }
})

# Show form
# Launching Enhanced installer GUI (silent mode)
$Form.ShowDialog() | Out-Null
# Enhanced installer completed (silent mode)
