#############################################################
#### ntfy Desktop Client Setup for Windows               ####
#### Subscribe to ntfy push notifications with Windows   ####
#### toast notifications                                 ####
####                                                     ####
#### Author: Phil Connor                                 ####
#### Contact: contact@mylinux.work                       ####
#### License: MIT                                        ####
#### Version: 1.0                                        ####
####                                                     ####
#### Usage: .\ntfy-client-setup-windows.ps1              ####
#############################################################

$ErrorActionPreference = "Stop"

# --- Configuration ---
$NtfyVersion = "2.8.0"
$InstallDir = "$env:LOCALAPPDATA\ntfy"
$ConfigDir = "$env:APPDATA\ntfy"

# --- Interactive Prompts ---
Write-Host ""
Write-Host "=== ntfy Desktop Notifications Setup ===" -ForegroundColor Cyan
Write-Host "Installing for user: $env:USERNAME"
Write-Host ""

# Server URL
$ServerUrl = Read-Host "Enter your ntfy server URL (e.g. https://ntfy.example.com)"
$ServerUrl = $ServerUrl.TrimEnd("/")
if ([string]::IsNullOrWhiteSpace($ServerUrl)) {
    Write-Host "ERROR: Server URL is required." -ForegroundColor Red
    exit 1
}

# Access token (optional - some servers allow anonymous access)
$Token = Read-Host "Enter your access token (leave blank if not required)"

# Topics
$topicInput = Read-Host "Enter topics to subscribe to, comma-separated (e.g. alerts-critical,alerts-all)"
if ([string]::IsNullOrWhiteSpace($topicInput)) {
    Write-Host "ERROR: At least one topic is required." -ForegroundColor Red
    exit 1
}
$Topics = $topicInput -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" }

Write-Host ""
Write-Host "Server:  $ServerUrl" -ForegroundColor White
Write-Host "Topics:  $($Topics -join ', ')" -ForegroundColor White
Write-Host "Token:   $(if ($Token) { '********' } else { '(none)' })" -ForegroundColor White
Write-Host ""

# --- Create directories ---
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null

# --- Download ntfy if not already installed ---
if (Test-Path "$InstallDir\ntfy.exe") {
    Write-Host "ntfy already installed at: $InstallDir\ntfy.exe" -ForegroundColor Green
} else {
    Write-Host "Downloading ntfy v$NtfyVersion..."
    $downloadUrl = "https://github.com/binwiederhier/ntfy/releases/download/v$NtfyVersion/ntfy_${NtfyVersion}_windows_amd64.zip"
    $zipPath = "$env:TEMP\ntfy.zip"
    Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath

    Write-Host "Extracting..."
    $extractPath = "$env:TEMP\ntfy_extract"
    Remove-Item -Path $extractPath -Recurse -Force -ErrorAction SilentlyContinue
    Expand-Archive -Path $zipPath -DestinationPath $extractPath -Force
    Remove-Item $zipPath

    # Find the exe (may be in a subfolder)
    $ntfyExe = Get-ChildItem -Path $extractPath -Recurse -Filter "ntfy.exe" | Select-Object -First 1
    if ($ntfyExe) {
        Copy-Item -Path $ntfyExe.FullName -Destination "$InstallDir\ntfy.exe" -Force
    } else {
        Write-Host "ERROR: Could not find ntfy.exe in downloaded archive." -ForegroundColor Red
        exit 1
    }
    Remove-Item -Path $extractPath -Recurse -Force -ErrorAction SilentlyContinue

    Write-Host "Installed to: $InstallDir\ntfy.exe" -ForegroundColor Green
}
Write-Host ""

# --- Create client.yml config ---
$clientYml = @"
default-host: $ServerUrl
"@

if ($Token) {
    $clientYml += "`ndefault-token: $Token"
}

$clientYmlPath = "$ConfigDir\client.yml"
$clientYml | Out-File -FilePath $clientYmlPath -Encoding UTF8
Write-Host "Client config saved to: $clientYmlPath" -ForegroundColor Green

# --- Build topic URLs ---
$topicUrls = @()
foreach ($topic in $Topics) {
    $topicUrls += "$ServerUrl/$topic"
}
$topicUrlsString = $topicUrls -join " "

# --- Create PowerShell notification script ---
# Build the token environment line only if a token was provided
$tokenLine = ""
if ($Token) {
    $tokenLine = "`$env:NTFY_TOKEN = `"$Token`""
}

$psScriptContent = @"
Add-Type -AssemblyName System.Windows.Forms

# Create a persistent notification icon in the system tray
`$global:notifyIcon = New-Object System.Windows.Forms.NotifyIcon
`$global:notifyIcon.Icon = [System.Drawing.SystemIcons]::Information
`$global:notifyIcon.Visible = `$true
`$global:notifyIcon.Text = "ntfy alerts"

function Show-Notification {
    param([string]`$Title, [string]`$Message, [int]`$Priority)

    # Map ntfy priority levels to Windows balloon icon types
    #   1 (min), 2 (low)   -> None
    #   3 (default)        -> Info
    #   4 (high), 5 (max)  -> Error
    `$icon = [System.Windows.Forms.ToolTipIcon]::Info
    if (`$Priority -ge 4) { `$icon = [System.Windows.Forms.ToolTipIcon]::Error }
    elseif (`$Priority -le 2) { `$icon = [System.Windows.Forms.ToolTipIcon]::None }

    `$global:notifyIcon.BalloonTipIcon = `$icon
    `$global:notifyIcon.BalloonTipTitle = `$Title
    `$global:notifyIcon.BalloonTipText = `$Message
    `$global:notifyIcon.ShowBalloonTip(30000)
}

# Set access token if configured
$tokenLine
`$ntfyExe = "$InstallDir\ntfy.exe"

# Subscribe and process JSON output line by line
& `$ntfyExe subscribe $topicUrlsString 2>&1 | ForEach-Object {
    `$line = `$_
    if (`$line -match '"event":"message"') {
        try {
            `$json = `$line | ConvertFrom-Json
            `$title = if (`$json.title) { `$json.title } else { `$json.topic }
            `$message = `$json.message
            `$priority = if (`$json.priority) { `$json.priority } else { 3 }
            Show-Notification -Title `$title -Message `$message -Priority `$priority
        } catch { }
    }
}

`$global:notifyIcon.Dispose()
"@

$psScriptPath = "$ConfigDir\run-subscribe.ps1"
$psScriptContent | Out-File -FilePath $psScriptPath -Encoding UTF8
Write-Host "Notification script saved to: $psScriptPath" -ForegroundColor Green

# --- Create VBS wrapper for hidden startup (no console window) ---
$vbsContent = @"
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "powershell -ExecutionPolicy Bypass -WindowStyle Hidden -File ""$psScriptPath""", 0
Set WshShell = Nothing
"@

$vbsPath = "$ConfigDir\run-subscribe-hidden.vbs"
$vbsContent | Out-File -FilePath $vbsPath -Encoding ASCII
Write-Host "Hidden launcher saved to: $vbsPath" -ForegroundColor Green
Write-Host ""

# --- Create startup shortcut ---
Write-Host "Creating startup shortcut..."
$startupPath = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup"
$shortcutPath = "$startupPath\ntfy-subscribe.lnk"

$shell = New-Object -ComObject WScript.Shell
$shortcut = $shell.CreateShortcut($shortcutPath)
$shortcut.TargetPath = "wscript.exe"
$shortcut.Arguments = "`"$vbsPath`""
$shortcut.WorkingDirectory = $ConfigDir
$shortcut.WindowStyle = 7  # Minimized
$shortcut.Description = "ntfy notification subscriber"
$shortcut.Save()

Write-Host "Startup shortcut created at: $shortcutPath" -ForegroundColor Green
Write-Host ""

# --- Start the subscriber now ---
Write-Host "Starting ntfy subscriber..."

# Stop any existing ntfy or subscriber processes
Stop-Process -Name ntfy -ErrorAction SilentlyContinue
Get-Process powershell -ErrorAction SilentlyContinue | Where-Object { $_.Id -ne $PID } | ForEach-Object {
    try {
        $cmdLine = (Get-CimInstance Win32_Process -Filter "ProcessId = $($_.Id)" -ErrorAction SilentlyContinue).CommandLine
        if ($cmdLine -like "*run-subscribe*") { Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue }
    } catch {}
}
Start-Sleep -Seconds 1

$process = Start-Process -FilePath "powershell" `
    -ArgumentList @("-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-File", $psScriptPath) `
    -WindowStyle Hidden `
    -PassThru

Start-Sleep -Seconds 2

# --- Print status and management commands ---
if ($process -and !$process.HasExited) {
    Write-Host ""
    Write-Host "=== Setup Complete ===" -ForegroundColor Green
    Write-Host ""
    Write-Host "ntfy is running and will start automatically on login." -ForegroundColor Green
    Write-Host "You should see Windows toast notifications when messages arrive."
    Write-Host ""
    Write-Host "Management commands (run in PowerShell):" -ForegroundColor Cyan
    Write-Host "  Check status:    Get-Process ntfy -ErrorAction SilentlyContinue"
    Write-Host "  Stop:            Stop-Process -Name ntfy"
    Write-Host "  Start manually:  wscript.exe '$vbsPath'"
    Write-Host "  Edit config:     notepad '$clientYmlPath'"
    Write-Host "  Edit topics:     notepad '$psScriptPath'"
    Write-Host ""
} else {
    Write-Host ""
    Write-Host "WARNING: ntfy may not have started correctly." -ForegroundColor Yellow
    Write-Host "Try running manually:  wscript.exe '$vbsPath'"
    Write-Host ""
}

Write-Host "To test, send a notification from another machine:" -ForegroundColor Cyan
Write-Host "  curl -d 'Test message' $ServerUrl/$($Topics[0])"
Write-Host ""
