/**
 * ComponentRegistry - Central registry for UI components
 * Manages component registration, creation, and lifecycle
 */

class ComponentRegistry {
    constructor() {
        this.components = new Map();
        this.instances = new WeakMap();
        this._initialized = false;
        Object.seal(this);
    }

    /**
     * Initialize the component registry
     */
    async init() {
        if (this._initialized) return;

        console.log('🎨 Initializing Component Registry...');

        // Auto-register core components
        await this._registerCoreComponents();

        this._initialized = true;
        console.log('✅ Component Registry initialized');
    }

    /**
     * Register core UI components
     * @private
     */
    async _registerCoreComponents() {
        try {
            // Import and register Button component
            const { default: Button } = await import('./Button.js');
            this.register('Button', Button, {
                category: 'input',
                description: 'Interactive button with loading states and icons'
            });

            // Import and register ProgressBar component
            const { default: ProgressBar } = await import('./ProgressBar.js');
            this.register('ProgressBar', ProgressBar, {
                category: 'feedback',
                description: 'Progress indicator with animation and themes'
            });

            // Import and register Card component
            const { default: Card } = await import('./Card.js');
            this.register('Card', Card, {
                category: 'layout',
                description: 'Versatile card container for content sections'
            });

            // Import and register Panel component
            const { default: Panel } = await import('./Panel.js');
            this.register('Panel', Panel, {
                category: 'layout',
                description: 'Collapsible content panel with themes'
            });

            console.log(`✅ Registered ${this.components.size} core components`);
        } catch (error) {
            console.error('❌ Failed to register core components:', error);
            throw error;
        }
    }

    /**
     * Register a component class
     * @param {string} name - Component name
     * @param {Class} componentClass - Component constructor
     * @param {Object} metadata - Component metadata
     */
    register(name, componentClass, metadata = {}) {
        if (!name || typeof name !== 'string') {
            throw new Error('Component name must be a non-empty string');
        }

        if (!componentClass || typeof componentClass !== 'function') {
            throw new Error('Component class must be a constructor function');
        }

        if (this.components.has(name)) {
            console.warn(`⚠️ Component '${name}' already registered. Overriding...`);
        }

        this.components.set(name, {
            class: componentClass,
            metadata: {
                name,
                category: metadata.category || 'general',
                description: metadata.description || 'No description provided',
                version: metadata.version || '1.0.0',
                ...metadata
            },
            created: 0,
            active: 0
        });

        console.log(`📝 Registered component: ${name} (${metadata.category})`);
    }

    /**
     * Create a component instance
     * @param {string} name - Component name
     * @param {Object} options - Component options
     * @param {HTMLElement} container - Optional container to append to
     * @returns {Object} Component instance
     */
    create(name, options = {}, container = null) {
        if (!this.components.has(name)) {
            throw new Error(`Component '${name}' is not registered`);
        }

        const componentInfo = this.components.get(name);
        const ComponentClass = componentInfo.class;

        try {
            // Create instance
            const instance = new ComponentClass(options);

            // Track instance
            this.instances.set(instance, {
                name,
                created: Date.now(),
                options: { ...options }
            });

            // Update stats
            componentInfo.created++;
            componentInfo.active++;

            // Auto-append if container provided
            if (container && instance.appendTo) {
                instance.appendTo(container);
            }

            console.log(`🎨 Created ${name} component`);
            return instance;

        } catch (error) {
            console.error(`❌ Failed to create ${name} component:`, error);
            throw error;
        }
    }

    /**
     * Destroy a component instance
     * @param {Object} instance - Component instance
     */
    destroy(instance) {
        if (!instance) return;

        const instanceInfo = this.instances.get(instance);
        if (!instanceInfo) {
            console.warn('⚠️ Component instance not tracked by registry');
            return;
        }

        try {
            // Call instance destroy method if available
            if (instance.destroy && typeof instance.destroy === 'function') {
                instance.destroy();
            }

            // Update stats
            const componentInfo = this.components.get(instanceInfo.name);
            if (componentInfo) {
                componentInfo.active = Math.max(0, componentInfo.active - 1);
            }

            // Remove from tracking
            this.instances.delete(instance);

            console.log(`🗑️ Destroyed ${instanceInfo.name} component`);

        } catch (error) {
            console.error('❌ Error destroying component:', error);
        }
    }

    /**
     * Get registered component names
     * @param {string} category - Optional category filter
     * @returns {Array<string>} Component names
     */
    getComponentNames(category = null) {
        const names = Array.from(this.components.keys());

        if (category) {
            return names.filter(name => {
                const component = this.components.get(name);
                return component.metadata.category === category;
            });
        }

        return names;
    }

    /**
     * Get component metadata
     * @param {string} name - Component name
     * @returns {Object} Component metadata
     */
    getMetadata(name) {
        if (!this.components.has(name)) {
            return null;
        }

        return { ...this.components.get(name).metadata };
    }

    /**
     * Get component statistics
     * @param {string} name - Optional component name
     * @returns {Object} Statistics
     */
    getStats(name = null) {
        if (name) {
            const component = this.components.get(name);
            if (!component) return null;

            return {
                name,
                created: component.created,
                active: component.active,
                metadata: component.metadata
            };
        }

        // Return overall stats
        const stats = {
            totalRegistered: this.components.size,
            totalCreated: 0,
            totalActive: 0,
            byCategory: {},
            components: []
        };

        this.components.forEach((component, name) => {
            stats.totalCreated += component.created;
            stats.totalActive += component.active;

            const category = component.metadata.category;
            if (!stats.byCategory[category]) {
                stats.byCategory[category] = {
                    registered: 0,
                    created: 0,
                    active: 0
                };
            }

            stats.byCategory[category].registered++;
            stats.byCategory[category].created += component.created;
            stats.byCategory[category].active += component.active;

            stats.components.push({
                name,
                category,
                created: component.created,
                active: component.active
            });
        });

        return stats;
    }

    /**
     * Check if component exists
     * @param {string} name - Component name
     * @returns {boolean} Whether component is registered
     */
    has(name) {
        return this.components.has(name);
    }

    /**
     * List all registered components with details
     * @returns {Array<Object>} Component information
     */
    list() {
        return Array.from(this.components.entries()).map(([name, info]) => ({
            name,
            category: info.metadata.category,
            description: info.metadata.description,
            version: info.metadata.version,
            created: info.created,
            active: info.active
        }));
    }

    /**
     * Get component creation helpers
     * @returns {Object} Helper methods for each component
     */
    getHelpers() {
        const helpers = {};

        this.components.forEach((info, name) => {
            // Create helper method for each component
            helpers[name.toLowerCase()] = (options = {}, container = null) => {
                return this.create(name, options, container);
            };

            // Create factory methods if component has static methods
            const ComponentClass = info.class;
            if (ComponentClass.primary) {
                helpers[`${name.toLowerCase()}Primary`] = (...args) => {
                    return ComponentClass.primary(...args);
                };
            }
            if (ComponentClass.secondary) {
                helpers[`${name.toLowerCase()}Secondary`] = (...args) => {
                    return ComponentClass.secondary(...args);
                };
            }
            if (ComponentClass.success) {
                helpers[`${name.toLowerCase()}Success`] = (...args) => {
                    return ComponentClass.success(...args);
                };
            }
        });

        return helpers;
    }

    /**
     * Clean up inactive components
     */
    cleanup() {
        console.log('🧹 Cleaning up component registry...');

        let cleanedCount = 0;
        this.components.forEach((info, name) => {
            if (info.active === 0 && info.created > 0) {
                // Component has been created but no active instances
                console.log(`🧹 Component '${name}' has no active instances`);
                cleanedCount++;
            }
        });

        console.log(`✅ Component cleanup complete (${cleanedCount} components reviewed)`);
    }

    /**
     * Get registry status
     * @returns {Object} Registry status
     */
    getStatus() {
        return {
            initialized: this._initialized,
            components: this.components.size,
            stats: this.getStats()
        };
    }
}

// Create singleton instance
const componentRegistry = new ComponentRegistry();

export default componentRegistry;