/**
 * Alert - Individual alert object
 */
class Alert {
    constructor(alertType, source, state, message = null) {
        this.type = alertType;
        this.source = source;
        this.state = state;
        this.timestamp = new Date();

        // Generate message based on type
        if (message) {
            this.msg = message;
        } else if (alertType === 'signal') {
            this.msg = `Signal "${source}" changed to ${state ? 'TRUE' : 'FALSE'}`;
        } else if (alertType === 'strategy') {
            this.msg = `Strategy: ${source} - ${state}`;
        } else if (alertType === 'trade') {
            this.msg = `Trade: ${source} - ${state}`;
        } else if (alertType === 'error') {
            this.msg = `Error: ${source} - ${state}`;
        } else if (alertType === 'notification') {
            this.msg = message || state;
        } else {
            this.msg = `${alertType}: ${source} = ${state}`;
        }
    }

    getTimeString() {
        return this.timestamp.toLocaleTimeString();
    }

    getTypeIcon() {
        switch (this.type) {
            case 'signal': return '🔔';
            case 'strategy': return '📊';
            case 'trade': return '💰';
            case 'error': return '⚠️';
            case 'notification': return '📢';
            default: return '•';
        }
    }

    getTypeClass() {
        return `alert-${this.type}`;
    }
}

/**
 * Alerts - Manages alert collection and display
 */
class Alerts {
    constructor(targetId) {
        this.alerts = [];
        this.targetId = targetId;
        this.target = null;
        this.maxAlerts = 50;  // Keep last 50 alerts
        this.comms = null;
    }

    /**
     * Initialize alerts system with communications
     * @param {Object} comms - The communications instance
     */
    initialize(comms) {
        this.comms = comms;

        if (this.comms) {
            // Register for updates (contains s_updates for signal changes)
            this.comms.on('updates', this.handleUpdates.bind(this));
            // Register for direct alerts
            this.comms.on('alert', this.handleAlert.bind(this));
            // Register for strategy events
            this.comms.on('strategy_events', this.handleStrategyEvents.bind(this));

            console.log('Alerts system initialized');
        }
    }

    /**
     * Handle updates from server (includes signal state changes)
     */
    handleUpdates(data) {
        // Handle signal state changes
        if (data.s_updates && Object.keys(data.s_updates).length > 0) {
            this.publishAlerts('signal_changes', data.s_updates);
        }

        // Handle strategy events that should trigger alerts
        if (data.stg_updts && Array.isArray(data.stg_updts)) {
            for (const event of data.stg_updts) {
                if (event.type === 'error') {
                    this.addAlert(new Alert('error', event.strategy_name || 'Strategy', event.message));
                } else if (event.type === 'trade_executed') {
                    this.addAlert(new Alert('trade', event.strategy_name || 'Trade',
                        `${event.side} ${event.amount} @ ${event.price}`));
                } else if (event.type === 'strategy_exited') {
                    this.addAlert(new Alert('strategy', event.strategy_name || 'Strategy', 'Exited'));
                }
            }
        }
    }

    /**
     * Handle direct alert from server
     */
    handleAlert(data) {
        const alert = new Alert(
            data.type || 'notification',
            data.source || 'System',
            data.state || data.message,
            data.message
        );
        this.addAlert(alert);
    }

    /**
     * Handle strategy events
     */
    handleStrategyEvents(data) {
        if (!data || !data.events) return;

        for (const event of data.events) {
            if (event.type === 'trade_executed') {
                this.addAlert(new Alert('trade', data.strategy_name || 'Strategy',
                    `${event.side} ${event.amount} @ ${event.price}`));
            } else if (event.type === 'error') {
                this.addAlert(new Alert('error', data.strategy_name || 'Strategy', event.message));
            } else if (event.type === 'notification') {
                this.addAlert(new Alert('notification', data.strategy_name || 'Strategy', event.message));
            }
        }
    }

    /**
     * Publish alerts based on type and data
     */
    publishAlerts(alertType, data) {
        if (alertType === 'signal_changes') {
            // data is { signalName: state, ... }
            for (const sig in data) {
                this.addAlert(new Alert('signal', sig, data[sig]));
            }
        } else if (alertType === 'strategy') {
            this.addAlert(new Alert('strategy', data.source || 'Strategy', data.message || data));
        } else if (alertType === 'trade') {
            this.addAlert(new Alert('trade', data.source || 'Trade', data.message || data));
        }
    }

    /**
     * Add a single alert
     */
    addAlert(alert) {
        this.alerts.unshift(alert);  // Add to front (newest first)

        // Trim to max alerts
        if (this.alerts.length > this.maxAlerts) {
            this.alerts = this.alerts.slice(0, this.maxAlerts);
        }

        this.updateHtml();
        console.log('Alert added:', alert.msg);
    }

    /**
     * Clear all alerts
     */
    clearAlerts() {
        this.alerts = [];
        this.updateHtml();
    }

    /**
     * Update the HTML display
     */
    updateHtml() {
        if (!this.target) return;

        if (this.alerts.length === 0) {
            this.target.innerHTML = '<div class="no-alerts">No Alerts</div>';
            return;
        }

        let html = '';
        for (const alert of this.alerts) {
            html += `
                <div class="alert-item ${alert.getTypeClass()}">
                    <span class="alert-icon">${alert.getTypeIcon()}</span>
                    <span class="alert-time">${alert.getTimeString()}</span>
                    <span class="alert-message">${alert.msg}</span>
                </div>
            `;
        }
        this.target.innerHTML = html;
    }

    /**
     * Set the target DOM element (called after DOM is ready)
     */
    set_target() {
        this.target = document.getElementById(this.targetId);
        if (this.target) {
            this.updateHtml();
        }
    }

    /**
     * Programmatically add an alert (for use from other JS modules)
     */
    notify(type, source, message) {
        this.addAlert(new Alert(type, source, message, message));
    }
}
