"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.LoginSessionCollector = 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 LoginSessionCollector {
    constructor() {
        this.lastCollectTime = new Date(Date.now() - 86400000); // 24h ago
    }
    async collect() {
        if (process.platform === 'win32') {
            return this.collectWindows();
        }
        return this.collectLinux();
    }
    /** Collect idle time in milliseconds for the current interactive session */
    async getIdleTime() {
        if (process.platform === 'win32') {
            return this.getIdleTimeWindows();
        }
        return 0;
    }
    collectWindows() {
        return new Promise((resolve) => {
            const scriptContent = `
$ErrorActionPreference = 'SilentlyContinue'
$sessions = @()

function Convert-LogonType($value) {
  switch ([string]$value) {
    '2' { 'interactive' }
    '10' { 'rdp' }
    '11' { 'cached' }
    default { if ([string]::IsNullOrWhiteSpace([string]$value)) { 'other' } else { [string]$value } }
  }
}

# Current logged on sessions via query user
try {
  $quResult = query user 2>$null
  if ($quResult) {
    $quResult | Select-Object -Skip 1 | ForEach-Object {
      $line = $_ -replace '\\s{2,}', '|'
      $parts = $line.Trim().TrimStart('>').Split('|')
      if ($parts.Length -ge 4) {
        $username = $parts[0].Trim()
        $sessionName = $parts[1].Trim()
        $idleStr = if($parts.Length -ge 5){$parts[3].Trim()}else{'.'}
        $logonStr = if($parts.Length -ge 6){$parts[4].Trim() + ' ' + $parts[5].Trim()}else{$parts[3].Trim() + ' ' + $parts[4].Trim()}

        $idleMs = 0
        if ($idleStr -match '(\\d+)\\+(\\d+):(\\d+)') {
          $idleMs = ([int]$Matches[1]*86400 + [int]$Matches[2]*3600 + [int]$Matches[3]*60) * 1000
        } elseif ($idleStr -match '(\\d+):(\\d+)') {
          $idleMs = ([int]$Matches[1]*3600 + [int]$Matches[2]*60) * 1000
        } elseif ($idleStr -match '^(\\d+)$') {
          $idleMs = [int]$Matches[1] * 60000
        }

        $lt = try{[DateTime]::Parse($logonStr).ToString('o')}catch{[DateTime]::Now.ToString('o')}
        $st = if($sessionName -match 'console'){'console'}elseif($sessionName -match 'rdp'){'rdp'}else{'interactive'}
        $sessions += [PSCustomObject]@{
          username = $username
          sessionType = $st
          loginTime = $lt
          logoutTime = $null
          duration = 0
          ipAddress = ''
          isActive = $true
          sourceHost = ''
          sourcePort = $null
          authMethod = ''
          idleMs = $idleMs
        }
      }
    }
  }
} catch {}

# Recent logon events from Security log
try {
  $logonEvents = Get-WinEvent -FilterHashtable @{
    LogName = 'Security'; Id = 4624; StartTime = (Get-Date).AddHours(-24)
  } -MaxEvents 20 -ErrorAction SilentlyContinue

  foreach ($e in $logonEvents) {
    $xml = [xml]$e.ToXml()
    $data = @{}
    foreach ($node in $xml.Event.EventData.Data) {
      if ($node.Name) { $data[$node.Name] = [string]$node.'#text' }
    }
    $logonType = [string]$data.LogonType
    # Only interactive (2), remote interactive (10), cached (11)
    if ($logonType -in '2','10','11') {
      $user = [string]$data.TargetUserName
      $ip = [string]$data.IpAddress
      $domain = [string]$data.TargetDomainName

      # Skip system/service accounts
      if ($user -notmatch '\\$$|^(SYSTEM|LOCAL SERVICE|NETWORK SERVICE|DWM-|UMFD-|ANONYMOUS)') {
        $un2 = if($domain){"$domain\\$user"}else{$user}
        $st2 = Convert-LogonType $logonType
        $ip2 = if($ip -and $ip -ne '-'){$ip}else{''}
        $ipPort = [string]$data.IpPort
        if ($ipPort -eq '-') { $ipPort = '' }
        $sessions += [PSCustomObject]@{
          username = $un2
          sessionType = $st2
          loginTime = $e.TimeCreated.ToString('o')
          logoutTime = $null
          duration = 0
          ipAddress = $ip2
          isActive = $false
          sourceHost = [string]$data.WorkstationName
          sourcePort = if ($ipPort) { [int]$ipPort } else { $null }
          authMethod = if ($data.AuthenticationPackageName) { [string]$data.AuthenticationPackageName } else { [string]$data.LogonProcessName }
          idleMs = 0
        }
      }
    }
  }
} catch {}

if ($sessions.Count -gt 0) {
  $sessions | ConvertTo-Json -Depth 3 -Compress
} else {
  Write-Output '[]'
}
`;
            const scriptPath = path.join(os.tmpdir(), 'appstats-logins.ps1');
            try {
                fs.writeFileSync(scriptPath, scriptContent, 'utf-8');
            }
            catch (writeErr) {
                logger_1.logger.error(`Failed to write login sessions script: ${writeErr.message}`);
                resolve([]);
                return;
            }
            (0, child_process_1.execFile)('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath], { timeout: 30000, maxBuffer: 1024 * 1024 }, (err, stdout, stderr) => {
                this.lastCollectTime = new Date();
                if (err) {
                    logger_1.logger.warn(`Login session collection error: ${err.message}${stderr ? ' stderr: ' + stderr.substring(0, 200) : ''}`);
                    resolve([]);
                    return;
                }
                try {
                    const raw = stdout.trim();
                    if (!raw || raw === 'null' || raw === '') {
                        resolve([]);
                        return;
                    }
                    let parsed = JSON.parse(raw);
                    if (!Array.isArray(parsed))
                        parsed = [parsed];
                    logger_1.logger.info(`Login sessions collected: ${parsed.length} sessions`);
                    resolve(parsed);
                }
                catch (parseErr) {
                    logger_1.logger.warn(`Login sessions parse error: ${parseErr.message}, raw length: ${stdout.length}`);
                    resolve([]);
                }
            });
        });
    }
    getIdleTimeWindows() {
        return new Promise((resolve) => {
            const scriptContent = `
Add-Type @'
using System;
using System.Runtime.InteropServices;
public struct LASTINPUTINFO { public uint cbSize; public uint dwTime; }
public class IdleTime {
  [DllImport("user32.dll")] public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
  public static uint Get() {
    LASTINPUTINFO lii = new LASTINPUTINFO();
    lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
    GetLastInputInfo(ref lii);
    return ((uint)Environment.TickCount - lii.dwTime);
  }
}
'@
[IdleTime]::Get()
`;
            const scriptPath = path.join(os.tmpdir(), 'appstats-idle.ps1');
            try {
                fs.writeFileSync(scriptPath, scriptContent, 'utf-8');
            }
            catch {
                resolve(0);
                return;
            }
            (0, child_process_1.execFile)('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath], { timeout: 5000 }, (err, stdout) => {
                if (err) {
                    resolve(0);
                    return;
                }
                resolve(parseInt(stdout.trim()) || 0);
            });
        });
    }
    collectLinux() {
        return new Promise((resolve) => {
            (0, child_process_1.execFile)('sh', ['-c', 'who -u 2>/dev/null || w -h 2>/dev/null'], { timeout: 5000 }, (err, stdout) => {
                this.lastCollectTime = new Date();
                if (err) {
                    resolve([]);
                    return;
                }
                try {
                    const sessions = stdout.trim().split('\n')
                        .filter((line) => line.trim())
                        .map((line) => {
                        const parts = line.trim().split(/\s+/);
                        return {
                            username: parts[0] || 'unknown',
                            sessionType: parts[1]?.includes('pts') ? 'ssh' : 'console',
                            loginTime: new Date().toISOString(),
                            logoutTime: null,
                            duration: 0,
                            ipAddress: parts.find((p) => p.match(/\d+\.\d+\.\d+\.\d+/)) || '',
                            isActive: true,
                            sourceHost: '',
                            sourcePort: null,
                            authMethod: parts[1]?.includes('pts') ? 'ssh' : '',
                        };
                    });
                    resolve(sessions);
                }
                catch {
                    resolve([]);
                }
            });
        });
    }
}
exports.LoginSessionCollector = LoginSessionCollector;
//# sourceMappingURL=login-sessions.js.map