/**
 * Markdown conversion utilities using Marked and Turndown
 */
import { marked } from 'marked';
import TurndownService from 'turndown';

/**
 * MarkdownConverter - Handles bidirectional HTML ↔ Markdown conversion
 */
export class MarkdownConverter {
    constructor() {
        this.initializeMarked();
        this.initializeTurndown();
    }

    /**
     * Configure marked for HTML output - MINIMAL MODE
     * Only supports: **bold**, *italic*, and [links](url)
     * Matches server-side goldmark configuration
     */
    initializeMarked() {
        marked.setOptions({
            gfm: false,             // Disable GFM to match server minimal mode
            breaks: true,           // Convert \n to <br> (matches server)
            pedantic: false,        // Don't be overly strict
            sanitize: false,        // Allow HTML (we control the input)
            smartLists: false,      // Disable lists (not supported on server)
            smartypants: false      // Don't convert quotes/dashes
        });

        // Override renderers to restrict to minimal feature set
        marked.use({
            renderer: {
                // Disable headings - treat as plain text
                heading(text, level) {
                    return text;
                },
                // Disable lists - treat as plain text
                list(body, ordered, start) {
                    return body.replace(/<\/?li>/g, '');
                },
                listitem(text) {
                    return text + '\n';
                },
                // Disable code blocks - treat as plain text
                code(code, language) {
                    return code;
                },
                blockquote(quote) {
                    return quote; // Disable blockquotes - treat as plain text
                },
                // Disable horizontal rules
                hr() {
                    return '';
                },
                // Disable tables
                table(header, body) {
                    return header + body;
                },
                tablecell(content, flags) {
                    return content;
                },
                tablerow(content) {
                    return content;
                }
            }
        });
    }

    /**
     * Configure turndown for markdown output - MINIMAL MODE  
     * Only supports: **bold**, *italic*, and [links](url)
     * Matches server-side goldmark configuration
     */
    initializeTurndown() {
        this.turndown = new TurndownService({
            // Minimal configuration - only basic formatting
            headingStyle: 'atx',           // # headers (but will be disabled)
            hr: '---',                     // horizontal rule (but will be disabled)
            bulletListMarker: '-',         // bullet list (but will be disabled)
            codeBlockStyle: 'fenced',      // code blocks (but will be disabled)
            fence: '```',                  // fence marker (but will be disabled)
            emDelimiter: '*',              // *italic* - matches server
            strongDelimiter: '**',         // **bold** - matches server
            linkStyle: 'inlined',          // [text](url) - matches server
            linkReferenceStyle: 'full'     // full reference links
        });

        // Add custom rules for better conversion
        this.addTurndownRules();
    }

    /**
     * Add custom turndown rules - MINIMAL MODE
     * Only supports: **bold**, *italic*, and [links](url)
     * Disables all other formatting to match server
     */
    addTurndownRules() {
        // Handle paragraph spacing properly - ensure double newlines between paragraphs
        this.turndown.addRule('paragraph', {
            filter: 'p',
            replacement: function (content) {
                if (!content.trim()) return '';
                return content.trim() + '\n\n';
            }
        });

        // Handle bold text in markdown - keep this (supported)
        this.turndown.addRule('bold', {
            filter: ['strong', 'b'],
            replacement: function (content) {
                if (!content.trim()) return '';
                return '**' + content + '**';
            }
        });

        // Handle italic text in markdown - keep this (supported)
        this.turndown.addRule('italic', {
            filter: ['em', 'i'],
            replacement: function (content) {
                if (!content.trim()) return '';
                return '*' + content + '*';
            }
        });

        // DISABLE unsupported features - convert to plain text
        this.turndown.addRule('disableHeadings', {
            filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
            replacement: function (content) {
                return content; // Just return text content, no # markup
            }
        });

        this.turndown.addRule('disableLists', {
            filter: ['ul', 'ol', 'li'],
            replacement: function (content) {
                return content; // Just return text content, no list markup
            }
        });

        this.turndown.addRule('disableCode', {
            filter: ['pre', 'code'],
            replacement: function (content) {
                return content; // Just return text content, no code markup
            }
        });

        this.turndown.addRule('disableBlockquotes', {
            filter: 'blockquote',
            replacement: function (content) {
                return content; // Just return text content, no > markup
            }
        });

        this.turndown.addRule('disableHR', {
            filter: 'hr',
            replacement: function () {
                return ''; // Remove horizontal rules entirely
            }
        });
    }

    /**
     * Convert HTML to Markdown
     * @param {string} html - HTML string to convert
     * @returns {string} - Markdown string
     */
    htmlToMarkdown(html) {
        if (!html || html.trim() === '') {
            return '';
        }

        try {
            const markdown = this.turndown.turndown(html);
            // Clean up and normalize newlines for proper paragraph separation
            return markdown
                .replace(/\n{3,}/g, '\n\n')  // Replace 3+ newlines with 2
                .replace(/^\n+|\n+$/g, '')   // Remove leading/trailing newlines
                .trim();                      // Remove other whitespace
        } catch (error) {
            console.warn('HTML to Markdown conversion failed:', error);
            // Fallback: extract text content
            const tempDiv = document.createElement('div');
            tempDiv.innerHTML = html;
            return tempDiv.textContent || tempDiv.innerText || '';
        }
    }

    /**
     * Convert Markdown to HTML
     * @param {string} markdown - Markdown string to convert
     * @returns {string} - HTML string
     */
    markdownToHtml(markdown) {
        if (!markdown || markdown.trim() === '') {
            return '';
        }

        try {
            const html = marked(markdown);
            return html;
        } catch (error) {
            console.warn('Markdown to HTML conversion failed:', error);
            // Fallback: convert line breaks to paragraphs
            return markdown
                .split(/\n\s*\n/)
                .filter(p => p.trim())
                .map(p => `<p>${p.trim()}</p>`)
                .join('');
        }
    }

    /**
     * Extract HTML content from a group of elements
     * @param {HTMLElement[]} elements - Array of DOM elements
     * @returns {string} - Combined HTML content
     */
    extractGroupHTML(elements) {
        const htmlParts = [];
        
        elements.forEach(element => {
            // Wrap inner content in paragraph tags to preserve structure
            const html = element.innerHTML.trim();
            if (html) {
                // If element is already a paragraph, use its outer HTML
                if (element.tagName.toLowerCase() === 'p') {
                    htmlParts.push(element.outerHTML);
                } else {
                    // Wrap in paragraph tags
                    htmlParts.push(`<p>${html}</p>`);
                }
            }
        });
        
        return htmlParts.join('\n');
    }

    /**
     * Convert HTML content from group elements to markdown
     * @param {HTMLElement[]} elements - Array of DOM elements  
     * @returns {string} - Markdown representation
     */
    extractGroupMarkdown(elements) {
        const html = this.extractGroupHTML(elements);
        const markdown = this.htmlToMarkdown(html);
        return markdown;
    }

    /**
     * Update group elements with markdown content
     * @param {HTMLElement[]} elements - Array of DOM elements to update
     * @param {string} markdown - Markdown content to render
     */
    updateGroupElements(elements, markdown) {
        const html = this.markdownToHtml(markdown);
        
        // Split HTML into paragraphs
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = html;
        
        const paragraphs = Array.from(tempDiv.querySelectorAll('p, div, h1, h2, h3, h4, h5, h6'));
        
        // Handle case where we have more/fewer paragraphs than elements
        const maxCount = Math.max(elements.length, paragraphs.length);
        
        for (let i = 0; i < maxCount; i++) {
            if (i < elements.length && i < paragraphs.length) {
                // Update existing element with corresponding paragraph
                elements[i].innerHTML = paragraphs[i].innerHTML;
            } else if (i < elements.length) {
                // More elements than paragraphs - clear extra elements
                elements[i].innerHTML = '';
            } else if (i < paragraphs.length) {
                // More paragraphs than elements - create new element
                const newElement = document.createElement('p');
                newElement.innerHTML = paragraphs[i].innerHTML;
                
                // Insert after the last existing element
                const lastElement = elements[elements.length - 1];
                lastElement.parentNode.insertBefore(newElement, lastElement.nextSibling);
                elements.push(newElement); // Add to our elements array for future updates
            }
        }
    }
}

// Export singleton instance
export const markdownConverter = new MarkdownConverter();