/**
 * Editor - Handles all content types with markdown-first approach
 */
import { markdownConverter } from '../utils/markdown.js';
import { Previewer } from './previewer.js';

export class Editor {
    constructor() {
        this.currentOverlay = null;
        this.previewer = new Previewer();
    }

    /**
     * Edit any content element with markdown interface
     * @param {Object} meta - Element metadata {element, contentId, contentType}
     * @param {string|Object} currentContent - Current content value
     * @param {Function} onSave - Save callback
     * @param {Function} onCancel - Cancel callback
     */
    edit(meta, currentContent, onSave, onCancel) {
        const { element } = meta;
        
        // Handle both single elements and groups uniformly
        const elements = Array.isArray(element) ? element : [element];
        const context = new EditContext(elements, currentContent);
        
        // Close any existing editor
        this.close();
        
        // Create editor form
        const form = this.createForm(context, meta);
        const overlay = this.createOverlay(form);
        
        // Position relative to primary element
        this.positionForm(context.primaryElement, overlay);
        
        // Setup event handlers
        this.setupEventHandlers(form, overlay, context, { onSave, onCancel });
        
        // Show editor
        document.body.appendChild(overlay);
        this.currentOverlay = overlay;
        
        // Focus textarea
        const textarea = form.querySelector('textarea');
        if (textarea) {
            setTimeout(() => textarea.focus(), 100);
        }
        
        return overlay;
    }

    /**
     * Create editing form for any content type
     */
    createForm(context, meta) {
        const config = this.getFieldConfig(context);
        const currentContent = context.extractContent();
        
        const form = document.createElement('div');
        form.className = 'insertr-edit-form';
        
        // Build form HTML
        let formHTML = `<div class="insertr-form-header">${config.label}</div>`;
        
        // Markdown textarea (always present)
        formHTML += this.createMarkdownField(config, currentContent);
        
        // URL field (for links only)
        if (config.includeUrl) {
            formHTML += this.createUrlField(currentContent);
        }
        
        // Form actions
        formHTML += `
            <div class="insertr-form-actions">
                <button type="button" class="insertr-btn-save">Save</button>
                <button type="button" class="insertr-btn-cancel">Cancel</button>
                <button type="button" class="insertr-btn-history" data-content-id="${meta.contentId}">View History</button>
            </div>
        `;
        
        form.innerHTML = formHTML;
        return form;
    }

    /**
     * Get field configuration for any element type (markdown-first)
     */
    getFieldConfig(context) {
        const elementCount = context.elements.length;
        const primaryElement = context.primaryElement;
        const isLink = primaryElement.tagName.toLowerCase() === 'a';
        
        // Multi-element groups
        if (elementCount > 1) {
            return {
                type: 'markdown',
                includeUrl: false,
                label: `Group Content (${elementCount} elements)`,
                rows: Math.max(8, elementCount * 2),
                placeholder: 'Edit all content together using markdown...'
            };
        }
        
        // Single elements - all get markdown by default
        const tag = primaryElement.tagName.toLowerCase();
        const baseConfig = {
            type: 'markdown',
            includeUrl: isLink,
            placeholder: 'Enter content using markdown...'
        };
        
        // Customize by element type
        switch (tag) {
            case 'h1':
                return { ...baseConfig, label: 'Main Headline', rows: 1, placeholder: 'Enter main headline...' };
            case 'h2':
                return { ...baseConfig, label: 'Subheading', rows: 1, placeholder: 'Enter subheading...' };
            case 'h3': case 'h4': case 'h5': case 'h6':
                return { ...baseConfig, label: 'Heading', rows: 2, placeholder: 'Enter heading (markdown supported)...' };
            case 'p':
                return { ...baseConfig, label: 'Content', rows: 4, placeholder: 'Enter content using markdown...' };
            case 'span':
                return { ...baseConfig, label: 'Text', rows: 2, placeholder: 'Enter text (markdown supported)...' };
            case 'button':
                return { ...baseConfig, label: 'Button Text', rows: 1, placeholder: 'Enter button text...' };
            case 'a':
                return { ...baseConfig, label: 'Link', rows: 2, placeholder: 'Enter link text (markdown supported)...' };
            default:
                return { ...baseConfig, label: 'Content', rows: 3, placeholder: 'Enter content using markdown...' };
        }
    }

    /**
     * Create markdown textarea field
     */
    createMarkdownField(config, content) {
        const textContent = typeof content === 'object' ? content.text || '' : content;
        
        return `
            <div class="insertr-form-group">
                <textarea class="insertr-form-textarea insertr-markdown-editor" name="content" 
                          rows="${config.rows}"
                          placeholder="${config.placeholder}">${this.escapeHtml(textContent)}</textarea>
                <div class="insertr-form-help">
                    Supports Markdown formatting (bold, italic, links, etc.)
                </div>
            </div>
        `;
    }

    /**
     * Create URL field for links
     */
    createUrlField(content) {
        const url = typeof content === 'object' ? content.url || '' : '';
        
        return `
            <div class="insertr-form-group">
                <label class="insertr-form-label">Link URL:</label>
                <input type="url" class="insertr-form-input" name="url" 
                       value="${this.escapeHtml(url)}" 
                       placeholder="https://example.com">
            </div>
        `;
    }

    /**
     * Setup event handlers
     */
    setupEventHandlers(form, overlay, context, { onSave, onCancel }) {
        const textarea = form.querySelector('textarea');
        const urlInput = form.querySelector('input[name="url"]');
        const saveBtn = form.querySelector('.insertr-btn-save');
        const cancelBtn = form.querySelector('.insertr-btn-cancel');
        const historyBtn = form.querySelector('.insertr-btn-history');
        
        // Initialize previewer
        this.previewer.setActiveContext(context);
        
        // Setup live preview for content changes
        if (textarea) {
            textarea.addEventListener('input', () => {
                const content = this.extractFormData(form);
                this.previewer.schedulePreview(context, content);
            });
        }
        
        // Setup live preview for URL changes (links only)
        if (urlInput) {
            urlInput.addEventListener('input', () => {
                const content = this.extractFormData(form);
                this.previewer.schedulePreview(context, content);
            });
        }
        
        // Save handler
        if (saveBtn) {
            saveBtn.addEventListener('click', () => {
                const content = this.extractFormData(form);
                
                // Apply final content to elements
                context.applyContent(content);
                
                // Update stored original content to match current state
                // This makes the saved content the new baseline for future edits
                context.updateOriginalContent();
                
                // Clear preview styling (won't restore content since original matches current)
                this.previewer.clearPreview();
                
                // Callback with the content
                onSave(content);
                this.close();
            });
        }
        
        // Cancel handler
        if (cancelBtn) {
            cancelBtn.addEventListener('click', () => {
                this.previewer.clearPreview();
                onCancel();
                this.close();
            });
        }
        
        // History handler
        if (historyBtn) {
            historyBtn.addEventListener('click', () => {
                const contentId = historyBtn.getAttribute('data-content-id');
                console.log('Version history not implemented yet for:', contentId);
                // TODO: Implement version history integration
            });
        }
        
        // ESC key handler
        const keyHandler = (e) => {
            if (e.key === 'Escape') {
                this.previewer.clearPreview();
                onCancel();
                this.close();
                document.removeEventListener('keydown', keyHandler);
            }
        };
        document.addEventListener('keydown', keyHandler);
        
        // Click outside handler
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) {
                this.previewer.clearPreview();
                onCancel();
                this.close();
            }
        });
    }

    /**
     * Extract form data consistently
     */
    extractFormData(form) {
        const textarea = form.querySelector('textarea[name="content"]');
        const urlInput = form.querySelector('input[name="url"]');
        
        const content = textarea ? textarea.value : '';
        
        if (urlInput) {
            // Link content
            return {
                text: content,
                url: urlInput.value
            };
        }
        
        // Regular content
        return content;
    }

    /**
     * Create overlay with backdrop
     */
    createOverlay(form) {
        const overlay = document.createElement('div');
        overlay.className = 'insertr-form-overlay';
        overlay.appendChild(form);
        return overlay;
    }

    /**
     * Position form relative to primary element
     */
    positionForm(element, overlay) {
        const rect = element.getBoundingClientRect();
        const form = overlay.querySelector('.insertr-edit-form');
        const viewportWidth = window.innerWidth;
        
        // Calculate optimal width
        let formWidth;
        if (viewportWidth < 768) {
            formWidth = Math.min(viewportWidth - 40, 500);
        } else {
            const minComfortableWidth = 600;
            const maxWidth = Math.min(viewportWidth * 0.9, 800);
            formWidth = Math.max(minComfortableWidth, Math.min(rect.width * 1.5, maxWidth));
        }
        
        form.style.width = `${formWidth}px`;
        
        // Position below element
        const top = rect.bottom + window.scrollY + 10;
        const centerLeft = rect.left + window.scrollX + (rect.width / 2) - (formWidth / 2);
        const minLeft = 20;
        const maxLeft = window.innerWidth - formWidth - 20;
        const left = Math.max(minLeft, Math.min(centerLeft, maxLeft));
        
        overlay.style.position = 'absolute';
        overlay.style.top = `${top}px`;
        overlay.style.left = `${left}px`;
        overlay.style.zIndex = '10000';
        
        // Ensure visibility
        this.ensureModalVisible(overlay);
    }

    /**
     * Ensure modal is visible by scrolling if needed
     */
    ensureModalVisible(overlay) {
        requestAnimationFrame(() => {
            const modal = overlay.querySelector('.insertr-edit-form');
            const modalRect = modal.getBoundingClientRect();
            const viewportHeight = window.innerHeight;
            
            if (modalRect.bottom > viewportHeight) {
                const scrollAmount = modalRect.bottom - viewportHeight + 20;
                window.scrollBy({
                    top: scrollAmount,
                    behavior: 'smooth'
                });
            }
        });
    }

    /**
     * Close current editor
     */
    close() {
        if (this.previewer) {
            this.previewer.clearPreview();
        }
        
        if (this.currentOverlay) {
            this.currentOverlay.remove();
            this.currentOverlay = null;
        }
    }

    /**
     * Escape HTML to prevent XSS
     */
    escapeHtml(text) {
        if (typeof text !== 'string') return '';
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }
}

/**
 * EditContext - Represents content elements for editing
 */
class EditContext {
    constructor(elements, currentContent) {
        this.elements = elements;
        this.primaryElement = elements[0];
        this.originalContent = null;
        this.currentContent = currentContent;
    }

    /**
     * Extract content from elements in markdown format
     */
    extractContent() {
        if (this.elements.length === 1) {
            const element = this.elements[0];
            
            // Handle links specially
            if (element.tagName.toLowerCase() === 'a') {
                return {
                    text: markdownConverter.htmlToMarkdown(element.innerHTML),
                    url: element.href
                };
            }
            
            // Single element - convert to markdown
            return markdownConverter.htmlToMarkdown(element.innerHTML);
        } else {
            // Multiple elements - use group extraction
            return markdownConverter.extractGroupMarkdown(this.elements);
        }
    }

    /**
     * Apply content to elements from markdown/object
     */
    applyContent(content) {
        if (this.elements.length === 1) {
            const element = this.elements[0];
            
            // Handle links specially
            if (element.tagName.toLowerCase() === 'a' && typeof content === 'object') {
                element.innerHTML = markdownConverter.markdownToHtml(content.text || '');
                if (content.url) {
                    element.href = content.url;
                }
                return;
            }
            
            // Single element - convert markdown to HTML
            const html = markdownConverter.markdownToHtml(content);
            element.innerHTML = html;
        } else {
            // Multiple elements - use group update
            markdownConverter.updateGroupElements(this.elements, content);
        }
    }

    /**
     * Store original content for preview restoration
     */
    storeOriginalContent() {
        this.originalContent = this.elements.map(el => ({
            innerHTML: el.innerHTML,
            href: el.href // Store href for links
        }));
    }

    /**
     * Restore original content (for preview cancellation)
     */
    restoreOriginalContent() {
        if (this.originalContent) {
            this.elements.forEach((el, index) => {
                if (this.originalContent[index] !== undefined) {
                    el.innerHTML = this.originalContent[index].innerHTML;
                    if (this.originalContent[index].href) {
                        el.href = this.originalContent[index].href;
                    }
                }
            });
        }
    }

    /**
     * Update original content to match current element state (after save)
     * This makes the current content the new baseline for future cancellations
     */
    updateOriginalContent() {
        this.originalContent = this.elements.map(el => ({
            innerHTML: el.innerHTML,
            href: el.href // Store href for links
        }));
    }

    /**
     * Apply preview styling to all elements
     */
    applyPreviewStyling() {
        this.elements.forEach(el => {
            el.classList.add('insertr-preview-active');
        });
        
        // Also apply to containers if they're groups
        if (this.primaryElement.classList.contains('insertr-group')) {
            this.primaryElement.classList.add('insertr-preview-active');
        }
    }

    /**
     * Remove preview styling from all elements
     */
    removePreviewStyling() {
        this.elements.forEach(el => {
            el.classList.remove('insertr-preview-active');
        });
        
        // Also remove from containers
        if (this.primaryElement.classList.contains('insertr-group')) {
            this.primaryElement.classList.remove('insertr-preview-active');
        }
    }
}