const CleanupManager = (function() {
    const state = {
        eventListeners: [],
        timeouts: [],
        intervals: [],
        animationFrames: [],
        resources: new Map(),
        debug: false,
        memoryOptimizationInterval: null
    };

    function log(message, ...args) {
        if (state.debug) {
            console.log(`[CleanupManager] ${message}`, ...args);
        }
    }

    const publicAPI = {
        addListener: function(element, type, handler, options = false) {
            if (!element) {
                log('Warning: Attempted to add listener to null/undefined element');
                return handler;
            }

            element.addEventListener(type, handler, options);
            state.eventListeners.push({ element, type, handler, options });
            log(`Added ${type} listener to`, element);
            return handler;
        },

        setTimeout: function(callback, delay) {
            const id = window.setTimeout(callback, delay);
            state.timeouts.push(id);
            log(`Created timeout ${id} with ${delay}ms delay`);
            return id;
        },

        setInterval: function(callback, delay) {
            const id = window.setInterval(callback, delay);
            state.intervals.push(id);
            log(`Created interval ${id} with ${delay}ms delay`);
            return id;
        },

        requestAnimationFrame: function(callback) {
            const id = window.requestAnimationFrame(callback);
            state.animationFrames.push(id);
            log(`Requested animation frame ${id}`);
            return id;
        },

        registerResource: function(type, resource, cleanupFn) {
            const id = `${type}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
            state.resources.set(id, { resource, cleanupFn });
            log(`Registered custom resource ${id} of type ${type}`);
            return id;
        },

        unregisterResource: function(id) {
            const resourceInfo = state.resources.get(id);
            if (resourceInfo) {
                try {
                    resourceInfo.cleanupFn(resourceInfo.resource);
                    state.resources.delete(id);
                    log(`Unregistered and cleaned up resource ${id}`);
                    return true;
                } catch (error) {
                    console.error(`[CleanupManager] Error cleaning up resource ${id}:`, error);
                    return false;
                }
            }
            log(`Resource ${id} not found`);
            return false;
        },

        clearTimeout: function(id) {
            const index = state.timeouts.indexOf(id);
            if (index !== -1) {
                window.clearTimeout(id);
                state.timeouts.splice(index, 1);
                log(`Cleared timeout ${id}`);
            }
        },

        clearInterval: function(id) {
            const index = state.intervals.indexOf(id);
            if (index !== -1) {
                window.clearInterval(id);
                state.intervals.splice(index, 1);
                log(`Cleared interval ${id}`);
            }
        },

        cancelAnimationFrame: function(id) {
            const index = state.animationFrames.indexOf(id);
            if (index !== -1) {
                window.cancelAnimationFrame(id);
                state.animationFrames.splice(index, 1);
                log(`Cancelled animation frame ${id}`);
            }
        },

        removeListener: function(element, type, handler, options = false) {
            if (!element) return;

            try {
                element.removeEventListener(type, handler, options);
                log(`Removed ${type} listener from`, element);
            } catch (error) {
                console.error(`[CleanupManager] Error removing event listener:`, error);
            }

            state.eventListeners = state.eventListeners.filter(
                listener => !(listener.element === element &&
                            listener.type === type &&
                            listener.handler === handler)
            );
        },

        removeListenersByElement: function(element) {
            if (!element) return;

            const listenersToRemove = state.eventListeners.filter(
                listener => listener.element === element
            );

            listenersToRemove.forEach(({ element, type, handler, options }) => {
                try {
                    element.removeEventListener(type, handler, options);
                    log(`Removed ${type} listener from`, element);
                } catch (error) {
                    console.error(`[CleanupManager] Error removing event listener:`, error);
                }
            });

            state.eventListeners = state.eventListeners.filter(
                listener => listener.element !== element
            );
        },

        clearAllTimeouts: function() {
            state.timeouts.forEach(id => {
                window.clearTimeout(id);
            });
            const count = state.timeouts.length;
            state.timeouts = [];
            log(`Cleared all timeouts (${count})`);
        },

        clearAllIntervals: function() {
            state.intervals.forEach(id => {
                window.clearInterval(id);
            });
            const count = state.intervals.length;
            state.intervals = [];
            log(`Cleared all intervals (${count})`);
        },

        clearAllAnimationFrames: function() {
            state.animationFrames.forEach(id => {
                window.cancelAnimationFrame(id);
            });
            const count = state.animationFrames.length;
            state.animationFrames = [];
            log(`Cancelled all animation frames (${count})`);
        },

        clearAllResources: function() {
            let successCount = 0;
            let errorCount = 0;

            state.resources.forEach((resourceInfo, id) => {
                try {
                    resourceInfo.cleanupFn(resourceInfo.resource);
                    successCount++;
                } catch (error) {
                    console.error(`[CleanupManager] Error cleaning up resource ${id}:`, error);
                    errorCount++;
                }
            });

            state.resources.clear();
            log(`Cleared all custom resources (${successCount} success, ${errorCount} errors)`);
        },

        clearAllListeners: function() {
            state.eventListeners.forEach(({ element, type, handler, options }) => {
                if (element) {
                    try {
                        element.removeEventListener(type, handler, options);
                    } catch (error) {
                        console.error(`[CleanupManager] Error removing event listener:`, error);
                    }
                }
            });
            const count = state.eventListeners.length;
            state.eventListeners = [];
            log(`Removed all event listeners (${count})`);
        },

        clearAll: function() {
            const counts = {
                listeners: state.eventListeners.length,
                timeouts: state.timeouts.length,
                intervals: state.intervals.length,
                animationFrames: state.animationFrames.length,
                resources: state.resources.size
            };

            this.clearAllListeners();
            this.clearAllTimeouts();
            this.clearAllIntervals();
            this.clearAllAnimationFrames();
            this.clearAllResources();

            log(`All resources cleaned up:`, counts);
            return counts;
        },

        getResourceCounts: function() {
            return {
                listeners: state.eventListeners.length,
                timeouts: state.timeouts.length,
                intervals: state.intervals.length,
                animationFrames: state.animationFrames.length,
                resources: state.resources.size,
                total: state.eventListeners.length +
                      state.timeouts.length +
                      state.intervals.length +
                      state.animationFrames.length +
                      state.resources.size
            };
        },

        setupMemoryOptimization: function(options = {}) {
            const memoryCheckInterval = options.interval || 2 * 60 * 1000; 
            const maxCacheSize = options.maxCacheSize || 100;
            const maxDataSize = options.maxDataSize || 1000;

            if (state.memoryOptimizationInterval) {
                this.clearInterval(state.memoryOptimizationInterval);
            }

            this.addListener(document, 'visibilitychange', () => {
                if (document.hidden) {
                    log('Tab hidden - running memory optimization');
                    this.optimizeMemory({
                        maxCacheSize: maxCacheSize,
                        maxDataSize: maxDataSize
                    });
                } else if (window.TooltipManager) {
                    window.TooltipManager.cleanup();
                }
            });

            state.memoryOptimizationInterval = this.setInterval(() => {
                if (document.hidden) {
                    log('Periodic memory optimization');
                    this.optimizeMemory({
                        maxCacheSize: maxCacheSize,
                        maxDataSize: maxDataSize
                    });
                }
            }, memoryCheckInterval);

            log('Memory optimization setup complete');
            return state.memoryOptimizationInterval;
        },

        optimizeMemory: function(options = {}) {
            log('Running memory optimization');

            if (window.TooltipManager && typeof window.TooltipManager.cleanup === 'function') {
                window.TooltipManager.cleanup();
            }

            if (window.IdentityManager && typeof window.IdentityManager.limitCacheSize === 'function') {
                window.IdentityManager.limitCacheSize(options.maxCacheSize || 100);
            }

            this.cleanupOrphanedResources();

            if (window.gc) {
                try {
                    window.gc();
                    log('Forced garbage collection');
                } catch (e) {
                }
            }

            document.dispatchEvent(new CustomEvent('memoryOptimized', {
                detail: {
                    timestamp: Date.now(),
                    maxDataSize: options.maxDataSize || 1000
                }
            }));

            log('Memory optimization complete');
        },

        cleanupOrphanedResources: function() {
            let removedListeners = 0;
            const validListeners = [];

            for (let i = 0; i < state.eventListeners.length; i++) {
                const listener = state.eventListeners[i];
                if (!listener.element) {
                    removedListeners++;
                    continue;
                }

                try {

                    const isDetached = !(listener.element instanceof Node) ||
                                    !document.body.contains(listener.element) ||
                                    (listener.element.classList && listener.element.classList.contains('hidden')) ||
                                    (listener.element.style && listener.element.style.display === 'none');

                    if (isDetached) {
                        try {
                            if (listener.element instanceof Node) {
                                listener.element.removeEventListener(listener.type, listener.handler, listener.options);
                            }
                            removedListeners++;
                        } catch (e) {

                        }
                    } else {
                        validListeners.push(listener);
                    }
                } catch (e) {

                    log(`Error checking listener (removing): ${e.message}`);
                    removedListeners++;
                }
            }

            if (removedListeners > 0) {
                state.eventListeners = validListeners;
                log(`Removed ${removedListeners} event listeners for detached/hidden elements`);
            }

            let removedResources = 0;
            const resourcesForRemoval = [];

            state.resources.forEach((info, id) => {
                const resource = info.resource;

                try {

                    if (resource instanceof Element && !document.body.contains(resource)) {
                        resourcesForRemoval.push(id);
                    }

                    if (resource && resource.element) {

                        if (resource.element instanceof Node && !document.body.contains(resource.element)) {
                            resourcesForRemoval.push(id);
                        }
                    }
                } catch (e) {
                    log(`Error checking resource ${id}: ${e.message}`);
                }
            });

            resourcesForRemoval.forEach(id => {
                this.unregisterResource(id);
                removedResources++;
            });

            if (removedResources > 0) {
                log(`Removed ${removedResources} orphaned resources`);
            }

            if (window.TooltipManager) {
                if (typeof window.TooltipManager.cleanupOrphanedTooltips === 'function') {
                    try {
                        window.TooltipManager.cleanupOrphanedTooltips();
                    } catch (e) {

                        if (typeof window.TooltipManager.cleanup === 'function') {
                            try {
                                window.TooltipManager.cleanup();
                            } catch (err) {
                                log(`Error cleaning up tooltips: ${err.message}`);
                            }
                        }
                    }
                } else if (typeof window.TooltipManager.cleanup === 'function') {
                    try {
                        window.TooltipManager.cleanup();
                    } catch (e) {
                        log(`Error cleaning up tooltips: ${e.message}`);
                    }
                }
            }

            try {
                this.cleanupTooltipDOM();
            } catch (e) {
                log(`Error in cleanupTooltipDOM: ${e.message}`);
            }
        },

        cleanupTooltipDOM: function() {
            let removedElements = 0;

            try {

                const tooltipSelectors = [
                    '[role="tooltip"]',
                    '[id^="tooltip-"]',
                    '.tippy-box',
                    '[data-tippy-root]'
                ];

                tooltipSelectors.forEach(selector => {
                    try {
                        const elements = document.querySelectorAll(selector);

                        elements.forEach(element => {
                            try {

                                if (!(element instanceof Element)) return;

                                const isDetached = !element.parentElement ||
                                                !document.body.contains(element.parentElement) ||
                                                element.classList.contains('hidden') ||
                                                element.style.display === 'none' ||
                                                element.style.visibility === 'hidden';

                                if (isDetached) {
                                    try {
                                        element.remove();
                                        removedElements++;
                                    } catch (e) {

                                    }
                                }
                            } catch (err) {

                            }
                        });
                    } catch (err) {

                        log(`Error querying for ${selector}: ${err.message}`);
                    }
                });
            } catch (e) {
                log(`Error in tooltip DOM cleanup: ${e.message}`);
            }

            if (removedElements > 0) {
                log(`Removed ${removedElements} detached tooltip elements`);
            }
        },

        setDebugMode: function(enabled) {
            state.debug = Boolean(enabled);
            log(`Debug mode ${state.debug ? 'enabled' : 'disabled'}`);
            return state.debug;
        },

        dispose: function() {
            this.clearAll();
            log('CleanupManager disposed');
        },

        initialize: function(options = {}) {
            if (options.debug !== undefined) {
                this.setDebugMode(options.debug);
            }

            if (typeof window !== 'undefined' && !options.noAutoCleanup) {
                this.addListener(window, 'beforeunload', () => {
                    this.clearAll();
                });
            }

            if (typeof window !== 'undefined' && !options.noMemoryOptimization) {
                this.setupMemoryOptimization(options.memoryOptions || {});
            }

            log('CleanupManager initialized');
            return this;
        }
    };

    return publicAPI;
})();

if (typeof module !== 'undefined' && module.exports) {
    module.exports = CleanupManager;
}

if (typeof window !== 'undefined') {
    window.CleanupManager = CleanupManager;
}

if (typeof window !== 'undefined' && typeof document !== 'undefined') {
    if (document.readyState === 'complete' || document.readyState === 'interactive') {
        CleanupManager.initialize({ debug: false });
    } else {
        document.addEventListener('DOMContentLoaded', () => {
            CleanupManager.initialize({ debug: false });
        }, { once: true });
    }
}
