import * as plugins from '../../plugins.js';
import * as interfaces from '../../../dist_ts_interfaces/index.js';
import { MetricsManager } from '../../monitoring/index.js';
import { SecurityLogger } from '../../security/classes.securitylogger.js';
import { commitinfo } from '../../00_commitinfo_data.js';
import { requireOpsAuth } from '../helpers/auth.js';
export class StatsHandler {
    opsServerRef;
    constructor(opsServerRef) {
        this.opsServerRef = opsServerRef;
        this.registerHandlers();
    }
    registerHandlers() {
        // All stats endpoints register directly on viewRouter (valid identity required via middleware)
        const router = this.opsServerRef.viewRouter;
        // Server Statistics Handler
        router.addTypedHandler(new plugins.typedrequest.TypedHandler('getServerStatistics', async (dataArg, toolsArg) => {
            await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'stats:read' });
            const stats = await this.collectServerStats();
            return {
                stats: {
                    uptime: stats.uptime,
                    startTime: Date.now() - (stats.uptime * 1000),
                    memoryUsage: stats.memoryUsage,
                    cpuUsage: stats.cpuUsage,
                    activeConnections: stats.activeConnections,
                    totalConnections: stats.totalConnections,
                    requestsPerSecond: stats.requestsPerSecond,
                    throughput: stats.throughput,
                },
                history: dataArg.includeHistory ? stats.history : undefined,
            };
        }));
        // Email Statistics Handler
        router.addTypedHandler(new plugins.typedrequest.TypedHandler('getEmailStatistics', async (dataArg, toolsArg) => {
            await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'stats:read' });
            const emailServer = this.opsServerRef.dcRouterRef.emailServer;
            if (!emailServer) {
                return {
                    stats: {
                        sent: 0,
                        received: 0,
                        bounced: 0,
                        queued: 0,
                        failed: 0,
                        averageDeliveryTime: 0,
                        deliveryRate: 0,
                        bounceRate: 0,
                    },
                };
            }
            const stats = await this.collectEmailStats();
            return {
                stats: {
                    sent: stats.sentToday,
                    received: stats.receivedToday,
                    bounced: Math.floor(stats.sentToday * stats.bounceRate / 100),
                    queued: stats.queueSize,
                    failed: 0,
                    averageDeliveryTime: 0,
                    deliveryRate: stats.deliveryRate,
                    bounceRate: stats.bounceRate,
                },
                domainBreakdown: dataArg.includeDetails ? stats.domainBreakdown : undefined,
            };
        }));
        // DNS Statistics Handler
        router.addTypedHandler(new plugins.typedrequest.TypedHandler('getDnsStatistics', async (dataArg, toolsArg) => {
            await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'stats:read' });
            const dnsServer = this.opsServerRef.dcRouterRef.dnsServer;
            if (!dnsServer) {
                return {
                    stats: {
                        totalQueries: 0,
                        cacheHits: 0,
                        cacheMisses: 0,
                        cacheHitRate: 0,
                        activeDomains: 0,
                        averageResponseTime: 0,
                        queryTypes: {},
                    },
                };
            }
            const stats = await this.collectDnsStats();
            return {
                stats: {
                    totalQueries: stats.totalQueries,
                    cacheHits: stats.cacheHits,
                    cacheMisses: stats.cacheMisses,
                    cacheHitRate: stats.cacheHitRate,
                    activeDomains: stats.topDomains.length,
                    averageResponseTime: 0,
                    queryTypes: stats.queryTypes,
                },
                domainBreakdown: dataArg.includeQueryTypes ? stats.domainBreakdown : undefined,
            };
        }));
        // Queue Status Handler
        router.addTypedHandler(new plugins.typedrequest.TypedHandler('getQueueStatus', async (dataArg, toolsArg) => {
            await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'stats:read' });
            const emailServer = this.opsServerRef.dcRouterRef.emailServer;
            const queues = [];
            if (emailServer) {
                const status = await this.getQueueStatus();
                queues.push({
                    name: dataArg.queueName || 'default',
                    size: status.pending,
                    processing: status.active,
                    failed: status.failed,
                    retrying: status.retrying,
                    averageProcessingTime: 0,
                });
            }
            return {
                queues,
                totalItems: queues.reduce((sum, q) => sum + q.size + q.processing + q.failed + q.retrying, 0),
            };
        }));
        // Health Status Handler
        router.addTypedHandler(new plugins.typedrequest.TypedHandler('getHealthStatus', async (dataArg, toolsArg) => {
            await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'stats:read' });
            const health = await this.checkHealthStatus();
            return {
                health: {
                    healthy: health.healthy,
                    uptime: process.uptime(),
                    services: health.services.reduce((acc, service) => {
                        acc[service.name] = {
                            status: service.status,
                            message: service.message,
                            lastCheck: Date.now(),
                        };
                        return acc;
                    }, {}),
                    version: commitinfo.version,
                },
            };
        }));
        // Combined Metrics Handler - More efficient for frontend polling
        router.addTypedHandler(new plugins.typedrequest.TypedHandler('getCombinedMetrics', async (dataArg, toolsArg) => {
            await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'stats:read' });
            const sections = dataArg.sections || {
                server: true,
                email: true,
                dns: true,
                security: true,
                network: true,
            };
            const metrics = {};
            // Run all metrics collection in parallel
            const promises = [];
            if (sections.server) {
                promises.push(this.collectServerStats().then(stats => {
                    metrics.server = {
                        uptime: stats.uptime,
                        startTime: Date.now() - (stats.uptime * 1000),
                        memoryUsage: stats.memoryUsage,
                        cpuUsage: stats.cpuUsage,
                        activeConnections: stats.activeConnections,
                        totalConnections: stats.totalConnections,
                        requestsPerSecond: stats.requestsPerSecond,
                        throughput: stats.throughput,
                    };
                }));
            }
            if (sections.email) {
                promises.push(this.collectEmailStats().then(stats => {
                    // Get time-series data from MetricsManager
                    const timeSeries = this.opsServerRef.dcRouterRef.metricsManager
                        ? this.opsServerRef.dcRouterRef.metricsManager.getEmailTimeSeries(24)
                        : undefined;
                    metrics.email = {
                        sent: stats.sentToday,
                        received: stats.receivedToday,
                        bounced: Math.floor(stats.sentToday * stats.bounceRate / 100),
                        queued: stats.queueSize,
                        failed: 0,
                        averageDeliveryTime: 0,
                        deliveryRate: stats.deliveryRate,
                        bounceRate: stats.bounceRate,
                        timeSeries,
                    };
                }));
            }
            if (sections.dns) {
                promises.push(this.collectDnsStats().then(stats => {
                    // Get time-series data from MetricsManager
                    const timeSeries = this.opsServerRef.dcRouterRef.metricsManager
                        ? this.opsServerRef.dcRouterRef.metricsManager.getDnsTimeSeries(24)
                        : undefined;
                    metrics.dns = {
                        totalQueries: stats.totalQueries,
                        cacheHits: stats.cacheHits,
                        cacheMisses: stats.cacheMisses,
                        cacheHitRate: stats.cacheHitRate,
                        activeDomains: stats.topDomains.length,
                        averageResponseTime: 0,
                        queryTypes: stats.queryTypes,
                        timeSeries,
                        recentQueries: stats.recentQueries,
                    };
                }));
            }
            if (sections.security && this.opsServerRef.dcRouterRef.metricsManager) {
                promises.push(this.opsServerRef.dcRouterRef.metricsManager.getSecurityStats().then(stats => {
                    // Get recent events from the SecurityLogger singleton
                    const securityLogger = SecurityLogger.getInstance();
                    const recentEvents = securityLogger.getRecentEvents(50).map((evt) => ({
                        timestamp: evt.timestamp,
                        level: evt.level,
                        type: evt.type,
                        message: evt.message,
                        details: evt.details,
                        ipAddress: evt.ipAddress,
                        domain: evt.domain,
                        success: evt.success,
                    }));
                    metrics.security = {
                        blockedIPs: stats.blockedIPs,
                        reputationScores: {},
                        spamDetected: stats.spamDetected,
                        malwareDetected: stats.malwareDetected,
                        phishingDetected: stats.phishingDetected,
                        authenticationFailures: stats.authFailures,
                        suspiciousActivities: stats.totalThreatsBlocked,
                        recentEvents,
                    };
                }));
            }
            if (sections.network && this.opsServerRef.dcRouterRef.metricsManager) {
                promises.push((async () => {
                    const stats = await this.opsServerRef.dcRouterRef.metricsManager.getNetworkStats();
                    const serverStats = await this.collectServerStats();
                    // Build per-IP bandwidth lookup from throughputByIP
                    const ipBandwidth = new Map();
                    if (stats.throughputByIP) {
                        for (const [ip, tp] of stats.throughputByIP) {
                            ipBandwidth.set(ip, { in: tp.in, out: tp.out });
                        }
                    }
                    // Build connectionDetails from real per-IP data
                    const connectionDetails = [];
                    for (const [ip, count] of stats.connectionsByIP) {
                        const tp = stats.throughputByIP?.get(ip);
                        connectionDetails.push({
                            remoteAddress: ip,
                            protocol: 'https',
                            state: 'connected',
                            startTime: 0,
                            bytesIn: tp?.in || 0,
                            bytesOut: tp?.out || 0,
                            connectionCount: count,
                        });
                    }
                    metrics.network = {
                        totalBandwidth: {
                            in: stats.throughputRate.bytesInPerSecond,
                            out: stats.throughputRate.bytesOutPerSecond,
                        },
                        totalBytes: {
                            in: stats.totalDataTransferred.bytesIn,
                            out: stats.totalDataTransferred.bytesOut,
                        },
                        activeConnections: serverStats.activeConnections,
                        connectionDetails,
                        topEndpoints: stats.topIPs.map(ip => ({
                            endpoint: ip.ip,
                            connections: ip.count,
                            bandwidth: ipBandwidth.get(ip.ip) || { in: 0, out: 0 },
                        })),
                        topEndpointsByBandwidth: stats.topIPsByBandwidth.map(ip => ({
                            endpoint: ip.ip,
                            connections: ip.count,
                            bandwidth: { in: ip.bwIn, out: ip.bwOut },
                        })),
                        topASNs: stats.topASNs || [],
                        domainActivity: stats.domainActivity || [],
                        throughputHistory: stats.throughputHistory || [],
                        requestsPerSecond: stats.requestsPerSecond || 0,
                        requestsTotal: stats.requestsTotal || 0,
                        backends: stats.backends || [],
                        frontendProtocols: stats.frontendProtocols || null,
                        backendProtocols: stats.backendProtocols || null,
                    };
                })());
            }
            if (sections.radius) {
                promises.push((async () => {
                    const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
                    if (!radiusServer)
                        return;
                    const stats = radiusServer.getStats();
                    const accountingStats = radiusServer.getAccountingManager().getStats();
                    metrics.radius = {
                        running: stats.running,
                        uptime: stats.uptime,
                        authRequests: stats.authRequests,
                        authAccepts: stats.authAccepts,
                        authRejects: stats.authRejects,
                        accountingRequests: stats.accountingRequests,
                        activeSessions: stats.activeSessions,
                        totalInputBytes: accountingStats.totalInputBytes,
                        totalOutputBytes: accountingStats.totalOutputBytes,
                    };
                })());
            }
            if (sections.vpn) {
                promises.push((async () => {
                    const vpnManager = this.opsServerRef.dcRouterRef.vpnManager;
                    const vpnConfig = this.opsServerRef.dcRouterRef.options.vpnConfig;
                    if (!vpnManager)
                        return;
                    const connected = await vpnManager.getConnectedClients();
                    metrics.vpn = {
                        running: vpnManager.running,
                        subnet: vpnManager.getSubnet(),
                        registeredClients: vpnManager.listClients().length,
                        connectedClients: connected.length,
                        wgListenPort: vpnConfig?.wgListenPort ?? 51820,
                    };
                })());
            }
            await Promise.all(promises);
            return {
                metrics,
                timestamp: Date.now(),
            };
        }));
    }
    async collectServerStats() {
        // Get metrics from MetricsManager if available
        if (this.opsServerRef.dcRouterRef.metricsManager) {
            const serverStats = await this.opsServerRef.dcRouterRef.metricsManager.getServerStats();
            return {
                uptime: serverStats.uptime,
                cpuUsage: serverStats.cpuUsage,
                memoryUsage: serverStats.memoryUsage,
                requestsPerSecond: serverStats.requestsPerSecond,
                activeConnections: serverStats.activeConnections,
                totalConnections: serverStats.totalConnections,
                throughput: serverStats.throughput,
                history: [], // TODO: Implement history tracking
            };
        }
        // Fallback to basic stats if MetricsManager not available
        const uptime = process.uptime();
        const memUsage = process.memoryUsage();
        const cpuUsage = plugins.os.loadavg()[0] * 100 / plugins.os.cpus().length;
        return {
            uptime,
            cpuUsage: {
                user: cpuUsage * 0.7,
                system: cpuUsage * 0.3,
            },
            memoryUsage: {
                heapUsed: memUsage.heapUsed,
                heapTotal: memUsage.heapTotal,
                external: memUsage.external,
                rss: memUsage.rss,
            },
            requestsPerSecond: 0,
            activeConnections: 0,
            totalConnections: 0,
            throughput: { bytesIn: 0, bytesOut: 0, bytesInPerSecond: 0, bytesOutPerSecond: 0 },
            history: [],
        };
    }
    async collectEmailStats() {
        // Get metrics from MetricsManager if available
        if (this.opsServerRef.dcRouterRef.metricsManager) {
            const emailStats = await this.opsServerRef.dcRouterRef.metricsManager.getEmailStats();
            return {
                sentToday: emailStats.sentToday,
                receivedToday: emailStats.receivedToday,
                bounceRate: emailStats.bounceRate,
                deliveryRate: emailStats.deliveryRate,
                queueSize: emailStats.queueSize,
            };
        }
        // Fallback if MetricsManager not available
        return {
            sentToday: 0,
            receivedToday: 0,
            bounceRate: 0,
            deliveryRate: 100,
            queueSize: 0,
        };
    }
    async collectDnsStats() {
        // Get metrics from MetricsManager if available
        if (this.opsServerRef.dcRouterRef.metricsManager) {
            const dnsStats = await this.opsServerRef.dcRouterRef.metricsManager.getDnsStats();
            return {
                queriesPerSecond: dnsStats.queriesPerSecond,
                totalQueries: dnsStats.totalQueries,
                cacheHits: dnsStats.cacheHits,
                cacheMisses: dnsStats.cacheMisses,
                cacheHitRate: dnsStats.cacheHitRate,
                topDomains: dnsStats.topDomains,
                queryTypes: dnsStats.queryTypes,
                recentQueries: dnsStats.recentQueries,
            };
        }
        // Fallback if MetricsManager not available
        return {
            queriesPerSecond: 0,
            totalQueries: 0,
            cacheHits: 0,
            cacheMisses: 0,
            cacheHitRate: 0,
            topDomains: [],
            queryTypes: {},
        };
    }
    async getQueueStatus() {
        const emailServer = this.opsServerRef.dcRouterRef.emailServer;
        if (!emailServer) {
            return {
                pending: 0,
                active: 0,
                failed: 0,
                retrying: 0,
                items: [],
            };
        }
        const queueStats = emailServer.getQueueStats();
        const items = emailServer.getQueueItems()
            .sort((a, b) => {
            const left = a.createdAt instanceof Date ? a.createdAt.getTime() : new Date(a.createdAt).getTime();
            const right = b.createdAt instanceof Date ? b.createdAt.getTime() : new Date(b.createdAt).getTime();
            return right - left;
        })
            .slice(0, 50)
            .map((item) => {
            const emailLike = item.processingResult;
            const recipients = Array.isArray(emailLike?.to)
                ? emailLike.to
                : Array.isArray(emailLike?.email?.to)
                    ? emailLike.email.to
                    : [];
            const subject = emailLike?.subject || emailLike?.email?.subject || '';
            return {
                id: item.id,
                recipient: recipients[0] || '',
                subject,
                status: item.status,
                attempts: item.attempts,
                nextRetry: item.nextAttempt instanceof Date ? item.nextAttempt.getTime() : undefined,
            };
        });
        return {
            pending: queueStats.status.pending,
            active: queueStats.status.processing,
            failed: queueStats.status.failed,
            retrying: queueStats.status.deferred,
            items,
        };
    }
    async checkHealthStatus() {
        const dcRouter = this.opsServerRef.dcRouterRef;
        const health = dcRouter.serviceManager.getHealth();
        const services = health.services.map((svc) => {
            let status;
            switch (svc.state) {
                case 'running':
                    status = 'healthy';
                    break;
                case 'starting':
                case 'degraded':
                    status = 'degraded';
                    break;
                case 'failed':
                    status = svc.criticality === 'critical' ? 'unhealthy' : 'degraded';
                    break;
                case 'stopped':
                case 'stopping':
                default:
                    status = 'degraded';
                    break;
            }
            let message;
            if (svc.state === 'failed' && svc.lastError) {
                message = svc.lastError;
            }
            else if (svc.retryCount > 0 && svc.state !== 'running') {
                message = `Retry attempt ${svc.retryCount}`;
            }
            return { name: svc.name, status, message };
        });
        const healthy = health.overall === 'healthy';
        return {
            healthy,
            services,
            checks: [
                {
                    name: 'Memory Usage',
                    passed: process.memoryUsage().heapUsed < (plugins.os.totalmem() * 0.9),
                    message: 'Memory usage within limits',
                },
            ],
        };
    }
}
//# sourceMappingURL=data:application/json;base64, 