<?php
 
/**
 * =============================================================================
 * @package         Blue Raven (Free Version)
 * @Plugin URI      https://enterrahost.com/plugins/blue-raven
 * 
 * @Author          EnterraHost
 * @Author URI      https://enterrahost.com
 * @License         GPL-2.0-or-later
 *  
 * @Copyright       (c) 2025 EnterraHost
 * @Contents        Blue Raven Admin Tools and Tool Settings
 *
 * =============================================================================
 * 
 * || INDEX:
 * ||   - WP AJAX BLUE RAVEN TOOLS 
 * ||   - ROBOTS
 * ||   - SITE MAP
 * ||   - ALT IMAGES
 * ||   - META
 * ||   - SITE VERIFICATION 
 * ||   - SITE ANALYTICS 
 * ||   - SCHEMA
 * ||   - FORM BUILDER 
 * ||   - EXTRA BLOCKS
 * ||   - UPDATE TABLE
 * ||   
 * =============================================================================
 */

if ( ! defined( 'ABSPATH' ) ) exit; 

/*
============================================================
    WP AJAX BLUE RAVEN TOOLS 
============================================================
*/

add_action('wp_ajax_blue_raven_tools', 'blue_raven_run_tools');

function blue_raven_run_tools() {
    
    ## =========== Security check =========== ##
    
	$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';

	if ( ! wp_verify_nonce( $nonce, 'blue_raven_tools_nonce' ) ) {
		BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "blue_raven_run_tools", "Invalid nonce");
		wp_send_json_error('Invalid nonce');
	}
    
    ## =========== Get Page =========== ##
     
    $subaction = sanitize_text_field(wp_unslash($_POST['subaction'] ?? ''));

/*
============================================================
   ROBOTS
============================================================
*/

    ## =========== Robots.txt =========== ##
        
    if ($subaction === 'create save robots file') {
        
        $textValue = sanitize_textarea_field(wp_unslash($_POST['content'][0] ?? ''));
        
        if ($textValue) {
            $filePath = '';

			if ( isset( $_SERVER['DOCUMENT_ROOT'] ) ) {
				$documentRoot = sanitize_text_field( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) );

				$realPath = realpath( $documentRoot );
				if ( $realPath !== false && is_dir( $realPath ) ) {
					$filePath = $realPath . '/robots.txt';
				} else {
					$filePath = ''; // Handle error or set fallback
				}
			}
            file_put_contents($filePath, $textValue);
            echo 'robots.txt saved successfully.';
            exit();
        } else {
            echo 'No content received.';
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "create save robots file", "No content received");
            http_response_code(400);
        }
        
/*
============================================================
   SITE MAP
============================================================
*/

    ## =========== site map =========== ##
        
    }else if ($subaction === 'enable site map') {
        
        $enable = isset($_POST['content'][0]) ? sanitize_text_field(wp_unslash($_POST['content'][0])) : '';
        
        if ($enable) {
            try{
                BlueRaven_saveToTable('site-map', $enable, '');
                
                require_once BLUERAVEN_PLUGIN_DIR . 'includes/routines/admin-cron-site-map.php';
                $blueRavenCron = new BlueRaven_Site_Map_Cron();
                if($enable == 'true'){
                    $blueRavenCron->activate();
                    echo 'Site Map has been enabled.';
                    
                }else{
                    $blueRavenCron->deactivate();
                    echo 'Site Map has been disabled.';
                }
            } catch (Exception $e) {
                BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "SITE MAP ERROR", $e->getMessage());
                return false;
            }
        } else {
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "enable site map", "No content received");
            http_response_code(400);
        }       
        
    }else if ($subaction === 'enable bing site map') {
        
        $content = isset($_POST['content']) ? array_map('sanitize_text_field', wp_unslash($_POST['content'])) : [];
        
        if (empty($content)) {
            echo 'Content is missing';
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "enable bing site map", "No content received");
            return;
        }
        
        global $wpdb;

        $enable = $content[0];
        $code = $content[1] ?? ''; 
        $code = preg_replace('/[^a-zA-Z0-9]/', '', $code);
        $analyticsTypes = ['enable bing site map' => 'bing-site-map-key', ];
        $analyticsType = $analyticsTypes[$subaction];

        if (array_key_exists($subaction, $analyticsTypes) && $code != '') {
            if($subaction == 'enable bing site map'){
                
    ## =========== Remove old txt file =========== ##
    
                $bingSiteMapKeys = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}BlueRavenValues WHERE setting LIKE %s",'%bing-site-map-key%'));

                if (!empty($bingSiteMapKeys) && ($bingSiteMapKeys[0]->value != $code)) {
                    
                    $key = $bingSiteMapKeys[0]->value;
                   	$old_txt_path = rtrim(realpath(sanitize_text_field(wp_unslash($_SERVER['DOCUMENT_ROOT'] ?? ABSPATH))), '/') . '/' . sanitize_file_name($key) . '.txt';
					
                    if (file_exists($old_txt_path) && !wp_delete_file($old_txt_path)) return new WP_Error('delete_failed', 'Failed to delete old IndexNow key file.');
                }
                
    ## =========== Add new txt file =========== ##
                
                $root_path = rtrim(sanitize_text_field(wp_unslash($_SERVER['DOCUMENT_ROOT'] ?? ABSPATH)), '/') . '/' . $code . '.txt';
            
                if (!file_exists($root_path)) {
                    $written = file_put_contents($root_path, $code);
            
                    if (!$written) return new WP_Error('write_failed', 'Failed to write IndexNow key file.');
                }
            }

    ## =========== Update table =========== ##
    
            if (BlueRaven_saveToTable($analyticsType, $enable, $code)) {
                echo esc_html(ucfirst(explode(' ', $subaction)[1]) . ' site map key has been updated.');
            } else {
                BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "enable bing site map", "Faled to save to table");
                echo 'Failed';
            }

        } else if( array_key_exists($subaction, $analyticsTypes) && $code == ''){
            $bingSiteMapKeys = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}BlueRavenValues WHERE setting LIKE %s", '%bing-site-map-key%'));

            if (!empty($bingSiteMapKeys)) {
                $key = $bingSiteMapKeys[0]->value;
              	$old_txt_path = rtrim(realpath(sanitize_text_field(wp_unslash($_SERVER['DOCUMENT_ROOT'] ?? ABSPATH))), '/') . '/' . sanitize_file_name($key) . '.txt';
                if (file_exists($old_txt_path) && !wp_delete_file($old_txt_path)) return new WP_Error('delete_failed', 'Failed to delete old IndexNow key file.');
            }

            if (BlueRaven_saveToTable($analyticsType, $enable, $code)) {
                echo esc_html(ucfirst(explode(' ', $subaction)[1]) . ' site map key has been updated.');
            } else {
                BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "enable bing site map", "Faled to save to table");
                echo 'Failed';
            }

        } else {
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "enable bing site map", "Invalid subaction");
            echo 'Invalid subaction';
        }   
        
        exit();
        
/*
============================================================
   ALT IMAGES
============================================================
*/

    ## =========== Alt Text =========== ##
        
    }else if ($subaction === 'save alt text') {

        $altInfo = isset($_POST['content']) ? array_map('sanitize_text_field', wp_unslash($_POST['content'])) : [];

        if (is_array($altInfo) && isset($altInfo[0], $altInfo[1])) {
            $image_id = (int) $altInfo[0];
            $altText = sanitize_text_field($altInfo[1]);

            if (get_post_type($image_id) === 'attachment') {
                update_post_meta($image_id, '_wp_attachment_image_alt', $altText);
                echo 'Alt Text updated successfully.';
            } else {
                echo 'Invalid image ID.';
                http_response_code(400);
            }
        } else {
            echo 'No content received.';
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "save alt text", "No content received");
            http_response_code(400);
        }
         
/*
============================================================
   META
============================================================
*/

    ## =========== Save Meta =========== ##
        
    } else if ($subaction === 'save meta for page') {
        
        $rawContent =  isset($_POST['content']) ? array_map('sanitize_text_field', wp_unslash($_POST['content'])) : [];

        // Defensive: Check if $rawContent is array and has element 0
        if (is_array($rawContent) && isset($rawContent[0])) {
            $jsonString = stripslashes($rawContent[0]);
        } else if (is_string($rawContent)) {
            $jsonString = stripslashes($rawContent);
        } else {
            // Invalid input, respond with error early
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "save meta for page", "Malformed content received.");
            echo 'Malformed content received.';
            http_response_code(400);
            exit;
        }

        $metaInfo = json_decode($jsonString, true);

        if ($metaInfo === null) {
            // JSON parsing failed
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "save meta for page", "Invalid JSON: " . json_last_error_msg());
            echo 'Invalid JSON data.';
            http_response_code(400);
            exit;
        }
        
        $page_id = isset($metaInfo['pageId']) ? intval($metaInfo['pageId']) : 0;
        $metaDescriptionText = $metaInfo['metaDesc'] ?? '';
        $metaTagstext = $metaInfo['metaKeywords'] ?? '';
        
        if ($page_id > 0) {
            
            // Sanitize inputs carefully
            $metaDescriptionText = sanitize_text_field($metaDescriptionText);
            $metaTagstext = sanitize_text_field($metaTagstext);
        
            // Update post meta safely
            update_post_meta($page_id, '_blue_raven_meta_description', $metaDescriptionText);
            update_post_meta($page_id, '_blue_raven_meta_tags', $metaTagstext);
        
            echo 'Meta description and tags updated successfully.';
            
        } else {
            
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "save meta for page", "No valid page ID received.");
            echo 'No valid page ID received.';
            http_response_code(400);
        }

    ## =========== Enable Meta =========== ##

    }else if ($subaction === 'enable site meta') {
        
        $content =  isset($_POST['content']) ? array_map('sanitize_text_field', wp_unslash($_POST['content'])) : [];
		
		if (is_array($content)) {
			$content = array_map('sanitize_text_field', $content);
		}
        $enable = $content[0];
        
        if ($enable) {
            BlueRaven_saveToTable('main-site-meta', $enable, '');
            echo 'Main Meta has been ' . ($enable === 'true' ? 'enabled' : 'disabled') . '.';
            
        } else {
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "enable site meta", "No content received");
            echo 'No content received.';
            http_response_code(400);
        }
    
/*
============================================================
   SITE VERIFICATION 
============================================================
*/

    }else if ($subaction === 'enable site verification' || $subaction === 'enable google verification' ||  $subaction === 'enable bing verification' ||  $subaction === 'enable facebook verification' ||  $subaction === 'enable ahref verification') {
        
       	$content = isset($_POST['content']) ? array_map('sanitize_text_field', wp_unslash($_POST['content'])) : [];
		
		if (is_array($content)) {
			$content = array_map('sanitize_text_field', $content);
		}
    
        if (empty($content)) {
            echo 'Content is missing';
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "site verification", "Content is missing");
            return;
        }
    
        $enable = $content[0];
        $code = $content[1] ?? ''; 
        $verificationTypes = [
            'enable site verification' => 'overall-site-verification',
            'enable google verification' => 'google-site-verification',
            'enable bing verification' => 'bing-site-verification',
            'enable facebook verification' => 'facebook-site-verification',
            'enable ahref verification' => 'ahref-site-verification'
        ];
    
        if (array_key_exists($subaction, $verificationTypes)) {
            $verificationType = $verificationTypes[$subaction];
            
            if (BlueRaven_saveToTable($verificationType, $enable, $code)) {
                echo esc_html(ucfirst(explode(' ', $subaction)[1]) . ' site verification has been updated.');
            } else {
                echo 'Failed';
                BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "site verification", "Failed");
            }
        } else {
            echo 'Invalid subaction';
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "site verification", "Invalid subaction");
        }
        
/*
============================================================
   SITE ANALYTICS 
============================================================
*/        
        
    }else if ($subaction === 'enable site analytics' || $subaction === 'enable google analytics' ||  $subaction === 'enable meta analytics' ||  $subaction === 'enable microsoft analytics' ||  $subaction === 'enable ahref analytics') {
        
		$content =  isset($_POST['content']) ? array_map('sanitize_text_field', wp_unslash($_POST['content'])) : [];
		
		if (is_array($content)) {
			$content = array_map('sanitize_text_field', $content);
		}

        if (empty($content)) {
            echo 'Content is missing';
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "site analytics", "Content is missing");
            return;
        }
    
        $enable = $content[0];
        $code = $content[1] ?? ''; 
        $analyticsTypes = [
            'enable site analytics' => 'overall-site-analytics',
            'enable google analytics' => 'google-site-analytics',
            'enable meta analytics' => 'meta-site-analytics',
            'enable microsoft analytics' => 'microsoft-site-analytics',
            'enable ahref analytics' => 'ahref-site-analytics'
        ];
    
        if (array_key_exists($subaction, $analyticsTypes)) {
            $analyticsType = $analyticsTypes[$subaction];
            echo esc_html(BlueRaven_saveToTable($analyticsType, $enable, $code)? ucfirst(explode(' ', $subaction)[1]) . ' site analytics has been updated.': 'Failed');
        } else {
            echo 'Invalid subaction';
        }    
        
/*
============================================================
   SCHEMA
============================================================
*/      
    
    ## ============ enable Schema =========== ##
    
    }else if ($subaction === 'enable site schema') {
        
        $enable = isset($_POST['content'][0]) ? sanitize_text_field(wp_unslash($_POST['content'][0])) : '';
        
        if ($enable) {
            BlueRaven_saveToTable('schema-enable', $enable, '');
            echo 'Main Schema has been ' . ($enable === 'true' ? 'enabled' : 'disabled') . '.';
            
        } else {
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "Schema", "No content received");
            echo 'No content received.';
            http_response_code(400);
        }  
        
    ## ============ Save Schema =========== ##
        
    } else if ($subaction === 'save schema') {

        global $wpdb;

        // Check user capabilities
        if (!current_user_can('manage_options')) {
            wp_die('You do not have sufficient permissions to access this page.');
        }

        if (empty($_POST['content'][0])) {
            http_response_code(400);
            echo 'No content received.';
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "Schema", "No content received");
            return;
        }
        
        $content = isset($_POST['content'][0]) ? wp_unslash($_POST['content'][0]) : '';
        parse_str($content, $output);

        $sanitized_output = array();
        foreach ($output as $key => $value) {
            $sanitized_output[$key] = is_array($value) 
                ? array_map('sanitize_text_field', $value)
                : sanitize_text_field($value);
        }
        
        // Sanitize all fields
        $name = sanitize_text_field($output['name'] ?? '');
        $foundingDate = sanitize_text_field($output['founding-date'] ?? '');
        $businessSlogan = sanitize_text_field($output['business-slogan'] ?? ''); 
        $businessDescription = sanitize_text_field($output['business-description'] ?? ''); 
        
        // Business Type
        $businessType = '';
        if (!empty($output['business-type-3'])) {
            $businessType = sanitize_text_field($output['business-type-3']);
        } elseif (!empty($output['business-type-2'])) {
            $businessType = sanitize_text_field($output['business-type-2']);
        } elseif (!empty($output['business-type-1'])) {
            $businessType = sanitize_text_field($output['business-type-1']);
        }
        
        $businessType1 = isset($output['business-type-1']) ? sanitize_text_field(trim($output['business-type-1'], '"')) : '';
        $businessType2 = isset($output['business-type-2']) ? sanitize_text_field(trim($output['business-type-2'], '"')) : '';
        $businessType3 = isset($output['business-type-3']) ? sanitize_text_field(trim($output['business-type-3'], '"')) : '';
        
        // Sanitize socials
        $socials = [];
        if (!empty($output['socials']) && is_array($output['socials'])) {
            foreach ($output['socials'] as $social) {
                $socials[] = esc_url_raw(sanitize_url($social));
            }
        }
        
        // Sanitize contact information
        $contactType = [];
        $contactEmail = [];
        $contactNumber = [];
        $contactURL = [];
        $contactLanguages = [];
        
        if (!empty($output['contact-type']) && is_array($output['contact-type'])) {
            $contactType = array_map('sanitize_text_field', $output['contact-type']);
        }
        if (!empty($output['contact-email']) && is_array($output['contact-email'])) {
            $contactEmail = array_map('sanitize_email', $output['contact-email']);
        }
        if (!empty($output['contact-number']) && is_array($output['contact-number'])) {
            $contactNumber = array_map('sanitize_text_field', $output['contact-number']);
        }
        if (!empty($output['url']) && is_array($output['url'])) {
            $contactURL = array_map('esc_url_raw', array_map('sanitize_url', $output['url']));
        }
        if (!empty($output['languages']) && is_array($output['languages'])) {
            $contactLanguages = array_map('sanitize_text_field', $output['languages']);
        }
        
        // Sanitize areas
        $areaType = [];
        $areaName = []; 
        if (!empty($output['area-type']) && is_array($output['area-type'])) {
            $areaType = array_map('sanitize_text_field', $output['area-type']);
        }
        if (!empty($output['area-name']) && is_array($output['area-name'])) {
            $areaName = array_map('sanitize_text_field', $output['area-name']);
        }
        
        // Prepare data for JSON
        $data = [
            'name' => $name,
            'foundingDate' => $foundingDate,
            'businessSlogan' => $businessSlogan,
            'businessDescription' => $businessDescription,
            'businessType1' => $businessType1,
            'businessType2' => $businessType2,
            'businessType3' => $businessType3,
            'socials' => $socials,
            'contact' => [
                'type' => $contactType,
                'email' => $contactEmail,
                'number' => $contactNumber,
                'url' => $contactURL,
                'languages' => $contactLanguages,
            ],
            'area' => [
                'type' => $areaType,
                'name' => $areaName,
            ],
        ];
        
        $jsonData = wp_json_encode($data);
        
        BlueRaven_saveToTable('schema-json', 1, $jsonData);
        
        // Build Schema
        $businessUrl = home_url(); 
        $custom_logo_id = get_theme_mod('custom_logo');
        $logo_url = wp_get_attachment_image_url($custom_logo_id, 'full');

        $schema = '<script type="application/ld+json">
    {
        "@context": "https://schema.org",
        "@type": "' . $businessType . '",
        "@id": "' . esc_url($businessUrl) . '/#organization",
        "name": "' . $name . '",
        "url": "' . esc_url($businessUrl) . '",
        "logo": {
            "@type": "ImageObject",
            "url": "' . esc_url($logo_url) . '",
            "width": 300,
            "height": 300
        },
        "description": "' . $businessDescription . '",
        "slogan": "' . $businessSlogan . '",
        "foundingDate": "' . $foundingDate . '",
        "sameAs": [';

        $socialLinks = array_filter($socials);
        $schema .= '"' . implode('","', $socialLinks) . '"';

        $schema .= '],
        "contactPoint": ';

        $contactPoints = [];
        for ($i = 0; $i < count($contactType); $i++) {
            $contact = [
                '@type' => 'ContactPoint',
                'contactType' => $contactType[$i] ?? '',
                'url' => $contactURL[$i] ?? '',
                'availableLanguage' => $contactLanguages[$i] ?? ''
            ];

            if (!empty($contactEmail[$i])) {
                $contact['email'] = $contactEmail[$i];
            }

            if (!empty($contactNumber[$i])) {
                $contact['telephone'] = $contactNumber[$i];
            }

            $contactPoints[] = $contact;
        }

        $schema .= wp_json_encode($contactPoints, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

        $schema .= ',
        "areaServed": ';

        $areaServedArray = [];
        for ($i = 0; $i < count($areaType); $i++) {
            $areaServedArray[] = [
                "@type" => $areaType[$i] ?? '',
                "name" => $areaName[$i] ?? ''
            ];
        }

        $schema .= wp_json_encode($areaServedArray, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        $schema .= '
}
</script>';
    
        BlueRaven_saveToTable('schema-script', 1, $schema);
        echo 'Meta Schema Updated.';

/*
============================================================
    FORM BUILDER 
============================================================
*/
    }else if ($subaction === 'create-new-form-block') {
        
        global $wpdb;
        $messages_table_name = $wpdb->prefix . 'BlueRavenMessages';
        $random_id = substr(md5(uniqid(wp_rand(), true)), 0, 7); 
        $shortcode = 'blueRaven_Form id="' . $random_id . '"';
        
        ///-- Create a new entery in the table

        $inserted = $wpdb->insert($messages_table_name,['title'     => 'My New Form','shortcode' => $shortcode, 'status'    => 'active',],['%s', '%s', '%s'] );
        if (!$inserted) { BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "Failed to Create a Form", json_encode($wpdb->last_error));}

        ///-- Push new row UI to the from

        ob_start();
        include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-mail-form-row.php';
        $html = ob_get_clean();
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $html is fully escaped or trusted template output
        echo $html;
        exit();
        
    ## =========== Delete Mail Form Builder Row =========== ##

    }else if ($subaction === 'delete-form-block') {    
       
        $id = intval($_POST['content'][0]);
        global $wpdb;
        $messages_table_name = $wpdb->prefix . 'BlueRavenMessages';

        ///-- Find the row we want to delete

        $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $messages_table_name WHERE id = %d", $id ) );
        if ($row === null) { error_log("No row found with id: $id"); return;}
        
        ///-- Delete the form row 

        $deleted = $wpdb->delete( $messages_table_name,['id' => $id],['%d']);
        if (false === $deleted) BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "Failed to delete a Form", json_encode($wpdb->last_error));
        
        ob_start();
        include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-mail-form-row.php';
        $html = ob_get_clean();
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $html is fully escaped or trusted template output
        echo $html;
        exit();
        
    ## =========== Open Mail Form Builder Editor =========== ##

    }else if ($subaction === 'open-edit-form-block') {   
        
        global $wpdb;
        $messages_table_name = $wpdb->prefix . 'BlueRavenMessages';
        $id = intval($_POST['content'][0]);
        
        ///-- Find the row we want to edit

        $form_row = $wpdb->get_row($wpdb->prepare("SELECT * FROM $messages_table_name WHERE id = %d", $id),ARRAY_A );
        if (!$form_row) {BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "Form with ID $id not found", "");exit();}
        
        ///-- Push the UI to the front

        ob_start();
        include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-edit-form.php';
        $html = ob_get_clean();
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $html is fully escaped or trusted template output
        echo $html;
        exit();
        
    ## =========== Save Mail Form Builder Changes =========== ##

    }else if ($subaction === 'save-form-block') {   
        
        global $wpdb;
        $messages_table_name = $wpdb->prefix . 'BlueRavenMessages';
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $values = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];
        $id = intval($values[0]);
        $rawHTML = $values[2];
        
        $dom = new DOMDocument();
        libxml_use_internal_errors(true);
        $dom->loadHTML(mb_convert_encoding($rawHTML, 'HTML-ENTITIES', 'UTF-8'));
        libxml_clear_errors();

        $allowed_tags = [
            'h2' => ['id' => true, 'style' => true],
            'h5' => ['id' => true],
            'div' => ['id' => true, 'style' => true],
            'label' => ['for' => true, 'class' => true, 'style' => true],
            'input' => [
                'type' => true,
                'name' => true,
                'placeholder' => true,
                'style' => true,
                'required' => true,  
            ],
            'textarea' => [
                'name' => true,
                'placeholder' => true,
                'class' => true,
                'style' => true,
                'required' => true,   
            ],
            'select' => [
                'name' => true,
                'id' => true,
                'class' => true,
                'style' => true,
                'required' => true,
                'disabled' => true,
            ],
            'option' => [
                'value' => true,
                'selected' => true,
                'disabled' => true,
            ],
            'button' => ['id' => true, 'style' => true]
        ];

        // Convert body children to array
        $body = $dom->getElementsByTagName('body')->item(0);
        $json = [];
        foreach ($body->childNodes as $child) {
            $childArray = BlueRaven_nodeToArrayWP($child, $allowed_tags);
            if ($childArray !== null) $json[] = $childArray;
        }

        // Other fields sanitized as before
        $form_json      = json_encode($json);
        $messages       = wp_kses_post(stripslashes($values[3]));
        $bot_prevention = wp_kses_post(stripslashes($values[4]));
        $template       = wp_kses_post(stripslashes($values[9]));

        $data = [
            'title'          => sanitize_text_field($values[1]),
            'form'           => $form_json,
            'messages'       => $messages,
            'bot_prevention' => $bot_prevention,
            'email_to'       => sanitize_email($values[5]),
            'email_from'     => sanitize_email($values[6]),
            'reply_to'       => sanitize_text_field($values[7]),
            'subject'        => sanitize_text_field($values[8]),
            'template'       => $template,
        ];
        
        $where = ['id' => $id];
        $updated = $wpdb->update($messages_table_name, $data, $where);

        if (false === $updated) {
            BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "Failed to Save a Form", json_encode($wpdb->last_error));
        } else {
            echo 'Your form has been saved!';
        }

        exit();
        
/*
============================================================
   EXTRA BLOCKS
============================================================
*/
    
    ## =========== MAIN SCHEMA > GET CONTENT BLOCK =========== ##
        
    }else if ($subaction === 'get contact block') {
        
        $id = isset($_POST['content'][0]) ? sanitize_text_field(wp_unslash($_POST['content'][0])) : '';
        
        ob_start();
        include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-contact-points.php';
        $html = ob_get_clean();
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $html is fully escaped or trusted template output
        echo $html;
        exit();
        
    ## =========== MAIN SCHEMA > GET SERVICE AREA BLOCK =========== ##
    
    }else if ($subaction === 'get area block') {
        
        $area_id = isset($_POST['content'][0]) ? sanitize_text_field(wp_unslash($_POST['content'][0])) : '';
    
        ob_start();
        include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-area-serviced.php';
        $html = ob_get_clean();
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $html is fully escaped or trusted template output
        echo $html;
        exit();
        
    ## =========== SUB ACTION CANT BE FOUND =========== ##
    
    }else {
        BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "Schema", "Sub-Action not found.");
        echo 'Sub-Action not found.';
        http_response_code(404);
    }
    
    exit;
    wp_die(); 
}

/*
============================================================
   UPDATE TABLE
============================================================
*/

function BlueRaven_saveToTable($setting_key, $enable, $value){
    
    ## =========== get Data =========== ##
    
    global $wpdb;
    
    try {
        $table = $wpdb->prefix . 'BlueRavenValues';
        $data = ['value' => $value, 'enabled' => ($enable == 'true') ? 1 : 0,'updated_at' => current_time('mysql', 1)];
        $exists = $wpdb->get_var( $wpdb->prepare("SELECT id FROM $table WHERE setting = %s", $setting_key));

    ## =========== Update / Insert Update =========== ##
    
        if ($exists) {
            return $wpdb->update(
                $table,
                $data,
                ['setting' => $setting_key]
            ) !== false;
        } else {
            $data['setting'] = $setting_key;
            $data['created_at'] = current_time('mysql', 1);
            
            return $wpdb->insert($table, $data) !== false;
        }
    } catch (Exception $e) {
        BlueRaven_SendError("ERROR", "blue-raven/includes/admin-tools.php", "SAVE TO TABLE ERROR", $e->getMessage());
        error_log('saving update to table failed: ' . $e->getMessage());
        return false;
    }
}

/*
============================================================
   SANITIZE FORM ELEMENT
============================================================
*/
function BlueRaven_nodeToArrayWP($node, $allowed_tags) {
    $result = [];

    if ($node->nodeType === XML_ELEMENT_NODE) {
        $tag = $node->nodeName;

        // Skip disallowed tags
        if (!array_key_exists($tag, $allowed_tags)) {
            return null;
        }

        $result['tag'] = $tag;

        // Handle attributes
        if ($node->hasAttributes()) {
            foreach ($node->attributes as $attr) {
                if (isset($allowed_tags[$tag][$attr->nodeName])) {
                    $filtered = wp_kses_attr(
                        $attr->nodeValue,
                        $tag,
                        $attr->nodeName,
                        $allowed_tags
                    );

                    $filtered = trim($filtered, '<>');

                    // ✅ Handle boolean attributes like required/checked
                    if ($filtered === '' && in_array($attr->nodeName, ['required','checked','disabled','readonly','selected'], true)) {
                        $result['attributes'][$attr->nodeName] = true;
                    } elseif ($filtered !== false && $filtered !== '') {
                        $result['attributes'][$attr->nodeName] = $filtered;
                    }
                }
            }
        }

        // Handle child nodes
        $children = [];
        foreach ($node->childNodes as $child) {
            $childArray = BlueRaven_nodeToArrayWP($child, $allowed_tags);
            if ($childArray !== null) {
                $children[] = $childArray;
            }
        }
        if (!empty($children)) {
            $result['children'] = $children;
        }

    } elseif ($node->nodeType === XML_TEXT_NODE) {
        $text = trim($node->nodeValue);
        if ($text !== '') {
            $result = ['text' => esc_html($text)];
        } else {
            return null;
        }
    }

    return $result;
}