/**
 * Shared SSE service for dashboard components.
 * Manages a single EventSource connection and distributes events to subscribers.
 */
(function(globalThis) {
    'use strict';
    
    class SSEService {
        constructor() {
            this.eventSource = null;
            this.subscribers = new Map();
            this.isConnecting = false;
            this.reconnectDelay = 1000;
            this.maxReconnectDelay = 30000;
            this.connectionState = "disconnected";
            this.connectAttempts = 0;
        }
        
        /**
         * Subscribe to specific event types
         * @param {string} id - Unique subscriber ID
         * @param {Set<string>} eventTypes - Event types to listen for
         * @param {Function} callback - Callback function for events
         */
        subscribe(id, eventTypes, callback) {
            this.subscribers.set(id, { eventTypes, callback });
            
            if (!this.eventSource && !this.isConnecting) {
                // Wait for page to be fully loaded before connecting
                if (document.readyState === 'complete') {
                    setTimeout(() => this.connect(), 100);
                } else {
                    window.addEventListener('load', () => {
                        setTimeout(() => this.connect(), 100);
                    }, { once: true });
                }
            }
            
            // Return unsubscribe function
            return () => {
                this.subscribers.delete(id);
                if (this.subscribers.size === 0 && this.eventSource) {
                    this.disconnect();
                }
            };
        }
        
        connect() {
            if (this.isConnecting || this.eventSource) {
                return;
            }
            
            this.isConnecting = true;
            
            // Wait for APP_CONFIG to be loaded from /config before connecting
            const configReady = globalThis.__APP_CONFIG_READY__ || Promise.resolve(globalThis.APP_CONFIG);
            configReady.then(() => {
                this._doConnect();
            }).catch(() => {
                this._doConnect();
            });
        }
        
        _doConnect() {
            if (this.eventSource) {
                this.isConnecting = false;
                return;
            }
            
            const apiUrl = globalThis.APP_CONFIG?.api_url || globalThis.location.origin;
            const apiKey = globalThis.APP_CONFIG?.api_key || "sk-proxy-local-dev";
            const sseUrl = new URL("/dashboard/events/stream", apiUrl);
            sseUrl.searchParams.set("token", apiKey);
            
            try {
                this.connectAttempts++;
                this.connectionState = "connecting";
                this.eventSource = new EventSource(sseUrl.toString());
                
                this.eventSource.onopen = () => {
                    this.connectionState = "connected";
                    this.connectAttempts = 0;
                    this.reconnectDelay = 1000;
                    this.isConnecting = false;
                };
                
                this.eventSource.onmessage = (evt) => {
                    try {
                        const event = JSON.parse(evt.data);
                        this.distributeEvent(event);
                    } catch (e) {
                        // Silently ignore malformed events
                    }
                };
                
                this.eventSource.onerror = () => {
                    // Only log after multiple failures to reduce noise
                    if (this.connectAttempts > 2) {
                        console.warn("SSE reconnecting... (attempt " + this.connectAttempts + ")");
                    }
                    this.connectionState = "error";
                    this.isConnecting = false;
                    this.disconnect();
                    
                    // Exponential backoff reconnection
                    setTimeout(() => {
                        if (this.subscribers.size > 0) {
                            this.connect();
                        }
                    }, this.reconnectDelay);
                    
                    this.reconnectDelay = Math.min(
                        this.reconnectDelay * 2,
                        this.maxReconnectDelay
                    );
                };
                
            } catch (e) {
                this.connectionState = "error";
                this.isConnecting = false;
            }
        }
        
        disconnect() {
            if (this.eventSource) {
                this.eventSource.close();
                this.eventSource = null;
                this.connectionState = "disconnected";
            }
        }
        
        /**
         * Get current connection state
         * @returns {string} - 'disconnected' | 'connecting' | 'connected' | 'error'
         */
        getConnectionState() {
            return this.connectionState;
        }
        
        /**
         * Check if currently connected
         * @returns {boolean}
         */
        isConnected() {
            return this.connectionState === "connected" && 
                   this.eventSource !== null && 
                   this.eventSource.readyState === EventSource.OPEN;
        }
        
        distributeEvent(event) {
            if (!event?.event_type) return;
            
            for (const [id, { eventTypes, callback }] of this.subscribers) {
                if (eventTypes.has(event.event_type)) {
                    try {
                        callback(event);
                    } catch (e) {
                        console.error(`Error in SSE subscriber ${id}:`, e);
                    }
                }
            }
        }
    }
    
    // Create singleton instance
    globalThis.SSEService = new SSEService();
    
})(globalThis);
