import { getMetricsCollector } from './classes.metrics.js';
import { getServiceWorkerInstance } from './init.js';
import { getPersistentStore } from './classes.persistentstore.js';
import { getRequestLogStore } from './classes.requestlogstore.js';
import * as interfaces from './env.js';
/**
 * Dashboard generator that creates a terminal-like metrics display
 * served directly from the service worker as a single-page app
 */
export class DashboardGenerator {
    /**
     * Serves the dashboard HTML page
     */
    serveDashboard() {
        return new Response(this.generateDashboardHtml(), {
            headers: {
                'Content-Type': 'text/html; charset=utf-8',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Serves the metrics JSON endpoint with ALL initial data
     * This is the single HTTP seed request that provides:
     * - Current metrics
     * - Initial events (last 50)
     * - Initial request logs (last 50)
     * - Request stats and methods
     * - Resource data
     */
    async serveMetrics() {
        try {
            const metrics = getMetricsCollector();
            const persistentStore = getPersistentStore();
            await persistentStore.init();
            const requestLogStore = getRequestLogStore();
            // Get event data
            const eventResult = await persistentStore.getEventLog({ limit: 50 });
            const oneHourAgo = Date.now() - 3600000;
            const eventCountLastHour = await persistentStore.getEventCount(oneHourAgo);
            // Build comprehensive initial response
            const data = {
                // Core metrics
                ...metrics.getMetrics(),
                cacheHitRate: metrics.getCacheHitRate(),
                networkSuccessRate: metrics.getNetworkSuccessRate(),
                resourceCount: metrics.getResourceCount(),
                summary: metrics.getSummary(),
                // Resources data
                resources: metrics.getCachedResources(),
                domains: metrics.getDomainStats(),
                contentTypes: metrics.getContentTypeStats(),
                // Events data (initial 50)
                events: eventResult.events,
                eventTotalCount: eventResult.totalCount,
                eventCountLastHour,
                // Request logs data (initial 50)
                requestLogs: requestLogStore.getEntries({ limit: 50 }),
                requestTotalCount: requestLogStore.getTotalCount(),
                requestStats: requestLogStore.getStats(),
                requestMethods: requestLogStore.getMethods(),
            };
            return new Response(JSON.stringify(data), {
                headers: {
                    'Content-Type': 'application/json',
                    'Cache-Control': 'no-store',
                },
            });
        }
        catch (error) {
            console.error('[SW Dashboard] serveMetrics error:', error);
            // Return error response with valid JSON structure so client doesn't crash
            return new Response(JSON.stringify({
                error: String(error),
                cache: { hits: 0, misses: 0, errors: 0, bytesServedFromCache: 0, bytesFetched: 0, averageResponseTime: 0 },
                network: { totalRequests: 0, successfulRequests: 0, failedRequests: 0, timeouts: 0, averageLatency: 0, totalBytesTransferred: 0 },
                update: { totalChecks: 0, successfulChecks: 0, failedChecks: 0, updatesFound: 0, updatesApplied: 0, lastCheckTimestamp: 0, lastUpdateTimestamp: 0 },
                connection: { connectedClients: 0, totalConnectionAttempts: 0, successfulConnections: 0, failedConnections: 0 },
                speedtest: { lastDownloadSpeedMbps: 0, lastUploadSpeedMbps: 0, lastLatencyMs: 0, lastTestTimestamp: 0, testCount: 0, isOnline: false },
                startTime: Date.now(),
                uptime: 0,
                cacheHitRate: 0,
                networkSuccessRate: 0,
                resourceCount: 0,
                events: [],
                eventTotalCount: 0,
                eventCountLastHour: 0,
                requestLogs: [],
                requestTotalCount: 0,
                requestStats: { totalRequests: 0, totalResponses: 0, methodCounts: {}, errorCount: 0, avgDurationMs: 0 },
                requestMethods: [],
            }), {
                headers: {
                    'Content-Type': 'application/json',
                    'Cache-Control': 'no-store',
                },
            });
        }
    }
    /**
     * Serves detailed resource data for the SPA views
     */
    serveResources() {
        return new Response(this.generateResourcesJson(), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Serves event log data
     */
    async serveEventLog(searchParams) {
        const persistentStore = getPersistentStore();
        await persistentStore.init();
        const limit = searchParams.get('limit') ? parseInt(searchParams.get('limit'), 10) : undefined;
        const type = searchParams.get('type');
        const since = searchParams.get('since') ? parseInt(searchParams.get('since'), 10) : undefined;
        const result = await persistentStore.getEventLog({ limit, type, since });
        return new Response(JSON.stringify(result), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Serves event count since a timestamp
     */
    async serveEventCount(searchParams) {
        const persistentStore = getPersistentStore();
        await persistentStore.init();
        const since = searchParams.get('since') ? parseInt(searchParams.get('since'), 10) : Date.now() - 3600000; // Default: last hour
        const count = await persistentStore.getEventCount(since);
        return new Response(JSON.stringify({ count, since }), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Serves cumulative metrics
     */
    async serveCumulativeMetrics() {
        const persistentStore = getPersistentStore();
        await persistentStore.init();
        const metrics = persistentStore.getCumulativeMetrics();
        return new Response(JSON.stringify(metrics), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Clears the event log
     */
    async clearEventLog() {
        const persistentStore = getPersistentStore();
        await persistentStore.init();
        const success = await persistentStore.clearEventLog();
        return new Response(JSON.stringify({ success }), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    // ================================
    // TypedRequest Traffic Endpoints
    // ================================
    /**
     * Serves TypedRequest traffic logs
     */
    serveTypedRequestLogs(searchParams) {
        const requestLogStore = getRequestLogStore();
        const limit = searchParams.get('limit') ? parseInt(searchParams.get('limit'), 10) : undefined;
        const method = searchParams.get('method') || undefined;
        const since = searchParams.get('since') ? parseInt(searchParams.get('since'), 10) : undefined;
        const logs = requestLogStore.getEntries({ limit, method, since });
        const totalCount = requestLogStore.getTotalCount({ method, since });
        return new Response(JSON.stringify({ logs, totalCount }), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Serves TypedRequest traffic statistics
     */
    serveTypedRequestStats() {
        const requestLogStore = getRequestLogStore();
        const stats = requestLogStore.getStats();
        return new Response(JSON.stringify(stats), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Clears TypedRequest traffic logs
     */
    clearTypedRequestLogs() {
        const requestLogStore = getRequestLogStore();
        requestLogStore.clear();
        return new Response(JSON.stringify({ success: true }), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Serves unique method names from TypedRequest logs
     */
    serveTypedRequestMethods() {
        const requestLogStore = getRequestLogStore();
        const methods = requestLogStore.getMethods();
        return new Response(JSON.stringify({ methods }), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    // Speedtest configuration
    static TEST_DURATION_MS = 5000; // 5 seconds per test
    static CHUNK_SIZE_KB = 64; // 64KB chunks
    /**
     * Runs a time-based speedtest and returns the results
     * Each test (download/upload) runs for TEST_DURATION_MS, transferring chunks continuously
     */
    async runSpeedtest() {
        const metrics = getMetricsCollector();
        const persistentStore = getPersistentStore();
        await persistentStore.init();
        const results = { isOnline: false };
        // Log speedtest start
        await persistentStore.logEvent('speedtest_started', 'Speedtest initiated');
        try {
            const sw = getServiceWorkerInstance();
            // Check if TypedSocket is connected
            if (!sw.typedsocket) {
                results.error = 'TypedSocket not connected';
                return new Response(JSON.stringify(results), {
                    headers: {
                        'Content-Type': 'application/json',
                        'Cache-Control': 'no-store',
                    },
                });
            }
            // Create typed request for speedtest
            const speedtestRequest = sw.typedsocket.createTypedRequest('serviceworker_speedtest');
            // Latency test - simple ping
            const latencyStart = Date.now();
            await speedtestRequest.fire({ type: 'latency' });
            const latencyDuration = Date.now() - latencyStart;
            results.latency = { durationMs: latencyDuration };
            metrics.recordSpeedtest('latency', latencyDuration);
            results.isOnline = true;
            metrics.setOnlineStatus(true);
            // Download test - request chunks for TEST_DURATION_MS
            {
                const downloadStart = Date.now();
                let totalBytes = 0;
                while (Date.now() - downloadStart < DashboardGenerator.TEST_DURATION_MS) {
                    const chunkResult = await speedtestRequest.fire({
                        type: 'download_chunk',
                        chunkSizeKB: DashboardGenerator.CHUNK_SIZE_KB,
                    });
                    totalBytes += chunkResult.bytesTransferred;
                }
                const downloadDuration = Date.now() - downloadStart;
                const downloadSpeedMbps = downloadDuration > 0 ? (totalBytes * 8) / (downloadDuration * 1000) : 0;
                results.download = { durationMs: downloadDuration, speedMbps: downloadSpeedMbps, bytesTransferred: totalBytes };
                metrics.recordSpeedtest('download', downloadSpeedMbps);
            }
            // Upload test - send chunks for TEST_DURATION_MS
            {
                const uploadPayload = 'x'.repeat(DashboardGenerator.CHUNK_SIZE_KB * 1024);
                const uploadStart = Date.now();
                let totalBytes = 0;
                while (Date.now() - uploadStart < DashboardGenerator.TEST_DURATION_MS) {
                    const chunkResult = await speedtestRequest.fire({
                        type: 'upload_chunk',
                        payload: uploadPayload,
                    });
                    totalBytes += chunkResult.bytesTransferred;
                }
                const uploadDuration = Date.now() - uploadStart;
                const uploadSpeedMbps = uploadDuration > 0 ? (totalBytes * 8) / (uploadDuration * 1000) : 0;
                results.upload = { durationMs: uploadDuration, speedMbps: uploadSpeedMbps, bytesTransferred: totalBytes };
                metrics.recordSpeedtest('upload', uploadSpeedMbps);
            }
            // Log speedtest completion
            await persistentStore.logEvent('speedtest_completed', 'Speedtest finished', {
                downloadMbps: results.download?.speedMbps.toFixed(2),
                uploadMbps: results.upload?.speedMbps.toFixed(2),
                latencyMs: results.latency?.durationMs,
            });
        }
        catch (error) {
            results.error = error instanceof Error ? error.message : String(error);
            results.isOnline = false;
            metrics.setOnlineStatus(false);
            // Log speedtest failure
            await persistentStore.logEvent('speedtest_failed', `Speedtest failed: ${results.error}`, {
                error: results.error,
            });
        }
        return new Response(JSON.stringify(results), {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
            },
        });
    }
    /**
     * Generates JSON metrics response
     */
    generateMetricsJson() {
        const metrics = getMetricsCollector();
        return JSON.stringify({
            ...metrics.getMetrics(),
            cacheHitRate: metrics.getCacheHitRate(),
            networkSuccessRate: metrics.getNetworkSuccessRate(),
            resourceCount: metrics.getResourceCount(),
            summary: metrics.getSummary(),
        });
    }
    /**
     * Generates JSON response with detailed resource data
     */
    generateResourcesJson() {
        const metrics = getMetricsCollector();
        return JSON.stringify({
            resources: metrics.getCachedResources(),
            domains: metrics.getDomainStats(),
            contentTypes: metrics.getContentTypeStats(),
            resourceCount: metrics.getResourceCount(),
        });
    }
    /**
     * Generates a minimal HTML shell that loads the Lit-based dashboard bundle
     */
    generateDashboardHtml() {
        return interfaces.serviceworker.SW_DASH_HTML;
    }
}
// Export singleton getter
let dashboardInstance = null;
export const getDashboardGenerator = () => {
    if (!dashboardInstance) {
        dashboardInstance = new DashboardGenerator();
    }
    return dashboardInstance;
};
//# sourceMappingURL=data:application/json;base64, 