/**
 * Card Component - Reusable card container with consistent styling
 * Extracted from DRS module patterns (exercise cards, question cards, result cards)
 */

class Card {
    constructor(options = {}) {
        // Default configuration
        this.config = {
            title: options.title || null,
            content: options.content || '',
            footer: options.footer || null,
            type: options.type || 'default', // default, exercise, question, result, info, warning, success, danger
            size: options.size || 'normal', // sm, normal, lg
            elevated: options.elevated !== false, // true by default
            interactive: options.interactive || false, // hover effects, clickable
            onClick: options.onClick || null,
            className: options.className || '',
            id: options.id || null,
            ...options
        };

        this.element = null;
        this.headerElement = null;
        this.bodyElement = null;
        this.footerElement = null;

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

    /**
     * Create the card element
     * @private
     */
    _createCard() {
        this.element = document.createElement('div');
        this.element.className = this._getCardClasses();

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

        // Create card structure
        this.element.innerHTML = this._getCardHTML();

        // Get references to sections
        this.headerElement = this.element.querySelector('.card-header');
        this.bodyElement = this.element.querySelector('.card-body');
        this.footerElement = this.element.querySelector('.card-footer');

        this._attachEventListeners();
        this._setupARIA();
    }

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

        // Type classes
        if (this.config.type !== 'default') {
            classes.push(`card-${this.config.type}`);
        }

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

        // State classes
        if (this.config.elevated) {
            classes.push('card-elevated');
        }

        if (this.config.interactive) {
            classes.push('card-interactive');
        }

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

        return classes.join(' ');
    }

    /**
     * Get card HTML structure
     * @returns {string} - HTML string
     * @private
     */
    _getCardHTML() {
        return `
            ${this.config.title ? `<div class="card-header"><h3 class="card-title">${this.config.title}</h3></div>` : ''}
            <div class="card-body">
                ${this.config.content}
            </div>
            ${this.config.footer ? `<div class="card-footer">${this.config.footer}</div>` : ''}
        `;
    }

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

            this.element.addEventListener('keydown', (event) => {
                if (event.key === 'Enter' || event.key === ' ') {
                    event.preventDefault();
                    this.config.onClick(event, this);
                }
            });
        }
    }

    /**
     * Setup ARIA attributes for accessibility
     * @private
     */
    _setupARIA() {
        if (this.config.interactive) {
            this.element.setAttribute('tabindex', '0');
            this.element.setAttribute('role', 'button');
            this.element.setAttribute('aria-label', this.config.title || 'Interactive card');
        }
    }

    // Public API

    /**
     * Set card title
     * @param {string} title - New title
     */
    setTitle(title) {
        this.config.title = title;

        if (title) {
            if (!this.headerElement) {
                // Create header if it doesn't exist
                const headerHTML = `<div class="card-header"><h3 class="card-title">${title}</h3></div>`;
                this.element.insertAdjacentHTML('afterbegin', headerHTML);
                this.headerElement = this.element.querySelector('.card-header');
            } else {
                const titleElement = this.headerElement.querySelector('.card-title');
                if (titleElement) {
                    titleElement.textContent = title;
                }
            }
        } else if (this.headerElement) {
            this.headerElement.remove();
            this.headerElement = null;
        }

        return this;
    }

    /**
     * Set card content
     * @param {string|HTMLElement} content - New content
     */
    setContent(content) {
        this.config.content = content;

        if (this.bodyElement) {
            if (typeof content === 'string') {
                this.bodyElement.innerHTML = content;
            } else if (content instanceof HTMLElement) {
                this.bodyElement.innerHTML = '';
                this.bodyElement.appendChild(content);
            }
        }

        return this;
    }

    /**
     * Append content to card body
     * @param {string|HTMLElement} content - Content to append
     */
    appendContent(content) {
        if (this.bodyElement) {
            if (typeof content === 'string') {
                this.bodyElement.insertAdjacentHTML('beforeend', content);
            } else if (content instanceof HTMLElement) {
                this.bodyElement.appendChild(content);
            }
        }

        return this;
    }

    /**
     * Set card footer
     * @param {string} footer - New footer content
     */
    setFooter(footer) {
        this.config.footer = footer;

        if (footer) {
            if (!this.footerElement) {
                // Create footer if it doesn't exist
                const footerHTML = `<div class="card-footer">${footer}</div>`;
                this.element.insertAdjacentHTML('beforeend', footerHTML);
                this.footerElement = this.element.querySelector('.card-footer');
            } else {
                this.footerElement.innerHTML = footer;
            }
        } else if (this.footerElement) {
            this.footerElement.remove();
            this.footerElement = null;
        }

        return this;
    }

    /**
     * Set card type/theme
     * @param {string} type - Card type (default, exercise, question, result, info, warning, success, danger)
     */
    setType(type) {
        // Remove old type class
        this.element.className = this.element.className.replace(/card-\w+/g, '');

        this.config.type = type;

        // Add new type class
        if (type !== 'default') {
            this.element.classList.add(`card-${type}`);
        }

        return this;
    }

    /**
     * Enable or disable interactive state
     * @param {boolean} interactive - Whether card is interactive
     * @param {Function} onClick - Optional click handler
     */
    setInteractive(interactive, onClick = null) {
        this.config.interactive = interactive;

        if (onClick) {
            this.config.onClick = onClick;
        }

        this.element.classList.toggle('card-interactive', interactive);

        if (interactive) {
            this.element.setAttribute('tabindex', '0');
            this.element.setAttribute('role', 'button');
            this._attachEventListeners();
        } else {
            this.element.removeAttribute('tabindex');
            this.element.removeAttribute('role');
        }

        return this;
    }

    /**
     * Enable or disable elevation shadow
     * @param {boolean} elevated - Whether card has elevation
     */
    setElevated(elevated) {
        this.config.elevated = elevated;
        this.element.classList.toggle('card-elevated', elevated);
        return this;
    }

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

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

    /**
     * Toggle CSS class on card
     * @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 card with optional animation
     * @param {string} animation - Animation type (fade, slide, scale)
     */
    show(animation = null) {
        this.element.style.display = '';

        if (animation) {
            this.element.classList.add(`card-animate-${animation}`);
            setTimeout(() => {
                this.element.classList.remove(`card-animate-${animation}`);
            }, 300);
        }

        return this;
    }

    /**
     * Hide the card with optional animation
     * @param {string} animation - Animation type (fade, slide, scale)
     */
    hide(animation = null) {
        if (animation) {
            this.element.classList.add(`card-animate-${animation}-out`);
            setTimeout(() => {
                this.element.style.display = 'none';
                this.element.classList.remove(`card-animate-${animation}-out`);
            }, 300);
        } else {
            this.element.style.display = 'none';
        }

        return this;
    }

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

    /**
     * Get card header element
     * @returns {HTMLElement|null} - The header element
     */
    getHeader() {
        return this.headerElement;
    }

    /**
     * Get card body element
     * @returns {HTMLElement} - The body element
     */
    getBody() {
        return this.bodyElement;
    }

    /**
     * Get card footer element
     * @returns {HTMLElement|null} - The footer element
     */
    getFooter() {
        return this.footerElement;
    }

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

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

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

    // Static factory methods

    /**
     * Create an exercise card
     * @param {string} title - Exercise title
     * @param {string} content - Exercise content
     * @param {Object} options - Additional options
     * @returns {Card} - Card instance
     */
    static exercise(title, content, options = {}) {
        return new Card({
            title,
            content,
            type: 'exercise',
            elevated: true,
            ...options
        });
    }

    /**
     * Create a question card
     * @param {string} question - Question text
     * @param {Object} options - Additional options
     * @returns {Card} - Card instance
     */
    static question(question, options = {}) {
        return new Card({
            content: question,
            type: 'question',
            elevated: true,
            ...options
        });
    }

    /**
     * Create a result card
     * @param {string} result - Result content
     * @param {boolean} success - Whether result is positive
     * @param {Object} options - Additional options
     * @returns {Card} - Card instance
     */
    static result(result, success = true, options = {}) {
        return new Card({
            content: result,
            type: success ? 'success' : 'danger',
            elevated: true,
            ...options
        });
    }

    /**
     * Create an info card
     * @param {string} title - Info title
     * @param {string} content - Info content
     * @param {Object} options - Additional options
     * @returns {Card} - Card instance
     */
    static info(title, content, options = {}) {
        return new Card({
            title,
            content,
            type: 'info',
            ...options
        });
    }
}

export default Card;