/**
 * Windows: resolve which PID owns a listening TCP port and kill process trees reliably.
 * Used for Gateway cleanup (npm spawns a child Node; SIGTERM on parent leaves listeners behind).
 */
import { execSync } from 'child_process';
/**
 * Find the PID that is LISTENING on local TCP `port` (IPv4/IPv6).
 * Skips TIME_WAIT lines (PID 0) — those caused bogus "System Idle Process" in the Connection Portal.
 */
export function findListeningPidWindows(port) {
    if (process.platform !== 'win32')
        return null;
    try {
        const netstatOutput = execSync('netstat -ano', {
            encoding: 'utf-8',
            windowsHide: true,
            maxBuffer: 1024 * 1024,
        });
        const lines = netstatOutput.split(/\r?\n/);
        for (const line of lines) {
            const trimmed = line.trim();
            if (!trimmed)
                continue;
            const parts = trimmed.split(/\s+/);
            if (parts.length < 5)
                continue;
            const pidStr = parts[parts.length - 1];
            if (!/^\d+$/.test(pidStr))
                continue;
            const pid = parseInt(pidStr, 10);
            if (pid <= 0)
                continue;
            const portSuffix = `:${port}`;
            const mentionsPort = parts.some((p) => p.endsWith(portSuffix));
            if (!mentionsPort)
                continue;
            const state = (parts[parts.length - 2] ?? '').toUpperCase();
            if (state === 'LISTENING') {
                return pid;
            }
        }
        return null;
    }
    catch {
        return null;
    }
}
/** Image name from tasklist CSV (e.g. node.exe) */
export function getWindowsProcessImageName(pid) {
    if (process.platform !== 'win32' || pid <= 0)
        return null;
    try {
        const out = execSync(`tasklist /FI "PID eq ${pid}" /FO CSV`, {
            encoding: 'utf-8',
            windowsHide: true,
        });
        const lines = out.split(/\r?\n/).filter((l) => l.trim().length > 0);
        if (lines.length < 2)
            return null;
        const name = lines[1].split(',')[0]?.replace(/^"|"$/g, '');
        return name?.trim() || null;
    }
    catch {
        return null;
    }
}
/**
 * Kill a process and all descendants on Windows (critical for npm-run Gateway children).
 */
export function killPidTreeWindows(pid) {
    if (process.platform !== 'win32' || pid <= 0)
        return false;
    try {
        execSync(`taskkill /PID ${pid} /T /F`, {
            stdio: 'ignore',
            windowsHide: true,
            timeout: 20000,
        });
        return true;
    }
    catch {
        return false;
    }
}
//# sourceMappingURL=win-port-pid.js.map