/**
 * Core Utilities Module for MYP Platform
 * Consolidated utilities to eliminate redundancy and improve performance
 */

(function(window) {
    'use strict';

    // Module namespace
    const MYP = window.MYP || {};

    // ===== CONFIGURATION =====
    const config = {
        apiTimeout: 30000,
        cacheExpiry: 5 * 60 * 1000, // 5 minutes
        notificationDuration: 5000,
        debounceDelay: 300,
        throttleDelay: 100
    };

    // ===== CACHE MANAGEMENT =====
    const cache = new Map();
    const requestCache = new Map();

    // ===== CSRF TOKEN HANDLING =====
    const csrf = {
        token: null,
        
        get() {
            if (!this.token) {
                const meta = document.querySelector('meta[name="csrf-token"]');
                this.token = meta ? meta.getAttribute('content') : '';
            }
            return this.token;
        },
        
        headers() {
            return {
                'X-CSRFToken': this.get(),
                'Content-Type': 'application/json'
            };
        }
    };

    // ===== DOM UTILITIES =====
    const dom = {
        // Cached selectors
        selectors: new Map(),
        
        // Get element with caching
        get(selector, parent = document) {
            const key = `${parent === document ? 'doc' : 'el'}_${selector}`;
            if (!this.selectors.has(key)) {
                this.selectors.set(key, parent.querySelector(selector));
            }
            return this.selectors.get(key);
        },
        
        // Get all elements
        getAll(selector, parent = document) {
            return parent.querySelectorAll(selector);
        },
        
        // Clear cache
        clearCache() {
            this.selectors.clear();
        },
        
        // Safe element creation
        create(tag, attrs = {}, text = '') {
            const el = document.createElement(tag);
            Object.entries(attrs).forEach(([key, val]) => {
                if (key === 'class') {
                    el.className = val;
                } else if (key === 'dataset') {
                    Object.entries(val).forEach(([k, v]) => {
                        el.dataset[k] = v;
                    });
                } else {
                    el.setAttribute(key, val);
                }
            });
            if (text) el.textContent = text;
            return el;
        }
    };

    // ===== API REQUEST HANDLING =====
    const api = {
        // Request deduplication
        pending: new Map(),
        
        async request(url, options = {}) {
            const key = `${options.method || 'GET'}_${url}`;
            
            // Check for pending request
            if (this.pending.has(key)) {
                return this.pending.get(key);
            }
            
            // Check cache for GET requests
            if (!options.method || options.method === 'GET') {
                const cached = requestCache.get(key);
                if (cached && Date.now() - cached.timestamp < config.cacheExpiry) {
                    return Promise.resolve(cached.data);
                }
            }
            
            // Prepare request
            const requestOptions = {
                ...options,
                headers: {
                    ...csrf.headers(),
                    ...options.headers
                }
            };
            
            // Create request promise
            const promise = fetch(url, requestOptions)
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! status: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    // Cache successful GET requests
                    if (!options.method || options.method === 'GET') {
                        requestCache.set(key, {
                            data,
                            timestamp: Date.now()
                        });
                    }
                    return data;
                })
                .finally(() => {
                    this.pending.delete(key);
                });
            
            this.pending.set(key, promise);
            return promise;
        },
        
        get(url, options = {}) {
            return this.request(url, { ...options, method: 'GET' });
        },
        
        post(url, data, options = {}) {
            return this.request(url, {
                ...options,
                method: 'POST',
                body: JSON.stringify(data)
            });
        },
        
        put(url, data, options = {}) {
            return this.request(url, {
                ...options,
                method: 'PUT',
                body: JSON.stringify(data)
            });
        },
        
        delete(url, options = {}) {
            return this.request(url, { ...options, method: 'DELETE' });
        }
    };

    // ===== UNIFIED NOTIFICATION SYSTEM =====
    const notifications = {
        container: null,
        queue: [],
        
        init() {
            if (this.container) return;
            
            this.container = dom.create('div', {
                id: 'myp-notifications',
                class: 'fixed top-4 right-4 z-50 space-y-2'
            });
            document.body.appendChild(this.container);
        },
        
        show(message, type = 'info', duration = config.notificationDuration) {
            this.init();
            
            const notification = dom.create('div', {
                class: `notification notification-${type} glass-navbar p-4 rounded-lg shadow-lg transform translate-x-full transition-transform duration-300`,
                role: 'alert'
            });
            
            const content = dom.create('div', {
                class: 'flex items-center space-x-3'
            });
            
            // Icon
            const icon = dom.create('i', {
                class: `fas ${this.getIcon(type)} text-lg`
            });
            
            // Message
            const text = dom.create('span', {
                class: 'flex-1'
            }, message);
            
            // Close button
            const close = dom.create('button', {
                class: 'ml-4 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200',
                'aria-label': 'Close'
            });
            close.innerHTML = '&times;';
            close.onclick = () => this.remove(notification);
            
            content.appendChild(icon);
            content.appendChild(text);
            content.appendChild(close);
            notification.appendChild(content);
            
            this.container.appendChild(notification);
            
            // Animate in
            requestAnimationFrame(() => {
                notification.classList.remove('translate-x-full');
            });
            
            // Auto remove
            if (duration > 0) {
                setTimeout(() => this.remove(notification), duration);
            }
            
            return notification;
        },
        
        remove(notification) {
            notification.classList.add('translate-x-full');
            setTimeout(() => {
                notification.remove();
            }, 300);
        },
        
        getIcon(type) {
            const icons = {
                success: 'fa-check-circle text-green-500',
                error: 'fa-exclamation-circle text-red-500',
                warning: 'fa-exclamation-triangle text-yellow-500',
                info: 'fa-info-circle text-blue-500'
            };
            return icons[type] || icons.info;
        },
        
        success(message, duration) {
            return this.show(message, 'success', duration);
        },
        
        error(message, duration) {
            return this.show(message, 'error', duration);
        },
        
        warning(message, duration) {
            return this.show(message, 'warning', duration);
        },
        
        info(message, duration) {
            return this.show(message, 'info', duration);
        }
    };

    // ===== PERFORMANCE UTILITIES =====
    const performance = {
        debounce(func, delay = config.debounceDelay) {
            let timeoutId;
            return function(...args) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(() => func.apply(this, args), delay);
            };
        },
        
        throttle(func, delay = config.throttleDelay) {
            let lastCall = 0;
            return function(...args) {
                const now = Date.now();
                if (now - lastCall >= delay) {
                    lastCall = now;
                    return func.apply(this, args);
                }
            };
        },
        
        memoize(func) {
            const cache = new Map();
            return function(...args) {
                const key = JSON.stringify(args);
                if (cache.has(key)) {
                    return cache.get(key);
                }
                const result = func.apply(this, args);
                cache.set(key, result);
                return result;
            };
        },
        
        lazy(selector, callback) {
            const observer = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        callback(entry.target);
                        observer.unobserve(entry.target);
                    }
                });
            });
            
            dom.getAll(selector).forEach(el => observer.observe(el));
            return observer;
        }
    };

    // ===== STORAGE UTILITIES =====
    const storage = {
        set(key, value, expiry = null) {
            const data = {
                value,
                timestamp: Date.now(),
                expiry
            };
            try {
                localStorage.setItem(`myp_${key}`, JSON.stringify(data));
                return true;
            } catch (e) {
                console.error('Storage error:', e);
                return false;
            }
        },
        
        get(key) {
            try {
                const item = localStorage.getItem(`myp_${key}`);
                if (!item) return null;
                
                const data = JSON.parse(item);
                if (data.expiry && Date.now() - data.timestamp > data.expiry) {
                    this.remove(key);
                    return null;
                }
                return data.value;
            } catch (e) {
                console.error('Storage error:', e);
                return null;
            }
        },
        
        remove(key) {
            localStorage.removeItem(`myp_${key}`);
        },
        
        clear() {
            Object.keys(localStorage)
                .filter(key => key.startsWith('myp_'))
                .forEach(key => localStorage.removeItem(key));
        }
    };

    // ===== EVENT UTILITIES =====
    const events = {
        listeners: new Map(),
        
        on(element, event, handler, options = {}) {
            const key = `${element}_${event}`;
            if (!this.listeners.has(key)) {
                this.listeners.set(key, new Set());
            }
            
            this.listeners.get(key).add(handler);
            element.addEventListener(event, handler, options);
        },
        
        off(element, event, handler) {
            const key = `${element}_${event}`;
            if (this.listeners.has(key)) {
                this.listeners.get(key).delete(handler);
                if (this.listeners.get(key).size === 0) {
                    this.listeners.delete(key);
                }
            }
            element.removeEventListener(event, handler);
        },
        
        once(element, event, handler, options = {}) {
            const onceHandler = (e) => {
                handler(e);
                this.off(element, event, onceHandler);
            };
            this.on(element, event, onceHandler, options);
        },
        
        emit(name, detail = {}) {
            const event = new CustomEvent(name, {
                detail,
                bubbles: true,
                cancelable: true
            });
            document.dispatchEvent(event);
        },
        
        cleanup() {
            this.listeners.forEach((handlers, key) => {
                const [element, event] = key.split('_');
                handlers.forEach(handler => {
                    element.removeEventListener(event, handler);
                });
            });
            this.listeners.clear();
        }
    };

    // ===== FORM UTILITIES =====
    const forms = {
        serialize(form) {
            const data = new FormData(form);
            const obj = {};
            for (const [key, value] of data.entries()) {
                if (obj[key]) {
                    if (!Array.isArray(obj[key])) {
                        obj[key] = [obj[key]];
                    }
                    obj[key].push(value);
                } else {
                    obj[key] = value;
                }
            }
            return obj;
        },
        
        validate(form) {
            const inputs = form.querySelectorAll('[required]');
            let valid = true;
            
            inputs.forEach(input => {
                if (!input.value.trim()) {
                    input.classList.add('border-red-500');
                    valid = false;
                } else {
                    input.classList.remove('border-red-500');
                }
            });
            
            return valid;
        },
        
        reset(form) {
            form.reset();
            form.querySelectorAll('.border-red-500').forEach(el => {
                el.classList.remove('border-red-500');
            });
        }
    };

    // ===== INITIALIZATION =====
    const init = () => {
        // Initialize notifications
        notifications.init();
        
        // Clean up on page unload
        window.addEventListener('beforeunload', () => {
            events.cleanup();
            dom.clearCache();
        });
    };

    // ===== PUBLIC API =====
    MYP.utils = {
        csrf,
        dom,
        api,
        notifications,
        performance,
        storage,
        events,
        forms,
        init,
        config
    };

    // Auto-initialize when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // Export to global scope
    window.MYP = MYP;

})(window);