# Minimal PC data collection script
# For locked-down PCs with restricted permissions

$apiUrl = "https://tsgwp00525.rd.ds.ge.com/shopdb/api.asp"
$logFile = "$env:TEMP\shopdb-update.log"

# Start fresh log
"$(Get-Date) - Starting minimal PC update" | Out-File $logFile

$data = @{
    action = 'updateCompleteAsset'
    hostname = $env:COMPUTERNAME
    manufacturer = 'Unknown'
    model = 'Unknown'
    serialNumber = 'Unknown'
    pcType = 'Measuring'  # Default, will be updated if PC-DMIS is found
}

"Hostname: $($data.hostname)" | Tee-Object -FilePath $logFile -Append

# Try to get serial number
try {
    $bios = Get-CimInstance -ClassName Win32_BIOS -ErrorAction Stop
    $data.serialNumber = $bios.SerialNumber
    "Serial: $($data.serialNumber)" | Tee-Object -FilePath $logFile -Append
} catch {
    "ERROR getting serial: $_" | Tee-Object -FilePath $logFile -Append
}

# Try to get manufacturer/model
try {
    $cs = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop
    $data.manufacturer = $cs.Manufacturer
    $data.model = $cs.Model
    "Manufacturer: $($data.manufacturer)" | Tee-Object -FilePath $logFile -Append
    "Model: $($data.model)" | Tee-Object -FilePath $logFile -Append
} catch {
    "ERROR getting system info: $_" | Tee-Object -FilePath $logFile -Append
}

# Get IP address using ipconfig (no elevated permissions required)
$interfaces = @()
try {
    $ipconfig = ipconfig /all
    $currentIP = ""
    $currentMAC = ""

    foreach ($line in $ipconfig) {
        if ($line -match '^\S') {
            # New adapter section - save previous if valid
            if ($currentIP -and $currentIP -notlike '127.*' -and $currentIP -notlike '169.254.*') {
                $interfaces += @{
                    IPAddress = $currentIP
                    MACAddress = $currentMAC
                }
                "IP: $currentIP | MAC: $currentMAC" | Tee-Object -FilePath $logFile -Append
            }
            $currentIP = ""
            $currentMAC = ""
        }
        elseif ($line -match 'IPv4 Address.*:\s*(\d+\.\d+\.\d+\.\d+)') {
            $currentIP = $matches[1] -replace '\(Preferred\)',''
        }
        elseif ($line -match 'Physical Address.*:\s*([0-9A-F-]+)') {
            $currentMAC = $matches[1] -replace '-',':'
        }
    }
    # Don't forget the last adapter
    if ($currentIP -and $currentIP -notlike '127.*' -and $currentIP -notlike '169.254.*') {
        $interfaces += @{
            IPAddress = $currentIP
            MACAddress = $currentMAC
        }
        "IP: $currentIP | MAC: $currentMAC" | Tee-Object -FilePath $logFile -Append
    }
} catch {
    "ERROR getting network info: $_" | Tee-Object -FilePath $logFile -Append
}

if ($interfaces.Count -gt 0) {
    $data.networkInterfaces = ($interfaces | ConvertTo-Json -Compress)
}

# Try to get OS and last boot time
try {
    $os = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop
    $data.osVersion = $os.Caption
    "OS: $($data.osVersion)" | Tee-Object -FilePath $logFile -Append

    # Get last boot time
    if ($os.LastBootUpTime) {
        $data.lastBootUpTime = $os.LastBootUpTime.ToString("yyyy-MM-dd HH:mm:ss")
        "Last Boot: $($data.lastBootUpTime)" | Tee-Object -FilePath $logFile -Append
    }
} catch {
    "ERROR getting OS: $_" | Tee-Object -FilePath $logFile -Append
}

# Try to get logged in user
try {
    $data.loggedInUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
    "User: $($data.loggedInUser)" | Tee-Object -FilePath $logFile -Append
} catch {
    "ERROR getting user: $_" | Tee-Object -FilePath $logFile -Append
}

# Try to get machine number (no admin required for reading HKLM)
try {
    $machineNo = $null

    # Primary location: GE Aircraft Engines DNC registry (64-bit and 32-bit)
    $regPaths = @(
        "HKLM:\SOFTWARE\GE Aircraft Engines\DNC\General",
        "HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General"
    )

    foreach ($regPath in $regPaths) {
        if (Test-Path $regPath) {
            $regValue = (Get-ItemProperty -Path $regPath -Name "MachineNo" -ErrorAction SilentlyContinue).MachineNo
            if ($regValue) {
                $machineNo = $regValue
                "Machine # from registry ($regPath): $machineNo" | Tee-Object -FilePath $logFile -Append
                break
            }
        }
    }

    # Fall back to DNC.ini file
    if (-not $machineNo) {
        $dncIniPath = "C:\DNC\DNC.ini"
        if (Test-Path $dncIniPath) {
            $iniContent = Get-Content $dncIniPath -Raw -ErrorAction SilentlyContinue
            if ($iniContent -match 'MachineNo\s*=\s*(.+)') {
                $machineNo = $matches[1].Trim()
                "Machine # from DNC.ini: $machineNo" | Tee-Object -FilePath $logFile -Append
            }
        }
    }

    if ($machineNo) {
        # Check if machine number is a generic/placeholder value
        # These should not be sent to API - must be set manually
        # Generic machine numbers - don't send to API but can help identify PC type
        $genericMachineTypes = @{
            "^WJPRT"  = "Measuring"    # Generic printer/measuring tool
            "^WJCMM"  = "CMM"          # Generic CMM
            "^WJMEAS" = "Measuring"    # Generic measuring
            "^0600$"  = "Wax Trace"    # Wax trace machines
            "^0612$"  = "Part Marker"  # Part markers
            "^0613$"  = "Part Marker"  # Part markers
            "^0615"   = "Part Marker"  # Part markers
            "^TEST"   = $null          # Test machines - no type hint
            "^TEMP"   = $null          # Temporary - no type hint
            "^DEFAULT"= $null          # Default value - no type hint
            "^0+$"    = $null          # All zeros - no type hint
        }

        $isGeneric = $false
        $genericTypeHint = $null
        foreach ($pattern in $genericMachineTypes.Keys) {
            if ($machineNo -match $pattern) {
                $isGeneric = $true
                $genericTypeHint = $genericMachineTypes[$pattern]
                break
            }
        }

        if ($isGeneric) {
            if ($genericTypeHint) {
                "Machine # '$machineNo' is generic ($genericTypeHint) - NOT sending to API (requires manual assignment)" | Tee-Object -FilePath $logFile -Append
                # Store the type hint for later use in PC type detection
                $script:genericTypeHint = $genericTypeHint
            } else {
                "Machine # '$machineNo' is generic/placeholder - NOT sending to API (requires manual assignment)" | Tee-Object -FilePath $logFile -Append
            }
            # Don't set $data.machineNo - leave it out of API call
        } else {
            $data.machineNo = $machineNo
        }
    } else {
        "No machine number found" | Tee-Object -FilePath $logFile -Append
    }
} catch {
    "ERROR getting machine number: $_" | Tee-Object -FilePath $logFile -Append
}

# Check for VNC installation
try {
    $hasVnc = $false

    # Check registry for installed programs (both 32-bit and 64-bit)
    $regPaths = @(
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
        "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
    )

    foreach ($path in $regPaths) {
        if (Test-Path $path) {
            $apps = Get-ItemProperty $path -ErrorAction SilentlyContinue |
                Where-Object { $_.DisplayName -like "*VNC Server*" -or $_.DisplayName -like "*VNC Connect*" -or $_.DisplayName -like "*RealVNC*" }
            if ($apps) {
                $hasVnc = $true
                "VNC detected: $($apps.DisplayName -join ', ')" | Tee-Object -FilePath $logFile -Append
                break
            }
        }
    }

    # Also check for VNC service
    if (-not $hasVnc) {
        $vncService = Get-Service -Name "vncserver*" -ErrorAction SilentlyContinue
        if ($vncService) {
            $hasVnc = $true
            "VNC service detected: $($vncService.Name)" | Tee-Object -FilePath $logFile -Append
        }
    }

    if ($hasVnc) {
        $data.hasVnc = "1"
    } else {
        $data.hasVnc = "0"
        "No VNC detected" | Tee-Object -FilePath $logFile -Append
    }
} catch {
    "ERROR checking VNC: $_" | Tee-Object -FilePath $logFile -Append
    $data.hasVnc = "0"
}

# Check for WinRM status
try {
    $hasWinRM = $false

    # Check if WinRM service is running
    $winrmService = Get-Service -Name "WinRM" -ErrorAction SilentlyContinue
    if ($winrmService -and $winrmService.Status -eq "Running") {
        # Also verify WinRM is configured to accept connections
        try {
            $winrmConfig = winrm get winrm/config/service 2>$null
            if ($winrmConfig -match "AllowRemoteAccess\s*=\s*true") {
                $hasWinRM = $true
                "WinRM enabled and accepting connections" | Tee-Object -FilePath $logFile -Append
            } else {
                "WinRM service running but remote access not enabled" | Tee-Object -FilePath $logFile -Append
            }
        } catch {
            # If we can't check config, assume it's enabled if service is running
            $hasWinRM = $true
            "WinRM service running (config check skipped)" | Tee-Object -FilePath $logFile -Append
        }
    } else {
        "WinRM service not running" | Tee-Object -FilePath $logFile -Append
    }

    if ($hasWinRM) {
        $data.hasWinRM = "1"
    } else {
        $data.hasWinRM = "0"
    }
} catch {
    "ERROR checking WinRM: $_" | Tee-Object -FilePath $logFile -Append
    $data.hasWinRM = "0"
}

# Load applications.csv for app matching
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$csvPath = Join-Path $scriptDir "applications.csv"
$appMappings = @()

if (Test-Path $csvPath) {
    try {
        $appMappings = Import-Csv $csvPath | Where-Object { $_.enabled -eq "1" -and $_.app_id }
        "Loaded $($appMappings.Count) app mappings from CSV" | Tee-Object -FilePath $logFile -Append
    } catch {
        "ERROR loading applications.csv: $_" | Tee-Object -FilePath $logFile -Append
    }
} else {
    "WARNING: applications.csv not found at $csvPath" | Tee-Object -FilePath $logFile -Append
}

# Get installed applications from registry and match against CSV
$matchedApps = @()
$hasPcDmis = $false
$hasFormTracePak = $false
$hasKeyence = $false
$hasEAS1000 = $false
$hasGoCMM = $false
$hasDODA = $false
$hasFormStatusMonitor = $false
$hasGageCal = $false
$hasNISoftware = $false
$hasGenspect = $false
$hasHeatTreat = $false
try {
    $regPaths = @(
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
        "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
    )

    # Get all installed apps
    $installedApps = @()
    foreach ($path in $regPaths) {
        if (Test-Path $path) {
            $apps = Get-ItemProperty $path -ErrorAction SilentlyContinue |
                Where-Object { $_.DisplayName -and $_.DisplayName.Trim() -ne "" }
            foreach ($app in $apps) {
                $installedApps += @{
                    DisplayName = $app.DisplayName.Trim()
                    Version = if ($app.DisplayVersion) { $app.DisplayVersion.Trim() } else { "" }
                }
            }
        }
    }

    "Found $($installedApps.Count) installed applications" | Tee-Object -FilePath $logFile -Append

    # Match against CSV patterns
    foreach ($mapping in $appMappings) {
        $patterns = $mapping.search_patterns -split '\|'
        foreach ($installedApp in $installedApps) {
            $matched = $false
            foreach ($pattern in $patterns) {
                if ($installedApp.DisplayName -match $pattern) {
                    $matched = $true
                    break
                }
            }
            if ($matched) {
                # Avoid duplicates
                if (-not ($matchedApps | Where-Object { $_.appid -eq $mapping.app_id })) {
                    $matchedApps += @{
                        appid = [int]$mapping.app_id
                        appname = $mapping.app_name
                        version = $installedApp.Version
                    }
                    "$($mapping.app_name) (ID:$($mapping.app_id)) detected: $($installedApp.DisplayName)" | Tee-Object -FilePath $logFile -Append

                    # Check for PC type indicators
                    switch ($mapping.app_name) {
                        "PC-DMIS" { $hasPcDmis = $true }
                        "goCMM" { $hasGoCMM = $true }
                        "DODA" { $hasDODA = $true }
                        "FormTracePak" { $hasFormTracePak = $true }
                        "FormStatusMonitor" { $hasFormStatusMonitor = $true }
                        "Keyence VR Series" { $hasKeyence = $true }
                        "GageCal" { $hasGageCal = $true }
                        "NI Software" { $hasNISoftware = $true }
                        "Genspect" { $hasGenspect = $true }
                        "HeatTreat" { $hasHeatTreat = $true }
                    }
                }
                break
            }
        }
    }

    "Matched $($matchedApps.Count) tracked applications" | Tee-Object -FilePath $logFile -Append

    if ($matchedApps.Count -gt 0) {
        $data.installedApps = ($matchedApps | ConvertTo-Json -Compress)
    }
} catch {
    "ERROR getting installed apps: $_" | Tee-Object -FilePath $logFile -Append
}

# File path fallbacks for apps that may not be in registry
# Check PC-DMIS
if (-not $hasPcDmis) {
    try {
        $pcDmisPaths = @(
            "C:\ProgramData\Hexagon\PC-DMIS*",
            "C:\Program Files\Hexagon\PC-DMIS*",
            "C:\Program Files (x86)\Hexagon\PC-DMIS*",
            "C:\Program Files\WAI\PC-DMIS*",
            "C:\Program Files (x86)\WAI\PC-DMIS*"
        )
        foreach ($dmisPath in $pcDmisPaths) {
            if (Test-Path $dmisPath) {
                $hasPcDmis = $true
                "PC-DMIS found at: $dmisPath" | Tee-Object -FilePath $logFile -Append
                break
            }
        }
    } catch {
        "ERROR checking PC-DMIS paths: $_" | Tee-Object -FilePath $logFile -Append
    }
}

# Check UDC if not already matched
if (-not ($matchedApps | Where-Object { $_.appid -eq 2 })) {
    if (Test-Path "C:\Program Files\UDC") {
        $matchedApps += @{ appid = 2; appname = "UDC"; version = "" }
        "UDC found at: C:\Program Files\UDC" | Tee-Object -FilePath $logFile -Append
    }
}

# Check eDNC if not already matched
if (-not ($matchedApps | Where-Object { $_.appid -eq 8 })) {
    if (Test-Path "C:\Program Files (x86)\DNC") {
        $matchedApps += @{ appid = 8; appname = "eDNC"; version = "" }
        "eDNC found at: C:\Program Files (x86)\DNC" | Tee-Object -FilePath $logFile -Append
    }
}

# Check FormTracePak if not already matched
if (-not $hasFormTracePak) {
    try {
        $formTracePaths = @(
            "C:\Program Files\MitutoyoApp*",
            "C:\Program Files (x86)\MitutoyoApp*"
        )
        foreach ($ftPath in $formTracePaths) {
            if (Test-Path $ftPath) {
                $hasFormTracePak = $true
                if (-not ($matchedApps | Where-Object { $_.appid -eq 76 })) {
                    $matchedApps += @{ appid = 76; appname = "FormTracePak"; version = "" }
                }
                "FormTracePak found at: $ftPath" | Tee-Object -FilePath $logFile -Append
                break
            }
        }
    } catch {
        "ERROR checking FormTracePak paths: $_" | Tee-Object -FilePath $logFile -Append
    }
}

# Update installedApps data if we found more apps via file paths
if ($matchedApps.Count -gt 0) {
    $data.installedApps = ($matchedApps | ConvertTo-Json -Compress)
}

# Set PC type based on application detection
# Priority: CMM > Wax Trace > Keyence > EAS1000 > Genspect > Heat Treat > Generic hint > default Shopfloor
$isCMM = ($hasPcDmis -or $hasGoCMM -or $hasDODA)
$isWaxTrace = ($hasFormTracePak -or $hasFormStatusMonitor)
$isEAS1000 = ($hasGageCal -or $hasNISoftware)

if ($isCMM) {
    $data.pcType = "CMM"
    $detected = @()
    if ($hasPcDmis) { $detected += "PC-DMIS" }
    if ($hasGoCMM) { $detected += "goCMM" }
    if ($hasDODA) { $detected += "DODA" }
    "PC Type set to: CMM ($($detected -join ', '))" | Tee-Object -FilePath $logFile -Append
} elseif ($isWaxTrace) {
    $data.pcType = "Wax Trace"
    $detected = @()
    if ($hasFormTracePak) { $detected += "FormTracePak" }
    if ($hasFormStatusMonitor) { $detected += "FormStatusMonitor" }
    "PC Type set to: Wax Trace ($($detected -join ', '))" | Tee-Object -FilePath $logFile -Append
} elseif ($hasKeyence) {
    $data.pcType = "Keyence"
    "PC Type set to: Keyence (Keyence VR Series)" | Tee-Object -FilePath $logFile -Append
} elseif ($isEAS1000) {
    $data.pcType = "EAS1000"
    $detected = @()
    if ($hasGageCal) { $detected += "GageCal" }
    if ($hasNISoftware) { $detected += "NI Software" }
    "PC Type set to: EAS1000 ($($detected -join ', '))" | Tee-Object -FilePath $logFile -Append
} elseif ($hasGenspect) {
    $data.pcType = "Genspect"
    "PC Type set to: Genspect" | Tee-Object -FilePath $logFile -Append
} elseif ($hasHeatTreat) {
    $data.pcType = "Heat Treat"
    "PC Type set to: Heat Treat" | Tee-Object -FilePath $logFile -Append
} elseif ($script:genericTypeHint) {
    # Use generic machine number hint when no software detected
    $data.pcType = $script:genericTypeHint
    "PC Type set to: $($script:genericTypeHint) (from generic machine # - requires manual assignment)" | Tee-Object -FilePath $logFile -Append
} else {
    $data.pcType = "Shopfloor"
    "No specialized apps detected, defaulting to: Shopfloor" | Tee-Object -FilePath $logFile -Append
}

# Send to API
"Sending to API: $apiUrl" | Tee-Object -FilePath $logFile -Append

try {
    $response = Invoke-RestMethod -Uri $apiUrl -Method Post -Body $data -ErrorAction Stop
    "API Response: $($response | ConvertTo-Json -Compress)" | Tee-Object -FilePath $logFile -Append

    if ($response.success) {
        "SUCCESS - MachineID: $($response.machineid)" | Tee-Object -FilePath $logFile -Append
    } else {
        "FAILED - $($response.message)" | Tee-Object -FilePath $logFile -Append
    }
} catch {
    "ERROR calling API: $_" | Tee-Object -FilePath $logFile -Append
}

"$(Get-Date) - Done" | Tee-Object -FilePath $logFile -Append
