/**
 * DOM Renderer - Clean separation between business logic and DOM manipulation
 *
 * This class handles all DOM operations and UI events, while delegating
 * business logic to the SectionManager.
 */

// Import EditState if available, otherwise define locally
const EditState = (typeof window !== 'undefined' && window.MarkitectEditor?.EditState)
    ? window.MarkitectEditor.EditState
    : {
        ORIGINAL: 'original',
        EDITING: 'editing',
        MODIFIED: 'modified',
        SAVED: 'saved'
    };

/**
 * DOMRenderer class - Handles DOM rendering and UI interactions
 *
 * Responsibilities:
 * - Render sections to DOM elements
 * - Handle UI events (clicks, keyboard)
 * - Manage textarea creation and styling
 * - Sync DOM state with Section objects
 * - Provide visual feedback for different states
 */
class DOMRenderer {
    constructor(sectionManager, containerElement) {
        this.sectionManager = sectionManager;
        this.container = containerElement;
        this.currentTextarea = null;
        this.currentSection = null;

        // Bind event handlers
        this.handleSectionClick = this.handleSectionClick.bind(this);
        this.handleAccept = this.handleAccept.bind(this);
        this.handleCancel = this.handleCancel.bind(this);
        this.handleReset = this.handleReset.bind(this);
        this.handleKeydown = this.handleKeydown.bind(this);

        // Listen to section manager events
        this.setupEventListeners();
    }

    /**
     * Setup event listeners for section manager events
     */
    setupEventListeners() {
        this.sectionManager.on('sections-created', (data) => {
            this.renderAllSections(data.sections);
        });

        this.sectionManager.on('edit-started', (data) => {
            this.showEditor(data.sectionId, data.content);
        });

        this.sectionManager.on('edit-stopped', (data) => {
            this.hideEditor(data.sectionId);
            this.updateSectionVisual(data.sectionId, data.section);
        });

        this.sectionManager.on('changes-accepted', (data) => {
            this.hideEditor(data.sectionId);
            this.updateSectionContent(data.sectionId, data.content);
            this.updateSectionVisual(data.sectionId, data.section);
        });

        this.sectionManager.on('changes-cancelled', (data) => {
            this.hideEditor(data.sectionId);
            this.updateSectionContent(data.sectionId, data.content);
            this.updateSectionVisual(data.sectionId, data.section);
        });

        this.sectionManager.on('section-reset', (data) => {
            this.updateTextareaContent(data.content);
        });

        this.sectionManager.on('content-updated', (data) => {
            this.updateSectionVisual(data.sectionId, data.section);
        });
    }

    /**
     * Render all sections to the DOM
     * @param {Array<Section>} sections - Sections to render
     */
    renderAllSections(sections) {
        this.container.innerHTML = '';

        sections.forEach(section => {
            const element = this.createSectionElement(section);
            section.domElement = element;
            this.container.appendChild(element);
        });

        // Add click handlers to all sections
        this.container.addEventListener('click', this.handleSectionClick);
    }

    /**
     * Create a DOM element for a section
     * @param {Section} section - The section to create element for
     * @returns {HTMLElement} The created DOM element
     */
    createSectionElement(section) {
        const element = document.createElement('div');
        element.className = 'markitect-section-editable';
        element.setAttribute('data-section-id', section.id);
        element.setAttribute('data-section-type', section.sectionType);

        // Parse markdown to HTML - use pending changes if they exist and section isn't being edited
        const contentToRender = (section.state === EditState.MODIFIED && section.pendingMarkdown)
            ? section.pendingMarkdown
            : section.currentMarkdown;

        if (typeof marked !== 'undefined') {
            element.innerHTML = marked.parse(contentToRender);
        } else {
            // Fallback for testing environment
            element.innerHTML = `<p>${contentToRender}</p>`;
        }

        this.updateSectionVisual(section.id, section.getStatus());

        return element;
    }

    /**
     * Update section visual state based on its status
     * @param {string} sectionId - The section ID
     * @param {Object} status - The section status object
     */
    updateSectionVisual(sectionId, status) {
        const element = this.findSectionElement(sectionId);
        if (!element) return;

        // Remove all state classes
        element.classList.remove('section-original', 'section-editing', 'section-modified', 'section-saved');

        // Add appropriate state class
        element.classList.add(`section-${status.state}`);

        // Add visual indicators for modified sections
        if (status.isModified) {
            element.style.backgroundColor = 'rgba(255, 235, 59, 0.1)'; // Light yellow
            element.style.borderLeft = '3px solid #ffc107'; // Orange border
        } else if (status.state === 'saved') {
            element.style.backgroundColor = 'rgba(76, 175, 80, 0.1)'; // Light green
            element.style.borderLeft = '3px solid #4caf50'; // Green border
        } else {
            element.style.backgroundColor = '';
            element.style.borderLeft = '';
        }
    }

    /**
     * Find DOM element for a section
     * @param {string} sectionId - The section ID
     * @returns {HTMLElement|null} The DOM element or null
     */
    findSectionElement(sectionId) {
        return this.container.querySelector(`[data-section-id="${sectionId}"]`);
    }

    /**
     * Handle section click events
     * @param {Event} event - The click event
     */
    handleSectionClick(event) {
        const sectionElement = event.target.closest('.markitect-section-editable');
        if (!sectionElement) return;

        const sectionId = sectionElement.getAttribute('data-section-id');
        if (!sectionId) return;

        // Don't start editing if already editing this section
        if (this.currentSection === sectionId) return;

        try {
            this.sectionManager.startEditing(sectionId);
        } catch (error) {
            console.error('Failed to start editing:', error);
            this.showError(error.message);
        }
    }

    /**
     * Show editor for a section
     * @param {string} sectionId - The section ID
     * @param {string} content - The content to edit
     */
    showEditor(sectionId, content) {
        const element = this.findSectionElement(sectionId);
        if (!element) return;

        // Hide any existing editor first
        this.hideCurrentEditor();

        // Create editor container
        const editorContainer = this.createEditorContainer(content, sectionId);

        // Replace section content with editor
        element.innerHTML = '';
        element.appendChild(editorContainer);

        // Focus the textarea
        const textarea = editorContainer.querySelector('textarea');
        if (textarea) {
            textarea.focus();
            textarea.setSelectionRange(0, 0);
            this.currentTextarea = textarea;
        }

        this.currentSection = sectionId;
    }

    /**
     * Create editor container with textarea and controls
     * @param {string} content - The initial content
     * @param {string} sectionId - The section ID
     * @returns {HTMLElement} The editor container
     */
    createEditorContainer(content, sectionId) {
        const container = document.createElement('div');
        container.className = 'markitect-edit-container';

        // Create textarea wrapper
        const textareaWrapper = document.createElement('div');
        textareaWrapper.className = 'markitect-textarea-wrapper';

        // Create textarea
        const textarea = document.createElement('textarea');
        textarea.className = 'edit-mode';
        textarea.value = content;
        textarea.addEventListener('input', () => {
            try {
                this.sectionManager.updateContent(sectionId, textarea.value);
            } catch (error) {
                console.error('Failed to update content:', error);
            }
        });

        // Add keyboard shortcuts
        textarea.addEventListener('keydown', this.handleKeydown);

        // Auto-resize functionality
        this.setupAutoResize(textarea);

        textareaWrapper.appendChild(textarea);

        // Create controls
        const controls = this.createControlButtons(sectionId);

        container.appendChild(textareaWrapper);
        container.appendChild(controls);

        return container;
    }

    /**
     * Create control buttons for section
     * @param {string} sectionId - The section ID
     * @returns {HTMLElement} The controls container
     */
    createControlButtons(sectionId) {
        const controls = document.createElement('div');
        controls.className = 'markitect-section-controls';

        // Accept button
        const acceptBtn = document.createElement('button');
        acceptBtn.className = 'markitect-section-btn accept';
        acceptBtn.innerHTML = '<span>✓</span> Accept';
        acceptBtn.title = 'Accept changes and save this section';
        acceptBtn.addEventListener('click', () => this.handleAccept(sectionId));

        // Cancel button
        const cancelBtn = document.createElement('button');
        cancelBtn.className = 'markitect-section-btn cancel';
        cancelBtn.innerHTML = '<span>✗</span> Cancel';
        cancelBtn.title = 'Cancel editing and revert to state before editing started';
        cancelBtn.addEventListener('click', () => this.handleCancel(sectionId));

        // Reset button
        const resetBtn = document.createElement('button');
        resetBtn.className = 'markitect-section-btn reset';
        resetBtn.innerHTML = '<span>🔄</span> Reset';
        resetBtn.title = 'Reset to original content from render time (discards all changes)';
        resetBtn.addEventListener('click', () => this.handleReset(sectionId));

        controls.appendChild(acceptBtn);
        controls.appendChild(cancelBtn);
        controls.appendChild(resetBtn);

        return controls;
    }

    /**
     * Setup auto-resize for textarea
     * @param {HTMLTextAreaElement} textarea - The textarea element
     */
    setupAutoResize(textarea) {
        const autoResize = () => {
            const transition = textarea.style.transition;
            textarea.style.transition = 'none';

            textarea.style.height = 'auto';
            const contentHeight = textarea.scrollHeight;
            const padding = 24;

            const lineCount = textarea.value.split('\n').length;
            const minHeight = Math.max(60, lineCount * 24 + padding);
            const maxHeight = 360;

            const newHeight = Math.max(60, Math.min(maxHeight, Math.max(minHeight, contentHeight + 4)));
            textarea.style.height = newHeight + 'px';

            textarea.style.transition = transition;
        };

        textarea.addEventListener('input', autoResize);
        textarea.addEventListener('paste', () => setTimeout(autoResize, 10));

        // Initial sizing
        setTimeout(autoResize, 20);
    }

    /**
     * Hide current editor
     */
    hideCurrentEditor() {
        if (this.currentSection) {
            this.hideEditor(this.currentSection);
        }
    }

    /**
     * Hide editor for specific section
     * @param {string} sectionId - The section ID
     */
    hideEditor(sectionId) {
        // Section manager will trigger re-render through events
        this.currentTextarea = null;
        this.currentSection = null;
    }

    /**
     * Update section content in DOM
     * @param {string} sectionId - The section ID
     * @param {string} content - The new content
     */
    updateSectionContent(sectionId, content) {
        const element = this.findSectionElement(sectionId);
        if (!element) return;

        // Parse markdown to HTML
        if (typeof marked !== 'undefined') {
            element.innerHTML = marked.parse(content);
        } else {
            element.innerHTML = `<p>${content}</p>`;
        }
    }

    /**
     * Update textarea content
     * @param {string} content - The new content
     */
    updateTextareaContent(content) {
        if (this.currentTextarea) {
            this.currentTextarea.value = content;
        }
    }

    /**
     * Handle accept button click
     * @param {string} sectionId - The section ID
     */
    handleAccept(sectionId) {
        try {
            this.sectionManager.acceptChanges(sectionId);
        } catch (error) {
            console.error('Failed to accept changes:', error);
            this.showError(error.message);
        }
    }

    /**
     * Handle cancel button click
     * @param {string} sectionId - The section ID
     */
    handleCancel(sectionId) {
        try {
            this.sectionManager.cancelChanges(sectionId);
        } catch (error) {
            console.error('Failed to cancel changes:', error);
            this.showError(error.message);
        }
    }

    /**
     * Handle reset button click
     * @param {string} sectionId - The section ID
     */
    handleReset(sectionId) {
        try {
            this.sectionManager.resetToOriginal(sectionId);
        } catch (error) {
            console.error('Failed to reset section:', error);
            this.showError(error.message);
        }
    }

    /**
     * Handle keyboard shortcuts
     * @param {KeyboardEvent} event - The keyboard event
     */
    handleKeydown(event) {
        if (!this.currentSection) return;

        if (event.ctrlKey || event.metaKey) {
            switch (event.key) {
                case 'Enter':
                    event.preventDefault();
                    this.handleAccept(this.currentSection);
                    break;
                case 'Escape':
                    event.preventDefault();
                    this.handleCancel(this.currentSection);
                    break;
            }
        }

        if (event.key === 'Escape') {
            event.preventDefault();
            this.handleCancel(this.currentSection);
        }
    }

    /**
     * Show error message to user
     * @param {string} message - The error message
     */
    showError(message) {
        // Simple error display - could be enhanced with better UI
        console.error('Section Editor Error:', message);

        // Create temporary error message
        const errorDiv = document.createElement('div');
        errorDiv.className = 'markitect-error';
        errorDiv.textContent = message;
        errorDiv.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: #f44336;
            color: white;
            padding: 12px 20px;
            border-radius: 4px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            z-index: 10000;
            font-size: 14px;
            max-width: 300px;
        `;

        document.body.appendChild(errorDiv);

        // Remove after 5 seconds
        setTimeout(() => {
            if (errorDiv.parentNode) {
                errorDiv.parentNode.removeChild(errorDiv);
            }
        }, 5000);
    }

    /**
     * Reset all sections to original state
     */
    resetAllSections() {
        try {
            this.sectionManager.resetAllToOriginal();
            this.hideCurrentEditor();
            // Re-render all sections
            const sections = this.sectionManager.getAllSections();
            this.renderAllSections(sections);
        } catch (error) {
            console.error('Failed to reset all sections:', error);
            this.showError(error.message);
        }
    }

    /**
     * Get document status for UI display
     * @returns {Object} Document status
     */
    getDocumentStatus() {
        return this.sectionManager.getDocumentStatus();
    }

    /**
     * Get complete document markdown
     * @returns {string} The markdown document
     */
    getDocumentMarkdown() {
        return this.sectionManager.getDocumentMarkdown();
    }

    /**
     * Destroy the renderer and clean up event listeners
     */
    destroy() {
        this.container.removeEventListener('click', this.handleSectionClick);
        this.hideCurrentEditor();
        this.container.innerHTML = '';
    }
}

// Export for testing and usage
if (typeof module !== 'undefined' && module.exports) {
    module.exports = { DOMRenderer };
} else {
    window.MarkitectEditor = window.MarkitectEditor || {};
    window.MarkitectEditor.DOMRenderer = DOMRenderer;
}