/**
 * MPR Express Checkout - Standardized Modal Helper
 *
 * Provides a consistent API for managing modals across the module.
 *
 * Usage:
 *   const modal = new MPRModal('my-modal-id');
 *   modal.show();
 *   modal.setHeader('success', 'icon-check', 'Operation Complete');
 *   modal.setBody('<p>Content here</p>');
 *   modal.setFooter([
 *       { type: 'cancel', label: 'Close' },
 *       { type: 'primary', label: 'Continue', icon: 'arrow-right', onClick: () => {} }
 *   ]);
 */

class MPRModal {
    /**
     * @param {string} modalId - The modal element ID (without #)
     * @param {Object} options - Configuration options
     * @param {Function} options.onShow - Callback when modal is shown
     * @param {Function} options.onHide - Callback when modal is hidden
     * @param {Function} options.onCancel - Callback when cancel/close is clicked
     */
    constructor(modalId, options = {}) {
        this.modalId = modalId;
        this.$modal = $(`#${modalId}`);
        this.$header = this.$modal.find('.mpr-modal-header');
        this.$title = this.$modal.find('.mpr-modal-title');
        this.$titleText = this.$modal.find('.mpr-modal-title-text');
        this.$titleIcon = this.$modal.find('.mpr-modal-icon');
        this.$body = this.$modal.find('.mpr-modal-body');
        this.$footer = this.$modal.find('.mpr-modal-footer');
        this.options = options;
        this.currentView = null;

        this._bindEvents();
    }

    /**
     * Bind modal events
     */
    _bindEvents() {
        this.$modal.on('shown.bs.modal', () => {
            if (typeof this.options.onShow === 'function') {
                this.options.onShow();
            }
        });

        this.$modal.on('hidden.bs.modal', () => {
            if (typeof this.options.onHide === 'function') {
                this.options.onHide();
            }
        });

        this.$modal.on('click', '[data-dismiss="modal"]', () => {
            if (typeof this.options.onCancel === 'function') {
                this.options.onCancel();
            }
        });
    }

    /**
     * Show the modal
     * @param {Object} options - Bootstrap modal options
     */
    show(options = {}) {
        if (this.$modal.length === 0) {
            console.error('[MPRModal] Modal element not found');
            return;
        }

        this.$modal.modal({
            backdrop: options.static ? 'static' : true,
            keyboard: !options.static,
            ...options
        });
    }

    /**
     * Hide the modal
     */
    hide() {
        this.$modal.modal('hide');
    }

    /**
     * Set header appearance
     * @param {string} type - Header type: default, primary, success, warning, danger, dark
     * @param {string} icon - Icon class without prefix (e.g., 'shield' for icon-shield)
     * @param {string} title - Title text
     */
    setHeader(type, icon, title) {
        // Remove all header type classes
        this.$header.removeClass(
            'mpr-modal-header-default mpr-modal-header-primary mpr-modal-header-success ' +
            'mpr-modal-header-warning mpr-modal-header-danger mpr-modal-header-dark'
        );
        this.$header.addClass(`mpr-modal-header-${type}`);

        if (icon) {
            if (this.$titleIcon.length) {
                this.$titleIcon.attr('class', `mpr-icon icon-${icon} mpr-modal-icon`);
            } else {
                this.$title.prepend(`<i class="mpr-icon icon-${icon} mpr-modal-icon"></i>`);
                this.$titleIcon = this.$modal.find('.mpr-modal-icon');
            }
        }

        if (title !== undefined) {
            this.$titleText.text(title);
        }
    }

    /**
     * Set only the header type/color
     * @param {string} type - Header type: default, primary, success, warning, danger, dark
     */
    setHeaderType(type) {
        this.$header.removeClass(
            'mpr-modal-header-default mpr-modal-header-primary mpr-modal-header-success ' +
            'mpr-modal-header-warning mpr-modal-header-danger mpr-modal-header-dark'
        );
        this.$header.addClass(`mpr-modal-header-${type}`);
    }

    /**
     * Set the header title
     * @param {string} title - Title text
     */
    setTitle(title) {
        this.$titleText.text(title);
    }

    /**
     * Set the header icon
     * @param {string} icon - Icon class without prefix
     */
    setIcon(icon) {
        if (this.$titleIcon.length) {
            this.$titleIcon.attr('class', `icon-${icon} mpr-modal-icon`);
        }
    }

    /**
     * Set modal size
     * @param {string} size - Size: sm, md, lg, xl, fullwidth
     */
    setSize(size) {
        const $dialog = this.$modal.find('.modal-dialog');
        $dialog.removeClass('modal-sm modal-lg modal-xl modal-fullwidth');
        if (size === 'sm') {
            $dialog.addClass('modal-sm');
        } else if (size === 'lg') {
            $dialog.addClass('modal-lg');
        } else if (size === 'xl') {
            $dialog.addClass('modal-xl');
        } else if (size === 'fullwidth') {
            $dialog.addClass('modal-fullwidth');
        }
    }

    /**
     * Set body content
     * @param {string} html - HTML content for the body
     */
    setBody(html) {
        this.$body.html(html);
    }

    /**
     * Append content to body
     * @param {string} html - HTML content to append
     */
    appendBody(html) {
        this.$body.append(html);
    }

    /**
     * Set footer buttons
     * @param {Array} buttons - Array of button configurations
     *   Each button: { type, label, icon, id, onClick, disabled, className, size }
     *   type: 'cancel', 'primary', 'success', 'warning', 'danger', 'default', 'dark',
     *         'outline-primary', 'outline-danger', 'ghost'
     *   size: 'sm', 'lg' (optional)
     */
    setFooter(buttons) {
        this.$footer.empty();

        buttons.forEach(btn => {
            const btnType = btn.type === 'cancel' ? 'default' : btn.type;
            let btnClass = `mpr-btn mpr-btn-${btnType}`;

            if (btn.size) {
                btnClass += ` mpr-btn-${btn.size}`;
            }
            if (btn.className) {
                btnClass += ` ${btn.className}`;
            }

            const $btn = $('<button>', {
                type: 'button',
                class: btnClass,
                id: btn.id || undefined,
                disabled: btn.disabled || false
            });

            if (btn.type === 'cancel' || btn.dismiss) {
                $btn.attr('data-dismiss', 'modal');
            }

            // Add icon - cancel buttons get 'close' icon by default if no icon specified
            const iconName = btn.icon || (btn.type === 'cancel' ? 'close' : null);
            if (iconName) {
                $btn.append(`<i class="mpr-icon icon-${iconName}"></i> `);
            }

            // Support HTML in labels (for inline icons) or plain text
            if (btn.html) {
                $btn.append(btn.label);
            } else {
                $btn.append(document.createTextNode(btn.label));
            }

            if (typeof btn.onClick === 'function') {
                $btn.on('click', btn.onClick);
            }

            this.$footer.append($btn);
        });
    }

    /**
     * Set button loading state
     * @param {string} buttonId - Button ID
     * @param {boolean} loading - Loading state
     */
    setButtonLoading(buttonId, loading) {
        const $btn = $(`#${buttonId}`);
        if (loading) {
            $btn.addClass('mpr-btn-loading').prop('disabled', true);
        } else {
            $btn.removeClass('mpr-btn-loading').prop('disabled', false);
        }
    }

    /**
     * Show footer
     */
    showFooter() {
        this.$footer.removeClass('hidden');
    }

    /**
     * Hide footer
     */
    hideFooter() {
        this.$footer.addClass('hidden');
    }

    /**
     * Enable/disable a footer button by ID
     * @param {string} buttonId - Button ID
     * @param {boolean} enabled - Enable or disable
     */
    setButtonEnabled(buttonId, enabled) {
        $(`#${buttonId}`).prop('disabled', !enabled);
    }

    /**
     * Update button label
     * @param {string} buttonId - Button ID
     * @param {string} label - New label
     * @param {string} icon - Optional new icon
     */
    setButtonLabel(buttonId, label, icon = null) {
        const $btn = $(`#${buttonId}`);
        $btn.empty();
        if (icon) {
            $btn.append(`<i class="mpr-icon icon-${icon}"></i> `);
        }
        $btn.append(document.createTextNode(label));
    }

    /**
     * Switch between views (for multi-step modals)
     * Views should have class 'mpr-modal-view' and a data-view attribute
     * @param {string} viewName - The view to show
     */
    showView(viewName) {
        this.$body.find('.mpr-modal-view').removeClass('active');
        this.$body.find(`[data-view="${viewName}"]`).addClass('active');
        this.currentView = viewName;
    }

    /**
     * Get current view name
     * @returns {string|null}
     */
    getCurrentView() {
        return this.currentView;
    }

    /**
     * Create and show a simple confirmation modal
     * @param {Object} config - Configuration
     * @param {string} config.type - Header type
     * @param {string} config.icon - Header icon
     * @param {string} config.title - Title
     * @param {string} config.message - Body message (can be HTML)
     * @param {string} config.confirmLabel - Confirm button label
     * @param {string} config.confirmType - Confirm button type (primary, danger, etc.)
     * @param {string} config.cancelLabel - Cancel button label
     * @param {Function} config.onConfirm - Confirm callback
     * @param {Function} config.onCancel - Cancel callback
     */
    confirm(config) {
        this.setHeader(
            config.type || 'primary',
            config.icon || 'question',
            config.title || 'Confirm'
        );

        this.setBody(`
            <div class="mpr-modal-center">
                <p>${config.message}</p>
            </div>
        `);

        this.setFooter([
            {
                type: 'cancel',
                label: config.cancelLabel || 'Cancel',
                onClick: config.onCancel
            },
            {
                type: config.confirmType || 'primary',
                label: config.confirmLabel || 'Confirm',
                icon: config.confirmIcon,
                onClick: () => {
                    if (typeof config.onConfirm === 'function') {
                        config.onConfirm();
                    }
                    if (config.autoClose !== false) {
                        this.hide();
                    }
                }
            }
        ]);

        this.show({ static: config.static || false });
    }

    /**
     * Show a progress state
     * @param {Object} config - Configuration
     * @param {string} config.title - Progress title
     * @param {string} config.subtitle - Progress subtitle
     * @param {number} config.percent - Initial percentage (0-100)
     */
    showProgress(config = {}) {
        const title = config.title || 'Processing...';
        const subtitle = config.subtitle || 'Please wait';
        const percent = config.percent || 0;

        this.setBody(`
            <div class="mpr-modal-progress">
                <i class="icon-refresh mpr-modal-progress-icon"></i>
                <div class="mpr-modal-progress-title">${title}</div>
                <div class="mpr-modal-progress-subtitle">${subtitle}</div>
                <div class="mpr-modal-progress-bar-container">
                    <div class="mpr-modal-progress-bar" style="width: ${percent}%"></div>
                </div>
                <div class="mpr-modal-progress-percent">${percent}%</div>
                <div class="mpr-modal-progress-current"></div>
            </div>
        `);

        this.hideFooter();
        this.setHeaderType('primary');
    }

    /**
     * Update progress bar
     * @param {number} percent - Percentage (0-100)
     * @param {string} currentItem - Current item being processed
     */
    updateProgress(percent, currentItem = '') {
        this.$body.find('.mpr-modal-progress-bar').css('width', `${percent}%`);
        this.$body.find('.mpr-modal-progress-percent').text(`${Math.round(percent)}%`);
        if (currentItem) {
            this.$body.find('.mpr-modal-progress-current').text(currentItem);
        }
    }

    /**
     * Show a result state
     * @param {Object} config - Configuration
     * @param {string} config.type - Result type: success, warning, danger, info
     * @param {string} config.icon - Icon (defaults based on type)
     * @param {string} config.title - Result title
     * @param {string} config.message - Result message
     * @param {string} config.closeLabel - Close button label
     * @param {Function} config.onClose - Close callback
     */
    showResult(config) {
        const iconMap = {
            success: 'check-circle',
            warning: 'warning',
            danger: 'times-circle',
            info: 'info-circle'
        };

        const icon = config.icon || iconMap[config.type] || 'info-circle';

        this.setHeaderType(config.type === 'info' ? 'primary' : config.type);

        this.setBody(`
            <div class="mpr-modal-result">
                <i class="icon-${icon} mpr-modal-result-icon result-${config.type}"></i>
                <div class="mpr-modal-result-title">${config.title}</div>
                <div class="mpr-modal-result-message">${config.message}</div>
            </div>
        `);

        this.setFooter([
            {
                type: 'primary',
                label: config.closeLabel || 'Close',
                onClick: () => {
                    if (typeof config.onClose === 'function') {
                        config.onClose();
                    }
                    this.hide();
                }
            }
        ]);

        this.showFooter();
    }

    /**
     * Lock modal (prevent closing)
     */
    lock() {
        this.$modal.data('bs.modal').options.backdrop = 'static';
        this.$modal.data('bs.modal').options.keyboard = false;
        this.$modal.find('.mpr-modal-close').hide();
    }

    /**
     * Unlock modal (allow closing)
     */
    unlock() {
        this.$modal.data('bs.modal').options.backdrop = true;
        this.$modal.data('bs.modal').options.keyboard = true;
        this.$modal.find('.mpr-modal-close').show();
    }

    /**
     * Destroy the modal instance
     */
    destroy() {
        this.$modal.modal('dispose');
        this.$modal.off();
    }
}

/**
 * Factory function to create modals dynamically
 * Creates the modal HTML and appends it to the body
 *
 * @param {Object} config - Modal configuration
 * @param {string} config.id - Modal ID
 * @param {string} config.size - Modal size: sm, md, lg, xl
 * @param {boolean} config.static - Static backdrop
 * @returns {MPRModal}
 */
MPRModal.create = function(config) {
    const id = config.id || 'mpr-modal-' + Date.now();
    const sizeClass = config.size === 'sm' ? 'modal-sm' :
                      config.size === 'lg' ? 'modal-lg' :
                      config.size === 'xl' ? 'modal-xl' :
                      config.size === 'fullwidth' ? 'modal-fullwidth' : '';

    const html = `
        <div class="modal fade mpr-modal" id="${id}" tabindex="-1" role="dialog"
             ${config.static ? 'data-backdrop="static" data-keyboard="false"' : ''}>
            <div class="modal-dialog ${sizeClass}" role="document">
                <div class="modal-content">
                    <div class="modal-header mpr-modal-header mpr-modal-header-primary">
                        <h5 class="modal-title mpr-modal-title">
                            <i class="mpr-modal-icon"></i>
                            <span class="mpr-modal-title-text"></span>
                        </h5>
                        <button type="button" class="close mpr-modal-close" data-dismiss="modal">
                            <span>&times;</span>
                        </button>
                    </div>
                    <div class="modal-body mpr-modal-body"></div>
                    <div class="modal-footer mpr-modal-footer"></div>
                </div>
            </div>
        </div>
    `;

    $('body').append(html);

    return new MPRModal(id, config);
};

// Export for module systems if available
if (typeof module !== 'undefined' && module.exports) {
    module.exports = MPRModal;
}
