"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SoftwareCollector = void 0;
const logger_1 = require("../logger");
const child_process_1 = require("child_process");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
class SoftwareCollector {
    constructor() {
        this.lastSoftwareSnapshot = [];
    }
    async collect() {
        if (process.platform === 'win32') {
            return this.collectWindows();
        }
        return this.collectLinux();
    }
    collectWindows() {
        return new Promise((resolve) => {
            const scriptContent = `
$ErrorActionPreference = 'SilentlyContinue'
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$software = @()
$paths = @(
  'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*',
  'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*',
  'HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'
)
foreach ($regPath in $paths) {
  try {
    Get-ItemProperty $regPath -ErrorAction SilentlyContinue |
      Where-Object { $_.DisplayName -and $_.DisplayName -ne '' } |
      ForEach-Object {
        $ver = if($_.DisplayVersion){$_.DisplayVersion}else{''}
        $pub = if($_.Publisher){$_.Publisher}else{''}
        $idate = if($_.InstallDate){$_.InstallDate}else{''}
        $iloc = if($_.InstallLocation){$_.InstallLocation}else{''}
        $sz = if($_.EstimatedSize){[int]$_.EstimatedSize * 1024}else{0}
        $arc = if($regPath -match 'WOW6432'){'x86'}else{'x64'}
        $software += [PSCustomObject]@{
          name = $_.DisplayName
          version = $ver
          publisher = $pub
          installDate = $idate
          installLocation = $iloc
          size = $sz
          type = 'application'
          architecture = $arc
        }
      }
  } catch {}
}
if ($software.Count -eq 0) {
  try {
    Get-Package -ErrorAction SilentlyContinue |
      Where-Object { $_.Name -and $_.Name -ne '' } |
      ForEach-Object {
        $software += [PSCustomObject]@{
          name = $_.Name
          version = (if($_.Version){$_.Version.ToString()}else{''})
          publisher = (if($_.ProviderName){$_.ProviderName}else{''})
          installDate = ''
          installLocation = ''
          size = 0
          type = 'package'
          architecture = ''
        }
      }
  } catch {}
}
if ($software.Count -gt 0) {
  $software | Sort-Object name -Unique | ConvertTo-Json -Depth 2 -Compress
} else {
  Write-Output '[]'
}
`;
            const scriptPath = path.join(os.tmpdir(), 'appstats-software.ps1');
            try {
                fs.writeFileSync(scriptPath, scriptContent, 'utf-8');
            }
            catch (writeErr) {
                logger_1.logger.error(`Failed to write software script: ${writeErr.message}`);
                resolve([]);
                return;
            }
            (0, child_process_1.execFile)('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath], { timeout: 90000, maxBuffer: 16 * 1024 * 1024 }, (err, stdout, stderr) => {
                if (err && !stdout?.trim()) {
                    logger_1.logger.warn(`Software collection error: ${err.message}${stderr ? ' stderr: ' + stderr.substring(0, 200) : ''}`);
                    resolve(this.lastSoftwareSnapshot.length ? this.lastSoftwareSnapshot : []);
                    return;
                }
                try {
                    const raw = (stdout || '')
                        .replace(/^\uFEFF/, '')
                        .replace(/\u0000/g, '')
                        .trim();
                    if (!raw || raw === 'null' || raw === '') {
                        resolve([]);
                        return;
                    }
                    let parsed;
                    try {
                        parsed = JSON.parse(raw);
                    }
                    catch {
                        const match = raw.match(/(\[[\s\S]*\]|\{[\s\S]*\})/);
                        if (!match)
                            throw new Error('No JSON payload found');
                        parsed = JSON.parse(match[1]);
                    }
                    if (!Array.isArray(parsed))
                        parsed = [parsed];
                    logger_1.logger.info(`Software collected: ${parsed.length} entries`);
                    this.lastSoftwareSnapshot = parsed;
                    resolve(parsed);
                }
                catch (parseErr) {
                    logger_1.logger.warn(`Software parse error: ${parseErr.message}, raw length: ${stdout.length}`);
                    resolve(this.lastSoftwareSnapshot.length ? this.lastSoftwareSnapshot : []);
                }
            });
        });
    }
    collectLinux() {
        return new Promise((resolve) => {
            (0, child_process_1.execFile)('sh', ['-c', "dpkg-query -W -f='${Package}||${Version}||${Maintainer}||${Installed-Size}\\n' 2>/dev/null || rpm -qa --queryformat '%{NAME}||%{VERSION}-%{RELEASE}||%{VENDOR}||%{SIZE}\\n' 2>/dev/null"], { timeout: 15000, maxBuffer: 2 * 1024 * 1024 }, (err, stdout) => {
                if (err) {
                    resolve([]);
                    return;
                }
                try {
                    const software = stdout.trim().split('\n')
                        .filter((line) => line.includes('||'))
                        .map((line) => {
                        const [name, version, publisher, size] = line.split('||');
                        return {
                            name: name || '',
                            version: version || '',
                            publisher: publisher || '',
                            installDate: '',
                            installLocation: '',
                            size: parseInt(size) || 0,
                            type: 'package',
                            architecture: process.arch,
                        };
                    });
                    resolve(software);
                }
                catch {
                    resolve([]);
                }
            });
        });
    }
}
exports.SoftwareCollector = SoftwareCollector;
//# sourceMappingURL=software.js.map