/**
 * Button Component - Reusable button with consistent styling and behavior
 * Extracted from DRS module patterns (TextModule, AudioModule, etc.)
 */

class Button {
    constructor(options = {}) {
        // Default configuration
        this.config = {
            text: options.text || 'Button',
            icon: options.icon || null,
            type: options.type || 'primary', // primary, secondary, outline, success, danger
            size: options.size || 'normal', // sm, normal, lg
            disabled: options.disabled || false,
            loading: options.loading || false,
            onClick: options.onClick || (() => {}),
            className: options.className || '',
            id: options.id || null,
            ...options
        };

        this.element = null;
        this.originalText = this.config.text;
        this.originalIcon = this.config.icon;

        this._createButton();
        Object.seal(this);
    }

    /**
     * Create the button element
     * @private
     */
    _createButton() {
        this.element = document.createElement('button');
        this.element.type = 'button'; // CRITICAL: Prevent form submission (default is "submit")
        this.element.className = this._getButtonClasses();

        if (this.config.id) {
            this.element.id = this.config.id;
        }

        this._updateContent();
        this._attachEventListeners();
        this._updateState();
    }

    /**
     * Get CSS classes for the button
     * @returns {string} - Space-separated CSS classes
     * @private
     */
    _getButtonClasses() {
        const classes = ['btn'];

        // Type classes
        classes.push(`btn-${this.config.type}`);

        // Size classes
        if (this.config.size !== 'normal') {
            classes.push(`btn-${this.config.size}`);
        }

        // Custom classes
        if (this.config.className) {
            classes.push(this.config.className);
        }

        return classes.join(' ');
    }

    /**
     * Update button content (text and icon)
     * @private
     */
    _updateContent() {
        let content = '';

        if (this.config.loading) {
            content = `
                <span class="btn-spinner">⟳</span>
                <span class="btn-text">${this.config.loadingText || 'Loading...'}</span>
            `;
        } else {
            if (this.config.icon) {
                content += `<span class="btn-icon">${this.config.icon}</span>`;
            }
            if (this.config.text) {
                content += `<span class="btn-text">${this.config.text}</span>`;
            }
        }

        this.element.innerHTML = content;
    }

    /**
     * Attach event listeners
     * @private
     */
    _attachEventListeners() {
        this.element.addEventListener('click', (event) => {
            if (!this.config.disabled && !this.config.loading) {
                this.config.onClick(event, this);
            }
        });

        // Prevent default form submission if inside a form
        this.element.addEventListener('click', (event) => {
            if (this.element.type === 'button') {
                event.preventDefault();
            }
        });
    }

    /**
     * Update button state (disabled, loading, etc.)
     * @private
     */
    _updateState() {
        this.element.disabled = this.config.disabled || this.config.loading;

        // Update ARIA attributes
        this.element.setAttribute('aria-disabled', this.config.disabled);
        if (this.config.loading) {
            this.element.setAttribute('aria-busy', 'true');
        } else {
            this.element.removeAttribute('aria-busy');
        }
    }

    // Public API

    /**
     * Set button text
     * @param {string} text - New button text
     */
    setText(text) {
        this.config.text = text;
        this._updateContent();
        return this;
    }

    /**
     * Set button icon
     * @param {string} icon - New button icon (emoji or HTML)
     */
    setIcon(icon) {
        this.config.icon = icon;
        this._updateContent();
        return this;
    }

    /**
     * Enable the button
     */
    enable() {
        this.config.disabled = false;
        this._updateState();
        return this;
    }

    /**
     * Disable the button
     */
    disable() {
        this.config.disabled = true;
        this._updateState();
        return this;
    }

    /**
     * Set loading state
     * @param {boolean} loading - Whether button is loading
     * @param {string} loadingText - Optional loading text
     */
    setLoading(loading, loadingText = null) {
        this.config.loading = loading;
        if (loadingText) {
            this.config.loadingText = loadingText;
        }
        this._updateContent();
        this._updateState();
        return this;
    }

    /**
     * Update onClick handler
     * @param {Function} handler - New click handler
     */
    setOnClick(handler) {
        this.config.onClick = handler || (() => {});
        return this;
    }

    /**
     * Add CSS class to button
     * @param {string} className - CSS class to add
     */
    addClass(className) {
        this.element.classList.add(className);
        return this;
    }

    /**
     * Remove CSS class from button
     * @param {string} className - CSS class to remove
     */
    removeClass(className) {
        this.element.classList.remove(className);
        return this;
    }

    /**
     * Toggle CSS class on button
     * @param {string} className - CSS class to toggle
     * @param {boolean} force - Force add/remove
     */
    toggleClass(className, force) {
        this.element.classList.toggle(className, force);
        return this;
    }

    /**
     * Show the button
     */
    show() {
        this.element.style.display = '';
        return this;
    }

    /**
     * Hide the button
     */
    hide() {
        this.element.style.display = 'none';
        return this;
    }

    /**
     * Focus the button
     */
    focus() {
        this.element.focus();
        return this;
    }

    /**
     * Get the DOM element
     * @returns {HTMLButtonElement} - The button element
     */
    getElement() {
        return this.element;
    }

    /**
     * Append button to a container
     * @param {HTMLElement} container - Container to append to
     */
    appendTo(container) {
        if (container && container.appendChild) {
            container.appendChild(this.element);
        }
        return this;
    }

    /**
     * Remove button from DOM
     */
    remove() {
        if (this.element && this.element.parentNode) {
            this.element.parentNode.removeChild(this.element);
        }
        return this;
    }

    /**
     * Destroy the button and clean up
     */
    destroy() {
        this.remove();
        this.element = null;
        this.config = null;
    }

    /**
     * Clone the button with new options
     * @param {Object} newOptions - Options to override
     * @returns {Button} - New button instance
     */
    clone(newOptions = {}) {
        return new Button({
            ...this.config,
            ...newOptions
        });
    }

    // Static factory methods

    /**
     * Create a primary button
     * @param {string} text - Button text
     * @param {Function} onClick - Click handler
     * @param {string} icon - Optional icon
     * @returns {Button} - Button instance
     */
    static primary(text, onClick, icon = null) {
        return new Button({
            text,
            onClick,
            icon,
            type: 'primary'
        });
    }

    /**
     * Create a secondary button
     * @param {string} text - Button text
     * @param {Function} onClick - Click handler
     * @param {string} icon - Optional icon
     * @returns {Button} - Button instance
     */
    static secondary(text, onClick, icon = null) {
        return new Button({
            text,
            onClick,
            icon,
            type: 'secondary'
        });
    }

    /**
     * Create an outline button
     * @param {string} text - Button text
     * @param {Function} onClick - Click handler
     * @param {string} icon - Optional icon
     * @returns {Button} - Button instance
     */
    static outline(text, onClick, icon = null) {
        return new Button({
            text,
            onClick,
            icon,
            type: 'outline'
        });
    }

    /**
     * Create a success button
     * @param {string} text - Button text
     * @param {Function} onClick - Click handler
     * @param {string} icon - Optional icon
     * @returns {Button} - Button instance
     */
    static success(text, onClick, icon = null) {
        return new Button({
            text,
            onClick,
            icon,
            type: 'success'
        });
    }

    /**
     * Create a danger button
     * @param {string} text - Button text
     * @param {Function} onClick - Click handler
     * @param {string} icon - Optional icon
     * @returns {Button} - Button instance
     */
    static danger(text, onClick, icon = null) {
        return new Button({
            text,
            onClick,
            icon,
            type: 'danger'
        });
    }
}

export default Button;