/**
 * Base Module class - Enforces strict module contracts
 * Every module MUST extend this class and implement required methods
 */

const privateData = new WeakMap();

class Module {
    constructor(name, dependencies = []) {
        if (new.target === Module) {
            throw new Error('Module is abstract and cannot be instantiated directly');
        }

        if (!name || typeof name !== 'string') {
            throw new Error('Module name is required and must be a string');
        }

        // Private data storage
        privateData.set(this, {
            name,
            dependencies,
            state: 'uninitialized',
            initialized: false,
            destroyed: false
        });

        // Note: Object.seal(this) is called by child classes after they define their properties
    }

    // Public getters (read-only)
    get name() {
        return privateData.get(this).name;
    }

    get dependencies() {
        return [...privateData.get(this).dependencies]; // Return copy
    }

    get state() {
        return privateData.get(this).state;
    }

    get isInitialized() {
        return privateData.get(this).initialized;
    }

    get isDestroyed() {
        return privateData.get(this).destroyed;
    }

    // Abstract methods - MUST be implemented by subclasses
    init() {
        throw new Error(`Module ${this.name}: init() method must be implemented`);
    }

    destroy() {
        throw new Error(`Module ${this.name}: destroy() method must be implemented`);
    }

    // Protected methods (for internal use)
    _setState(newState) {
        const data = privateData.get(this);
        if (data.destroyed) {
            throw new Error(`Module ${this.name} is destroyed and cannot change state`);
        }
        data.state = newState;
    }

    _setInitialized() {
        const data = privateData.get(this);
        if (data.initialized) {
            throw new Error(`Module ${this.name} is already initialized`);
        }
        data.initialized = true;
        data.state = 'initialized';
    }

    _setDestroyed() {
        const data = privateData.get(this);
        data.destroyed = true;
        data.initialized = false;
        data.state = 'destroyed';
    }

    // Validation helpers
    _validateNotDestroyed() {
        if (this.isDestroyed) {
            throw new Error(`Module ${this.name} is destroyed and cannot be used`);
        }
    }

    _validateInitialized() {
        if (!this.isInitialized) {
            throw new Error(`Module ${this.name} must be initialized before use`);
        }
    }
}

// Freeze the class to prevent modification
Object.freeze(Module);
Object.freeze(Module.prototype);

export default Module;