class Modal {
    constructor(config = {}) {
        this.config = {
            type: config.type || 'dialog',
            title: config.title || '',
            content: config.content || '',
            size: config.size || 'medium',
            closeable: config.closeable !== false,
            backdrop: config.backdrop !== false,
            keyboard: config.keyboard !== false,
            buttons: config.buttons || [],
            onShow: config.onShow || null,
            onHide: config.onHide || null,
            className: config.className || '',
            ...config
        };

        this.modal = null;
        this.isVisible = false;
        this.currentResolve = null;
        this.focusableElements = [];
        this.previousActiveElement = null;

        this.init();
    }

    init() {
        this.createModal();
        this.setupEventListeners();
    }

    createModal() {

        this.modal = document.createElement('div');
        this.modal.className = `modal modal-${this.config.type} ${this.config.className}`;
        this.modal.setAttribute('role', 'dialog');
        this.modal.setAttribute('aria-modal', 'true');
        this.modal.setAttribute('tabindex', '-1');

        if (this.config.title) {
            this.modal.setAttribute('aria-labelledby', 'modal-title');
        }

        const modalHTML = `
            ${this.config.backdrop ? '<div class="modal-backdrop"></div>' : ''}
            <div class="modal-content modal-${this.config.size}">
                ${this.config.closeable ? '<button class="modal-close" type="button" aria-label="Close modal" title="Close (Esc)"><span class="close-icon">✕</span></button>' : ''}
                ${this.config.title ? `<div class="modal-header"><h3 id="modal-title">${this.escapeHtml(this.config.title)}</h3></div>` : ''}
                <div class="modal-body">${this.config.content}</div>
                ${this.config.buttons.length > 0 ? this.createFooter() : ''}
            </div>
        `;

        this.modal.innerHTML = modalHTML;

        this.backdrop = this.modal.querySelector('.modal-backdrop');
        this.content = this.modal.querySelector('.modal-content');
        this.closeBtn = this.modal.querySelector('.modal-close');
        this.header = this.modal.querySelector('.modal-header');
        this.body = this.modal.querySelector('.modal-body');
        this.footer = this.modal.querySelector('.modal-footer');
    }

    createFooter() {
        const buttons = this.config.buttons.map(btn => {
            const variant = btn.variant || 'secondary';
            const disabled = btn.disabled ? 'disabled' : '';
            return `<button type="button" class="btn btn-${variant}" data-action="${btn.action}" ${disabled}>${this.escapeHtml(btn.text)}</button>`;
        }).join('');

        return `<div class="modal-footer">${buttons}</div>`;
    }

    setupEventListeners() {

        if (this.backdrop && this.config.backdrop) {
            this.backdrop.addEventListener('click', () => this.hide());
        }

        if (this.closeBtn && this.config.closeable) {
            this.closeBtn.addEventListener('click', () => this.hide());
        }

        if (this.config.keyboard) {
            this.modal.addEventListener('keydown', (e) => this.handleKeydown(e));
        }

        if (this.footer) {
            this.footer.addEventListener('click', (e) => {
                const button = e.target.closest('[data-action]');
                if (button) {
                    const action = button.getAttribute('data-action');
                    this.handleButtonClick(action, button);
                }
            });
        }
    }

    handleKeydown(e) {
        if (e.key === 'Escape' && this.config.keyboard) {
            e.preventDefault();
            this.hide();
        } else if (e.key === 'Tab') {
            this.trapFocus(e);
        }
    }

    trapFocus(e) {
        if (this.focusableElements.length === 0) return;

        const firstElement = this.focusableElements[0];
        const lastElement = this.focusableElements[this.focusableElements.length - 1];

        if (e.shiftKey) {
            if (document.activeElement === firstElement) {
                e.preventDefault();
                lastElement.focus();
            }
        } else {
            if (document.activeElement === lastElement) {
                e.preventDefault();
                firstElement.focus();
            }
        }
    }

    handleButtonClick(action, button) {
        const buttonConfig = this.config.buttons.find(btn => btn.action === action);

        if (buttonConfig && buttonConfig.handler) {
            const result = buttonConfig.handler(this);
            if (result === false) return;
        }

        if (this.currentResolve) {
            this.currentResolve(action);
            this.currentResolve = null;
        }

        this.hide();
    }

    show() {
        return new Promise((resolve) => {
            this.currentResolve = resolve;

            this.previousActiveElement = document.activeElement;

            document.body.appendChild(this.modal);

            document.body.style.overflow = 'hidden';

            this.modal.style.display = 'flex';
            this.isVisible = true;

            setTimeout(() => {
                this.modal.classList.add('modal-show');
            }, 10);

            this.setupFocusManagement();

            if (this.config.onShow) {
                this.config.onShow(this);
            }
        });
    }

    hide() {
        if (!this.isVisible) return;

        this.modal.classList.add('modal-hide');
        this.modal.classList.remove('modal-show');

        setTimeout(() => {
            if (this.modal && this.modal.parentNode) {
                this.modal.parentNode.removeChild(this.modal);
            }

            document.body.style.overflow = '';

            if (this.previousActiveElement) {
                this.previousActiveElement.focus();
            }

            this.isVisible = false;

            if (this.config.onHide) {
                this.config.onHide(this);
            }

            if (this.currentResolve) {
                this.currentResolve(null);
                this.currentResolve = null;
            }
        }, 300);
    }

    setupFocusManagement() {

        this.focusableElements = this.modal.querySelectorAll(
            'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
        );

        if (this.focusableElements.length > 0) {
            this.focusableElements[0].focus();
        } else {
            this.modal.focus();
        }
    }

    updateContent(content) {
        if (this.body) {
            this.body.innerHTML = content;
            this.setupFocusManagement();
        }
    }

    updateTitle(title) {
        const titleElement = this.modal.querySelector('#modal-title');
        if (titleElement) {
            titleElement.textContent = title;
        }
    }

    escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    destroy() {
        if (this.isVisible) {
            this.hide();
        }

        setTimeout(() => {
            if (this.modal && this.modal.parentNode) {
                this.modal.parentNode.removeChild(this.modal);
            }
        }, 350);
    }
}

if (typeof window !== 'undefined') {
    window.Modal = Modal;
}