/**
 * Erweiterter Logger mit Processor-Architektur, Request-ID-Unterstützung und Server-Kommunikation.
 */
export class Logger {
    /**
     * Konfiguration des Loggers
     */
    static config = {
        enabled: true,
        apiEndpoint: '/api/log',
        consoleEnabled: true,
        serverEnabled: true,
        minLevel: 'debug',
    };

    /**
     * Liste der registrierten Processors
     */
    static processors = [];

    /**
     * Registrierte Handler
     */
    static handlers = [];

    /**
     * Aktive RequestID
     */
    static requestId = null;

    /**
     * Logger initialisieren
     */
    static initialize(config = {}) {
        // Konfiguration überschreiben
        this.config = { ...this.config, ...config };

        // Standard-Processors registrieren
        this.registerProcessor(this.requestIdProcessor);
        this.registerProcessor(this.timestampProcessor);

        // Standard-Handler registrieren
        if (this.config.consoleEnabled) {
            this.registerHandler(this.consoleHandler);
        }

        if (this.config.serverEnabled) {
            this.registerHandler(this.serverHandler);
        }

        // Request-ID aus dem Document laden, wenn vorhanden
        if (typeof document !== 'undefined') {
            this.initFromDocument();
        }

        // Unhandled Errors abfangen
        this.setupErrorHandling();
    }

    /**
     * Debug-Nachricht loggen
     */
    static debug(...args) {
        this.log('debug', ...args);
    }

    /**
     * Info-Nachricht loggen
     */
    static info(...args) {
        this.log('info', ...args);
    }

    /**
     * Warnungs-Nachricht loggen
     */
    static warn(...args) {
        this.log('warn', ...args);
    }

    /**
     * Fehler-Nachricht loggen
     */
    static error(...args) {
        this.log('error', ...args);
    }

    /**
     * Log-Nachricht mit beliebigem Level erstellen
     */
    static log(level, ...args) {
        if (!this.config.enabled) return;

        // Level-Validierung
        const validLevels = ['debug', 'info', 'warn', 'error'];
        if (!validLevels.includes(level)) {
            level = 'info';
        }

        // Nachricht und Kontext extrahieren
        const message = this.formatMessage(args);
        const context = args.find(arg => typeof arg === 'object' && arg !== null && !(arg instanceof Error)) || {};

        // Exception extrahieren, falls vorhanden
        const error = args.find(arg => arg instanceof Error);
        if (error) {
            context.exception = error;
        }

        // Log-Record erstellen
        let record = {
            level,
            message,
            context,
            timestamp: new Date(),
            extra: {},
        };

        // Alle Processors durchlaufen
        this.processors.forEach(processor => {
            record = processor(record);
        });

        // Log-Level-Prüfung (nach Processors, da sie das Level ändern könnten)
        const levelPriority = {
            debug: 100,
            info: 200,
            warn: 300,
            error: 400,
        };

        if (levelPriority[record.level] < levelPriority[this.config.minLevel]) {
            return;
        }

        // Alle Handler durchlaufen
        this.handlers.forEach(handler => {
            handler(record);
        });
    }

    /**
     * Nachricht aus verschiedenen Argumenten formatieren
     */
    static formatMessage(args) {
        return args
            .filter(arg => !(arg instanceof Error) && (typeof arg !== 'object' || arg === null))
            .map(arg => String(arg))
            .join(' ');
    }

    /**
     * Processor registrieren
     */
    static registerProcessor(processor) {
        if (typeof processor !== 'function') return;
        this.processors.push(processor);
    }

    /**
     * Handler registrieren
     */
    static registerHandler(handler) {
        if (typeof handler !== 'function') return;
        this.handlers.push(handler);
    }

    /**
     * Error-Handling-Setup
     */
    static setupErrorHandling() {
        if (typeof window !== 'undefined') {
            // Unbehandelte Fehler abfangen
            window.addEventListener('error', (event) => {
                this.error('Unbehandelter Fehler:', event.error || event.message);
            });

            // Unbehandelte Promise-Rejects abfangen
            window.addEventListener('unhandledrejection', (event) => {
                this.error('Unbehandelte Promise-Ablehnung:', event.reason);
            });
        }
    }

    /**
     * Request-ID aus dem Document laden
     */
    static initFromDocument() {
        const meta = document.querySelector('meta[name="request-id"]');
        if (meta) {
            const fullRequestId = meta.getAttribute('content');
            // Nur den ID-Teil ohne Signatur verwenden
            this.requestId = fullRequestId.split('.')[0] || null;
        }
    }

    /*** STANDARD-PROCESSORS ***/

    /**
     * Processor für Request-ID
     */
    static requestIdProcessor(record) {
        if (Logger.requestId) {
            record.extra.request_id = Logger.requestId;
        }
        return record;
    }

    /**
     * Processor für Timestamp-Formatierung
     */
    static timestampProcessor(record) {
        record.formattedTimestamp = record.timestamp.toLocaleTimeString('de-DE');
        return record;
    }

    /*** STANDARD-HANDLERS ***/

    /**
     * Handler für Console-Ausgabe
     */
    static consoleHandler(record) {
        const levelColors = {
            debug: 'color: gray',
            info: 'color: green',
            warn: 'color: orange',
            error: 'color: red',
        };

        const color = levelColors[record.level] || 'color: black';
        const requestIdStr = record.extra.request_id ? `[${record.extra.request_id}] ` : '';
        const formattedMessage = `[${record.formattedTimestamp}] [${record.level.toUpperCase()}] ${requestIdStr}${record.message}`;

        // Farbige Ausgabe in der Konsole
        console[record.level](
            `%c${formattedMessage}`,
            color,
            ...(record.context ? [record.context] : [])
        );
    }

    /**
     * Handler für Server-Kommunikation
     */
    static serverHandler(record) {
        fetch(Logger.config.apiEndpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Request-ID': Logger.requestId || ''
            },
            body: JSON.stringify({
                level: record.level,
                message: record.message,
                context: record.context || {}
            })
        })
        .then(response => {
            // Request-ID aus dem Header extrahieren
            const requestId = response.headers.get('X-Request-ID');
            if (requestId) {
                // Nur den ID-Teil ohne Signatur speichern
                const idPart = requestId.split('.')[0];
                if (idPart) {
                    Logger.requestId = idPart;
                }
            }
            return response.json();
        })
        .catch(() => {
            // Fehler beim Senden des Logs ignorieren (keine rekursive Fehlerbehandlung)
        });
    }
}

// Standard-Initialisierung
Logger.initialize();
