# Functions to collect shopfloor PC network and communication configurations

# Function to get all network interfaces and their configurations
function Get-NetworkInterfaceConfig {
    Write-Host "  Collecting network interface information..." -ForegroundColor Yellow
    
    $interfaces = @()
    
    try {
        # Get all network adapters with IP configurations
        $adapters = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' }
        
        foreach ($adapter in $adapters) {
            $ipConfig = Get-NetIPConfiguration -InterfaceIndex $adapter.ifIndex -ErrorAction SilentlyContinue
            
            if ($ipConfig -and $ipConfig.IPv4Address) {
                foreach ($ip in $ipConfig.IPv4Address) {
                    $gateway = if ($ipConfig.IPv4DefaultGateway) { $ipConfig.IPv4DefaultGateway[0].NextHop } else { $null }
                    
                    # Determine if this is a machine network (192.168.*.*)
                    $isMachineNetwork = $ip.IPAddress -match '^192\.168\.'
                    
                    $interface = @{
                        InterfaceName = $adapter.Name
                        IPAddress = $ip.IPAddress
                        SubnetMask = $ip.PrefixLength  # Will need conversion
                        DefaultGateway = $gateway
                        MACAddress = $adapter.MacAddress
                        IsDHCP = if ($ipConfig.NetIPv4Interface.Dhcp -eq 'Enabled') { 1 } else { 0 }
                        IsActive = 1
                        IsMachineNetwork = if ($isMachineNetwork) { 1 } else { 0 }
                    }
                    
                    $interfaces += $interface
                    
                    if ($isMachineNetwork) {
                        Write-Host "    Found machine network: $($ip.IPAddress) on $($adapter.Name)" -ForegroundColor Cyan
                    }
                    else {
                        Write-Host "    Found network: $($ip.IPAddress) on $($adapter.Name)" -ForegroundColor Gray
                    }
                }
            }
        }
    }
    catch {
        Write-Host "    Error collecting network info: $_" -ForegroundColor Red
    }
    
    # Alternative method using WMI if NetAdapter cmdlets fail
    if ($interfaces.Count -eq 0) {
        try {
            $wmiAdapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true }
            
            foreach ($adapter in $wmiAdapters) {
                if ($adapter.IPAddress) {
                    foreach ($i in 0..($adapter.IPAddress.Count - 1)) {
                        $ip = $adapter.IPAddress[$i]
                        
                        # Skip IPv6 addresses
                        if ($ip -match ':') { continue }
                        
                        $isMachineNetwork = $ip -match '^192\.168\.'
                        
                        $interface = @{
                            InterfaceName = $adapter.Description
                            IPAddress = $ip
                            SubnetMask = $adapter.IPSubnet[$i]
                            DefaultGateway = if ($adapter.DefaultIPGateway) { $adapter.DefaultIPGateway[0] } else { $null }
                            MACAddress = $adapter.MACAddress
                            IsDHCP = $adapter.DHCPEnabled
                            IsActive = 1
                            IsMachineNetwork = if ($isMachineNetwork) { 1 } else { 0 }
                        }
                        
                        $interfaces += $interface
                        
                        if ($isMachineNetwork) {
                            Write-Host "    Found machine network: $ip on $($adapter.Description)" -ForegroundColor Cyan
                        }
                    }
                }
            }
        }
        catch {
            Write-Host "    WMI method also failed: $_" -ForegroundColor Red
        }
    }
    
    return $interfaces
}

# Function to get serial port configurations from registry
function Get-SerialPortConfig {
    Write-Host "  Collecting serial port configurations..." -ForegroundColor Yellow
    
    $configs = @()
    
    # Registry paths to check
    $registryPaths = @{
        'Serial' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\Serial', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\Serial')
        'Mark' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\Mark', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\Mark')
        'PPDCS' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\PPDCS', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\PPDCS')
        'TQM9030' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\TQM9030', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\TQM9030')
        'TQMCaron' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\TQMCaron', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\TQMCaron')
    }
    
    foreach ($configType in $registryPaths.Keys) {
        foreach ($path in $registryPaths[$configType]) {
            if (Test-Path $path) {
                try {
                    $regValues = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
                    
                    if ($regValues) {
                        $config = @{
                            ConfigType = $configType
                            PortID = $regValues.'Port Id' -replace 'Port Id2', ''
                            Baud = $regValues.Baud
                            DataBits = $regValues.'Data Bits'
                            StopBits = $regValues.'Stop Bits'
                            Parity = $regValues.Parity
                            CRLF = $regValues.CRLF
                            IPAddress = $null
                            SocketNo = $null
                            AdditionalSettings = @{}
                        }
                        
                        # Collect any additional settings
                        $standardKeys = @('Port Id', 'Baud', 'Data Bits', 'Stop Bits', 'Parity', 'CRLF', 'PSPath', 'PSParentPath', 'PSChildName', 'PSProvider')
                        foreach ($prop in $regValues.PSObject.Properties) {
                            if ($prop.Name -notin $standardKeys -and $prop.Value) {
                                $config.AdditionalSettings[$prop.Name] = $prop.Value
                            }
                        }
                        
                        # Convert additional settings to JSON
                        if ($config.AdditionalSettings.Count -gt 0) {
                            $config.AdditionalSettings = $config.AdditionalSettings | ConvertTo-Json -Compress
                        }
                        else {
                            $config.AdditionalSettings = $null
                        }
                        
                        if ($config.PortID) {
                            $configs += $config
                            Write-Host "    Found $configType config: Port $($config.PortID), Baud $($config.Baud)" -ForegroundColor Cyan
                        }
                    }
                }
                catch {
                    Write-Host "    Error reading $configType registry: $_" -ForegroundColor Red
                }
            }
        }
    }
    
    # Check for eFocas configuration (network-based)
    $efocasPaths = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\eFocas', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\eFocas')
    foreach ($path in $efocasPaths) {
        if (Test-Path $path) {
            try {
                $regValues = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
                
                if ($regValues -and $regValues.IpAddr) {
                    $config = @{
                        ConfigType = 'eFocas'
                        PortID = $null
                        Baud = $null
                        DataBits = $null
                        StopBits = $null
                        Parity = $null
                        CRLF = $null
                        IPAddress = $regValues.IpAddr
                        SocketNo = $regValues.SocketNo
                        AdditionalSettings = @{
                            DualPath = $regValues.DualPath
                            Path1Name = $regValues.Path1Name
                            Path2Name = $regValues.Path2Name
                            Danobat = $regValues.Danobat
                            DataServer = $regValues.DataServer
                        } | ConvertTo-Json -Compress
                    }
                    
                    $configs += $config
                    Write-Host "    Found eFocas config: IP $($config.IPAddress), Socket $($config.SocketNo)" -ForegroundColor Cyan
                }
            }
            catch {
                Write-Host "    Error reading eFocas registry: $_" -ForegroundColor Red
            }
        }
    }
    
    return $configs
}

# Function to get GE Aircraft Engines registry information and DualPath configuration
function Get-GERegistryInfo {
    Write-Host "  Collecting GE Aircraft Engines registry information..." -ForegroundColor Yellow
    
    $geInfo = @{
        Registry32Bit = $false
        Registry64Bit = $false
        DualPathEnabled = $null
        Path1Name = $null
        Path2Name = $null
        RegistryNotes = @{}
    }
    
    # Check both 32-bit and 64-bit registry paths
    $registryPaths = @{
        '32bit' = 'HKLM:\SOFTWARE\GE Aircraft Engines'
        '64bit' = 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines'
    }
    
    foreach ($pathType in $registryPaths.Keys) {
        $basePath = $registryPaths[$pathType]
        Write-Host "    Checking $pathType registry: $basePath" -ForegroundColor Gray
        
        if (Test-Path $basePath) {
            Write-Host "      [FOUND] GE Aircraft Engines in $pathType registry" -ForegroundColor Green
            
            if ($pathType -eq '32bit') {
                $geInfo.Registry32Bit = $true
            } else {
                $geInfo.Registry64Bit = $true
            }
            
            # Collect information about what's under GE Aircraft Engines
            try {
                $subKeys = Get-ChildItem -Path $basePath -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name | ForEach-Object { Split-Path $_ -Leaf }
                $geInfo.RegistryNotes[$pathType] = @{
                    BasePath = $basePath
                    SubKeys = $subKeys -join ', '
                    Found = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
                }
                Write-Host "        Sub-keys found: $($subKeys -join ', ')" -ForegroundColor Cyan
            }
            catch {
                Write-Host "        Error reading sub-keys: $_" -ForegroundColor Red
                $geInfo.RegistryNotes[$pathType] = @{
                    Error = $_.Exception.Message
                }
            }
            
            # Check for DualPath configuration in eFocas
            $efocasPath = "$basePath\DNC\eFocas"
            if (Test-Path $efocasPath) {
                Write-Host "        Checking eFocas configuration for DualPath..." -ForegroundColor Yellow
                try {
                    $efocasValues = Get-ItemProperty -Path $efocasPath -ErrorAction SilentlyContinue
                    
                    if ($efocasValues.DualPath) {
                        Write-Host "          [FOUND] DualPath = $($efocasValues.DualPath)" -ForegroundColor Green
                        
                        # Handle case where both registry locations exist - prioritize settings from first found
                        if ($geInfo.DualPathEnabled -eq $null) {
                            $geInfo.DualPathEnabled = $efocasValues.DualPath -eq 'YES'
                            Write-Host "          Setting DualPath from $pathType registry: $($geInfo.DualPathEnabled)" -ForegroundColor Cyan
                        } else {
                            Write-Host "          DualPath already set from other registry location, keeping existing value" -ForegroundColor Yellow
                        }
                        
                        # Handle Path1Name - use first non-empty value found
                        if (!$geInfo.Path1Name -and $efocasValues.Path1Name) {
                            $geInfo.Path1Name = $efocasValues.Path1Name
                            Write-Host "          Path1Name = $($efocasValues.Path1Name)" -ForegroundColor Cyan
                        }
                        
                        # Handle Path2Name - use first non-empty value found
                        if (!$geInfo.Path2Name -and $efocasValues.Path2Name) {
                            $geInfo.Path2Name = $efocasValues.Path2Name
                            Write-Host "          Path2Name = $($efocasValues.Path2Name)" -ForegroundColor Cyan
                        }
                        
                        # Store additional eFocas settings
                        $geInfo.RegistryNotes["$pathType-eFocas"] = @{
                            DualPath = $efocasValues.DualPath
                            Path1Name = $efocasValues.Path1Name
                            Path2Name = $efocasValues.Path2Name
                            IpAddr = $efocasValues.IpAddr
                            SocketNo = $efocasValues.SocketNo
                            Danobat = $efocasValues.Danobat
                            DataServer = $efocasValues.DataServer
                        }
                    }
                }
                catch {
                    Write-Host "          Error reading eFocas configuration: $_" -ForegroundColor Red
                }
            }
        } else {
            Write-Host "      [NOT FOUND] No GE Aircraft Engines in $pathType registry" -ForegroundColor Gray
        }
    }
    
    # Summary
    Write-Host "    GE Registry Summary:" -ForegroundColor Green
    Write-Host "      32-bit registry: $(if ($geInfo.Registry32Bit) { 'YES' } else { 'NO' })" -ForegroundColor Cyan
    Write-Host "      64-bit registry: $(if ($geInfo.Registry64Bit) { 'YES' } else { 'NO' })" -ForegroundColor Cyan
    Write-Host "      DualPath enabled: $(if ($geInfo.DualPathEnabled -eq $null) { 'NOT FOUND' } elseif ($geInfo.DualPathEnabled) { 'YES' } else { 'NO' })" -ForegroundColor Cyan
    if ($geInfo.Path1Name) { Write-Host "      Path1Name: $($geInfo.Path1Name)" -ForegroundColor Cyan }
    if ($geInfo.Path2Name) { Write-Host "      Path2Name: $($geInfo.Path2Name)" -ForegroundColor Cyan }
    
    return $geInfo
}

# Function to get DNC configuration from registry
function Get-DNCConfig {
    Write-Host "  Collecting DNC configuration..." -ForegroundColor Yellow
    
    $dncConfig = $null
    $paths = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\General', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General')
    
    Write-Host "    Checking registry paths for DNC config..." -ForegroundColor Gray
    foreach ($path in $paths) {
        Write-Host "    Checking path: $path" -ForegroundColor Gray
        if (Test-Path $path) {
            Write-Host "      Path exists! Reading values..." -ForegroundColor Green
            try {
                $general = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
                $mxPath = $path -replace 'General', 'MX'
                $mx = Get-ItemProperty -Path $mxPath -ErrorAction SilentlyContinue
                $fmsPath = $path -replace 'General', 'FMS'
                $fms = Get-ItemProperty -Path $fmsPath -ErrorAction SilentlyContinue
                
                if ($general) {
                    Write-Host "      Found General config values!" -ForegroundColor Green
                    $dncConfig = @{
                        Site = $general.Site
                        CNC = $general.Cnc
                        NcIF = $general.NcIF
                        MachineNo = $general.MachineNo
                        HostType = $general.HostType
                        FtpHostPrimary = if ($mx) { $mx.FtpHostPrimary } else { $null }
                        FtpHostSecondary = if ($mx) { $mx.FtpHostSecondary } else { $null }
                        FtpAccount = if ($mx) { $mx.FtpAccount } else { $null }
                        Debug = $general.Debug
                        Uploads = $general.Uploads
                        Scanner = $general.Scanner
                        Dripfeed = $general.Dripfeed
                        AdditionalSettings = @{
                            Mode = $general.Mode
                            'Unit/Area' = $general.'Unit/Area'
                            DvUpldDir = $general.DvUpldDir
                            Ncedt = $general.Ncedt
                            Maint = $general.Maint
                            ChangeWorkstation = $general.ChangeWorkstation
                            FMSHostPrimary = if ($fms) { $fms.FMSHostPrimary } else { $null }
                            FMSHostSecondary = if ($fms) { $fms.FMSHostSecondary } else { $null }
                        } | ConvertTo-Json -Compress
                    }
                    
                    Write-Host "    Found DNC config: Site=$($dncConfig.Site), MachineNo=$($dncConfig.MachineNo), CNC=$($dncConfig.CNC)" -ForegroundColor Cyan
                    Write-Host "    DNC Config JSON: $($dncConfig | ConvertTo-Json -Compress)" -ForegroundColor Gray
                    break
                }
            }
            catch {
                Write-Host "    Error reading DNC registry: $_" -ForegroundColor Red
            }
        } else {
            Write-Host "      Path does not exist" -ForegroundColor Yellow
        }
    }
    
    if (-not $dncConfig) {
        Write-Host "    No DNC configuration found in registry" -ForegroundColor Yellow
    }
    
    return $dncConfig
}

# Main function to collect all shopfloor configurations
function Get-ShopfloorConfigurations {
    Write-Host "`nCollecting shopfloor-specific configurations..." -ForegroundColor Yellow
    
    $configurations = @{
        NetworkInterfaces = Get-NetworkInterfaceConfig
        CommConfigs = Get-SerialPortConfig
        DNCConfig = Get-DNCConfig
        GERegistryInfo = Get-GERegistryInfo
    }
    
    # Summary
    Write-Host "`n  Configuration Summary:" -ForegroundColor Green
    Write-Host "    Network Interfaces: $($configurations.NetworkInterfaces.Count)" -ForegroundColor Cyan
    Write-Host "    Comm Configs: $($configurations.CommConfigs.Count)" -ForegroundColor Cyan
    Write-Host "    DNC Config: $(if ($configurations.DNCConfig) { 'Yes' } else { 'No' })" -ForegroundColor Cyan
    Write-Host "    GE Registry (32-bit): $(if ($configurations.GERegistryInfo.Registry32Bit) { 'Yes' } else { 'No' })" -ForegroundColor Cyan
    Write-Host "    GE Registry (64-bit): $(if ($configurations.GERegistryInfo.Registry64Bit) { 'Yes' } else { 'No' })" -ForegroundColor Cyan
    Write-Host "    DualPath Enabled: $(if ($configurations.GERegistryInfo.DualPathEnabled -eq $null) { 'Not Found' } elseif ($configurations.GERegistryInfo.DualPathEnabled) { 'Yes' } else { 'No' })" -ForegroundColor Cyan
    
    return $configurations
}

function Get-InstalledApplications {
    <#
    .SYNOPSIS
        Detects UDC and CLM applications and their active status on shopfloor PCs
    .DESCRIPTION
        Checks for UDC (UDC.exe) and CLM (ppdcs.exe) processes and returns data
        compatible with your existing installedapps table structure.
    #>
    
    Write-Host "  Scanning for UDC and CLM applications..." -ForegroundColor Yellow
    
    $detectedApps = @()
    
    try {
        # Define the two applications we're looking for
        $appsToCheck = @{
            'UDC' = @{
                AppID = 2  # Universal Data Collector
                ProcessName = 'UDC'  # UDC.exe shows as 'UDC' in Get-Process
                Description = 'Universal Data Collector'
            }
            'CLM' = @{
                AppID = 4  # Legacy UDC (CLM)
                ProcessName = 'ppdcs'  # ppdcs.exe shows as 'ppdcs' in Get-Process  
                Description = 'Legacy UDC (Cell Level Manager)'
            }
        }
        
        foreach ($appName in $appsToCheck.Keys) {
            $app = $appsToCheck[$appName]
            
            Write-Host "    Checking for $appName (AppID: $($app.AppID))..." -ForegroundColor Gray
            
            # Check if the process is running
            $isActive = $false
            $processInfo = $null
            
            try {
                $processes = Get-Process -Name $app.ProcessName -ErrorAction SilentlyContinue
                if ($processes) {
                    $isActive = $true
                    $processInfo = $processes[0]  # Take first instance if multiple
                    Write-Host "      [ACTIVE] Found running process: $($app.ProcessName).exe (PID: $($processInfo.Id))" -ForegroundColor Green
                } else {
                    Write-Host "      [NOT ACTIVE] Process $($app.ProcessName).exe not running" -ForegroundColor Gray
                }
            } catch {
                Write-Host "      [ERROR] Failed to check process $($app.ProcessName): $($_.Exception.Message)" -ForegroundColor Yellow
            }
            
            # Always return app info (both active and inactive)
            $detectedApps += @{
                AppID = $app.AppID
                AppName = $appName
                Description = $app.Description
                ProcessName = $app.ProcessName
                IsActive = $isActive
                ProcessID = if ($processInfo) { $processInfo.Id } else { $null }
                ProcessStartTime = if ($processInfo) { $processInfo.StartTime } else { $null }
            }
        }
        
        # Business rule validation: Only one should be active
        $activeApps = $detectedApps | Where-Object { $_.IsActive -eq $true }
        
        if ($activeApps.Count -gt 1) {
            Write-Host "  [WARNING] Multiple applications active simultaneously:" -ForegroundColor Red
            foreach ($activeApp in $activeApps) {
                Write-Host "    - $($activeApp.AppName) (PID: $($activeApp.ProcessID))" -ForegroundColor Red
            }
        } elseif ($activeApps.Count -eq 1) {
            $activeApp = $activeApps[0]
            Write-Host "  [OK] Single active application: $($activeApp.AppName) (PID: $($activeApp.ProcessID))" -ForegroundColor Green
        } else {
            Write-Host "  [INFO] No UDC or CLM applications currently running" -ForegroundColor Gray
        }
        
        return $detectedApps
        
    } catch {
        Write-Host "  [ERROR] Failed to scan for applications: $($_.Exception.Message)" -ForegroundColor Red
        return @()
    }
}