<?php
namespace DiviBooster\ContactForm\EmailBlacklist;

// Constants
const DIVI4_MODULE_SLUG = 'et_pb_contact_form';
const DIVI5_MODULE_SLUG = 'divi/contact-form';
const D4_USE_KEY        = 'dbdb_use_email_blacklist';
const D4_LIST_KEY       = 'dbdb_email_blacklist';
const D4_MSG_KEY        = 'dbdb_email_blacklist_error_msg';
const D5_USE_KEY        = 'diviboosterUseEmailBlacklist';
const D5_LIST_KEY       = 'diviboosterEmailBlacklist';
const D5_MSG_KEY        = 'diviboosterEmailBlacklistErrorMsg';

// Bootstrap
// Admin / Builder UI CSS
add_action('admin_head', __NAMESPACE__ . '\\output_builder_ui_css');
add_action('wp_head', __NAMESPACE__ . '\\output_builder_ui_css_for_vb');

// Divi 4: register fields
add_filter('et_pb_all_fields_unprocessed_' . DIVI4_MODULE_SLUG, __NAMESPACE__ . '\\divi4_add_fields');

// Divi 4: filters for validation and output
add_filter('et_pb_module_shortcode_attributes', __NAMESPACE__ . '\\divi4_filter_blacklisted_email', 10, 3);
add_filter('et_pb_module_shortcode_attributes', __NAMESPACE__ . '\\divi4_register_email_fields', 10, 3);
add_filter('et_pb_contact_form_shortcode_output', __NAMESPACE__ . '\\divi4_remove_is_email_filter');
add_filter('et_module_shortcode_output', __NAMESPACE__ . '\\divi4_add_custom_error_message_filter', 10, 3);

// Divi 5: attribute registration (server-side)
add_filter('divi_module_library_register_module_attrs', __NAMESPACE__ . '\\divi5_register_attrs', 10, 2);

// Divi 5: conversion and attribute mapping (builder-only JS)
add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\enqueue_divi5_conversion_js');

// Divi 5: pre-render hook to attach validation filters just-in-time
add_filter('pre_render_block', __NAMESPACE__ . '\\divi5_pre_render_block', 9, 2);

// Divi 5: block output filter for message replacement and cleanup
add_filter('render_block_' . DIVI5_MODULE_SLUG, __NAMESPACE__ . '\\divi5_render_block', 10, 3);

// === Divi 4 Implementation (preserved, with internal helpers) ===

// Internal state for Divi 4
class D4_State {
    public static $current_blacklist = [];
    public static $current_contact_form = 0;
}

function divi4_add_fields($fields) {
    $toggle_slug = toggle_slug();
    $fields[D4_USE_KEY] = array(
        'label'             => esc_html__('Use Email Blacklist', 'divi_booster'),
        'type'              => 'yes_no_button',
        'option_category'   => 'configuration',
        'options'           => array(
            'on'  => esc_html__('Yes', 'et_builder'),
            'off' => esc_html__('No', 'et_builder'),
        ),
        'default_on_front'  => 'off',
        'toggle_slug'       => $toggle_slug,
        'description'       => esc_html__('Turn the email blacklist on or off using this button.', 'divi_booster'),
    );
    $fields[D4_LIST_KEY] = array(
        'label'             => esc_html__('Email Blacklist', 'divi_booster'),
        'type'              => 'textarea',
        'option_category'   => 'configuration',
        'toggle_slug'       => $toggle_slug,
        'description'       => esc_html__('When the sender\'s email address contains any of these strings, it will be rejected. One string per line. It will match inside words, so "example.com" will match "test@example.com", "mail@example.com" and "mail@anotherexample.com".', 'divi_booster'),
        'show_if' => array(
            D4_USE_KEY => 'on',
        ),
    );
    $fields[D4_MSG_KEY] = array(
        'label'             => esc_html__('Email Blacklisted Message', 'divi-booster'),
        'type'              => 'text',
        'option_category'   => 'configuration',
        'toggle_slug'       => $toggle_slug,
        'description'       => esc_html__('The message to display when a blacklisted email is submitted.".', 'divi-booster'),
        'default'           => esc_html__('Invalid Email.', 'et_builder'),
        'show_if' => array(
            D4_USE_KEY => 'on',
        ),
    );
    return $fields;
}

function divi4_add_custom_error_message_filter($output, $render_slug, $module) {
    if (!is_string($output)) {
        return $output;
    }
    if ($render_slug !== DIVI4_MODULE_SLUG) {
        return $output;
    }
    if (!isset($module->props)) {
        return $output;
    }
    $props = $module->props;
    if (preg_match('/<div class="et-pb-contact-message">(.*?)<\/div>/', $output, $matches)) {
        $output = str_replace($matches[0], '<div class="et-pb-contact-message">' . apply_filters(__NAMESPACE__ . '\\dbe_db_contact_form_error_text', $matches[1], $props) . '</div>', $output);
    }
    return $output;
}

function divi4_register_email_fields($props, $atts, $slug) {
    if ($slug === 'et_pb_contact_field') {
        if (isset($props['field_type']) && $props['field_type'] === 'email') {
            if (isset($props['field_id']) && !empty(D4_State::$current_blacklist)) {
                foreach (D4_State::$current_blacklist as $str) {
                    if (strpos(divi4_submitted_email($props['field_id'], D4_State::$current_contact_form), $str) !== false) {
                        add_filter('is_email', __NAMESPACE__ . '\\return_false');
                        add_filter(__NAMESPACE__ . '\\dbe_db_contact_form_error_text', __NAMESPACE__ . '\\set_custom_error_message_d4', 10, 2);
                        break;
                    }
                }
            }
        }
    }
    return $props;
}

function divi4_filter_blacklisted_email($props, $atts, $slug) {
    if ($slug !== DIVI4_MODULE_SLUG) {
        return $props;
    }

    static $contact_form_num = 0;
    $this_contact_form_num = $contact_form_num;
    $contact_form_num++;

    $submitted = !empty($_POST['et_pb_contactform_submit_' . $this_contact_form_num]);

    D4_State::$current_blacklist = email_blacklist_from_props($props);
    D4_State::$current_contact_form = $this_contact_form_num;

    if (!$submitted || !use_email_blacklist_from_props($props)) {
        return $props;
    }

    foreach (D4_State::$current_blacklist as $str) {
        if (strpos(divi4_submitted_email('email', $this_contact_form_num), $str) !== false) {
            add_filter('is_email', __NAMESPACE__ . '\\return_false');
            add_filter(__NAMESPACE__ . '\\dbe_db_contact_form_error_text', __NAMESPACE__ . '\\set_custom_error_message_d4', 10, 2);
            break;
        }
    }

    return $props;
}

function divi4_submitted_email($id, $contact_form_num) {
    $email_key = divi4_email_field_name($id, $contact_form_num);
    return !empty($_POST[$email_key]) ? $_POST[$email_key] : '';
}

function divi4_email_field_name($id, $contact_form_num) {
    if (divi_has_duplicate_contact_form_id_bug()) {
        $contact_form_num = max(1, (int) $contact_form_num);
    }
    return 'et_pb_contact_' . $id . '_' . $contact_form_num;
}

function divi_has_duplicate_contact_form_id_bug() {
    return theme_version_compare('3.18.1', '<');
}

function divi4_remove_is_email_filter($output) {
    remove_filter('is_email', __NAMESPACE__ . '\\return_false');
    remove_filter(__NAMESPACE__ . '\\dbe_db_contact_form_error_text', __NAMESPACE__ . '\\set_custom_error_message_d4');
    return $output;
}

function set_custom_error_message_d4($msg, $props) {
    if (!empty($msg) && use_email_blacklist_from_props($props) && !empty($props[D4_MSG_KEY])) {
        $msg = '<p class="et_pb_contact_error_text">' . esc_html($props[D4_MSG_KEY]) . '</p>';
    }
    return $msg;
}

// === Divi 5 Implementation ===

// State for Divi 5 per-render cycle
class D5_State {
    public static $counter_pre = 0;          // index used in pre_render_block
    public static $counter_render = 0;       // index used in render_block
    public static $triggered = [];           // [index => true]
    public static $msg_by_index = [];        // [index => custom_msg]
}

function divi5_register_attrs($module_attrs, $filter_args) {
    if (($filter_args['name'] ?? '') !== DIVI5_MODULE_SLUG) {
        return $module_attrs;
    }
    $def = get_divi5_attribute_definition();
    foreach ($def as $attr_key => $attr_def) {
        $module_attrs[$attr_key] = $attr_def;
    }
    return $module_attrs;
}

function enqueue_divi5_conversion_js() {
    if ((!function_exists('et_builder_d5_enabled') || !\et_builder_d5_enabled()) || (!function_exists('et_core_is_fb_enabled') || !\et_core_is_fb_enabled())) {
        return;
    }
    $handle = sanitize_title('divi-booster-' . DIVI5_MODULE_SLUG . '-' . D5_USE_KEY);
    $attribute_json = wp_json_encode(get_divi5_attribute_definition());
    $divi5_slug = wp_json_encode(DIVI5_MODULE_SLUG);
    $d5_use_key_json = wp_json_encode(D5_USE_KEY);
    $d5_list_key_json = wp_json_encode(D5_LIST_KEY);
    $d5_msg_key_json = wp_json_encode(D5_MSG_KEY);
    $map = [D4_USE_KEY => D5_USE_KEY, D4_LIST_KEY => D5_LIST_KEY, D4_MSG_KEY => D5_MSG_KEY];
    $mapping_js = '';
    foreach ($map as $d4 => $d5) {
        $mapping_js .= "conversionOutline.module['" . esc_js($d4) . "'] = '" . esc_js($d5) . ".*';\n";
    }
    $js = <<<END
window.vendor.wp.hooks.addFilter('divi.moduleLibrary.moduleMapping', 'divi', modules => {
  const path = [{$divi5_slug}, 'metadata', 'attributes'];
  const { set, get, has } = window.lodash;
  const target = get(modules, path) ? get(modules, path) : set(modules, path, {});
  if (has(modules, path)) {
    const defs = {$attribute_json};
    Object.keys(defs).forEach(k => target[k] = defs[k]);
  }
  return modules;
});
window.vendor.wp.hooks.addFilter('divi.moduleLibrary.conversion.moduleConversionOutline', 'divi', (conversionOutline, name) => {
  if (name !== {$divi5_slug}) return conversionOutline;
  {$mapping_js}
  return conversionOutline;
});
// Visibility: show dependent fields (Email Blacklist, Email Blacklisted Message) only when toggle is ON
window.vendor.wp.hooks.addFilter('divi.moduleLibrary.moduleAttributes.divi.contact-form', 'divi', (attributes) => {
    const toggleSlug = {$d5_use_key_json};
    const dependentSlugs = [{$d5_list_key_json}, {$d5_msg_key_json}];
    const isToggleOn = (attrs) => {
        const v = attrs?.[toggleSlug];
        if (!v) return false;
        if (v.desktop?.value) return v.desktop.value === 'on';
        if (v.value) return v.value === 'on';
        return false;
    };
    dependentSlugs.forEach(dep => {
        const items = attributes?.[dep]?.settings?.innerContent?.items;
        if (!items) return;
        Object.keys(items).forEach(key => {
            items[key].visible = ({ attrs }) => isToggleOn(attrs);
        });
    });
    return attributes;
});
END;
    \dbdb_enqueue_inline_script_if_dependencies_available($handle, $js, array('lodash', array('divi-vendor-wp-hooks', 'wp-hooks')));
}

function get_divi5_attribute_definition() {
    // All fields live under Content → Spam Protection group per module metadata
    return [
        D5_USE_KEY => [
            'type'     => 'object',
            'settings' => [
                'innerContent' => [
                    'groupType' => 'group-items',
                    'items'     => [
                        'diviboosterUseEmailBlacklistToggle' => [
                            'groupSlug'   => 'contentSpamProtection',
                            'attrName'    => D5_USE_KEY,
                            'label'       => 'Use Email Blacklist',
                            'description' => 'Turn the email blacklist on or off using this button.',
                            'features'    => [
                                'hover'      => false,
                                'sticky'     => false,
                                'responsive' => false,
                                'preset'     => 'content',
                            ],
                            'render'   => true,
                            'priority' => 50,
                            'component' => [ 'type' => 'field', 'name' => 'divi/toggle' ],
                            'defaultAttr' => [ 'desktop' => [ 'value' => 'off' ] ],
                        ],
                    ],
                ],
            ],
        ],
        D5_LIST_KEY => [
            'type'     => 'object',
            'settings' => [
                'innerContent' => [
                    'groupType' => 'group-items',
                    'items'     => [
                        'diviboosterEmailBlacklistTextarea' => [
                            'groupSlug'   => 'contentSpamProtection',
                            'attrName'    => D5_LIST_KEY,
                            'label'       => 'Email Blacklist',
                            'description' => 'When the sender\'s email address contains any of these strings, it will be rejected. One string per line. It will match inside words, so "example.com" will match "test@example.com", "mail@example.com" and "mail@anotherexample.com".',
                            'features'    => [ 'hover' => false, 'sticky' => false, 'responsive' => false, 'preset' => 'content' ],
                            'render'      => true,
                            'priority'    => 55,
                            'component'   => [ 'type' => 'field', 'name' => 'divi/textarea' ],
                        ],
                    ],
                ],
            ],
        ],
        D5_MSG_KEY => [
            'type'     => 'object',
            'settings' => [
                'innerContent' => [
                    'groupType' => 'group-items',
                    'items'     => [
                        'diviboosterEmailBlacklistErrorMsg' => [
                            'groupSlug'   => 'contentSpamProtection',
                            'attrName'    => D5_MSG_KEY,
                            'label'       => 'Email Blacklisted Message',
                            'description' => 'The message to display when a blacklisted email is submitted.".',
                            'features'    => [ 'hover' => false, 'sticky' => false, 'responsive' => false, 'preset' => 'content' ],
                            'render'      => true,
                            'priority'    => 56,
                            'component'   => [ 'type' => 'field', 'name' => 'divi/text' ],
                            'defaultAttr' => [ 'desktop' => [ 'value' => 'Invalid Email.' ] ],
                        ],
                    ],
                ],
            ],
        ],
    ];
}

function divi5_pre_render_block($pre_render, $block) {
    if (($block['blockName'] ?? '') !== DIVI5_MODULE_SLUG) {
        return $pre_render;
    }

    $this_index = D5_State::$counter_pre;
    D5_State::$counter_pre++;

    $attrs = $block['attrs'] ?? [];
    $use   = get_divi5_attr_value($attrs, D5_USE_KEY, 'off');
    if ($use !== 'on') {
        return $pre_render;
    }

    $blacklist = parse_blacklist(get_divi5_attr_value($attrs, D5_LIST_KEY, ''));
    if (!$blacklist) {
        return $pre_render;
    }
    $submitted = !empty($_POST['et_pb_contactform_submit_' . $this_index]);
    if (!$submitted) {
        return $pre_render;
    }

    // Scan posted values for any email field, regardless of index
    $hit = false;

    // Prefer parsing Divi's posted email field list to find the exact email field IDs
    $email_field_ids = [];
    foreach ($_POST as $k => $v) {
        if (!is_string($k) || !preg_match('/^et_pb_contact_email_fields_\d+$/', $k)) continue;
        if (!is_string($v) || $v === '') continue;
        $list = json_decode($v, true);
        if (!is_array($list)) continue;
        foreach ($list as $item) {
            if (!is_array($item)) continue;
            // Expect shape: { field_id: 'et_pb_contact_0_email_1', field_type: 'email', ... }
            if (($item['field_type'] ?? '') === 'email' && !empty($item['field_id']) && is_string($item['field_id'])) {
                $email_field_ids[] = $item['field_id'];
            }
        }
    }

    if (!empty($email_field_ids)) {
        foreach ($email_field_ids as $email_field_key) {
            if (!isset($_POST[$email_field_key]) || !is_string($_POST[$email_field_key])) continue;
            $val = $_POST[$email_field_key];
            foreach ($blacklist as $needle) {
                if ($needle !== '' && strpos($val, $needle) !== false) { $hit = true; break 2; }
            }
        }
    } else {
        // Fallback: match common email field key patterns across any index
        foreach ($_POST as $key => $val) {
            if (!is_string($key) || !is_string($val)) continue;
            // Matches: et_pb_contact_email_0  OR  et_pb_contact_0_email_1
            if (preg_match('/^et_pb_contact_(?:\\d+_)?email_\\d+$/', $key)) {
                foreach ($blacklist as $needle) {
                    if ($needle !== '' && strpos($val, $needle) !== false) { $hit = true; break; }
                }
                if ($hit) break;
            }
        }
    }

    if ($hit) {
        add_filter('is_email', __NAMESPACE__ . '\\return_false');
        D5_State::$triggered[$this_index] = true;
        D5_State::$msg_by_index[$this_index] = get_divi5_attr_value($attrs, D5_MSG_KEY, 'Invalid Email.');
    }

    return $pre_render;
}

function divi5_render_block($block_content, $parsed_block, $block) {
    $this_index = D5_State::$counter_render;
    D5_State::$counter_render++;

    // Cleanup the global email filter after this block renders
    remove_filter('is_email', __NAMESPACE__ . '\\return_false');

    if (!isset(D5_State::$triggered[$this_index]) || !D5_State::$triggered[$this_index]) {
        return $block_content;
    }

    // Replace error message content if error container exists
    if (preg_match('/<div class="et-pb-contact-message">(.*?)<\/div>/s', $block_content, $m)) {
        $msg = D5_State::$msg_by_index[$this_index] ?? 'Invalid Email.';
        $replacement = '<div class="et-pb-contact-message"><p class="et_pb_contact_error_text">' . esc_html($msg) . '</p></div>';
        $block_content = str_replace($m[0], $replacement, $block_content);
    }

    return $block_content;
}

// === Shared helpers ===

function output_builder_ui_css() {
    echo '<style>' . emailblacklist_toggle_selector() . ' .et-fb-option--yes-no_button .et-fb-no-vb-support-warning,'
        . emailblacklist_toggle_selector() . ' .et-fb-option--textarea .et-fb-no-vb-support-warning,'
        . emailblacklist_toggle_selector() . ' .et-fb-option--text .et-fb-no-vb-support-warning { display:none !important; }'
        . '</style>';
}

function output_builder_ui_css_for_vb() {
    if (!function_exists('et_core_is_fb_enabled') || !\et_core_is_fb_enabled()) {
        return;
    }
    output_builder_ui_css();
}

function emailblacklist_toggle_selector() {
    return '.et-fb-tabs__panel--general .et-fb-form__toggle-opened[data-name="' . esc_attr(toggle_slug()) . '"]';
}

function use_email_blacklist_from_props($props) {
    return isset($props[D4_USE_KEY]) && $props[D4_USE_KEY] === 'on';
}

function email_blacklist_from_props($props) {
    $val = isset($props[D4_LIST_KEY]) ? (string) $props[D4_LIST_KEY] : '';
    return parse_blacklist($val);
}

function parse_blacklist($raw) {
    if (!is_string($raw) || $raw === '') return [];
    $lines = preg_split('/\r\n|\r|\n/', $raw);
    $lines = array_map(__NAMESPACE__ . '\\canonicalize_blacklist_item', $lines);
    $lines = array_values(array_filter($lines, function($v){ return $v !== ''; }));
    $lines = array_unique($lines);
    return $lines;
}

function canonicalize_blacklist_item($line) {
    return trim(strip_tags((string) $line));
}

function toggle_slug() {
    return theme_version_compare('4.0', '>=') ? 'spam' : 'elements';
}

function theme_version_compare($version = false, $comparison = '==') {
    $template = get_template();
    $theme = wp_get_theme($template);
    $theme_version = $theme->get('Version');
    return $version ? version_compare($theme_version, $version, $comparison) : $theme_version;
}

function return_false() { return false; }

function get_divi5_attr_value($attrs, $key, $default = '') {
    if (!is_array($attrs)) return $default;
    if (!isset($attrs[$key])) return $default;
    $node = $attrs[$key];
    if (isset($node['desktop']['value'])) return $node['desktop']['value'];
    if (is_string($node)) return $node; // fallback if stored directly
    return $default;
}

// Custom filter name used internally for D4 error message replacement
add_filter(__NAMESPACE__ . '\\dbe_db_contact_form_error_text', function($msg){ return $msg; }, 10, 1);

// Created at 1762829890
// === Divi 5: PHP conversion outline registration ===
function dbdb_register_divi5_email_blacklist_conversion( $conversion_outline, $module_name ) {
    if ( DIVI5_MODULE_SLUG !== $module_name ) {
        return $conversion_outline;
    }
    if (!isset($conversion_outline['module']) || !is_array($conversion_outline['module'])) {
        $conversion_outline['module'] = array();
    }
    $conversion_outline['module'][D4_USE_KEY]  = D5_USE_KEY   . '.*';
    $conversion_outline['module'][D4_LIST_KEY] = D5_LIST_KEY  . '.*';
    $conversion_outline['module'][D4_MSG_KEY]  = D5_MSG_KEY   . '.*';
    return $conversion_outline;
}
add_filter( 'divi.moduleLibrary.conversion.moduleConversionOutline', __NAMESPACE__ . '\dbdb_register_divi5_email_blacklist_conversion', 10, 2 );
