<?php

function mrEmailTemplateModeCatalog(): array
{
    return [
        'code' => [
            'label' => 'HTML-Code',
            'description' => 'Direkte Bearbeitung des HTML-Codes ohne visuellen Editor.',
        ],
        'ckeditor' => [
            'label' => 'CKEditor',
            'description' => 'Klassischer Rich-Text-Editor fuer freie HTML-Bearbeitung.',
        ],
        'email_builder' => [
            'label' => 'E-Mail-Builder',
            'description' => 'Open-Source Block-Editor fuer strukturierte E-Mail-Layouts.',
        ],
    ];
}

function mrGetEmailTemplateModeLabel(string $mode): string
{
    $catalog = mrEmailTemplateModeCatalog();
    return $catalog[$mode]['label'] ?? $mode;
}

function mrNormalizeEditorMode(string $mode, array $allowedModes, string $fallbackMode): string
{
    $mode = trim($mode);
    if ($mode !== '' && in_array($mode, $allowedModes, true)) {
        return $mode;
    }

    if (in_array($fallbackMode, $allowedModes, true)) {
        return $fallbackMode;
    }

    return $allowedModes[0] ?? 'code';
}

function mrParseAllowedEditorModes($rawValue, bool $ckeditorEnabled): array
{
    $catalog = array_keys(mrEmailTemplateModeCatalog());
    $values = [];

    if (is_array($rawValue)) {
        $values = $rawValue;
    } elseif (is_string($rawValue)) {
        $values = preg_split('/\s*,\s*/', trim($rawValue)) ?: [];
    }

    $normalized = [];
    foreach ($values as $value) {
        $value = trim((string) $value);
        if ($value === '' || !in_array($value, $catalog, true)) {
            continue;
        }
        if ($value === 'ckeditor' && !$ckeditorEnabled) {
            continue;
        }
        if (!in_array($value, $normalized, true)) {
            $normalized[] = $value;
        }
    }

    if ($normalized !== []) {
        return $normalized;
    }

    return $ckeditorEnabled
        ? ['code', 'ckeditor', 'email_builder']
        : ['code', 'email_builder'];
}

function mrLoadSettingsMap(PDO $db, array $keys): array
{
    $keys = array_values(array_unique(array_filter(array_map('strval', $keys))));
    if ($keys === []) {
        return [];
    }

    $placeholders = implode(',', array_fill(0, count($keys), '?'));

    try {
        $stmt = $db->prepare("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ($placeholders)");
        $stmt->execute($keys);
        $rows = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
        ErrorLogger::logSqlSuccess('Editor settings geladen | table: settings | context: ' . json_encode(['keys' => $keys], JSON_UNESCAPED_UNICODE));
        return is_array($rows) ? $rows : [];
    } catch (Throwable $e) {
        ErrorLogger::logSqlError('Editor settings konnten nicht geladen werden | table: settings | error: ' . $e->getMessage());
        return [];
    }
}

function mrGetTemplateEditorSettings(array $config, ?PDO $db = null): array
{
    $ckeditorEnabled = !empty($config['editor']['use_ckeditor']);
    $configAllowed = $config['editor']['allowed_modes'] ?? [];
    $configDefault = (string) ($config['editor']['default_mode'] ?? ($ckeditorEnabled ? 'ckeditor' : 'code'));
    $allowedModes = mrParseAllowedEditorModes($configAllowed, $ckeditorEnabled);
    $defaultMode = mrNormalizeEditorMode($configDefault, $allowedModes, $allowedModes[0] ?? 'code');

    if ($db instanceof PDO) {
        $settings = mrLoadSettingsMap($db, ['default_editor_mode', 'allowed_editor_modes']);
        if (!empty($settings['allowed_editor_modes'])) {
            $allowedModes = mrParseAllowedEditorModes((string) $settings['allowed_editor_modes'], $ckeditorEnabled);
        }
        if (!empty($settings['default_editor_mode'])) {
            $defaultMode = mrNormalizeEditorMode((string) $settings['default_editor_mode'], $allowedModes, $defaultMode);
        } else {
            $defaultMode = mrNormalizeEditorMode($defaultMode, $allowedModes, $defaultMode);
        }
    }

    return [
        'ckeditor_enabled' => $ckeditorEnabled,
        'allowed_modes' => $allowedModes,
        'default_mode' => $defaultMode,
        'mode_catalog' => mrEmailTemplateModeCatalog(),
    ];
}

function mrCreateDefaultBuilderSource(string $html = ''): string
{
    $defaultHtml = trim($html) !== '' ? $html : '<p>Neuer Inhalt</p>';
    return json_encode([
        [
            'type' => 'text',
            'html' => $defaultHtml,
        ],
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}

function mrNormalizeBuilderColor(string $value, string $fallback): string
{
    $value = trim($value);
    if (preg_match('/^#[0-9a-fA-F]{6}$/', $value)) {
        return strtoupper($value);
    }

    return $fallback;
}

function mrNormalizeBuilderAlign(string $value, string $fallback = 'left'): string
{
    $allowed = ['left', 'center', 'right'];
    return in_array($value, $allowed, true) ? $value : $fallback;
}

function mrNormalizeBuilderLinkAction(string $value): string
{
    $allowed = ['none', 'assign_tag', 'remove_tag'];
    return in_array($value, $allowed, true) ? $value : 'none';
}

function mrBuildTrackedLinkAttributes(array $block): string
{
    $action = mrNormalizeBuilderLinkAction((string) ($block['link_action'] ?? 'none'));
    $tag = trim((string) ($block['link_tag'] ?? ''));
    if ($action === 'none' || $tag === '') {
        return '';
    }

    $attributes = ' data-mr-action="' . htmlspecialchars(str_replace('_', '-', $action), ENT_QUOTES, 'UTF-8') . '"';
    $attributes .= ' data-mr-tag="' . htmlspecialchars($tag, ENT_QUOTES, 'UTF-8') . '"';
    $attributes .= ' data-mr-only-once="' . (!empty($block['link_only_once']) ? 'true' : 'false') . '"';

    return $attributes;
}

function mrNormalizeSingleBuilderBlock(array $block, bool $allowColumns = true): ?array
{
    $type = (string) ($block['type'] ?? '');
    if ($type === '') {
        return null;
    }

    if ($type === 'text') {
        return [
            'type' => 'text',
            'html' => (string) ($block['html'] ?? '<p></p>'),
        ];
    }

    if ($type === 'preheader') {
        return [
            'type' => 'preheader',
            'text' => trim((string) ($block['text'] ?? '')),
        ];
    }

    if ($type === 'image') {
        return [
            'type' => 'image',
            'src' => trim((string) ($block['src'] ?? '')),
            'alt' => trim((string) ($block['alt'] ?? '')),
            'width' => max(50, min(700, (int) ($block['width'] ?? 600))),
            'align' => mrNormalizeBuilderAlign((string) ($block['align'] ?? 'center'), 'center'),
        ];
    }

    if ($type === 'video') {
        return [
            'type' => 'video',
            'thumbnail_url' => trim((string) ($block['thumbnail_url'] ?? '')),
            'video_url' => trim((string) ($block['video_url'] ?? '#')),
            'alt' => trim((string) ($block['alt'] ?? 'Video')),
            'caption' => trim((string) ($block['caption'] ?? '')),
            'width' => max(120, min(700, (int) ($block['width'] ?? 600))),
            'align' => mrNormalizeBuilderAlign((string) ($block['align'] ?? 'center'), 'center'),
        ];
    }

    if ($type === 'button') {
        return [
            'type' => 'button',
            'text' => trim((string) ($block['text'] ?? 'Button')),
            'url' => trim((string) ($block['url'] ?? '#')),
            'align' => mrNormalizeBuilderAlign((string) ($block['align'] ?? 'center'), 'center'),
            'background_color' => mrNormalizeBuilderColor((string) ($block['background_color'] ?? '#0D6EFD'), '#0D6EFD'),
            'text_color' => mrNormalizeBuilderColor((string) ($block['text_color'] ?? '#FFFFFF'), '#FFFFFF'),
            'radius' => max(0, min(30, (int) ($block['radius'] ?? 6))),
            'link_action' => mrNormalizeBuilderLinkAction((string) ($block['link_action'] ?? 'none')),
            'link_tag' => trim((string) ($block['link_tag'] ?? '')),
            'link_only_once' => !array_key_exists('link_only_once', $block) || !empty($block['link_only_once']),
        ];
    }

    if ($type === 'link') {
        return [
            'type' => 'link',
            'text' => trim((string) ($block['text'] ?? 'Linktext')),
            'url' => trim((string) ($block['url'] ?? 'https://')),
            'align' => mrNormalizeBuilderAlign((string) ($block['align'] ?? 'left'), 'left'),
            'text_color' => mrNormalizeBuilderColor((string) ($block['text_color'] ?? '#0D6EFD'), '#0D6EFD'),
            'font_size' => max(12, min(32, (int) ($block['font_size'] ?? 16))),
            'link_action' => mrNormalizeBuilderLinkAction((string) ($block['link_action'] ?? 'none')),
            'link_tag' => trim((string) ($block['link_tag'] ?? '')),
            'link_only_once' => !array_key_exists('link_only_once', $block) || !empty($block['link_only_once']),
        ];
    }

    if ($type === 'spacer') {
        return [
            'type' => 'spacer',
            'height' => max(4, min(120, (int) ($block['height'] ?? 24))),
        ];
    }

    if ($type === 'divider') {
        return [
            'type' => 'divider',
            'color' => mrNormalizeBuilderColor((string) ($block['color'] ?? '#D9E2EC'), '#D9E2EC'),
        ];
    }

    if ($type === 'columns' && $allowColumns) {
        $leftBlocks = mrNormalizeBuilderBlocks($block['left_blocks'] ?? [], false);
        $rightBlocks = mrNormalizeBuilderBlocks($block['right_blocks'] ?? [], false);

        // Legacy fallback: alte HTML-Felder in Text-Bloecke migrieren.
        if ($leftBlocks === [] && trim((string) ($block['left_html'] ?? '')) !== '') {
            $leftBlocks = [[
                'type' => 'text',
                'html' => (string) $block['left_html'],
            ]];
        }
        if ($rightBlocks === [] && trim((string) ($block['right_html'] ?? '')) !== '') {
            $rightBlocks = [[
                'type' => 'text',
                'html' => (string) $block['right_html'],
            ]];
        }

        if ($leftBlocks === []) {
            $leftBlocks = [[
                'type' => 'text',
                'html' => '<p>Linke Spalte</p>',
            ]];
        }
        if ($rightBlocks === []) {
            $rightBlocks = [[
                'type' => 'text',
                'html' => '<p>Rechte Spalte</p>',
            ]];
        }

        return [
            'type' => 'columns',
            'left_blocks' => $leftBlocks,
            'right_blocks' => $rightBlocks,
            'gap' => max(8, min(40, (int) ($block['gap'] ?? 20))),
        ];
    }

    return null;
}

function mrNormalizeBuilderBlocks($decoded, bool $allowColumns = true): array
{
    if (!is_array($decoded)) {
        return [];
    }

    $blocks = [];
    foreach ($decoded as $block) {
        if (!is_array($block)) {
            continue;
        }
        $normalized = mrNormalizeSingleBuilderBlock($block, $allowColumns);
        if ($normalized !== null) {
            $blocks[] = $normalized;
        }
    }

    return $blocks;
}

function mrDecodeBuilderSource(string $sourceContent): array
{
    $sourceContent = trim($sourceContent);
    if ($sourceContent === '') {
        return mrNormalizeBuilderBlocks(json_decode(mrCreateDefaultBuilderSource(), true));
    }

    $decoded = json_decode($sourceContent, true);
    if (!is_array($decoded)) {
        return mrNormalizeBuilderBlocks(json_decode(mrCreateDefaultBuilderSource($sourceContent), true));
    }

    $blocks = mrNormalizeBuilderBlocks($decoded);
    if ($blocks === []) {
        return mrNormalizeBuilderBlocks(json_decode(mrCreateDefaultBuilderSource(), true));
    }

    return $blocks;
}

function mrRenderEmailBuilderHtml(string $sourceContent): string
{
    $blocks = mrDecodeBuilderSource($sourceContent);
    $contentHtml = mrRenderEmailBuilderBlocks($blocks);
    return '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;background:#ffffff;"><tr><td style="padding:24px 24px 4px 24px;">' . $contentHtml . '</td></tr></table>';
}

function mrRenderEmailBuilderBlocks(array $blocks): string
{
    $parts = [];

    foreach ($blocks as $block) {
        switch ($block['type']) {
            case 'preheader':
                $text = trim((string) ($block['text'] ?? ''));
                if ($text !== '') {
                    $parts[] = '<div style="display:none!important;visibility:hidden;opacity:0;color:transparent;height:0;width:0;overflow:hidden;mso-hide:all;">' . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . '</div>';
                }
                break;

            case 'text':
                $parts[] = '<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>';
                break;

            case 'image':
                $align = mrNormalizeBuilderAlign((string) $block['align'], 'center');
                $parts[] = '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td align="' . $align . '" style="padding:0 0 20px 0;"><img src="' . htmlspecialchars((string) $block['src'], ENT_QUOTES, 'UTF-8') . '" alt="' . htmlspecialchars((string) $block['alt'], ENT_QUOTES, 'UTF-8') . '" width="' . (int) $block['width'] . '" style="display:block;max-width:100%;height:auto;border:0;outline:none;text-decoration:none;"></td></tr></table>';
                break;

            case 'video':
                $caption = trim((string) ($block['caption'] ?? ''));
                $captionHtml = $caption !== '' ? '<tr><td align="' . mrNormalizeBuilderAlign((string) $block['align'], 'center') . '" style="padding:8px 0 20px 0;font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.5;color:#486581;"><a href="' . htmlspecialchars((string) $block['video_url'], ENT_QUOTES, 'UTF-8') . '" style="color:#486581;text-decoration:underline;">' . htmlspecialchars($caption, ENT_QUOTES, 'UTF-8') . '</a></td></tr>' : '<tr><td height="20" style="font-size:0;line-height:0;">&nbsp;</td></tr>';
                $parts[] = '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td align="' . mrNormalizeBuilderAlign((string) $block['align'], 'center') . '" style="padding:0;"><a href="' . htmlspecialchars((string) $block['video_url'], ENT_QUOTES, 'UTF-8') . '" style="display:inline-block;text-decoration:none;"><img src="' . htmlspecialchars((string) $block['thumbnail_url'], ENT_QUOTES, 'UTF-8') . '" alt="' . htmlspecialchars((string) $block['alt'], ENT_QUOTES, 'UTF-8') . '" width="' . (int) $block['width'] . '" style="display:block;max-width:100%;height:auto;border:0;outline:none;text-decoration:none;"></a></td></tr>' . $captionHtml . '</table>';
                break;

            case 'button':
                $parts[] = '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td align="' . mrNormalizeBuilderAlign((string) $block['align'], 'center') . '" style="padding:0 0 20px 0;"><table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse:separate;"><tr><td bgcolor="' . htmlspecialchars((string) $block['background_color'], ENT_QUOTES, 'UTF-8') . '" style="border-radius:' . (int) $block['radius'] . 'px;"><a href="' . htmlspecialchars((string) $block['url'], ENT_QUOTES, 'UTF-8') . '"' . mrBuildTrackedLinkAttributes($block) . ' style="display:inline-block;padding:14px 24px;font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.2;color:' . htmlspecialchars((string) $block['text_color'], ENT_QUOTES, 'UTF-8') . ';text-decoration:none;border-radius:' . (int) $block['radius'] . 'px;background:' . htmlspecialchars((string) $block['background_color'], ENT_QUOTES, 'UTF-8') . ';">' . htmlspecialchars((string) $block['text'], ENT_QUOTES, 'UTF-8') . '</a></td></tr></table></td></tr></table>';
                break;

            case 'link':
                $parts[] = '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td align="' . mrNormalizeBuilderAlign((string) $block['align'], 'left') . '" style="padding:0 0 20px 0;font-family:Arial,Helvetica,sans-serif;font-size:' . (int) $block['font_size'] . 'px;line-height:1.5;"><a href="' . htmlspecialchars((string) $block['url'], ENT_QUOTES, 'UTF-8') . '"' . mrBuildTrackedLinkAttributes($block) . ' style="color:' . htmlspecialchars((string) $block['text_color'], ENT_QUOTES, 'UTF-8') . ';text-decoration:underline;">' . htmlspecialchars((string) $block['text'], ENT_QUOTES, 'UTF-8') . '</a></td></tr></table>';
                break;

            case 'spacer':
                $parts[] = '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse;"><tr><td height="' . (int) $block['height'] . '" style="font-size:0;line-height:0;">&nbsp;</td></tr></table>';
                break;

            case 'divider':
                $parts[] = '<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 ' . htmlspecialchars((string) $block['color'], ENT_QUOTES, 'UTF-8') . ';font-size:0;line-height:0;">&nbsp;</td></tr></table></td></tr></table>';
                break;

            case 'columns':
                $gap = (int) $block['gap'];
                $parts[] = '<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:' . (int) floor($gap / 2) . 'px;font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.6;color:#243B53;">' . mrRenderEmailBuilderBlocks((array) ($block['left_blocks'] ?? [])) . '</td><td valign="top" width="50%" style="padding-left:' . (int) ceil($gap / 2) . 'px;font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.6;color:#243B53;">' . mrRenderEmailBuilderBlocks((array) ($block['right_blocks'] ?? [])) . '</td></tr></table></td></tr></table>';
                break;
        }
    }

    return implode("\n", $parts);
}

function mrResolveTemplateEditorState(?array $template, array $editorSettings): array
{
    $template = is_array($template) ? $template : [];
    $legacyBodyHtml = (string) ($template['body_html'] ?? '');
    $fallbackMode = $editorSettings['ckeditor_enabled'] ? 'ckeditor' : 'code';
    $editorMode = (string) ($template['editor_mode'] ?? '');
    if ($editorMode === '') {
        $editorMode = $legacyBodyHtml !== '' ? $fallbackMode : $editorSettings['default_mode'];
    }
    $editorMode = mrNormalizeEditorMode($editorMode, $editorSettings['allowed_modes'], $editorSettings['default_mode']);

    $sourceFormat = (string) ($template['source_format'] ?? ($editorMode === 'email_builder' ? 'builder_json' : 'html'));
    $sourceContent = array_key_exists('source_content', $template) ? (string) ($template['source_content'] ?? '') : '';

    if ($editorMode === 'email_builder') {
        if (trim($sourceContent) === '') {
            $sourceContent = mrCreateDefaultBuilderSource($legacyBodyHtml);
        } else {
            $sourceContent = json_encode(mrDecodeBuilderSource($sourceContent), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        }
    } else {
        if ($sourceContent === '') {
            $sourceContent = $legacyBodyHtml;
        }
        $sourceFormat = 'html';
    }

    return array_merge($template, [
        'editor_mode' => $editorMode,
        'source_format' => $sourceFormat,
        'source_content' => $sourceContent,
        'body_html' => $legacyBodyHtml !== '' ? $legacyBodyHtml : ($editorMode === 'email_builder' ? mrRenderEmailBuilderHtml($sourceContent) : $sourceContent),
        'builder_schema_version' => (int) ($template['builder_schema_version'] ?? 4),
    ]);
}

function mrCollectPostedHtmlByMode(array $post, string $editorMode): string
{
    $hiddenBody = (string) ($post['body_html'] ?? '');
    if (trim($hiddenBody) !== '') {
        return $hiddenBody;
    }

    if ($editorMode === 'ckeditor') {
        return (string) ($post['ckeditor_body_html'] ?? '');
    }

    return (string) ($post['code_body_html'] ?? '');
}

function mrPrepareTemplateEditorPayload(array $post, array $editorSettings, ?array $existingTemplate = null): array
{
    $existingTemplate = is_array($existingTemplate) ? $existingTemplate : [];
    $fallbackMode = (string) ($existingTemplate['editor_mode'] ?? $editorSettings['default_mode']);
    $editorMode = mrNormalizeEditorMode((string) ($post['editor_mode'] ?? ''), $editorSettings['allowed_modes'], $fallbackMode);

    if ($editorMode === 'email_builder') {
        $sourceContent = trim((string) ($post['source_content'] ?? ''));
        if ($sourceContent === '') {
            $sourceContent = mrCreateDefaultBuilderSource(mrCollectPostedHtmlByMode($post, 'code'));
        }
        $normalizedBlocks = mrDecodeBuilderSource($sourceContent);
        $normalizedSource = json_encode($normalizedBlocks, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        return [
            'editor_mode' => 'email_builder',
            'source_format' => 'builder_json',
            'source_content' => $normalizedSource,
            'body_html' => mrRenderEmailBuilderHtml($normalizedSource),
            'builder_schema_version' => 4,
        ];
    }

    $html = mrCollectPostedHtmlByMode($post, $editorMode);

    return [
        'editor_mode' => $editorMode,
        'source_format' => 'html',
        'source_content' => $html,
        'body_html' => $html,
        'builder_schema_version' => 4,
    ];
}
