(function () {
    function escapeHtml(value) {
        return String(value ?? '')
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }

    function normalizeColor(value, fallback) {
        const color = String(value || '').trim();
        return /^#[0-9a-fA-F]{6}$/.test(color) ? color.toUpperCase() : fallback;
    }

    function normalizeAlign(value, fallback) {
        const allowed = ['left', 'center', 'right'];
        return allowed.includes(value) ? value : fallback;
    }

    function normalizeLinkAction(value) {
        const allowed = ['none', 'assign_tag', 'remove_tag'];
        return allowed.includes(value) ? value : 'none';
    }

    function clamp(value, min, max, fallback) {
        const parsed = parseInt(value, 10);
        if (Number.isNaN(parsed)) {
            return fallback;
        }
        return Math.min(max, Math.max(min, parsed));
    }

    function defaultBlock(type) {
        if (type === 'preheader') {
            return { type: 'preheader', text: 'Kurzer Vorschautext fuer den Posteingang' };
        }
        if (type === 'image') {
            return { type: 'image', src: '', alt: '', width: 600, align: 'center' };
        }
        if (type === 'video') {
            return { type: 'video', thumbnail_url: '', video_url: 'https://', alt: 'Video', caption: 'Video ansehen', width: 600, align: 'center' };
        }
        if (type === 'button') {
            return { type: 'button', text: 'Button', url: 'https://', align: 'center', background_color: '#0D6EFD', text_color: '#FFFFFF', radius: 6, link_action: 'none', link_tag: '', link_only_once: true };
        }
        if (type === 'link') {
            return { type: 'link', text: 'Linktext', url: 'https://', align: 'left', text_color: '#0D6EFD', font_size: 16, link_action: 'none', link_tag: '', link_only_once: true };
        }
        if (type === 'spacer') {
            return { type: 'spacer', height: 24 };
        }
        if (type === 'divider') {
            return { type: 'divider', color: '#D9E2EC' };
        }
        if (type === 'columns') {
            return {
                type: 'columns',
                left_blocks: [{ type: 'text', html: '<p>Linke Spalte</p>' }],
                right_blocks: [{ type: 'text', html: '<p>Rechte Spalte</p>' }],
                gap: 20
            };
        }
        return { type: 'text', html: '<p>Neuer Inhalt</p>' };
    }

    function normalizeBlocks(rawBlocks, allowColumns = true) {
        if (!Array.isArray(rawBlocks)) {
            return [defaultBlock('text')];
        }

        const blocks = rawBlocks.map((block) => {
            if (!block || typeof block !== 'object') {
                return null;
            }

            switch (block.type) {
                case 'text':
                    return { type: 'text', html: String(block.html || '<p></p>') };
                case 'preheader':
                    return { type: 'preheader', text: String(block.text || '').trim() };
                case 'image':
                    return {
                        type: 'image',
                        src: String(block.src || '').trim(),
                        alt: String(block.alt || '').trim(),
                        width: clamp(block.width, 50, 700, 600),
                        align: normalizeAlign(block.align, 'center')
                    };
                case 'video':
                    return {
                        type: 'video',
                        thumbnail_url: String(block.thumbnail_url || '').trim(),
                        video_url: String(block.video_url || '#').trim(),
                        alt: String(block.alt || 'Video').trim(),
                        caption: String(block.caption || '').trim(),
                        width: clamp(block.width, 120, 700, 600),
                        align: normalizeAlign(block.align, 'center')
                    };
                case 'button':
                    return {
                        type: 'button',
                        text: String(block.text || 'Button').trim(),
                        url: String(block.url || '#').trim(),
                        align: normalizeAlign(block.align, 'center'),
                        background_color: normalizeColor(block.background_color, '#0D6EFD'),
                        text_color: normalizeColor(block.text_color, '#FFFFFF'),
                        radius: clamp(block.radius, 0, 30, 6),
                        link_action: normalizeLinkAction(String(block.link_action || 'none').trim()),
                        link_tag: String(block.link_tag || '').trim(),
                        link_only_once: !Object.prototype.hasOwnProperty.call(block, 'link_only_once') || !!block.link_only_once
                    };
                case 'link':
                    return {
                        type: 'link',
                        text: String(block.text || 'Linktext').trim(),
                        url: String(block.url || '#').trim(),
                        align: normalizeAlign(block.align, 'left'),
                        text_color: normalizeColor(block.text_color, '#0D6EFD'),
                        font_size: clamp(block.font_size, 12, 32, 16),
                        link_action: normalizeLinkAction(String(block.link_action || 'none').trim()),
                        link_tag: String(block.link_tag || '').trim(),
                        link_only_once: !Object.prototype.hasOwnProperty.call(block, 'link_only_once') || !!block.link_only_once
                    };
                case 'spacer':
                    return { type: 'spacer', height: clamp(block.height, 4, 120, 24) };
                case 'divider':
                    return { type: 'divider', color: normalizeColor(block.color, '#D9E2EC') };
                case 'columns':
                    if (!allowColumns) {
                        return null;
                    }
                    return {
                        type: 'columns',
                        left_blocks: normalizeBlocks(Array.isArray(block.left_blocks) ? block.left_blocks : (String(block.left_html || '').trim() ? [{ type: 'text', html: String(block.left_html) }] : [{ type: 'text', html: '<p>Linke Spalte</p>' }]), false),
                        right_blocks: normalizeBlocks(Array.isArray(block.right_blocks) ? block.right_blocks : (String(block.right_html || '').trim() ? [{ type: 'text', html: String(block.right_html) }] : [{ type: 'text', html: '<p>Rechte Spalte</p>' }]), false),
                        gap: clamp(block.gap, 8, 40, 20)
                    };
                default:
                    return null;
            }
        }).filter(Boolean);

        return blocks.length ? blocks : [defaultBlock('text')];
    }

    function parseBlocks(rawValue) {
        if (!rawValue) {
            return [defaultBlock('text')];
        }

        try {
            return normalizeBlocks(JSON.parse(rawValue));
        } catch (error) {
            return [{ type: 'text', html: String(rawValue) }];
        }
    }

    function renderBuilderHtml(blocks) {
        return blocks.map((block) => {
            if (block.type === 'text') {
                return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td style="padding:0 0 20px 0;font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.6;color:#243B53;">${block.html}</td></tr></table>`;
            }
            if (block.type === 'preheader') {
                if (!block.text) {
                    return '';
                }
                return `<div style="display:none!important;visibility:hidden;opacity:0;color:transparent;height:0;width:0;overflow:hidden;mso-hide:all;">${escapeHtml(block.text)}</div>`;
            }
            if (block.type === 'image') {
                return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td align="${escapeHtml(block.align)}" style="padding:0 0 20px 0;"><img src="${escapeHtml(block.src)}" alt="${escapeHtml(block.alt)}" width="${block.width}" style="display:block;max-width:100%;height:auto;border:0;outline:none;text-decoration:none;"></td></tr></table>`;
            }
            if (block.type === 'video') {
                const captionRow = block.caption
                    ? `<tr><td align="${escapeHtml(block.align)}" style="padding:8px 0 20px 0;font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.5;color:#486581;"><a href="${escapeHtml(block.video_url)}" style="color:#486581;text-decoration:underline;">${escapeHtml(block.caption)}</a></td></tr>`
                    : '<tr><td height="20" style="font-size:0;line-height:0;">&nbsp;</td></tr>';
                return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td align="${escapeHtml(block.align)}" style="padding:0;"><a href="${escapeHtml(block.video_url)}" style="display:inline-block;text-decoration:none;"><img src="${escapeHtml(block.thumbnail_url)}" alt="${escapeHtml(block.alt)}" width="${block.width}" style="display:block;max-width:100%;height:auto;border:0;outline:none;text-decoration:none;"></a></td></tr>${captionRow}</table>`;
            }
            if (block.type === 'button') {
                const attrs = block.link_action !== 'none' && block.link_tag
                    ? ` data-mr-action="${escapeHtml(block.link_action.replace('_', '-'))}" data-mr-tag="${escapeHtml(block.link_tag)}" data-mr-only-once="${block.link_only_once ? 'true' : 'false'}"`
                    : '';
                return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td align="${escapeHtml(block.align)}" style="padding:0 0 20px 0;"><table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse:separate;"><tr><td bgcolor="${escapeHtml(block.background_color)}" style="border-radius:${block.radius}px;"><a href="${escapeHtml(block.url)}"${attrs} style="display:inline-block;padding:14px 24px;font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.2;color:${escapeHtml(block.text_color)};text-decoration:none;border-radius:${block.radius}px;background:${escapeHtml(block.background_color)};">${escapeHtml(block.text)}</a></td></tr></table></td></tr></table>`;
            }
            if (block.type === 'link') {
                const attrs = block.link_action !== 'none' && block.link_tag
                    ? ` data-mr-action="${escapeHtml(block.link_action.replace('_', '-'))}" data-mr-tag="${escapeHtml(block.link_tag)}" data-mr-only-once="${block.link_only_once ? 'true' : 'false'}"`
                    : '';
                return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td align="${escapeHtml(block.align)}" style="padding:0 0 20px 0;font-family:Arial,Helvetica,sans-serif;font-size:${block.font_size}px;line-height:1.5;"><a href="${escapeHtml(block.url)}"${attrs} style="color:${escapeHtml(block.text_color)};text-decoration:underline;">${escapeHtml(block.text)}</a></td></tr></table>`;
            }
            if (block.type === 'spacer') {
                return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td height="${block.height}" style="font-size:0;line-height:0;">&nbsp;</td></tr></table>`;
            }
            if (block.type === 'divider') {
                return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td style="padding:0 0 20px 0;"><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="border-top:1px solid ${escapeHtml(block.color)};font-size:0;line-height:0;">&nbsp;</td></tr></table></td></tr></table>`;
            }
            if (block.type === 'columns') {
                const leftGap = Math.floor(block.gap / 2);
                const rightGap = Math.ceil(block.gap / 2);
                return `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td style="padding:0 0 20px 0;"><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td valign="top" width="50%" style="padding-right:${leftGap}px;font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.6;color:#243B53;">${renderBuilderHtml(block.left_blocks || [])}</td><td valign="top" width="50%" style="padding-left:${rightGap}px;font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.6;color:#243B53;">${renderBuilderHtml(block.right_blocks || [])}</td></tr></table></td></tr></table>`;
            }
            return '';
        }).join('\n');
    }

    function createField(label, inputHtml) {
        return `<label class="form-label mb-1">${label}</label>${inputHtml}`;
    }

    function blockLabel(type) {
        const labels = {
            text: 'Text',
            preheader: 'Preheader',
            image: 'Bild',
            video: 'Video',
            button: 'Button',
            link: 'Link',
            columns: '2 Spalten',
            divider: 'Trenner',
            spacer: 'Abstand'
        };
        return labels[type] || type;
    }

    function renderLinkActionFields(block, index, tagOptionsHtml) {
        return `
            <div class="template-builder-link-settings">
                <div class="template-builder-link-settings-title">Link-Aktion</div>
                <div class="template-builder-field-grid">
                    <div>${createField('Aktion', `<select class="form-select" data-action="update-field" data-path="${index}" data-field="link_action"><option value="none"${block.link_action === 'none' ? ' selected' : ''}>Keine Zusatzaktion</option><option value="assign_tag"${block.link_action === 'assign_tag' ? ' selected' : ''}>Tag setzen</option><option value="remove_tag"${block.link_action === 'remove_tag' ? ' selected' : ''}>Tag entfernen</option></select>`)}</div>
                    <div>${createField('Tag', `<select class="form-select" data-action="update-field" data-path="${index}" data-field="link_tag"><option value="">-- Tag waehlen --</option>${tagOptionsHtml(block.link_tag)}</select>`)}</div>
                    <div class="template-builder-checkbox-wrap">${createField('Ausfuehrung', `<div class="form-check mt-2"><input class="form-check-input" type="checkbox" ${block.link_only_once ? 'checked' : ''} data-action="update-checkbox" data-path="${index}" data-field="link_only_once" id="link-only-once-${index}"><label class="form-check-label" for="link-only-once-${index}">Nur beim ersten echten Klick</label></div>`)}</div>
                </div>
            </div>
        `;
    }

    function nestedBlockButtons(collectionPath) {
        const types = [
            ['text', 'Text'],
            ['preheader', 'Preheader'],
            ['image', 'Bild'],
            ['video', 'Video'],
            ['button', 'Button'],
            ['link', 'Link'],
            ['divider', 'Trenner'],
            ['spacer', 'Abstand']
        ];

        return types.map(([type, label]) => (
            `<button type="button" class="btn btn-sm btn-outline-primary" data-action="add-child" data-collection-path="${escapeHtml(collectionPath)}" data-child-type="${type}">${label}</button>`
        )).join('');
    }

    function renderNestedBlockList(blocks, collectionPath, tagOptionsHtml) {
        if (!Array.isArray(blocks) || !blocks.length) {
            return '<div class="template-builder-nested-empty">Noch keine Elemente in dieser Spalte.</div>';
        }

        return blocks.map((block, index) => {
            const path = `${collectionPath}.${index}`;
            return `
                <div class="template-builder-nested-block">
                    <div class="template-builder-nested-block-header">
                        <strong>${escapeHtml(blockLabel(block.type))}</strong>
                        <div class="template-builder-block-actions">
                            <button type="button" class="btn btn-sm btn-outline-secondary" data-action="move-up" data-path="${escapeHtml(path)}">Nach oben</button>
                            <button type="button" class="btn btn-sm btn-outline-secondary" data-action="move-down" data-path="${escapeHtml(path)}">Nach unten</button>
                            <button type="button" class="btn btn-sm btn-outline-danger" data-action="remove" data-path="${escapeHtml(path)}">Entfernen</button>
                        </div>
                    </div>
                    <div class="template-builder-nested-block-body">
                        ${renderBlockFields(block, path, tagOptionsHtml)}
                    </div>
                </div>
            `;
        }).join('');
    }

    function renderColumnEditor(label, blocks, collectionPath, tagOptionsHtml) {
        return `
            <div class="template-builder-column-editor">
                <div class="template-builder-column-editor-header">
                    <strong>${label}</strong>
                </div>
                <div class="template-builder-column-toolbar">
                    ${nestedBlockButtons(collectionPath)}
                </div>
                <div class="template-builder-column-canvas">
                    ${renderNestedBlockList(blocks, collectionPath, tagOptionsHtml)}
                </div>
            </div>
        `;
    }

    function renderBlockFields(block, index, tagOptionsHtml) {
        if (block.type === 'text') {
            return `
                <div>
                    ${createField('HTML-Inhalt', `<textarea class="form-control" rows="6" data-action="update-field" data-path="${index}" data-field="html">${escapeHtml(block.html)}</textarea>`)}
                </div>
            `;
        }

        if (block.type === 'preheader') {
            return `<div>${createField('Vorschautext', `<input type="text" class="form-control" value="${escapeHtml(block.text)}" data-action="update-field" data-path="${index}" data-field="text">`)}</div>`;
        }

        if (block.type === 'image') {
            return `
                <div class="template-builder-field-grid">
                    <div>${createField('Bild-URL', `<input type="text" class="form-control" value="${escapeHtml(block.src)}" data-action="update-field" data-path="${index}" data-field="src">`)}</div>
                    <div>${createField('Alt-Text', `<input type="text" class="form-control" value="${escapeHtml(block.alt)}" data-action="update-field" data-path="${index}" data-field="alt">`)}</div>
                    <div>${createField('Breite', `<input type="number" min="50" max="700" class="form-control" value="${block.width}" data-action="update-field" data-path="${index}" data-field="width">`)}</div>
                    <div>${createField('Ausrichtung', `<select class="form-select" data-action="update-field" data-path="${index}" data-field="align"><option value="left"${block.align === 'left' ? ' selected' : ''}>Links</option><option value="center"${block.align === 'center' ? ' selected' : ''}>Zentriert</option><option value="right"${block.align === 'right' ? ' selected' : ''}>Rechts</option></select>`)}</div>
                </div>
            `;
        }

        if (block.type === 'video') {
            return `
                <div class="template-builder-field-grid">
                    <div>${createField('Thumbnail-URL', `<input type="text" class="form-control" value="${escapeHtml(block.thumbnail_url)}" data-action="update-field" data-path="${index}" data-field="thumbnail_url">`)}</div>
                    <div>${createField('Video-URL', `<input type="text" class="form-control" value="${escapeHtml(block.video_url)}" data-action="update-field" data-path="${index}" data-field="video_url">`)}</div>
                    <div>${createField('Alt-Text', `<input type="text" class="form-control" value="${escapeHtml(block.alt)}" data-action="update-field" data-path="${index}" data-field="alt">`)}</div>
                    <div>${createField('Beschriftung', `<input type="text" class="form-control" value="${escapeHtml(block.caption)}" data-action="update-field" data-path="${index}" data-field="caption">`)}</div>
                    <div>${createField('Breite', `<input type="number" min="120" max="700" class="form-control" value="${block.width}" data-action="update-field" data-path="${index}" data-field="width">`)}</div>
                    <div>${createField('Ausrichtung', `<select class="form-select" data-action="update-field" data-path="${index}" data-field="align"><option value="left"${block.align === 'left' ? ' selected' : ''}>Links</option><option value="center"${block.align === 'center' ? ' selected' : ''}>Zentriert</option><option value="right"${block.align === 'right' ? ' selected' : ''}>Rechts</option></select>`)}</div>
                </div>
            `;
        }

        if (block.type === 'button') {
            return `
                <div class="template-builder-field-grid">
                    <div>${createField('Button-Text', `<input type="text" class="form-control" value="${escapeHtml(block.text)}" data-action="update-field" data-path="${index}" data-field="text">`)}</div>
                    <div>${createField('Ziel-URL', `<input type="text" class="form-control" value="${escapeHtml(block.url)}" data-action="update-field" data-path="${index}" data-field="url">`)}</div>
                    <div>${createField('Ausrichtung', `<select class="form-select" data-action="update-field" data-path="${index}" data-field="align"><option value="left"${block.align === 'left' ? ' selected' : ''}>Links</option><option value="center"${block.align === 'center' ? ' selected' : ''}>Zentriert</option><option value="right"${block.align === 'right' ? ' selected' : ''}>Rechts</option></select>`)}</div>
                    <div>${createField('Eckenradius', `<input type="number" min="0" max="30" class="form-control" value="${block.radius}" data-action="update-field" data-path="${index}" data-field="radius">`)}</div>
                    <div>${createField('Hintergrund', `<input type="color" class="form-control form-control-color" value="${escapeHtml(block.background_color)}" data-action="update-field" data-path="${index}" data-field="background_color">`)}</div>
                    <div>${createField('Textfarbe', `<input type="color" class="form-control form-control-color" value="${escapeHtml(block.text_color)}" data-action="update-field" data-path="${index}" data-field="text_color">`)}</div>
                </div>
                ${renderLinkActionFields(block, index, tagOptionsHtml)}
            `;
        }

        if (block.type === 'link') {
            return `
                <div class="template-builder-field-grid">
                    <div>${createField('Link-Text', `<input type="text" class="form-control" value="${escapeHtml(block.text)}" data-action="update-field" data-path="${index}" data-field="text">`)}</div>
                    <div>${createField('Ziel-URL', `<input type="text" class="form-control" value="${escapeHtml(block.url)}" data-action="update-field" data-path="${index}" data-field="url">`)}</div>
                    <div>${createField('Ausrichtung', `<select class="form-select" data-action="update-field" data-path="${index}" data-field="align"><option value="left"${block.align === 'left' ? ' selected' : ''}>Links</option><option value="center"${block.align === 'center' ? ' selected' : ''}>Zentriert</option><option value="right"${block.align === 'right' ? ' selected' : ''}>Rechts</option></select>`)}</div>
                    <div>${createField('Schriftgroesse', `<input type="number" min="12" max="32" class="form-control" value="${block.font_size}" data-action="update-field" data-path="${index}" data-field="font_size">`)}</div>
                    <div>${createField('Textfarbe', `<input type="color" class="form-control form-control-color" value="${escapeHtml(block.text_color)}" data-action="update-field" data-path="${index}" data-field="text_color">`)}</div>
                </div>
                ${renderLinkActionFields(block, index, tagOptionsHtml)}
            `;
        }

        if (block.type === 'spacer') {
            return `<div>${createField('Hoehe', `<input type="number" min="4" max="120" class="form-control" value="${block.height}" data-action="update-field" data-path="${index}" data-field="height">`)}</div>`;
        }

        if (block.type === 'divider') {
            return `<div>${createField('Linienfarbe', `<input type="color" class="form-control form-control-color" value="${escapeHtml(block.color)}" data-action="update-field" data-path="${index}" data-field="color">`)}</div>`;
        }

        if (block.type === 'columns') {
            return `
                <div class="template-builder-field-grid">
                    <div>${createField('Spaltenabstand', `<input type="number" min="8" max="40" class="form-control" value="${block.gap}" data-action="update-field" data-path="${index}" data-field="gap">`)}</div>
                </div>
                <div class="template-builder-columns-editor">
                    ${renderColumnEditor('Linke Spalte', block.left_blocks || [], `${index}.left_blocks`, tagOptionsHtml)}
                    ${renderColumnEditor('Rechte Spalte', block.right_blocks || [], `${index}.right_blocks`, tagOptionsHtml)}
                </div>
            `;
        }

        return '';
    }

    function initEditor(form) {
        const editorMode = form.querySelector('[data-role="editor-mode"]');
        const modeNote = form.querySelector('[data-role="editor-mode-note"]');
        const panels = Array.from(form.querySelectorAll('[data-editor-panel]'));
        const codeTextarea = form.querySelector('[data-role="code-editor"]');
        const ckeditorTextarea = form.querySelector('[data-role="ckeditor-editor"]');
        const sourceContentInput = form.querySelector('[data-role="source-content"]');
        const bodyHtmlInput = form.querySelector('[data-role="body-html"]');
        const builderCanvas = form.querySelector('[data-role="builder-canvas"]');
        const builderPreview = form.querySelector('[data-role="builder-preview"]');
        const builderToolbar = form.querySelector('[data-role="builder-toolbar"]');
        const builderState = {
            blocks: parseBlocks(sourceContentInput ? sourceContentInput.value : '')
        };
        let builderTags = [];

        try {
            builderTags = JSON.parse(form.getAttribute('data-builder-tags') || '[]');
        } catch (error) {
            builderTags = [];
        }

        const tagOptionsHtml = (selectedValue) => builderTags.map((tag) => {
            const value = String(tag.name || '').trim();
            if (!value) {
                return '';
            }
            return `<option value="${escapeHtml(value)}"${value === String(selectedValue || '') ? ' selected' : ''}>${escapeHtml(value)}</option>`;
        }).join('');

        let ckeditorInstance = null;

        function syncCkeditorFrom(value) {
            if (ckeditorInstance) {
                ckeditorInstance.setData(value);
            } else if (ckeditorTextarea) {
                ckeditorTextarea.value = value;
            }
        }

        function currentHtmlValue() {
            const mode = editorMode ? editorMode.value : 'code';
            if (mode === 'ckeditor' && ckeditorInstance) {
                return ckeditorInstance.getData();
            }
            if (mode === 'ckeditor' && ckeditorTextarea) {
                return ckeditorTextarea.value;
            }
            return codeTextarea ? codeTextarea.value : '';
        }

        function refreshModeNote() {
            if (!modeNote || !editorMode) {
                return;
            }

            const mode = editorMode.value;
            const notes = {
                code: 'HTML-Code eignet sich fuer vollstaendige Kontrolle und Sonderfaelle.',
                ckeditor: 'CKEditor bleibt fuer freie Bearbeitung verfuegbar, erzeugt aber keine blockbasierte Mail-Struktur.',
                email_builder: 'Der E-Mail-Builder speichert strukturierte Bloecke, Link-Aktionen und erzeugt daraus versandfertiges HTML.'
            };
            modeNote.textContent = notes[mode] || '';
        }

        function togglePanels() {
            const mode = editorMode ? editorMode.value : 'code';
            panels.forEach((panel) => {
                panel.classList.toggle('is-active', panel.getAttribute('data-editor-panel') === mode);
            });
            refreshModeNote();
            syncHiddenFields();
        }

        function syncHiddenFields() {
            if (!sourceContentInput || !bodyHtmlInput || !editorMode) {
                return;
            }

            const mode = editorMode.value;
            if (mode === 'email_builder') {
                const json = JSON.stringify(builderState.blocks);
                sourceContentInput.value = json;
                bodyHtmlInput.value = renderBuilderHtml(builderState.blocks);
                return;
            }

            const html = currentHtmlValue();
            sourceContentInput.value = html;
            bodyHtmlInput.value = html;
        }

        function renderBuilder() {
            if (!builderCanvas || !builderPreview) {
                return;
            }

            builderCanvas.innerHTML = '';
            if (!builderState.blocks.length) {
                builderCanvas.innerHTML = '<div class="template-builder-empty">Noch keine Builder-Bloecke vorhanden.</div>';
            } else {
                builderState.blocks.forEach((block, index) => {
                    const wrapper = document.createElement('div');
                    wrapper.className = 'template-builder-block';
                    wrapper.innerHTML = `
                        <div class="template-builder-block-header">
	                            <strong>${escapeHtml(blockLabel(block.type))}</strong>
                            <div class="template-builder-block-actions">
                                <button type="button" class="btn btn-sm btn-outline-secondary" data-action="move-up" data-path="${index}">Nach oben</button>
                                <button type="button" class="btn btn-sm btn-outline-secondary" data-action="move-down" data-path="${index}">Nach unten</button>
                                <button type="button" class="btn btn-sm btn-outline-danger" data-action="remove" data-path="${index}">Entfernen</button>
                            </div>
                        </div>
                        <div class="template-builder-block-body">
                            ${renderBlockFields(block, index, tagOptionsHtml)}
                        </div>
                    `;
                    builderCanvas.appendChild(wrapper);
                });
            }

            builderPreview.innerHTML = renderBuilderHtml(builderState.blocks);
            syncHiddenFields();
        }

        function refreshBuilderPreviewOnly() {
            if (!builderPreview) {
                return;
            }
            builderPreview.innerHTML = renderBuilderHtml(builderState.blocks);
            syncHiddenFields();
        }

        function parsePath(path) {
            return String(path || '')
                .split('.')
                .filter((segment) => segment !== '')
                .map((segment) => (/^\d+$/.test(segment) ? parseInt(segment, 10) : segment));
        }

        function getNodeByPath(path) {
            const segments = parsePath(path);
            let current = builderState.blocks;
            for (const segment of segments) {
                if (current == null || !(segment in current)) {
                    return null;
                }
                current = current[segment];
            }
            return current;
        }

        function getCollectionByPath(path) {
            if (!path) {
                return builderState.blocks;
            }
            const segments = parsePath(path);
            let current = builderState.blocks;
            for (const segment of segments) {
                if (current == null || !(segment in current)) {
                    return null;
                }
                current = current[segment];
            }
            return Array.isArray(current) ? current : null;
        }

        function getParentCollectionInfo(path) {
            const segments = parsePath(path);
            if (!segments.length) {
                return null;
            }
            const index = segments.pop();
            let collection = builderState.blocks;
            for (const segment of segments) {
                if (collection == null || !(segment in collection)) {
                    return null;
                }
                collection = collection[segment];
            }
            if (!Array.isArray(collection) || typeof index !== 'number') {
                return null;
            }
            return { collection, index };
        }

        function updateBlockField(path, field, value, rerenderEditor = false) {
            const block = getNodeByPath(path);
            if (!block) {
                return;
            }

            if (field === 'width') {
                const min = block.type === 'video' ? 120 : 50;
                block.width = clamp(value, min, 700, block.width || 600);
            } else if (field === 'height') {
                block.height = clamp(value, 4, 120, block.height || 24);
            } else if (field === 'gap') {
                block.gap = clamp(value, 8, 40, block.gap || 20);
            } else if (field === 'radius') {
                block.radius = clamp(value, 0, 30, block.radius || 6);
            } else if (field === 'font_size') {
                block.font_size = clamp(value, 12, 32, block.font_size || 16);
            } else if (field === 'background_color' || field === 'text_color' || field === 'color') {
                block[field] = normalizeColor(value, block[field] || '#0D6EFD');
            } else if (field === 'align') {
                block.align = normalizeAlign(value, block.align || 'left');
            } else if (field === 'link_action') {
                block.link_action = normalizeLinkAction(value);
            } else {
                block[field] = value;
            }

            if (rerenderEditor) {
                renderBuilder();
                return;
            }

            refreshBuilderPreviewOnly();
        }

        if (builderToolbar) {
            builderToolbar.addEventListener('click', (event) => {
                const button = event.target.closest('[data-add-block]');
                if (!button) {
                    return;
                }
                builderState.blocks.push(defaultBlock(button.getAttribute('data-add-block')));
                renderBuilder();
            });
        }

        if (builderCanvas) {
            builderCanvas.addEventListener('click', (event) => {
                const button = event.target.closest('button[data-action]');
                if (!button) {
                    return;
                }
                const action = button.getAttribute('data-action');
                if (action === 'add-child') {
                    const collection = getCollectionByPath(button.getAttribute('data-collection-path'));
                    const type = button.getAttribute('data-child-type');
                    if (!collection || !type) {
                        return;
                    }
                    collection.push(defaultBlock(type));
                    renderBuilder();
                    return;
                }

                const info = getParentCollectionInfo(button.getAttribute('data-path'));
                if (!info) {
                    return;
                }

                if (action === 'remove') {
                    info.collection.splice(info.index, 1);
                    if (info.collection.length === 0) {
                        info.collection.push(defaultBlock('text'));
                    }
                    renderBuilder();
                }
                if (action === 'move-up' && info.index > 0) {
                    const temp = info.collection[info.index - 1];
                    info.collection[info.index - 1] = info.collection[info.index];
                    info.collection[info.index] = temp;
                    renderBuilder();
                }
                if (action === 'move-down' && info.index < info.collection.length - 1) {
                    const temp = info.collection[info.index + 1];
                    info.collection[info.index + 1] = info.collection[info.index];
                    info.collection[info.index] = temp;
                    renderBuilder();
                }
            });

            builderCanvas.addEventListener('input', (event) => {
                const field = event.target.closest('[data-action="update-field"]');
                if (!field) {
                    return;
                }
                updateBlockField(field.getAttribute('data-path'), field.getAttribute('data-field'), field.value, false);
            });

            builderCanvas.addEventListener('change', (event) => {
                const field = event.target.closest('[data-action="update-field"]');
                if (!field) {
                    const checkbox = event.target.closest('[data-action="update-checkbox"]');
                    if (!checkbox) {
                        return;
                    }
                    updateBlockField(checkbox.getAttribute('data-path'), checkbox.getAttribute('data-field'), checkbox.checked, true);
                    return;
                }
                updateBlockField(field.getAttribute('data-path'), field.getAttribute('data-field'), field.value, false);
            });
        }

        if (codeTextarea) {
            codeTextarea.addEventListener('input', syncHiddenFields);
        }

        if (ckeditorTextarea) {
            ckeditorTextarea.addEventListener('input', syncHiddenFields);
        }

        if (editorMode) {
            editorMode.addEventListener('change', () => {
                const html = currentHtmlValue();
                if (editorMode.value === 'ckeditor') {
                    syncCkeditorFrom(codeTextarea ? codeTextarea.value : html);
                }
                if (editorMode.value === 'code' && codeTextarea) {
                    codeTextarea.value = html;
                }
                if (editorMode.value === 'email_builder' && builderState.blocks.length === 1 && builderState.blocks[0].type === 'text') {
                    const currentHtml = html.trim();
                    if (currentHtml !== '' && currentHtml !== builderState.blocks[0].html) {
                        builderState.blocks = [{ type: 'text', html: currentHtml }];
                        renderBuilder();
                    }
                }
                togglePanels();
            });
        }

        if (window.CKEDITOR && ckeditorTextarea) {
            const requiredPlugins = [
                'ClassicEditor', 'Essentials', 'Bold', 'Italic', 'Font', 'Paragraph', 'Heading', 'Image', 'LinkImage',
                'SourceEditing', 'ImageInsertViaUrl', 'List', 'Alignment', 'Table', 'TableToolbar', 'TableCellProperties',
                'TableProperties', 'ImageToolbar', 'FullPage', 'HorizontalLine', 'FontFamily', 'FontSizeEditing', 'FontSizeUI',
                'TableColumnResize', 'AccessibilityHelp', 'AutoLink', 'Autosave', 'BlockQuote', 'FontBackgroundColor',
                'FontColor', 'HtmlComment', 'ImageBlock', 'ImageCaption', 'ImageInline', 'ImageResize', 'ImageStyle',
                'ImageTextAlternative', 'Link', 'ListProperties', 'SelectAll', 'TableCaption', 'TodoList', 'Underline', 'Undo'
            ];

            const ready = requiredPlugins.every((plugin) => Object.prototype.hasOwnProperty.call(window.CKEDITOR, plugin));
            if (ready) {
                const cke = window.CKEDITOR;
                cke.ClassicEditor.create(ckeditorTextarea, {
                    licenseKey: '<YOUR_LICENSE_KEY>',
                    fontSize: { options: [9, 11, 13, 'default', 17, 19, 21, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42] },
                    plugins: requiredPlugins.map((plugin) => cke[plugin]),
                    toolbar: [
                        'undo', 'redo', '|', 'heading', '|', 'fontfamily', 'fontSize', 'fontColor', 'fontBackgroundColor',
                        '|', 'bold', 'italic', '|', 'alignment', 'insertTable', 'link', 'insertImage', 'horizontalLine',
                        '|', 'bulletedList', 'numberedList', '|', 'sourceEditing'
                    ],
                    image: {
                        toolbar: ['toggleImageCaption', 'imageTextAlternative', '|', 'imageStyle:inline', 'imageStyle:wrapText', 'imageStyle:breakText', '|', 'resizeImage']
                    },
                    table: {
                        contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties']
                    }
                }).then((editor) => {
                    ckeditorInstance = editor;
                    editor.model.document.on('change:data', syncHiddenFields);
                    syncHiddenFields();
                }).catch((error) => {
                    console.error(error);
                });
            }
        }

        form.addEventListener('submit', () => {
            if (editorMode && editorMode.value === 'code' && ckeditorInstance) {
                codeTextarea.value = ckeditorInstance.getData();
            }
            syncHiddenFields();
        });

        renderBuilder();
        togglePanels();
    }

    document.addEventListener('DOMContentLoaded', function () {
        document.querySelectorAll('[data-template-editor-form]').forEach(initEditor);
    });
})();
