<?php

/**
 * Plugin Name: Easy AI Blog Generator
 * Plugin URI: https://www.easyaibloggenerator.com
 * Description: Generate AI blog posts, schedule posts, and manage content with OpenAI GPT, with features to convert formats, and more.
 * Version: 1.2
 * Author: Easy AI Blog Generator
 * Author URI: https://www.easyaibloggenerator.com
 * License: GPL-2.0+
 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain: easy-ai-blog-generator
 *
 * @package EasyAIBlogGenerator
 */
// Exit if accessed directly.
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
// Include the Freemius SDK.
require_once __DIR__ . '/vendor/freemius/start.php';
// Include the Personalization features.
require_once __DIR__ . '/easyaibloggen-personalization.php';
// Include the SEO Enhancement features.
require_once __DIR__ . '/easyaibloggen-seo.php';
// Include the new SEO Dashboard and Visualizations.
require_once __DIR__ . '/easyaibloggen-seo-enhancements.php';
/**
 * Enqueue admin scripts and styles for Easy AI Blog Generator.
 *
 * This function enqueues the external CSS and JS files located in the css and js folders.
 *
 * @param string $hook The current admin page hook.
 */
function easyaibloggen_admin_enqueue_scripts(  $hook  ) {
    // Optionally, load only on your plugin's admin pages.
    if ( !in_array( $hook, array('tools_page_easyaibloggen-settings', 'post.php', 'post-new.php'), true ) ) {
        return;
    }
    // Enqueue dashicons.
    wp_enqueue_style( 'dashicons' );
    // Enqueue the CSS files.
    wp_enqueue_style(
        'easyaibloggen-admin-css',
        plugin_dir_url( __FILE__ ) . 'css/easyaibloggen-admin.css',
        array(),
        '1.0'
    );
    wp_enqueue_style(
        'easyaibloggen-animations',
        plugin_dir_url( __FILE__ ) . 'css/easyaibloggen-animations.css',
        array(),
        '1.0'
    );
    // Enqueue the JS file.
    wp_enqueue_script(
        'easyaibloggen-admin-js',
        plugin_dir_url( __FILE__ ) . 'js/easyaibloggen-admin.js',
        array('jquery'),
        '1.0',
        true
    );
    // Localize variables for use in the JS file.
    $localized_array = array(
        'ajaxurl'              => admin_url( 'admin-ajax.php' ),
        'nonce'                => wp_create_nonce( 'easyaibloggen_nonce' ),
        'nonce_adjacent'       => wp_create_nonce( 'easyaibloggen_nonce_adjacent' ),
        'nonce_update'         => wp_create_nonce( 'easyaibloggen_nonce_update' ),
        'scheduleNonce'        => wp_create_nonce( 'easyaibloggen_schedule_nonce' ),
        'generatingPost'       => __( 'Generating post…', 'easy-ai-blog-generator' ),
        'postCreated'          => __( 'Post created with ID:', 'easy-ai-blog-generator' ),
        'errorGettingAdjacent' => __( 'Error getting adjacent topic:', 'easy-ai-blog-generator' ),
        'ajaxError'            => __( 'AJAX error:', 'easy-ai-blog-generator' ),
        'continuousStopped'    => __( 'Continuous generation stopped.', 'easy-ai-blog-generator' ),
        'enterSchedulingTopic' => __( 'Please enter a scheduling topic.', 'easy-ai-blog-generator' ),
        'generatingTopics'     => __( 'Generating topics and keywords...', 'easy-ai-blog-generator' ),
        'scheduleDataSaved'    => __( 'Schedule data generated and saved. Click Save Changes to save all Settings', 'easy-ai-blog-generator' ),
        'error'                => __( 'Error:', 'easy-ai-blog-generator' ),
    );
    wp_localize_script( 'easyaibloggen-admin-js', 'easyaibloggen_localized', $localized_array );
}

add_action( 'admin_enqueue_scripts', 'easyaibloggen_admin_enqueue_scripts' );
/*
 * FREEMIUS INTEGRATION
 *
 * This code auto-deactivates the free version when the paid one is activated.
 */
if ( function_exists( 'easyaibloggen_fs' ) ) {
    easyaibloggen_fs()->set_basename( false, __FILE__ );
} else {
    // DO NOT REMOVE THIS IF. It is essential for the function_exists() check.
    if ( !function_exists( 'easyaibloggen_fs' ) ) {
        /**
         * Helper function for Freemius access.
         */
        function easyaibloggen_fs() {
            global $easyaibloggen_fs;
            if ( !isset( $easyaibloggen_fs ) ) {
                // Include the Freemius SDK. Make sure you have placed the SDK
                // in the folder: vendor/freemius (renamed to "freemius").
                require_once __DIR__ . '/vendor/freemius/start.php';
                $easyaibloggen_fs = fs_dynamic_init( array(
                    'id'             => '17985',
                    'slug'           => 'easy-ai-blog-generator',
                    'type'           => 'plugin',
                    'public_key'     => 'pk_291f83587578dfd5e3f78437a353e',
                    'is_premium'     => false,
                    'premium_suffix' => 'Plus',
                    'has_addons'     => false,
                    'has_paid_plans' => true,
                    'trial'          => array(
                        'days'               => 10,
                        'is_require_payment' => true,
                    ),
                    'menu'           => array(
                        'slug'       => 'easyaibloggen-settings',
                        'first-path' => 'admin.php?page=easyaibloggen-settings&welcome-message=true',
                        'contact'    => false,
                        'support'    => false,
                        'parent'     => array(
                            'slug' => 'tools.php',
                        ),
                    ),
                    'is_live'        => true,
                ) );
            }
            return $easyaibloggen_fs;
        }

    }
    // Initialize Freemius.
    easyaibloggen_fs();
    // Signal that the Freemius SDK has loaded.
    do_action( 'easyaibloggen_fs_loaded' );
}
/*
==================================================
	1. SETTINGS & ADMIN PAGE
==================================================
*/
// Define the settings args as constants.
define( 'EASYAIBLOGGEN_API_KEY_ARGS', array(
    'sanitize_callback' => 'easyaibloggen_sanitize_api_key',
) );
define( 'EASYAIBLOGGEN_DEFAULT_IMAGE_STYLE_ARGS', array(
    'sanitize_callback' => 'easyaibloggen_sanitize_image_style',
    'default'           => 'modern digital art style',
) );
define( 'EASYAIBLOGGEN_DEFAULT_TONE_MODIFIER_ARGS', array(
    'sanitize_callback' => 'easyaibloggen_sanitize_tone_modifier',
    'default'           => 'informative',
) );
define( 'EASYAIBLOGGEN_ENABLE_SCHEDULING_ARGS', array(
    'sanitize_callback' => 'easyaibloggen_sanitize_checkbox',
    'default'           => 0,
) );
define( 'EASYAIBLOGGEN_SCHEDULE_TOPIC_ARGS', array(
    'sanitize_callback' => 'sanitize_textarea_field',
    'default'           => '',
) );
define( 'EASYAIBLOGGEN_SCHEDULE_INTERVAL_ARGS', array(
    'sanitize_callback' => 'absint',
    'default'           => 24,
) );
define( 'EASYAIBLOGGEN_SCHEDULE_TOPICS_KEYWORDS_ARGS', array(
    'sanitize_callback' => 'easyaibloggen_sanitize_json',
    'default'           => '',
) );
/**
 * Sanitize API key.
 *
 * @param string $input The API key input.
 * @return string Sanitized API key.
 */
function easyaibloggen_sanitize_api_key(  $input  ) {
    return sanitize_text_field( $input );
}

/**
 * Sanitize default image style.
 *
 * @param string $input The default image style input.
 * @return string Sanitized image style.
 */
function easyaibloggen_sanitize_image_style(  $input  ) {
    return sanitize_text_field( $input );
}

/**
 * Sanitize default tone modifier.
 *
 * @param string $input The default tone modifier input.
 * @return string Sanitized tone modifier.
 */
function easyaibloggen_sanitize_tone_modifier(  $input  ) {
    return sanitize_text_field( $input );
}

/**
 * Sanitize a checkbox value.
 *
 * @param mixed $input The checkbox input.
 * @return int 1 if checked, 0 otherwise.
 */
function easyaibloggen_sanitize_checkbox(  $input  ) {
    return ( 1 === (int) $input ? 1 : 0 );
}

/**
 * Sanitize JSON input.
 *
 * @param string $input The JSON input.
 * @return string The JSON input unchanged.
 */
function easyaibloggen_sanitize_json(  $input  ) {
    return $input;
}

/**
 * Register plugin settings.
 *
 * Registers settings for the Easy AI Blog Generator.
 *
 * @return void
 */
function easyaibloggen_register_settings() {
    register_setting( 'easyaibloggen_settings_group', 'easyaibloggen_api_key', EASYAIBLOGGEN_API_KEY_ARGS );
    register_setting( 'easyaibloggen_settings_group', 'easyaibloggen_default_image_style', EASYAIBLOGGEN_DEFAULT_IMAGE_STYLE_ARGS );
    register_setting( 'easyaibloggen_settings_group', 'easyaibloggen_default_tone_modifier', EASYAIBLOGGEN_DEFAULT_TONE_MODIFIER_ARGS );
    register_setting( 'easyaibloggen_settings_group', 'easyaibloggen_enable_scheduling', EASYAIBLOGGEN_ENABLE_SCHEDULING_ARGS );
    register_setting( 'easyaibloggen_settings_group', 'easyaibloggen_schedule_topic', EASYAIBLOGGEN_SCHEDULE_TOPIC_ARGS );
    register_setting( 'easyaibloggen_settings_group', 'easyaibloggen_schedule_interval', EASYAIBLOGGEN_SCHEDULE_INTERVAL_ARGS );
    register_setting( 'easyaibloggen_settings_group', 'easyaibloggen_schedule_topics_keywords', EASYAIBLOGGEN_SCHEDULE_TOPICS_KEYWORDS_ARGS );
}

add_action( 'admin_init', 'easyaibloggen_register_settings' );
/**
 * Add a settings page under Tools.
 */
function easyaibloggen_add_settings_page() {
    add_submenu_page(
        'tools.php',
        __( 'Auto Blog Generator Settings', 'easy-ai-blog-generator' ),
        __( 'Auto Blog Generator', 'easy-ai-blog-generator' ),
        'manage_options',
        'easyaibloggen-settings',
        'easyaibloggen_render_settings_page'
    );
}

add_action( 'admin_menu', 'easyaibloggen_add_settings_page' );
/**
 * Render the plugin settings page.
 */
function easyaibloggen_render_settings_page() {
    // Inline CSS for the premium badge.
    ?>
	<?php 
    // Define your image styles, tone options, etc.
    $image_styles = array(
        'Modern Digital Art Style',
        'Realistic',
        'True Life',
        'Cartoon',
        'Impressionist',
        'Abstract',
        'Surreal',
        'Minimalist',
        'Vintage',
        'Cyberpunk',
        'Futuristic',
        'Pop Art',
        'Graffiti',
        'Watercolor',
        'Oil Painting',
        'Digital Illustration',
        'Line Art',
        'Geometric',
        'Steampunk',
        'Anime',
        'Pixel Art',
        'Concept Art',
        'Photorealistic',
        'Fantasy',
        'Sci-fi',
        'Expressionist',
        'Art Deco',
        'Art Nouveau',
        'Cubism',
        'Fauvism',
        'Dadaism',
        'Hyperrealism',
        'Naïve Art',
        'Collage',
        'Glitch',
        'Vaporwave',
        'Retro',
        'Surrealist',
        'Mixed Media',
        'Minimal',
        'Hand-drawn',
        '3D Render',
        'Baroque',
        'Rococo',
        'Romantic',
        'Gothic',
        'Neoclassical',
        'Post-Impressionism',
        'Abstract Expressionism',
        'Op Art',
        'Kinetic Art',
        'Digital Surrealism',
        'Conceptual Art',
        'Modernism',
        'Street Art',
        'Lowbrow',
        'Outsider Art',
        'Contemporary',
        'Installation Art',
        'Hypermodern',
        'Futurism',
        'Avant-garde',
        'Psychedelic',
        'Pictorialism',
        'Feminist Art',
        'New Media',
        'Eco Art',
        'Visual Poetry',
        'Structuralism',
        'Constructivism',
        'Suprematism',
        'Art Informel',
        'Performance Art',
        'Opulence',
        'Modern Minimal',
        'Neo-Expressionism',
        'Color Field',
        'Hard Edge',
        'Digital Abstract',
        'Glitch Art',
        'Neo-Futurism',
        'Cyber Minimal'
    );
    $current_style = get_option( 'easyaibloggen_default_image_style', 'modern digital art style' );
    $tone_options = array(
        'informative',
        'informative and humorous',
        'informative and technical',
        'informative and casual',
        'informative and formal',
        'informative and friendly',
        'informative and authoritative',
        'informative and conversational',
        'informative and detailed',
        'informative and clear',
        'informative and engaging',
        'informative and persuasive',
        'informative and insightful',
        'informative and witty',
        'informative and practical',
        'informative and optimistic',
        'informative and inspiring',
        'informative and compelling',
        'informative and thorough',
        'informative and innovative',
        'informative and thoughtful',
        'informative and dynamic',
        'informative and upbeat',
        'informative and sincere',
        'informative and relaxed',
        'informative and crisp',
        'informative and vivid',
        'informative and modern',
        'informative and progressive',
        'informative and balanced',
        'informative and fun',
        'informative and comprehensive',
        'informative and professional',
        'informative and simplistic',
        'informative and poetic',
        'informative and direct',
        'informative and optimized',
        'informative and instructive',
        'informative and warm',
        'informative and vibrant'
    );
    $current_tone = get_option( 'easyaibloggen_default_tone_modifier', 'informative' );
    ?>
	<div class="wrap">
		<h1><?php 
    esc_html_e( 'Auto Blog Generator Settings', 'easy-ai-blog-generator' );
    ?></h1>
		<form method="post" action="options.php">
			<?php 
    settings_fields( 'easyaibloggen_settings_group' );
    do_settings_sections( 'easyaibloggen_settings_group' );
    ?>
			<table class="form-table">
				<tr valign="top">
					<th scope="row"><?php 
    esc_html_e( 'OpenAI API Key', 'easy-ai-blog-generator' );
    ?></th>
					<td>
						<input type="password" name="easyaibloggen_api_key" value="<?php 
    echo esc_attr( get_option( 'easyaibloggen_api_key' ) );
    ?>" style="width:300px;" />
						<p class="description">
							<?php 
    esc_html_e( 'Enter your OpenAI API key. It will be stored securely and masked.', 'easy-ai-blog-generator' );
    ?>
						</p>
						<div class="description" style="margin-top:10px;">
							<p>
								<?php 
    esc_html_e( 'You must create an account with OpenAI, create an API Key, fund the OpenAI account, then enter your OpenAI API Key below. The OpenAI model is fixed to gpt-4o and cannot be changed.', 'easy-ai-blog-generator' );
    ?>
							</p>
							<p>
								<strong><?php 
    esc_html_e( 'How to Obtain Your OpenAI API Key', 'easy-ai-blog-generator' );
    ?></strong><br>
								<?php 
    esc_html_e( 'Go to', 'easy-ai-blog-generator' );
    ?> 
								<a href="https://openai.com" target="_blank" rel="noopener noreferrer">openai.com</a> 
								<?php 
    esc_html_e( 'and sign up for an account or if you already have an account, go to step 2.', 'easy-ai-blog-generator' );
    ?>
							</p>
							<p>
								<?php 
    esc_html_e( 'Navigate to', 'easy-ai-blog-generator' );
    ?> 
								<a href="https://platform.openai.com/api-keys" target="_blank" rel="noopener noreferrer">https://platform.openai.com/api-keys</a> 
								<?php 
    esc_html_e( 'and click +Create new secret key. A pop‐up will appear; then click Create secret key.', 'easy-ai-blog-generator' );
    ?>
							</p>
							<p>
								<?php 
    esc_html_e( 'Click Copy to copy the secret key.', 'easy-ai-blog-generator' );
    ?>
							</p>
							<p>
								<?php 
    esc_html_e( 'Enter your API key in the field above and click Save Changes.', 'easy-ai-blog-generator' );
    ?>
							</p>
							<p>
								<?php 
    esc_html_e( 'Visit', 'easy-ai-blog-generator' );
    ?> 
								<a href="https://platform.openai.com/settings/organization/billing/overview" target="_blank" rel="noopener noreferrer">https://platform.openai.com/settings/organization/billing/overview</a> 
								<?php 
    esc_html_e( 'to fund your account.', 'easy-ai-blog-generator' );
    ?>
							</p>
							<p>
								<em><?php 
    esc_html_e( 'NOTE: Do NOT share your API key with anyone. You will not be able to view the key again after the pop up on the OpenAI page is closed, but you can always delete it and create a new one if needed.', 'easy-ai-blog-generator' );
    ?></em>
							</p>
						</div>
					</td>
				</tr>
				<!-- Other settings fields can go here -->
			</table>
			
			<!-- NEW: Scheduling Settings Section -->
			<hr>
			<h2><?php 
    esc_html_e( 'Scheduling Settings', 'easy-ai-blog-generator' );
    ?></h2>
			<table class="form-table">
				<tr valign="top">
					<th scope="row"><?php 
    esc_html_e( 'Enable Scheduling', 'easy-ai-blog-generator' );
    ?></th>
					<td>
						<input type="checkbox" name="easyaibloggen_enable_scheduling" value="1" <?php 
    checked( 1, get_option( 'easyaibloggen_enable_scheduling', 0 ) );
    ?> />
						<span class="premium-badge"> - Plus Feature</span>
						<p class="description"><?php 
    esc_html_e( 'Check to enable scheduled post generation.', 'easy-ai-blog-generator' );
    ?></p>
					</td>
				</tr>
				<tr valign="top">
					<th scope="row"><?php 
    esc_html_e( 'Scheduling Topic', 'easy-ai-blog-generator' );
    ?></th>
					<td>
						<input type="text" name="easyaibloggen_schedule_topic" value="<?php 
    echo esc_attr( get_option( 'easyaibloggen_schedule_topic', '' ) );
    ?>" style="width:300px;" />
						<span class="premium-badge"> - Plus Feature</span>
						<p class="description"><?php 
    esc_html_e( 'Enter a topic to generate topics and keywords.', 'easy-ai-blog-generator' );
    ?></p>
					</td>
				</tr>
				<tr valign="top">
					<th scope="row"><?php 
    esc_html_e( 'Scheduling Interval (Hours)', 'easy-ai-blog-generator' );
    ?></th>
					<td>
						<select name="easyaibloggen_schedule_interval">
							<?php 
    $interval = get_option( 'easyaibloggen_schedule_interval', 24 );
    $options = array(
        1,
        6,
        12,
        24
    );
    foreach ( $options as $opt ) {
        echo '<option value="' . esc_attr( $opt ) . '" ' . selected( $opt, $interval, false ) . '>' . esc_html( $opt ) . '</option>';
    }
    ?>
						</select>
						<span class="premium-badge"> - Plus Feature</span>
						<p class="description"><?php 
    esc_html_e( 'Select how many hours between scheduled post generations. Default is 24 hours.', 'easy-ai-blog-generator' );
    ?></p>
					</td>
				</tr>
				<tr valign="top">
					<th scope="row"><?php 
    esc_html_e( 'Generate Topics & Keywords', 'easy-ai-blog-generator' );
    ?></th>
					<td>
						<button id="easyaibloggen-generate-schedule-data" class="button">
							<?php 
    esc_html_e( 'Generate Topics & Keywords', 'easy-ai-blog-generator' );
    ?>
							<span class="premium-badge"> - Plus Feature</span>
						</button>
						<p class="description"><?php 
    esc_html_e( 'Click to generate topics and keywords based on the Scheduling Topic. This data will be used for scheduled post generation.', 'easy-ai-blog-generator' );
    ?></p>
						<div id="easyaibloggen-schedule-data-status" style="margin-top:10px;"></div>
					</td>
				</tr>
				<tr valign="top">
					<th scope="row"><?php 
    esc_html_e( 'Current Schedule Data', 'easy-ai-blog-generator' );
    ?></th>
					<td>
						<?php 
    $schedule_data = get_option( 'easyaibloggen_schedule_topics_keywords', '' );
    if ( !empty( $schedule_data ) ) {
        $data = json_decode( $schedule_data, true );
        if ( is_array( $data ) && isset( $data['topics'] ) && isset( $data['keywords'] ) ) {
            printf( 
                // translators: %1$d is the number of topics; %2$d is the number of keywords.
                esc_html__( 'Loaded %1$d topics and %2$d keywords.', 'easy-ai-blog-generator' ),
                count( $data['topics'] ),
                count( $data['keywords'] )
             );
        } else {
            echo esc_html__( 'Invalid schedule data.', 'easy-ai-blog-generator' );
        }
    } else {
        echo esc_html__( 'No schedule data generated yet.', 'easy-ai-blog-generator' );
    }
    ?>
					</td>
				</tr>
				<input type="hidden" name="easyaibloggen_schedule_topics_keywords" value="<?php 
    echo esc_attr( get_option( 'easyaibloggen_schedule_topics_keywords', '' ) );
    ?>" />
			</table>
			
			<?php 
    submit_button();
    ?>
		</form>
		
		<!-- NEW: Content Personalization Section -->
		<hr>
		<h2><?php 
    esc_html_e( 'Content Personalization', 'easy-ai-blog-generator' );
    ?></h2>
		<form method="post" action="options.php">
			<?php 
    settings_fields( 'easyaibloggen_personalization_group' );
    do_settings_sections( 'easyaibloggen-settings' );
    // This will render our personalization section.
    ?>
			<?php 
    submit_button( __( 'Save Personalization Settings', 'easy-ai-blog-generator' ) );
    ?>
		</form>
		
		<!-- The remainder of your settings page (Generate Blog Posts, etc.) goes here -->
		<hr>
		<h2><?php 
    esc_html_e( 'Generate Blog Posts', 'easy-ai-blog-generator' );
    ?></h2>
		<p><?php 
    esc_html_e( 'Enter a topic, and optionally your preferred keyword (if not entered, OpenAI will choose one), then choose a mode. The title will not start with "Blog Post" and external links will be appended to the post. After text generation, a separate call to DALL·E 3 creates an image that is inserted below the headline.', 'easy-ai-blog-generator' );
    ?></p>
		<table>
			<tr>
				<td>
					<input type="text" id="easyaibloggen-topic" placeholder="<?php 
    esc_attr_e( 'Enter blog topic...', 'easy-ai-blog-generator' );
    ?>" style="width:300px;" />
				</td>
				<td>
					<input type="text" id="easyaibloggen-keyword" placeholder="<?php 
    esc_attr_e( 'Preferred keyword (optional)...', 'easy-ai-blog-generator' );
    ?>" style="width:300px;" />
				</td>
				<td>
					<input type="number" id="easyaibloggen-count" placeholder="<?php 
    esc_attr_e( 'Number of posts', 'easy-ai-blog-generator' );
    ?>" min="1" style="width:100px;" />
				</td>
			</tr>
		</table>
		<br>
		<button id="easyaibloggen-single-post" class="button button-primary"><?php 
    esc_html_e( 'Generate Single Post', 'easy-ai-blog-generator' );
    ?></button>
		<button id="easyaibloggen-start-continuous" class="button">
			<?php 
    esc_html_e( 'Start Continuous Generation', 'easy-ai-blog-generator' );
    ?>
			<span class="premium-badge"> - Plus Feature</span>
		</button>
		<button id="easyaibloggen-stop-continuous" class="button" style="display:none;"><?php 
    esc_html_e( 'Stop Continuous Generation', 'easy-ai-blog-generator' );
    ?></button>
		<div id="easyaibloggen-status" style="margin-top:20px;"></div>
		<hr>
		<h2><?php 
    esc_html_e( 'Previously Generated Posts', 'easy-ai-blog-generator' );
    ?></h2>
		<?php 
    easyaibloggen_render_generated_posts_table();
    ?>
	</div>
	<?php 
}

/*
==================================================
1A. Render Generated Posts Table (Meta Box)
==================================================
*/
/**
 * Renders a table listing the latest generated posts (25 per page) with pagination.
 */
function easyaibloggen_render_generated_posts_table() {
    // Verify the nonce for pagination.
    if ( !isset( $_GET['_wpnonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'easyaibloggen_pagination' ) ) {
        $paged = 1;
    } else {
        $paged = ( isset( $_GET['easyaibloggen_page'] ) ? absint( wp_unslash( $_GET['easyaibloggen_page'] ) ) : 1 );
    }
    $args = array(
        'post_type'      => 'post',
        'meta_key'       => '_easyaibloggen_generated_topic',
        'posts_per_page' => 25,
        'paged'          => $paged,
        'orderby'        => 'date',
        'order'          => 'DESC',
    );
    $query = new WP_Query($args);
    ?>
	<div id="easyaibloggen-generated-posts">
		<table class="widefat fixed" cellspacing="0">
			<thead>
				<tr>
					<th><?php 
    esc_html_e( 'ID', 'easy-ai-blog-generator' );
    ?></th>
					<th><?php 
    esc_html_e( 'Title', 'easy-ai-blog-generator' );
    ?></th>
					<th><?php 
    esc_html_e( 'Date', 'easy-ai-blog-generator' );
    ?></th>
					<th><?php 
    esc_html_e( 'Preferred Keyword', 'easy-ai-blog-generator' );
    ?></th>
					<th><?php 
    esc_html_e( 'Actions', 'easy-ai-blog-generator' );
    ?></th>
				</tr>
			</thead>
			<tbody>
			<?php 
    if ( $query->have_posts() ) {
        ?>
				<?php 
        while ( $query->have_posts() ) {
            $query->the_post();
            ?>
					<?php 
            $post_id = get_the_ID();
            ?>
					<tr>
						<td><?php 
            echo esc_html( $post_id );
            ?></td>
						<td><a href="<?php 
            echo esc_url( get_permalink() );
            ?>"><?php 
            the_title();
            ?></a></td>
						<td><?php 
            echo esc_html( get_the_date() );
            ?></td>
						<td><?php 
            echo esc_html( get_post_meta( $post_id, '_easyaibloggen_preferred_keyword', true ) );
            ?></td>
						<td>
							<a href="<?php 
            echo esc_url( get_edit_post_link( $post_id ) );
            ?>" class="button"><?php 
            esc_html_e( 'Edit', 'easy-ai-blog-generator' );
            ?></a>
							<button class="button easyaibloggen-generate-similar" data-topic="<?php 
            echo esc_attr( get_the_title() );
            ?>" data-keyword="<?php 
            echo esc_attr( get_post_meta( $post_id, '_easyaibloggen_preferred_keyword', true ) );
            ?>"><?php 
            esc_html_e( 'Generate Similar', 'easy-ai-blog-generator' );
            ?></button>
						</td>
					</tr>
				<?php 
        }
        ?>
				<?php 
        wp_reset_postdata();
        ?>
			<?php 
    } else {
        ?>
				<tr>
					<td colspan="5"><?php 
        esc_html_e( 'No generated posts found.', 'easy-ai-blog-generator' );
        ?></td>
				</tr>
			<?php 
    }
    ?>
			</tbody>
		</table>
		<?php 
    $total_pages = $query->max_num_pages;
    if ( $total_pages > 1 ) {
        $current_page = max( 1, $paged );
        echo '<div class="tablenav"><div class="tablenav-pages">';
        echo wp_kses_post( paginate_links( array(
            'base'      => add_query_arg( array(
                'easyaibloggen_page' => '%#%',
                '_wpnonce'           => wp_create_nonce( 'easyaibloggen_pagination' ),
            ) ),
            'format'    => '',
            'prev_text' => __( '&laquo;', 'easy-ai-blog-generator' ),
            'next_text' => __( '&raquo;', 'easy-ai-blog-generator' ),
            'total'     => $total_pages,
            'current'   => $current_page,
        ) ) );
        echo '</div></div>';
    }
    ?>
	</div>
	<?php 
}

/*
==================================================
2. Unified API Call Function (with Debug Logging)
==================================================
*/
/**
 * Makes a unified API call to OpenAI.
 *
 * This function accepts a prompt and parameters to call either the text-generation
 * endpoint (using gpt-4o) or the image-generation endpoint (using DALL·E 3) based on $type.
 * Debug logging is added.
 *
 * @param string $prompt The prompt to send to OpenAI.
 * @param string $type   Either 'text' or 'image'.
 * @param array  $extra  (Optional) Additional parameters.
 *
 * @return mixed The API response as a string on success, false on failure.
 */
function easyaibloggen_unified_api_call(  $prompt, $type = 'text', $extra = array()  ) {
    $api_key = trim( get_option( 'easyaibloggen_api_key' ) );
    // Create a debug log file.
    $log_file = plugin_dir_path( __FILE__ ) . 'api-call-debug.log';
    // Initialize WP_Filesystem.
    global $wp_filesystem;
    if ( !isset( $wp_filesystem ) || !is_object( $wp_filesystem ) ) {
        if ( !function_exists( 'WP_Filesystem' ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }
        WP_Filesystem();
    }
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "API call initiated for type: {$type}\n", FILE_APPEND );
    if ( empty( $api_key ) ) {
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Error: API key is empty\n", FILE_APPEND );
        return false;
    }
    $defaults = array(
        'model'       => 'gpt-4o',
        'max_tokens'  => 5450,
        'temperature' => 0.7,
    );
    $params = wp_parse_args( $extra, $defaults );
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . 'Using model: ' . $params['model'] . "\n", FILE_APPEND );
    if ( 'text' === $type ) {
        $data = array(
            'model'       => $params['model'],
            'messages'    => array(array(
                'role'    => 'system',
                'content' => __( 'You are a creative and SEO-savvy content generator.', 'easy-ai-blog-generator' ),
            ), array(
                'role'    => 'user',
                'content' => $prompt,
            )),
            'max_tokens'  => $params['max_tokens'],
            'temperature' => $params['temperature'],
        );
        $endpoint = 'https://api.openai.com/v1/chat/completions';
    } elseif ( 'image' === $type ) {
        $data = array(
            'model'   => 'dall-e-3',
            'prompt'  => $prompt,
            'size'    => '1024x1024',
            'quality' => 'standard',
            'n'       => 1,
        );
        $endpoint = 'https://api.openai.com/v1/images/generations';
    } else {
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Error: Invalid type: {$type}\n", FILE_APPEND );
        return false;
    }
    // Apply filters to allow modification of API request data.
    $data = apply_filters( 'easyaibloggen_pre_api_call_data', $data, $type );
    $args = array(
        'headers' => array(
            'Content-Type'  => 'application/json',
            'Authorization' => 'Bearer ' . $api_key,
        ),
        'body'    => wp_json_encode( $data ),
        'timeout' => 90,
    );
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Making request to endpoint: {$endpoint}\n", FILE_APPEND );
    $response = wp_remote_post( $endpoint, $args );
    if ( is_wp_error( $response ) ) {
        $error_message = $response->get_error_message();
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "WP Error: {$error_message}\n", FILE_APPEND );
        return false;
    }
    $status_code = wp_remote_retrieve_response_code( $response );
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Response status code: {$status_code}\n", FILE_APPEND );
    $body = wp_remote_retrieve_body( $response );
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . 'Response body: ' . substr( $body, 0, 500 ) . "...\n", FILE_APPEND );
    $result = json_decode( $body, true );
    if ( !$result ) {
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Error: Could not decode JSON response\n", FILE_APPEND );
        return false;
    }
    // Check for error in the result.
    if ( isset( $result['error'] ) ) {
        $error_msg = ( isset( $result['error']['message'] ) ? $result['error']['message'] : 'Unknown API error' );
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "API Error: {$error_msg}\n", FILE_APPEND );
        return false;
    }
    if ( 'text' === $type ) {
        if ( isset( $result['choices'][0]['message']['content'] ) ) {
            $debug_text = trim( $result['choices'][0]['message']['content'] );
            $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . 'Success: Retrieved text content, length: ' . strlen( $debug_text ) . " chars\n", FILE_APPEND );
            return $debug_text;
        } elseif ( isset( $result['choices'][0]['text'] ) ) {
            $debug_text = trim( $result['choices'][0]['text'] );
            $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . 'Success: Retrieved text content (legacy format), length: ' . strlen( $debug_text ) . " chars\n", FILE_APPEND );
            return $debug_text;
        }
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Error: Could not find expected content in API response\n", FILE_APPEND );
    } elseif ( 'image' === $type ) {
        if ( isset( $result['data'][0]['url'] ) ) {
            $debug_image = trim( $result['data'][0]['url'] );
            $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Success: Retrieved image URL\n", FILE_APPEND );
            return $debug_image;
        }
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Error: Could not find image URL in API response\n", FILE_APPEND );
    }
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Error: No valid content found in response\n", FILE_APPEND );
    return false;
}

/*
==================================================
3. Blog Post Generation
==================================================
*/
/**
 * Generates a blog post based on a user-provided topic and an optional preferred keyword.
 *
 * Builds a prompt instructing OpenAI to generate an entirely new blog post with a structured title,
 * meta description, subheadings, and body content that adheres to strict formatting and SEO guidelines.
 * The prompt ensures that:
 * - If no preferred keyword is provided, OpenAI selects a suitable one.
 * - The title must be a unique, SEO-optimized title that is not simply the provided topic.
 * - The title does not begin with "Blog Post".
 * - The content includes external HTML links appended at the bottom.
 * - A separate call is made to DALL·E 3 to generate an image (representing the title) which is inserted below the headline.
 * - The response is returned as a JSON object with the keys: 'title', 'meta_description', 'content', and 'image_url'.
 *
 * IMPORTANT: All subheadings in the generated content must be returned using proper HTML tags (for example, <h2> for the main headline and <h3> for subheadings), not Markdown (e.g. "###").
 *
 * @param string $topic            The topic for the blog post.
 * @param string $preferred_keyword The preferred keyword (optional).
 *
 * @return int|false The new post ID on success, false on failure.
 */
function easyaibloggen_generate_blog_post(  $topic, $preferred_keyword = ''  ) {
    $keyword_text = ( !empty( $preferred_keyword ) ? $preferred_keyword : 'select a suitable keyword' );
    // Retrieve the tone modifier from settings.
    $tone_modifier = get_option( 'easyaibloggen_default_tone_modifier', 'informative' );
    $prompt = sprintf(
        /* translators: 1: blog topic, 2: preferred keyword, 3: tone modifier */
        __( "Generate a complete, original blog post about \"%1\$s\". Use the preferred keyword \"%2\$s\" naturally throughout the post (if none is provided, choose a suitable one). Ensure a keyword density of 1-3%% for optimal SEO (meaning the keyword should appear 1-3 times per 100 words). Use natural language as to convince readers you are human and use a %3\$s tone. The post must adhere to these guidelines:\n1. The content must be well-structured and formatted with subheadings and paragraphs. Each paragraph should consist of 5-7 sentences.\n2.  Use only simple words, preferably one or two syllables, and rely on common, everyday vocabulary. Break down any complex ideas into clear, direct statements. Structure the article with a brief introduction, a straightforward body, and a concise conclusion. The overall tone should be friendly and accessible, aiming to maximize clarity and simplicity. Ensure that No more than 25%% of sentences should contain more than 20 words.\n3. Between 40%% and 45%% of all sentences must include at least one transition word.\n4. The title must be under 60 characters and must strictly be comprised of the following percentages of words from the lists below of : 20%% common words, 10%% uncommon words, 10%% emotional words, and one power word. Do not start the title with 'Blog Post' or simply reuse the provided topic.\n5. Provide a compelling meta description ensuring that it is less than 160 characters.\n6. Insert subheadings between paragraphs to clearly break up the content.\n   IMPORTANT: All subheadings in the generated content must be returned using proper HTML tags (e.g. <h2> for the main headline and <h3> for subheadings), not Markdown syntax.\n7. Generate engaging, SEO-friendly body content in a natural, %3\$s tone.\n8. Append at the bottom of the post two relevant external HTML links (full anchor tags) for SEO purposes.\n9. Ensure less than 10%% of sentences use passive voice.\n10. VERY IMPORTANT: The final content MUST be comprehensive and detailed, with a minimum of 1000 words in length.\nReturn your response strictly as a JSON object with the keys: 'title', 'meta_description', 'content', and 'image_url' (if no image is available, return an empty string).\n\nAdditionally, to enhance headline SEO, use these lists in the percentages metioned above:\nTransitional Words: Again, Also, Like, In addition, Not to mention, If, Whenever, Because of, Due to, So long as, For example, Namely, In other words, In particular, Such as, But, Although, Instead, Despite, Besides, Likewise, In the same way, As well as, To say nothing of, Especially, First of all, Secondly, Finally, To begin with, Lastly, Afterward, Formerly, Meanwhile, At the same time, Eventually, Here, There, Where, Before, Across, In particular, To explain, Specifically, Namely, Including, Therefore, Finally, In short, As a result.\nPower Words: Great, Free, Focus, Remarkable, Confidential, Sale, Wanted, Obsession, Sizable, New, Absolutely Lowest, Surging, Wonderful, Professional, Interesting, Revisited, Delivered, Guaranteed, Challenge, Unique, Secrets, Special, Lifetime, Bargain, Scarce, Tested, Highest, Hurry, Alert Famous, Improved, Expert, Daring, Strong, Immediately, Advice, Pioneering, Unusual, Limited, The Truth About, Destiny, Outstanding, Simplistic, Compare, Unsurpassed, Energy, Powerful, Colorful, Genuine, Instructive, Big, Affordable, Informative, Liberal, Popular, Ultimate, Mainstream, Rare, Exclusive, Willpower, Complete, Edge, Valuable, Attractive, Last Chance, Superior, How To, Easily, Exploit, Unparalleled, Endorsed, Approved, Quality, Fascinating, Unlimited, Competitive, Gigantic, Compromise, Discount, Full, Love, Odd, Fundamentals, Mammoth, Lavishly, Bottom Line, Under Priced, Innovative, Reliable, Zinger, Suddenly, It's Here, Terrific, Simplified, Perspective, Just Arrived, Breakthrough, Tremendous, Launching, Sure Fire, Emerging, Helpful, Skill, Soar, Profitable, Special Offer, Reduced, Beautiful, Sampler, Technology, Better, Crammed, Noted, Selected, Shrewd, Growth, Luxury, Sturdy, Enormous, Promising, Unconditional, Wealth, Spotlight, Astonishing, Timely, Successful, Useful, Imagination, Bonanza, Opportunities, Survival, Greatest, Security, Last Minute, Largest, High Tech, Refundable, Monumental, Colossal, Latest, Quickly, Startling, Now, Important, Revolutionary, Quick, Unlock, Urgent, Miracle, Easy, Fortune, Amazing, Magic, Direct, Authentic, Exciting, Proven, Simple, Announcing, Portfolio, Reward, Strange, Huge Gift, Revealing, Weird, Value, Introducing, Sensational, Surprise, Insider, Practical, Excellent, Delighted, Download.\nCommon Words: a, an, the, and, but, or, for, nor, so, yet, with, in, on, at, by, from, of, as.\nUncommon Words: Happened, Need, Thing, Awesome, Heart, Never, Think, Baby, Here, New, Time, Beautiful, Its, Now, Valentines, Being, Know, Old, Video, Best, Life, One, Want, Better, Little, Out, Watch, Boy, Look, People, Way, Dog, Love, Photos, Ways, Down, Made, Really, World, Facebook, Make, Reasons, Year, First, Makes, Right, Years, Found, Man, See, You'll, Girl, Media, Seen, Good, Mind, Social, Guy, More, Something.\nEmotional Words: Destroy, Extra, In A, Devastating, Eye-opening, Gift, In The World, Devoted, Fail, In The, Faith, Grateful, Inexpensive, Dirty, Famous, Disastrous, Fantastic, Greed, Grit, Insanely, Disgusting, Fearless, Disinformation, Feast, Insidious, Dollar, Feeble, Gullible, Double, Fire, Hack, Fleece, Had Enough, Invasion, Drowning, Floundering, Happy, Ironclad, Dumb, Flush, Hate, Irresistibly, Hazardous, Is The, Fool, Is What Happens When, Fooled, Helpless, It Looks Like A, Embarrass, For The First Time, Help Are The, Jackpot, Forbidden, Hidden, Jail, Empower, Force-fed, High, Jaw-dropping, Forgotten, Jeopardy, Energize, Hoax, Jubilant, Foul, Hope, Killer, Frantic, Horrific, Know It All, Epic, How To Make, Evil, Freebie, Frenzy, Hurricane, Excited, Fresh On The Mind, Frightening, Hypnotic, Lawsuit, Frugal, Illegal, Fulfill, Lick, Explode, Lies, Exposed, Gambling, Like A Normal, Nightmare, Results, Line, No Good, Pound, Loathsome, No Questions Asked, Revenge, Lonely, Looks Like A, Obnoxious, Preposterous, Revolting, Looming, Priced, Lost, Prison, Lowest, Of The, Privacy, Rich, Lunatic, Off-limits, Private, Risky, Lurking, Offer, Prize, Ruthless, Lust, Official, Luxurious, On The, Profit, Scary, Lying, Outlawed, Protected, Scream, Searing, Overcome, Provocative, Make You, Painful, Pummel, Secure, Pale, Punish, Marked Down, Panic, Quadruple, Seductively, Massive, Pay Zero, Seize, Meltdown, Payback, Might Look Like A, Peril, Mind-blowing, Shameless, Minute, Rave, Shatter, Piranha, Reckoning, Shellacking, Mired, Pitfall, Reclaim, Mistakes, Plague, Sick And Tired, Money, Played, Refugee, Silly, Money-grubbing, Pluck, Refund, Moneyback, Plummet, Plunge, Murder, Pointless, Sinful, Myths, Poor, Remarkably, Six-figure, Never Again, Research, Surrender, To The, Varify, Skyrocket, Toxic, Vibrant, Slaughter, Swindle, Trap, Victim, Sleazy, Taboo, Treasure, Victory, Smash, Tailspin, Vindication, Smug, Tank, Triple, Viral, Smuggled, Tantalizing, Triumph, Volatile, Sniveling, Targeted, Truth, Vulnerable, Snob, Tawdry, Try Before You Buy, Tech, Turn The Tables, Wanton, Soaring, Warning, Teetering, Unauthorized, Spectacular, Temporary Fix, Unbelievably, Spine, Tempting, Uncommonly, What Happened, Spirit, What Happens When, Terror, Under, What Happens, Staggering, Underhanded, What This, That Will Make You, Undo.", 'easy-ai-blog-generator' ),
        $topic,
        $keyword_text,
        $tone_modifier
    );
    $response = easyaibloggen_unified_api_call( $prompt, 'text' );
    $response = trim( $response );
    if ( preg_match( '/^```(?:json)?\\s*(.*?)\\s*```/s', $response, $matches ) ) {
        $response = trim( $matches[1] );
    }
    $response = preg_replace( '/\\s*```$/', '', $response );
    if ( false === $response ) {
        return false;
    }
    $data = json_decode( $response, true );
    if ( !is_array( $data ) || !isset( $data['title'] ) || !isset( $data['content'] ) ) {
        if ( preg_match( '/\\{.*\\}/s', $response, $json_match ) ) {
            $data = json_decode( $json_match[0], true );
        }
        if ( !is_array( $data ) || !isset( $data['title'] ) || !isset( $data['content'] ) ) {
            $data = array(
                'title'            => 'Generated Blog Post',
                'meta_description' => '',
                'content'          => '',
                'image_url'        => '',
            );
        }
    }
    $post_data = array(
        'post_title'   => wp_strip_all_tags( $data['title'] ),
        'post_content' => wp_kses_post( $data['content'] ),
        'post_status'  => 'publish',
        'post_type'    => 'post',
    );
    $post_id = wp_insert_post( $post_data );
    if ( is_wp_error( $post_id ) || !$post_id ) {
        return false;
    }
    if ( !empty( $data['meta_description'] ) ) {
        $meta_desc = sanitize_text_field( $data['meta_description'] );
        update_post_meta( $post_id, '_yoast_wpseo_metadesc', $meta_desc );
        update_post_meta( $post_id, '_aioseo_description', $meta_desc );
        update_post_meta( $post_id, '_rank_math_description', $meta_desc );
    }
    update_post_meta( $post_id, '_easyaibloggen_preferred_keyword', sanitize_text_field( $preferred_keyword ) );
    update_post_meta( $post_id, '_easyaibloggen_generated_topic', sanitize_text_field( $topic ) );
    // Step 1: Retrieve a few post IDs without excluding any.
    $internal_args = array(
        'post_type'      => 'post',
        'posts_per_page' => 3,
        'fields'         => 'ids',
    );
    $internal_ids = get_posts( $internal_args );
    // Step 2: Filter out the current post ID.
    if ( !empty( $internal_ids ) ) {
        foreach ( $internal_ids as $key => $id ) {
            if ( $id === $post_id ) {
                unset($internal_ids[$key]);
            }
        }
        // Re-index the array so that array_slice works as expected.
        $internal_ids = array_values( $internal_ids );
        // Step 3: Limit to the desired number (2 posts).
        $internal_ids = array_slice( $internal_ids, 0, 2 );
        // Step 4: If we have any IDs left, perform a WP_Query with an inclusion parameter.
        if ( !empty( $internal_ids ) ) {
            $internal_query = new WP_Query(array(
                'post_type'      => 'post',
                'posts_per_page' => 2,
                'post__in'       => $internal_ids,
                'orderby'        => 'date',
                'order'          => 'DESC',
            ));
            if ( $internal_query->have_posts() ) {
                $post_obj = get_post( $post_id );
                $internal_links = "\n\n<hr>\n<h3>" . __( 'Internal Resources - Explore More on Our Site', 'easy-ai-blog-generator' ) . "</h3>\n<ul>";
                while ( $internal_query->have_posts() ) {
                    $internal_query->the_post();
                    $internal_links .= '<li><a href="' . esc_url( get_permalink() ) . '">' . get_the_title() . '</a></li>';
                }
                wp_reset_postdata();
                $current_content = $post_obj->post_content;
                $new_content = $current_content . $internal_links;
                wp_update_post( array(
                    'ID'           => $post_id,
                    'post_content' => $new_content,
                ) );
            }
        }
    }
    // ---- Updated Image Handling Section ----
    // Get the default image style from settings.
    $default_style = get_option( 'easyaibloggen_default_image_style', 'modern digital art style' );
    /* translators: 1: post title, 2: default image style */
    $img_prompt = sprintf( __( 'Create an image that represents the headline "%1$s" in a %2$s style.', 'easy-ai-blog-generator' ), $data['title'], $default_style );
    $img_url = easyaibloggen_unified_api_call( $img_prompt, 'image' );
    if ( $img_url ) {
        // Download the image into the Media Library and set it as the featured image.
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
        $attachment_id = media_sideload_image(
            $img_url,
            $post_id,
            null,
            'id'
        );
        if ( !is_wp_error( $attachment_id ) ) {
            // Set the image as the featured image.
            set_post_thumbnail( $post_id, $attachment_id );
            $post = get_post( $post_id );
            $insertion = '<p>' . wp_get_attachment_image(
                $attachment_id,
                'full',
                false,
                array(
                    'style' => 'max-width:100%; height:auto;',
                )
            ) . '</p>';
            $new_content = $insertion . "\n" . $post->post_content;
            wp_update_post( array(
                'ID'           => $post_id,
                'post_content' => $new_content,
            ) );
        }
    }
    // ---- End Updated Image Handling ----
    return $post_id;
}

/*
==================================================
3A. Suggest Adjacent Topic for Continuous Generation
==================================================
*/
/**
 * Suggests a new adjacent topic based on the current post's headline and content.
 *
 * @param int $post_id The post ID.
 * @return string|false The suggested new topic, or false on failure.
 */
function easyaibloggen_suggest_adjacent_topic(  $post_id  ) {
    $post = get_post( $post_id );
    if ( !$post ) {
        return false;
    }
    $prompt = sprintf( 
        /* translators: %s is the post headline. */
        __( 'Based on the headline "%s" and the post content, suggest a new adjacent blog topic that is related yet distinct. Return the topic as plain text.', 'easy-ai-blog-generator' ),
        $post->post_title
     );
    $response = easyaibloggen_unified_api_call( $prompt, 'text' );
    if ( false === $response ) {
        return false;
    }
    $suggested_topic = trim( $response );
    if ( easyaibloggen_topic_exists( $suggested_topic ) ) {
        $suggested_topic .= ' ' . time();
    }
    return $suggested_topic;
}

/**
 * Checks if a given topic has already been used.
 *
 * @param string $topic The topic to check.
 * @return bool True if topic exists, false otherwise.
 */
function easyaibloggen_topic_exists(  $topic  ) {
    $args = array(
        'post_type'      => 'post',
        'meta_key'       => '_easyaibloggen_generated_topic',
        'meta_value'     => $topic,
        'posts_per_page' => 1,
        'fields'         => 'ids',
    );
    $query = new WP_Query($args);
    return $query->have_posts();
}

/*
==================================================
4. AJAX Handlers
==================================================
*/
/**
 * Add custom cron schedules.
 *
 * @param array $schedules Existing cron schedules.
 * @return array Modified cron schedules.
 */
function easyaibloggen_custom_cron_schedules(  $schedules  ) {
    $schedules['easyaibloggen_1_hour'] = array(
        'interval' => 3600,
        'display'  => __( 'Every 1 Hour', 'easy-ai-blog-generator' ),
    );
    $schedules['easyaibloggen_6_hours'] = array(
        'interval' => 6 * 3600,
        'display'  => __( 'Every 6 Hours', 'easy-ai-blog-generator' ),
    );
    $schedules['easyaibloggen_12_hours'] = array(
        'interval' => 12 * 3600,
        'display'  => __( 'Every 12 Hours', 'easy-ai-blog-generator' ),
    );
    $schedules['easyaibloggen_24_hours'] = array(
        'interval' => 24 * 3600,
        'display'  => __( 'Every 24 Hours', 'easy-ai-blog-generator' ),
    );
    return $schedules;
}

add_filter( 'cron_schedules', 'easyaibloggen_custom_cron_schedules' );
/**
 * Schedule the periodic post generation if scheduling is enabled.
 */
function easyaibloggen_schedule_periodic_post_generation() {
    if ( get_option( 'easyaibloggen_enable_scheduling', 0 ) ) {
        // Determine interval schedule key based on option.
        $interval = absint( get_option( 'easyaibloggen_schedule_interval', 24 ) );
        switch ( $interval ) {
            case 1:
                $schedule = 'easyaibloggen_1_hour';
                break;
            case 6:
                $schedule = 'easyaibloggen_6_hours';
                break;
            case 12:
                $schedule = 'easyaibloggen_12_hours';
                break;
            case 24:
            default:
                $schedule = 'easyaibloggen_24_hours';
                break;
        }
        if ( !wp_next_scheduled( 'easyaibloggen_scheduled_post_generation' ) ) {
            wp_schedule_event( time(), $schedule, 'easyaibloggen_scheduled_post_generation' );
        }
    } else {
        // If scheduling is disabled, clear the event.
        $timestamp = wp_next_scheduled( 'easyaibloggen_scheduled_post_generation' );
        if ( $timestamp ) {
            wp_clear_scheduled_hook( 'easyaibloggen_scheduled_post_generation' );
        }
    }
}

add_action( 'wp', 'easyaibloggen_schedule_periodic_post_generation' );
/**
 * Callback function for scheduled post generation.
 *
 * Generates a blog post using a random topic and keyword from the saved schedule data.
 */
function easyaibloggen_scheduled_post_generation_callback() {
    return;
    // Retrieve the saved scheduling topic.
    $schedule_topic = get_option( 'easyaibloggen_schedule_topic', '' );
    $schedule_data = get_option( 'easyaibloggen_schedule_topics_keywords', '' );
    if ( empty( $schedule_data ) ) {
        return;
    }
    $data = json_decode( $schedule_data, true );
    if ( !is_array( $data ) || empty( $data['topics'] ) || empty( $data['keywords'] ) ) {
        return;
    }
    // Randomly select a topic and keyword.
    $random_topic = $data['topics'][array_rand( $data['topics'] )];
    $random_keyword = $data['keywords'][array_rand( $data['keywords'] )];
    // If a scheduling topic is saved, prepend it to the random topic.
    $final_topic = ( !empty( $schedule_topic ) ? $schedule_topic . ' - ' . $random_topic : $random_topic );
    // Generate a blog post using the final topic and random keyword.
    easyaibloggen_generate_blog_post( $final_topic, $random_keyword );
}

add_action( 'easyaibloggen_scheduled_post_generation', 'easyaibloggen_scheduled_post_generation_callback' );
/**
 * AJAX handler for generating a blog post.
 */
function easyaibloggen_generate_post_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_nonce', 'nonce' );
    $topic = ( isset( $_POST['topic'] ) ? sanitize_text_field( wp_unslash( $_POST['topic'] ) ) : '' );
    $keyword = ( isset( $_POST['keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['keyword'] ) ) : '' );
    $mode = ( isset( $_POST['mode'] ) ? sanitize_text_field( wp_unslash( $_POST['mode'] ) ) : 'single' );
    if ( empty( $topic ) ) {
        wp_send_json_error( __( 'Topic is empty.', 'easy-ai-blog-generator' ) );
        return;
    }
    // Premium check: continuous mode is premium-only.
    if ( 'continuous' === $mode && !easyaibloggen_fs()->can_use_premium_code__premium_only() ) {
        wp_send_json_error( __( 'This feature is available only in the premium version.', 'easy-ai-blog-generator' ) );
        return;
    }
    $post_id = easyaibloggen_generate_blog_post( $topic, $keyword );
    if ( false === $post_id ) {
        wp_send_json_error( __( 'Failed to generate blog post.', 'easy-ai-blog-generator' ) );
    } else {
        wp_send_json_success( $post_id );
    }
}

add_action( 'wp_ajax_easyaibloggen_generate_post', 'easyaibloggen_generate_post_ajax_handler' );
/**
 * AJAX handler for suggesting an adjacent topic.
 */
function easyaibloggen_suggest_adjacent_topic_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_nonce_adjacent', 'nonce' );
    $post_id = ( isset( $_POST['post_id'] ) ? absint( wp_unslash( $_POST['post_id'] ) ) : 0 );
    if ( 0 === $post_id ) {
        wp_send_json_error( __( 'Invalid post ID.', 'easy-ai-blog-generator' ) );
        return;
    }
    wp_send_json_error( __( 'This feature is available only in the premium version.', 'easy-ai-blog-generator' ) );
    return;
    $new_topic = easyaibloggen_suggest_adjacent_topic( $post_id );
    if ( $new_topic ) {
        wp_send_json_success( $new_topic );
    } else {
        wp_send_json_error( __( 'Failed to suggest adjacent topic.', 'easy-ai-blog-generator' ) );
    }
}

add_action( 'wp_ajax_easyaibloggen_suggest_adjacent_topic', 'easyaibloggen_suggest_adjacent_topic_ajax_handler' );
/**
 * AJAX handler for updating the headline.
 */
function easyaibloggen_update_headline_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_nonce_update', 'nonce' );
    $post_id = ( isset( $_POST['post_id'] ) ? absint( wp_unslash( $_POST['post_id'] ) ) : 0 );
    if ( 0 === $post_id ) {
        wp_send_json_error( __( 'Invalid post ID.', 'easy-ai-blog-generator' ) );
        return;
    }
    wp_send_json_error( __( 'This feature is available only in the premium version.', 'easy-ai-blog-generator' ) );
    return;
    $current_title = get_the_title( $post_id );
    $current_content = get_post_field( 'post_content', $post_id );
    // Define the headline criteria that must be applied.
    $headline_criteria = "The title must be a unique, SEO-savvy title that is under 60 characters and must strictly be comprised of the following percentages: 20% common words, 10% uncommon words, 10% emotional words, plus at least one power word using the words from corresponding lists below. Do not start the title with 'Blog Post' or simply reuse the provided topic. Additionally, to enhance headline SEO, use these lists in the percentages metioned above: \n    Power Words: Great, Free, Focus, Remarkable, Confidential, Sale, Wanted, Obsession, Sizable, New, Absolutely Lowest, Surging, Wonderful, Professional, Interesting, Revisited, Delivered, Guaranteed, Challenge, Unique, Secrets, Special, Lifetime, Bargain, Scarce, Tested, Highest, Hurry, Alert Famous, Improved, Expert, Daring, Strong, Immediately, Advice, Pioneering, Unusual, Limited, The Truth About, Destiny, Outstanding, Simplistic, Compare, Unsurpassed, Energy, Powerful, Colorful, Genuine, Instructive, Big, Affordable, Informative, Liberal, Popular, Ultimate, Mainstream, Rare, Exclusive, Willpower, Complete, Edge, Valuable, Attractive, Last Chance, Superior, How To, Easily, Exploit, Unparalleled, Endorsed, Approved, Quality, Fascinating, Unlimited, Competitive, Gigantic, Compromise, Discount, Full, Love, Odd, Fundamentals, Mammoth, Lavishly, Bottom Line, Under Priced, Innovative, Reliable, Zinger, Suddenly, It's Here, Terrific, Simplified, Perspective, Just Arrived, Breakthrough, Tremendous, Launching, Sure Fire, Emerging, Helpful, Skill, Soar, Profitable, Special Offer, Reduced, Beautiful, Sampler, Technology, Better, Crammed, Noted, Selected, Shrewd, Growth, Luxury, Sturdy, Enormous, Promising, Unconditional, Wealth, Spotlight, Astonishing, Timely, Successful, Useful, Imagination, Bonanza, Opportunities, Survival, Greatest, Security, Last Minute, Largest, High Tech, Refundable, Monumental, Colossal, Latest, Quickly, Startling, Now, Important, Revolutionary, Quick, Unlock, Urgent, Miracle, Easy, Fortune, Amazing, Magic, Direct, Authentic, Exciting, Proven, Simple, Announcing, Portfolio, Reward, Strange, Huge Gift, Revealing, Weird, Value, Introducing, Sensational, Surprise, Insider, Practical, Excellent, Delighted, Download.\n    Common Words: a, an, the, and, but, or, for, nor, so, yet, with, in, on, at, by, from, of, as.\n    Uncommon Words: Happened, Need, Thing, Awesome, Heart, Never, Think, Baby, Here, New, Time, Beautiful, Its, Now, Valentines, Being, Know, Old, Video, Best, Life, One, Want, Better, Little, Out, Watch, Boy, Look, People, Way, Dog, Love, Photos, Ways, Down, Made, Really, World, Facebook, Make, Reasons, Year, First, Makes, Right, Years, Found, Man, See, You'll, Girl, Media, Seen, Good, Mind, Social, Guy, More, Something.\n    Emotional Words: Destroy, Extra, In A, Devastating, Eye-opening, Gift, In The World, Devoted, Fail, In The, Faith, Grateful, Inexpensive, Dirty, Famous, Disastrous, Fantastic, Greed, Grit, Insanely, Disgusting, Fearless, Disinformation, Feast, Insidious, Dollar, Feeble, Gullible, Double, Fire, Hack, Fleece, Had Enough, Invasion, Drowning, Floundering, Happy, Ironclad, Dumb, Flush, Hate, Irresistibly, Hazardous, Is The, Fool, Is What Happens When, Fooled, Helpless, It Looks Like A, Embarrass, For The First Time, Help Are The, Jackpot, Forbidden, Hidden, Jail, Empower, Force-fed, High, Jaw-dropping, Forgotten, Jeopardy, Energize, Hoax, Jubilant, Foul, Hope, Killer, Frantic, Horrific, Know It All, Epic, How To Make, Evil, Freebie, Frenzy, Hurricane, Excited, Fresh On The Mind, Frightening, Hypnotic, Lawsuit, Frugal, Illegal, Fulfill, Lick, Explode, Lies, Exposed, Gambling, Like A Normal, Nightmare, Results, Line, No Good, Pound, Loathsome, No Questions Asked, Revenge, Lonely, Looks Like A, Obnoxious, Preposterous, Revolting, Looming, Priced, Lost, Prison, Lowest, Of The, Privacy, Rich, Lunatic, Off-limits, Private, Risky, Lurking, Offer, Prize, Ruthless, Lust, Official, Luxurious, On The, Profit, Scary, Lying, Outlawed, Protected, Scream, Searing, Overcome, Provocative, Make You, Painful, Pummel, Secure, Pale, Punish, Marked Down, Panic, Quadruple, Seductively, Massive, Pay Zero, Seize, Meltdown, Payback, Might Look Like A, Peril, Mind-blowing, Shameless, Minute, Rave, Shatter, Piranha, Reckoning, Shellacking, Mired, Pitfall, Reclaim, Mistakes, Plague, Sick And Tired, Money, Played, Refugee, Silly, Money-grubbing, Pluck, Refund, Moneyback, Plummet, Plunge, Murder, Pointless, Sinful, Myths, Poor, Remarkably, Six-figure, Never Again, Research, Surrender, To The, Varify, Skyrocket, Toxic, Vibrant, Slaughter, Swindle, Trap, Victim, Sleazy, Taboo, Treasure, Victory, Smash, Tailspin, Vindication, Smug, Tank, Triple, Viral, Smuggled, Tantalizing, Triumph, Volatile, Sniveling, Targeted, Truth, Vulnerable, Snob, Tawdry, Try Before You Buy, Tech, Turn The Tables, Wanton, Soaring, Warning, Teetering, Unauthorized, Spectacular, Temporary Fix, Unbelievably, Spine, Tempting, Uncommonly, What Happened, Spirit, What Happens When, Terror, Under, What Happens, Staggering, Underhanded, What This, That Will Make You, Undo.";
    // Updated prompt: explicitly instruct the API not to include any markdown or code fences.
    /* translators: 1: headline criteria, 2: current headline, 3: post content */
    $prompt = sprintf(
        __( "Update the following headline using the same criteria as before:\n\n%1\$s\n\nCurrent headline: \"%2\$s\"\n\nPost content: \"%3\$s\"\n\nReturn only the new headline as plain text without any markdown formatting or code fences.", 'easy-ai-blog-generator' ),
        $headline_criteria,
        $current_title,
        $current_content
    );
    $new_title = easyaibloggen_unified_api_call( $prompt, 'text' );
    if ( false === $new_title ) {
        wp_send_json_error( __( 'Failed to update headline.', 'easy-ai-blog-generator' ) );
    }
    if ( isset( $_POST['preview'] ) && '1' === $_POST['preview'] ) {
        wp_send_json_success( array(
            'preview' => $new_title,
        ) );
    } else {
        $update = wp_update_post( array(
            'ID'         => $post_id,
            'post_title' => wp_strip_all_tags( $new_title ),
        ) );
        if ( is_wp_error( $update ) ) {
            wp_send_json_error( __( 'Failed to update headline.', 'easy-ai-blog-generator' ) );
        }
        wp_send_json_success( array(
            'applied' => $new_title,
        ) );
    }
}

add_action( 'wp_ajax_easyaibloggen_update_headline', 'easyaibloggen_update_headline_ajax_handler' );
/**
 * AJAX handler for updating content to use less passive voice.
 */
function easyaibloggen_update_content_passive_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_nonce_update', 'nonce' );
    $post_id = ( isset( $_POST['post_id'] ) ? absint( wp_unslash( $_POST['post_id'] ) ) : 0 );
    if ( 0 === $post_id ) {
        wp_send_json_error( __( 'Invalid post ID.', 'easy-ai-blog-generator' ) );
        return;
    }
    wp_send_json_error( __( 'This feature is available only in the premium version.', 'easy-ai-blog-generator' ) );
    return;
    $post = get_post( $post_id );
    // Use the full post content (with HTML) to provide full context.
    $full_content = $post->post_content;
    // Build prompt that instructs OpenAI to analyze each sentence.
    $prompt = sprintf( 
        /* translators: %s: full post content */
        __( "Analyze the following post content and for each sentence that uses passive voice, provide a suggestion to rephrase it using active voice, and wrap any suggested subheadings in <h3> tags. For every sentence, return an object with two keys: 'original' (the original sentence) and 'suggested' (a revised version). Use the entire post content as input:\n\n%s", 'easy-ai-blog-generator' ),
        $full_content
     );
    // Call OpenAI API.
    $new_content = easyaibloggen_unified_api_call( $prompt, 'text' );
    if ( !$new_content ) {
        wp_send_json_error( __( 'Failed to update content for passive voice.', 'easy-ai-blog-generator' ) );
    }
    // Format the API response as an HTML ordered list.
    $formatted_output = '';
    $decoded = json_decode( $new_content, true );
    if ( is_array( $decoded ) ) {
        $formatted_output = '<ol>';
        foreach ( $decoded as $item ) {
            $original = ( isset( $item['original'] ) ? $item['original'] : '' );
            $suggested = ( isset( $item['suggested'] ) ? $item['suggested'] : '' );
            $formatted_output .= '<li><strong>Original:</strong> ' . esc_html( $original ) . '<br/><strong>Suggested:</strong> ' . esc_html( $suggested ) . '</li>';
        }
        $formatted_output .= '</ol>';
    } else {
        // Fallback in case decoding fails.
        $formatted_output = nl2br( esc_html( $new_content ) );
    }
    // Return the formatted suggestions if preview is requested.
    if ( isset( $_POST['preview'] ) && '1' === $_POST['preview'] ) {
        wp_send_json_success( array(
            'preview' => $formatted_output,
            'prompt'  => $prompt,
        ) );
    } else {
        $update = wp_update_post( array(
            'ID'           => $post_id,
            'post_content' => wp_kses_post( $formatted_output ),
        ) );
        if ( is_wp_error( $update ) ) {
            wp_send_json_error( __( 'Failed to update content.', 'easy-ai-blog-generator' ) );
        }
        wp_send_json_success( array(
            'applied' => $formatted_output,
        ) );
    }
}

add_action( 'wp_ajax_easyaibloggen_update_content_passive', 'easyaibloggen_update_content_passive_ajax_handler' );
/**
 * AJAX handler for updating content to use more transition words.
 */
function easyaibloggen_update_content_transition_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_nonce_update', 'nonce' );
    $post_id = ( isset( $_POST['post_id'] ) ? absint( wp_unslash( $_POST['post_id'] ) ) : 0 );
    if ( 0 === $post_id ) {
        wp_send_json_error( __( 'Invalid post ID.', 'easy-ai-blog-generator' ) );
        return;
    }
    wp_send_json_error( __( 'This feature is available only in the premium version.', 'easy-ai-blog-generator' ) );
    return;
    $post = get_post( $post_id );
    // Use the full post content (with HTML) for complete context.
    $full_content = $post->post_content;
    // Build prompt that instructs OpenAI to provide suggestions for adding transition words.
    $prompt = sprintf( 
        /* translators: %s: full post content */
        __( "Analyze the following post content and for each sentence, provide a suggestion to incorporate additional transition words, and wrap any suggested subheadings in <h3> tags. For every sentence, return an object with two keys: 'original' (the original sentence) and 'suggested' (a revised version with more transition words). Use the entire post content as input:\n\n%s", 'easy-ai-blog-generator' ),
        $full_content
     );
    // Call OpenAI API.
    $new_content = easyaibloggen_unified_api_call( $prompt, 'text' );
    if ( false === $new_content ) {
        wp_send_json_error( __( 'Failed to update content for transition words.', 'easy-ai-blog-generator' ) );
    }
    // Format the API response as an HTML ordered list.
    $formatted_output = '';
    $decoded = json_decode( $new_content, true );
    if ( is_array( $decoded ) ) {
        $formatted_output = '<ol>';
        foreach ( $decoded as $item ) {
            $original = ( isset( $item['original'] ) ? $item['original'] : '' );
            $suggested = ( isset( $item['suggested'] ) ? $item['suggested'] : '' );
            $formatted_output .= '<li><strong>Original:</strong> ' . esc_html( $original ) . '<br/><strong>Suggested:</strong> ' . esc_html( $suggested ) . '</li>';
        }
        $formatted_output .= '</ol>';
    } else {
        // Fallback in case decoding fails.
        $formatted_output = nl2br( esc_html( $new_content ) );
    }
    if ( isset( $_POST['preview'] ) && '1' === $_POST['preview'] ) {
        wp_send_json_success( array(
            'preview' => $formatted_output,
            'prompt'  => $prompt,
        ) );
    } else {
        $update = wp_update_post( array(
            'ID'           => $post_id,
            'post_content' => wp_kses_post( $formatted_output ),
        ) );
        if ( is_wp_error( $update ) ) {
            wp_send_json_error( __( 'Failed to update content.', 'easy-ai-blog-generator' ) );
        }
        wp_send_json_success( array(
            'applied' => $formatted_output,
        ) );
    }
}

add_action( 'wp_ajax_easyaibloggen_update_content_transition', 'easyaibloggen_update_content_transition_ajax_handler' );
/**
 * AJAX handler for updating the featured image.
 */
function easyaibloggen_update_image_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_nonce_update', 'nonce' );
    $post_id = ( isset( $_POST['post_id'] ) ? absint( wp_unslash( $_POST['post_id'] ) ) : 0 );
    if ( 0 === $post_id ) {
        wp_send_json_error( __( 'Invalid post ID.', 'easy-ai-blog-generator' ) );
        return;
    }
    wp_send_json_error( __( 'This feature is available only in the premium version.', 'easy-ai-blog-generator' ) );
    return;
    $post = get_post( $post_id );
    // Create a summary of the post content to avoid overly long prompts.
    $content = wp_strip_all_tags( $post->post_content );
    $words = explode( ' ', $content );
    if ( count( $words ) > 200 ) {
        $content_summary = implode( ' ', array_slice( $words, 0, 200 ) );
    } else {
        $content_summary = $content;
    }
    // Get image style from POST if provided; otherwise, use default from settings.
    $selected_style = ( isset( $_POST['image_style'] ) ? sanitize_text_field( wp_unslash( $_POST['image_style'] ) ) : get_option( 'easyaibloggen_default_image_style', 'modern digital art style' ) );
    // Build a prompt that instructs DALL·E 3 to create an image based on the title and summarized post content.
    $prompt = sprintf(
        /* translators: 1: post title, 2: summary of the post content, 3: selected image style */
        __( 'Create an image that represents the headline "%1$s" based on the following post summary: "%2$s" in a %3$s style.', 'easy-ai-blog-generator' ),
        $post->post_title,
        $content_summary,
        $selected_style
    );
    // Call OpenAI to generate an image.
    $img_url = easyaibloggen_unified_api_call( $prompt, 'image' );
    if ( !$img_url ) {
        wp_send_json_error( __( 'Failed to update image.', 'easy-ai-blog-generator' ) );
    }
    // In preview mode, return an HTML image tag.
    if ( isset( $_POST['preview'] ) && '1' === $_POST['preview'] ) {
        // Try to get an attachment ID from the image URL.
        $attachment_id = attachment_url_to_postid( $img_url );
        if ( $attachment_id ) {
            // Use wp_get_attachment_image() to generate the image markup.
            $img_html = wp_get_attachment_image(
                $attachment_id,
                'full',
                false,
                array(
                    'alt'   => esc_attr( $post->post_title ),
                    'style' => 'max-width:100%; height:auto;',
                )
            );
        } else {
            // Attempt to sideload the image to obtain an attachment ID.
            require_once ABSPATH . 'wp-admin/includes/file.php';
            require_once ABSPATH . 'wp-admin/includes/media.php';
            require_once ABSPATH . 'wp-admin/includes/image.php';
            $attachment_id = media_sideload_image(
                $img_url,
                0,
                null,
                'id'
            );
            if ( !is_wp_error( $attachment_id ) && $attachment_id ) {
                $img_html = wp_get_attachment_image(
                    $attachment_id,
                    'full',
                    false,
                    array(
                        'alt'   => esc_attr( $post->post_title ),
                        'style' => 'max-width:100%; height:auto;',
                    )
                );
            } else {
                // If we still don't have an attachment ID, return an empty string.
                $img_html = '';
            }
        }
        wp_send_json_success( array(
            'preview' => $img_html,
        ) );
    } else {
        // Not in preview mode:
        // If an image preview is provided (from the Apply Changes step), extract the URL from the preview HTML.
        if ( !empty( $_POST['image_preview'] ) ) {
            $preview_html = sanitize_text_field( wp_unslash( $_POST['image_preview'] ) );
            if ( preg_match( '/<img[^>]+src="([^"]+)"/i', $preview_html, $matches ) ) {
                $img_url = $matches[1];
            } else {
                $img_url = '';
            }
        } else {
            // Otherwise, generate a new image (this branch should normally not occur for image updates via Apply Changes).
            $img_url = easyaibloggen_unified_api_call( $prompt, 'image' );
        }
        if ( !$img_url ) {
            wp_send_json_error( __( 'Failed to update image.', 'easy-ai-blog-generator' ) );
        }
        // Download the image into the Media Library and update the post.
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
        $attachment_id = media_sideload_image(
            $img_url,
            $post_id,
            null,
            'id'
        );
        if ( is_wp_error( $attachment_id ) ) {
            wp_send_json_error( __( 'Failed to sideload new image.', 'easy-ai-blog-generator' ) );
        } else {
            // Set the image as the post's featured image.
            set_post_thumbnail( $post_id, $attachment_id );
            // Update the attachment metadata.
            update_post_meta( $attachment_id, '_wp_attachment_image_alt', $post->post_title );
            $attachment_post = array(
                'ID'           => $attachment_id,
                'post_title'   => $post->post_title,
                'post_excerpt' => $post->post_title,
                'post_content' => $post->post_title,
            );
            wp_update_post( $attachment_post );
            // Optionally, insert the image at the top of the post content.
            $post = get_post( $post_id );
            $img_html = wp_get_attachment_image(
                $attachment_id,
                'full',
                false,
                array(
                    'class' => 'easyaibloggen-featured-image',
                    'style' => 'max-width:100%; height:auto;',
                )
            );
            $new_content = '<p>' . $img_html . '</p>' . $post->post_content;
            wp_update_post( array(
                'ID'           => $post_id,
                'post_content' => $new_content,
            ) );
            wp_send_json_success( array(
                'applied' => $attachment_id,
                'message' => 'Image update applied successfully. Please refresh the page to see the updated featured image.',
            ) );
        }
    }
}

add_action( 'wp_ajax_easyaibloggen_update_image', 'easyaibloggen_update_image_ajax_handler' );
/**
 * AJAX handler for generating scheduling topics and keywords.
 */
function easyaibloggen_generate_schedule_data_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_schedule_nonce', 'nonce' );
    wp_send_json_error( __( 'This feature is available only in the premium version.', 'easy-ai-blog-generator' ) );
    return;
    $schedule_topic = ( isset( $_POST['schedule_topic'] ) ? sanitize_text_field( wp_unslash( $_POST['schedule_topic'] ) ) : '' );
    if ( empty( $schedule_topic ) ) {
        wp_send_json_error( __( 'Scheduling topic is empty.', 'easy-ai-blog-generator' ) );
        return;
    }
    // Prepare prompt for generating 100 topics and 100 keywords.
    $prompt = sprintf( 
        // translators: %s is the scheduling topic entered by the user.
        __( "Generate 100 distinct blog topics and 100 corresponding SEO keywords that users are likely to search for to find pages related to the following topic: \"%s\". Return your response strictly as a JSON object with two keys: 'topics' and 'keywords', each containing an array of 100 items.", 'easy-ai-blog-generator' ),
        $schedule_topic
     );
    $response = easyaibloggen_unified_api_call( $prompt, 'text' );
    $response = trim( $response );
    if ( preg_match( '/^```(?:json)?\\s*(.*?)\\s*```/s', $response, $matches ) ) {
        $response = trim( $matches[1] );
    }
    $data = json_decode( $response, true );
    if ( !is_array( $data ) || !isset( $data['topics'] ) || !isset( $data['keywords'] ) ) {
        wp_send_json_error( __( 'Failed to generate valid schedule data.', 'easy-ai-blog-generator' ) );
        return;
    }
    // Save the schedule data and the scheduling topic.
    update_option( 'easyaibloggen_schedule_topics_keywords', wp_json_encode( $data ) );
    update_option( 'easyaibloggen_schedule_topic', $schedule_topic );
    wp_send_json_success( __( 'Schedule data generated successfully.', 'easy-ai-blog-generator' ) );
}

add_action( 'wp_ajax_easyaibloggen_generate_schedule_data', 'easyaibloggen_generate_schedule_data_ajax_handler' );
/**
 * Add an update metabox to the admin edit post screen.
 */
function easyaibloggen_add_update_metabox() {
    add_meta_box(
        'easyaibloggen_update_metabox',
        __( 'Easy AI Blog Generator', 'easy-ai-blog-generator' ),
        'easyaibloggen_update_metabox_callback',
        'post',
        'side',
        'high'
    );
}

add_action( 'add_meta_boxes', 'easyaibloggen_add_update_metabox' );
/**
 * Callback for the update metabox.
 *
 * @param WP_Post $post The current post object.
 */
function easyaibloggen_update_metabox_callback(  $post  ) {
    // Output inline CSS for the premium badge.
    ?>
	<?php 
    // Define the 40 image style options (same as in settings).
    $image_styles = array(
        'Modern Digital Art Style',
        'Realistic',
        'True Life',
        'Cartoon',
        'Impressionist',
        'Abstract',
        'Surreal',
        'Minimalist',
        'Vintage',
        'Cyberpunk',
        'Futuristic',
        'Pop Art',
        'Graffiti',
        'Watercolor',
        'Oil Painting',
        'Digital Illustration',
        'Line Art',
        'Geometric',
        'Steampunk',
        'Anime',
        'Pixel Art',
        'Concept Art',
        'Photorealistic',
        'Fantasy',
        'Sci-fi',
        'Expressionist',
        'Art Deco',
        'Art Nouveau',
        'Cubism',
        'Fauvism',
        'Dadaism',
        'Hyperrealism',
        'Naïve Art',
        'Collage',
        'Glitch',
        'Vaporwave',
        'Retro',
        'Surrealist',
        'Mixed Media',
        'Minimal',
        'Hand-drawn',
        '3D Render',
        'Baroque',
        'Rococo',
        'Romantic',
        'Gothic',
        'Neoclassical',
        'Post-Impressionism',
        'Abstract Expressionism',
        'Op Art',
        'Kinetic Art',
        'Digital Surrealism',
        'Conceptual Art',
        'Modernism',
        'Street Art',
        'Lowbrow',
        'Outsider Art',
        'Contemporary',
        'Installation Art',
        'Hypermodern',
        'Futurism',
        'Avant-garde',
        'Psychedelic',
        'Pictorialism',
        'Feminist Art',
        'New Media',
        'Eco Art',
        'Visual Poetry',
        'Structuralism',
        'Constructivism',
        'Suprematism',
        'Art Informel',
        'Performance Art',
        'Opulence',
        'Modern Minimal',
        'Neo-Expressionism',
        'Color Field',
        'Hard Edge',
        'Digital Abstract',
        'Glitch Art',
        'Neo-Futurism',
        'Cyber Minimal'
    );
    // Set a default value (could be pre-selected to the default style from settings).
    $default_meta_style = 'Modern Digital Art Style';
    ?>
	<div id="easyaibloggen-update-buttons" style="padding:10px; border:1px solid #ddd;">
		<h3><?php 
    esc_html_e( 'Easy AI Blog Generator', 'easy-ai-blog-generator' );
    ?></h3>
		<button class="button easyaibloggen-update-btn" data-update-type="headline" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
			<?php 
    esc_html_e( 'Update Headline', 'easy-ai-blog-generator' );
    ?>
			<span class="premium-badge"> - Plus Feature</span>
		</button>
		<!-- Change these data-update-type values to match the PHP handlers -->
		<button class="button easyaibloggen-update-btn" data-update-type="content_passive" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
			<?php 
    esc_html_e( 'Suggest Ways To Reduce Passive Voice', 'easy-ai-blog-generator' );
    ?>
			<span class="premium-badge"> - Plus Feature</span>
		</button>
		<button class="button easyaibloggen-update-btn" data-update-type="content_transition" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
			<?php 
    esc_html_e( 'Suggest Ways To Increase Transition Words', 'easy-ai-blog-generator' );
    ?>
			<span class="premium-badge"> - Plus Feature</span>
		</button>
		
		<?php 
    // Get the preferred keyword if it exists
    $preferred_keyword = get_post_meta( $post->ID, '_easyaibloggen_preferred_keyword', true );
    $keyword_message = ( empty( $preferred_keyword ) ? __( 'No preferred keyword set. Please enter one below:', 'easy-ai-blog-generator' ) : sprintf( __( 'Current preferred keyword: "%s". You can update it below:', 'easy-ai-blog-generator' ), esc_html( $preferred_keyword ) ) );
    ?>
		<div class="easyaibloggen-preferred-keyword-section" style="margin: 15px 0; padding: 10px; background: #fff; border: 1px solid #ddd; border-left: 4px solid #007cba;">
			<h4 style="margin-top: 0;"><?php 
    esc_html_e( 'Preferred Keyword', 'easy-ai-blog-generator' );
    ?></h4>
			<p><?php 
    echo $keyword_message;
    ?></p>
			<?php 
    // Create the nonce
    $nonce = wp_create_nonce( 'easyaibloggen_preferred_keyword_action' );
    wp_nonce_field( 'easyaibloggen_preferred_keyword_action', 'easyaibloggen_preferred_keyword_nonce' );
    ?>
			<div style="display: flex; gap: 10px; align-items: center;">
				<input type="text" 
					id="easyaibloggen-preferred-keyword" 
					class="regular-text" 
					value="<?php 
    echo esc_attr( $preferred_keyword );
    ?>" 
					placeholder="<?php 
    esc_attr_e( 'Enter preferred keyword', 'easy-ai-blog-generator' );
    ?>" 
					style="flex: 1;">
				<button type="button" 
					id="easyaibloggen-save-preferred-keyword" 
					class="button button-primary" 
					data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>"
					data-nonce="<?php 
    echo esc_attr( $nonce );
    ?>">
					<?php 
    echo ( empty( $preferred_keyword ) ? esc_html__( 'Save Keyword', 'easy-ai-blog-generator' ) : esc_html__( 'Update Keyword', 'easy-ai-blog-generator' ) );
    ?>
				</button>
			</div>
			<div id="easyaibloggen-keyword-save-status" style="margin-top: 10px;"></div>
		</div>
		
		<button type="button" id="easyaibloggen-analyze-keyword" class="button" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
			<?php 
    esc_html_e( 'Analyze Keyword Density', 'easy-ai-blog-generator' );
    ?>
		</button>
		
		<div id="easyaibloggen-main-analysis-results" style="margin-top: 10px; display: none;">
			<h4><?php 
    esc_html_e( 'Keyword Analysis Results', 'easy-ai-blog-generator' );
    ?></h4>
			<div class="easyaibloggen-main-results-content"></div>
			
			<h4 style="margin-top: 10px;"><?php 
    esc_html_e( 'Suggestions', 'easy-ai-blog-generator' );
    ?></h4>
			<div class="easyaibloggen-main-suggestions"></div>
			
			<button type="button" id="easyaibloggen-main-apply-suggestions" class="button button-primary" style="margin-top: 10px; display: none;">
				<?php 
    esc_html_e( 'Apply Suggestions', 'easy-ai-blog-generator' );
    ?>
			</button>
		</div>
		
		<!-- Image Generation with Style Dropdown -->
		<div class="image-generation-section">
			<h3><?php 
    esc_html_e( 'Featured Image Generation', 'easy-ai-blog-generator' );
    ?></h3>
			<div class="image-generation-controls">
				<button class="button easyaibloggen-update-btn" data-update-type="image" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>" style="margin-right: 10px;">
					<?php 
    esc_html_e( 'Update Featured Image', 'easy-ai-blog-generator' );
    ?>
					<span class="premium-badge"> - Plus Feature</span>
				</button>
				<select id="easyaibloggen-meta-image-style" style="flex-grow: 1;">
					<?php 
    foreach ( $image_styles as $style ) {
        echo '<option value="' . esc_attr( $style ) . '" ' . selected( strtolower( $style ), strtolower( $default_meta_style ), false ) . '>' . esc_html( $style ) . '</option>';
    }
    ?>
				</select>
			</div>
			<p class="image-style-help"><?php 
    esc_html_e( 'Select the image style for updating the featured image. If you want to save the image, right click to Save It to your computer and then upload to your media library to use on your site', 'easy-ai-blog-generator' );
    ?></p>
		</div>
		
		<!-- Social Media Promotion Generator Section -->
		<hr style="margin: 15px 0;">
		<h4><?php 
    esc_html_e( 'Social Media Promotions', 'easy-ai-blog-generator' );
    ?></h4>
		<div class="easyaibloggen-social-buttons">
			<button class="button easyaibloggen-social-button twitter" data-platform="twitter" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
				<span class="dashicons dashicons-twitter" style="color: #1DA1F2;"></span> <?php 
    esc_html_e( 'Twitter/X', 'easy-ai-blog-generator' );
    ?>
			</button>
			<button class="button easyaibloggen-social-button facebook" data-platform="facebook" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
				<span class="dashicons dashicons-facebook" style="color: #4267B2;"></span> <?php 
    esc_html_e( 'Facebook', 'easy-ai-blog-generator' );
    ?>
			</button>
			<button class="button easyaibloggen-social-button linkedin" data-platform="linkedin" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
				<span class="dashicons dashicons-linkedin" style="color: #0077B5;"></span> <?php 
    esc_html_e( 'LinkedIn', 'easy-ai-blog-generator' );
    ?>
			</button>
			<button class="button easyaibloggen-social-button instagram" data-platform="instagram" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
				<span class="dashicons dashicons-instagram" style="color: #C13584;"></span> <?php 
    esc_html_e( 'Instagram', 'easy-ai-blog-generator' );
    ?>
			</button>
			<button class="button easyaibloggen-social-button all" data-platform="all" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
				<span class="dashicons dashicons-share"></span> <?php 
    esc_html_e( 'Generate All', 'easy-ai-blog-generator' );
    ?>
			</button>
		</div>
		<div id="easyaibloggen-social-previews"></div>
		
		<!-- Format Conversion Section -->
		<hr style="margin: 15px 0;">
		<h4><?php 
    esc_html_e( 'Format Conversion', 'easy-ai-blog-generator' );
    ?></h4>
		<select id="easyaibloggen-format-style" style="margin-bottom:10px; width:100%;">
			<option value="list"><?php 
    esc_html_e( 'List Format', 'easy-ai-blog-generator' );
    ?></option>
			<option value="how-to"><?php 
    esc_html_e( 'How-To Guide', 'easy-ai-blog-generator' );
    ?></option>
			<option value="comparison"><?php 
    esc_html_e( 'Comparison Format', 'easy-ai-blog-generator' );
    ?></option>
			<option value="case-study"><?php 
    esc_html_e( 'Case Study Format', 'easy-ai-blog-generator' );
    ?></option>
			<option value="faq"><?php 
    esc_html_e( 'FAQ Format', 'easy-ai-blog-generator' );
    ?></option>
			<option value="story"><?php 
    esc_html_e( 'Storytelling Format', 'easy-ai-blog-generator' );
    ?></option>
			<option value="review"><?php 
    esc_html_e( 'Review Format', 'easy-ai-blog-generator' );
    ?></option>
		</select>
		<button class="button easyaibloggen-convert-format-btn" data-postid="<?php 
    echo esc_attr( $post->ID );
    ?>">
			<?php 
    esc_html_e( 'Convert Format', 'easy-ai-blog-generator' );
    ?>
			<span class="premium-badge"> - Plus Feature</span>
		</button>
	</div>
	<div id="easyaibloggen-update-preview" style="margin-top:10px; padding:10px; border:1px dashed #999;"></div>
	<button id="easyaibloggen-apply-changes" class="button button-primary" style="margin-top:10px; display:none;"><?php 
    esc_html_e( 'Apply Changes', 'easy-ai-blog-generator' );
    ?></button>
	<?php 
}

/**
 * Enqueue admin-side update script on post edit pages.
 *
 * @param string $hook The current admin page hook.
 */
function easyaibloggen_enqueue_update_script_admin(  $hook  ) {
    if ( 'post.php' === $hook || 'post-new.php' === $hook ) {
        // Ensure animations CSS is loaded.
        wp_enqueue_style(
            'easyaibloggen-animations',
            plugin_dir_url( __FILE__ ) . 'css/easyaibloggen-animations.css',
            array(),
            '1.0'
        );
        // Enqueue the update script.
        wp_enqueue_script(
            'easyaibloggen-update-script',
            plugin_dir_url( __FILE__ ) . 'js/easyaibloggen-update.js',
            array('jquery'),
            '1.0',
            true
        );
        // Create a dedicated nonce for the preferred keyword functionality
        $ajax_data = array(
            'ajaxurl'               => admin_url( 'admin-ajax.php' ),
            'nonce'                 => wp_create_nonce( 'easyaibloggen_nonce_update' ),
            'preferredKeywordNonce' => wp_create_nonce( 'easyaibloggen_preferred_keyword_action' ),
        );
        wp_localize_script( 'easyaibloggen-update-script', 'easyaibloggenUpdate', $ajax_data );
    }
}

add_action( 'admin_enqueue_scripts', 'easyaibloggen_enqueue_update_script_admin' );
/**
 * AJAX handler for the format conversion functionality.
 */
function easyaibloggen_convert_format_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_nonce_update', 'nonce' );
    if ( !current_user_can( 'edit_posts' ) ) {
        wp_send_json_error( __( 'You do not have permission to edit posts.', 'easy-ai-blog-generator' ) );
        return;
    }
    wp_send_json_error( __( 'This feature is available only in the premium version.', 'easy-ai-blog-generator' ) );
    return;
    $post_id = ( isset( $_POST['post_id'] ) ? intval( wp_unslash( $_POST['post_id'] ) ) : 0 );
    $format = ( isset( $_POST['format'] ) ? sanitize_text_field( wp_unslash( $_POST['format'] ) ) : '' );
    $preview = ( isset( $_POST['preview'] ) ? (bool) $_POST['preview'] : false );
    // Add a parameter to check if we're applying from a saved preview.
    $from_preview = isset( $_POST['from_preview'] ) && (bool) $_POST['from_preview'];
    if ( !$post_id || !$format ) {
        wp_send_json_error( __( 'Missing post ID or format.', 'easy-ai-blog-generator' ) );
        return;
    }
    $post = get_post( $post_id );
    if ( !$post ) {
        wp_send_json_error( __( 'Post not found.', 'easy-ai-blog-generator' ) );
        return;
    }
    // Get existing post data and metadata.
    $topic = get_the_title( $post_id );
    $content = $post->post_content;
    $preferred_keyword = get_post_meta( $post_id, '_easyaibloggen_preferred_keyword', true );
    $tone_modifier = get_option( 'easyaibloggen_default_tone_modifier', 'informative' );
    // If applying from a saved preview, get the content from transient.
    if ( $from_preview ) {
        $preview_data = get_transient( 'easyaibloggen_format_preview_' . $post_id );
        if ( $preview_data ) {
            wp_send_json_success( __( 'Post format converted successfully using preview data.', 'easy-ai-blog-generator' ) );
            // Update the post with the preview data.
            $post_data = array(
                'ID'           => $post_id,
                'post_title'   => wp_strip_all_tags( $preview_data['title'] ),
                'post_content' => wp_kses_post( $preview_data['content'] ),
            );
            $updated_post_id = wp_update_post( $post_data );
            if ( is_wp_error( $updated_post_id ) ) {
                wp_send_json_error( $updated_post_id->get_error_message() );
                return;
            }
            // Update the post meta description.
            if ( !empty( $preview_data['meta_description'] ) ) {
                update_post_meta( $post_id, '_yoast_wpseo_metadesc', wp_strip_all_tags( $preview_data['meta_description'] ) );
                update_post_meta( $post_id, '_aioseo_description', wp_strip_all_tags( $preview_data['meta_description'] ) );
                update_post_meta( $post_id, '_rank_math_description', wp_strip_all_tags( $preview_data['meta_description'] ) );
            }
            // Delete the transient after use.
            delete_transient( 'easyaibloggen_format_preview_' . $post_id );
            return;
        }
    }
    // Prepare format-specific instructions based on the chosen format.
    $format_instructions = easyaibloggen_get_format_instructions( $format );
    // Build prompt with the original requirements but adding format-specific instructions
    // Include the original content in the prompt.
    $prompt = sprintf(
        /* translators: 1: blog topic, 2: preferred keyword, 3: tone modifier, 4: format instructions, 5: original content */
        __( "Rewrite and reformat the existing blog post about \"%1\$s\" into a %4\$s format. Use the preferred keyword \"%2\$s\" naturally throughout the post. Ensure a keyword density of 1-3%% for optimal SEO (meaning the keyword should appear 1-3 times per 100 words). Use natural language as to convince readers you are human and use a %3\$s tone. \n\nHere is the original content to reformat:\n%5\$s\n\nThe post must still adhere to these original guidelines AND must be SIGNIFICANTLY EXPANDED into a comprehensive, in-depth piece:\n1. The content must be well-structured and formatted with subheadings and paragraphs. Each paragraph should consist of 5-7 sentences.\n2. Use only simple words, preferably one or two syllables, and rely on common, everyday vocabulary. Break down any complex ideas into clear, direct statements. Structure the article with a brief introduction, a straightforward body, and a concise conclusion. The overall tone should be friendly and accessible, aiming to maximize clarity and simplicity. Ensure that No more than 25%% of sentences should contain more than 20 words.\n3. Between 40%% and 45%% of all sentences must include at least one transition word.\n4. The title must be under 60 characters and must strictly be comprised of the following percentages of words from the lists below of : 20%% common words, 10%% uncommon words, 10%% emotional words, and one power word. Do not start the title with 'Blog Post' or simply reuse the provided topic.\n5. Provide a compelling meta description ensuring that it is less than 160 characters.\n6. Insert subheadings between paragraphs to clearly break up the content.\n   IMPORTANT: All subheadings in the generated content must be returned using proper HTML tags (e.g. <h2> for the main headline and <h3> for subheadings), not Markdown syntax.\n7. Generate engaging, SEO-friendly body content in a natural, %3\$s tone.\n8. Append at the bottom of the post two relevant external HTML links (full anchor tags) for SEO purposes.\n9. Ensure less than 10%% of sentences use passive voice.\n10. VERY IMPORTANT: The output MUST be significantly longer and more detailed than the original content. Each section should be expanded with additional examples, explanations, and supporting details. The final content should be at least 50%% longer than the original, with a minimum of 1000 words regardless of original length.\n11. Include at least 3 additional subsections that weren't in the original content but are highly relevant to the topic.\n12. For each main point, provide concrete examples, case studies, statistics, or analogies to enhance understanding.\n\nReturn your response strictly as a JSON object with the keys: 'title', 'meta_description', 'content', and 'image_url' (if no image is available, return an empty string).\n\nAdditionally, to enhance headline SEO, use these lists in the percentages metioned above:\n[Lists of transitional words, power words, common words, uncommon words, and emotional words as in the original prompt]\n\nAdditional Format-Specific Instructions: %4\$s", 'easy-ai-blog-generator' ),
        $topic,
        $preferred_keyword,
        $tone_modifier,
        $format_instructions,
        $content
    );
    // Make the API call to regenerate the content.
    $response = easyaibloggen_unified_api_call( $prompt, 'text' );
    $response = trim( $response );
    // Extract JSON from the response if wrapped in code blocks.
    if ( preg_match( '/^```(?:json)?\\s*(.*?)\\s*```/s', $response, $matches ) ) {
        $response = trim( $matches[1] );
    }
    $response = preg_replace( '/\\s*```$/', '', $response );
    if ( false === $response ) {
        wp_send_json_error( __( 'Failed to get response from OpenAI API.', 'easy-ai-blog-generator' ) );
        return;
    }
    // Parse the JSON response.
    $data = json_decode( $response, true );
    if ( !is_array( $data ) || !isset( $data['title'] ) || !isset( $data['content'] ) ) {
        if ( preg_match( '/\\{.*\\}/s', $response, $json_match ) ) {
            $data = json_decode( $json_match[0], true );
        }
        if ( !is_array( $data ) || !isset( $data['title'] ) || !isset( $data['content'] ) ) {
            wp_send_json_error( __( 'Invalid response format from OpenAI API.', 'easy-ai-blog-generator' ) );
            return;
        }
    }
    // Handle preview mode.
    if ( $preview ) {
        $preview_html = '<h3>' . esc_html( $data['title'] ) . '</h3>';
        $preview_html .= '<p><em>' . esc_html( $data['meta_description'] ) . '</em></p>';
        $preview_html .= '<hr>';
        $preview_html .= wp_kses_post( $data['content'] );
        // Save the preview data in a transient for later use.
        set_transient( 'easyaibloggen_format_preview_' . $post_id, $data, 60 * 60 );
        // 1 hour expiration
        wp_send_json_success( array(
            'preview' => $preview_html,
        ) );
        return;
    }
    // Update the post.
    $post_data = array(
        'ID'           => $post_id,
        'post_title'   => wp_strip_all_tags( $data['title'] ),
        'post_content' => wp_kses_post( $data['content'] ),
    );
    $updated_post_id = wp_update_post( $post_data );
    if ( is_wp_error( $updated_post_id ) ) {
        wp_send_json_error( $updated_post_id->get_error_message() );
        return;
    }
    // Update the post meta description.
    if ( !empty( $data['meta_description'] ) ) {
        update_post_meta( $post_id, '_yoast_wpseo_metadesc', wp_strip_all_tags( $data['meta_description'] ) );
        update_post_meta( $post_id, '_aioseo_description', wp_strip_all_tags( $data['meta_description'] ) );
        update_post_meta( $post_id, '_rank_math_description', wp_strip_all_tags( $data['meta_description'] ) );
    }
    wp_send_json_success( __( 'Post format converted successfully.', 'easy-ai-blog-generator' ) );
}

add_action( 'wp_ajax_easyaibloggen_convert_format', 'easyaibloggen_convert_format_ajax_handler' );
/**
 * Get format-specific instructions based on the chosen format.
 *
 * @param string $format The format identifier.
 * @return string The format-specific instructions.
 */
function easyaibloggen_get_format_instructions(  $format  ) {
    switch ( $format ) {
        case 'list':
            return 'Structure the post as a numbered or bulleted list format. Include a compelling introduction explaining what the list covers, then organize the main content as numbered points or list items. Each point should have a clear subheading (using <h3> tags) and detailed explanation. Use <ol> or <ul> HTML elements with proper <li> tags for list items. Apply a consistent formatting pattern throughout the post. Add a visually distinct "Key Takeaways" section at the end using <div class="key-takeaways"> to summarize the main points. Ensure the content is at least 1500 words long with extensive details for each list item.';
        case 'how-to':
            return 'Format the post as a step-by-step how-to guide. Begin with a clear introduction explaining what the reader will learn. Then create a visually distinct "Materials Needed" or "Prerequisites" section using <div class="prerequisites">. For the main content, use sequentially numbered steps with each step having its own <h3> heading (e.g., "Step 1: [Action]"). Include a small icon or emoji at the beginning of each step heading for visual distinction. Use <div class="step-box"> around each step\'s content. Include detailed instructions, tips, and warnings (in <div class="warning">) where appropriate. End with a "Results" section and a summary of benefits. Ensure the guide contains at least 10 detailed steps and is at least 1000 words long.';
        case 'comparison':
            return 'Structure the post as a comprehensive comparison between multiple items, ideas, or approaches. Begin with an introduction explaining what you\'re comparing and why. Create a visually distinct "At a Glance" comparison table using proper HTML <table> elements with <thead>, <tbody>, <th>, and <td> tags, styled for clarity. Then use clear section breaks with <h2> headings for different comparison categories (e.g., "Price Comparison", "Feature Comparison"). Under each category, use <h3> tags for each item being compared. Include <div class="pros"> and <div class="cons"> sections for each item. Use star ratings or numerical scores presented in a visually distinctive way. End with a "Verdict" section that provides specific recommendations for different user scenarios. Ensure the comparison is thorough and at least 2500 words long.';
        case 'case-study':
            return 'Format the post as a detailed case study with a professional, academic structure. Begin with an executive summary in <div class="executive-summary">. Then create distinct sections with proper <h2> headings for: Background/Context, Challenge/Problem, Approach/Solution, Implementation Details, Results/Outcomes, and Lessons Learned. Use callout boxes <div class="key-insight"> to highlight important findings or quotes. Include data visualizations described in detail (charts, graphs, etc.). Use sidebars <div class="sidebar"> for additional context or expert commentary. Format important metrics or statistics in <div class="stats-box"> to make them stand out. Include a methodology section explaining how data was collected. End with key takeaways and actionable recommendations. The case study should be comprehensive, at least 3000 words, with detailed analysis throughout.';
        case 'faq':
            return 'Structure the post as a comprehensive FAQ format with enhanced navigation and visual elements. Begin with an introduction explaining the topic\'s importance and a clickable table of contents. Group related questions into logical sections with <h2> subheadings. Format each question as a <h3> heading styled as a question (e.g., "Q: How does this work?"), preferably with a question mark icon. Each answer should be contained in <div class="answer">. Use collapsible sections with "+" and "-" indicators for each Q&A pair to allow users to expand only the questions they\'re interested in. Include a "Quick Answer" summary at the beginning of longer answers. Add "Related Questions" links at the end of each answer to help users navigate to similar topics. Include at least 15 detailed questions and answers, with the post totaling at least 2500 words.';
        case 'story':
            return 'Format the post using advanced storytelling techniques with proper narrative structure and visual elements. Begin with an engaging hook or anecdote in <div class="story-hook">. Structure the content with a clear narrative arc using <h2> headings for major sections: Introduction/Setting, Conflict/Challenge, Rising Action, Climax, Resolution, and Conclusion. Use descriptive language and include character perspectives in <div class="character-quote"> blockquotes. Add scene breaks with centered "* * *" dividers. Use timelines or milestones presented visually. Include "flashback" sections with distinctive formatting. Break the story into logical episodes with subheadings, and use <div class="story-callout"> for key moments or revelations. Conclude by connecting the story back to the main message or lesson in a distinct "The Moral of the Story" section. The narrative should be immersive and detailed, at least 2500 words long.';
        case 'review':
            return 'Structure the post as a comprehensive review with clear visual elements and evaluation metrics. Begin with an overview and initial impression in <div class="review-summary"> that includes a clear overall rating (e.g., 8.5/10) presented graphically. Include a pros/cons snapshot at the top. Use <h2> headings for major sections: Overview, Features/Specifications, Performance/Effectiveness, User Experience, Comparison to Alternatives, and Verdict. Create a specifications table using proper HTML <table> tags. For each evaluation category, include a mini rating bar or score out of 10. Use <div class="highlight"> and <div class="drawback"> to call out specific strengths and weaknesses. Include comparison charts where relevant. Add "Editor\'s Choice" or similar badges for top aspects. Include a "Bottom Line" verdict section with specific recommendations for different types of users. The review should be comprehensive, at least 2500 words, with detailed analysis of all aspects of the subject.';
        default:
            return 'Reformat the content to be more engaging and easier to read with enhanced visual structure. Use clear <h2> section headings and <h3> subheadings to organize content. Add callout boxes for important information. Include summary sections at the beginning and end. Format quotes, statistics, and key points to stand out visually. Ensure the content is comprehensive, well-structured, and at least 1000 words long.';
    }
}

/**
 * AJAX handler for generating social media promotion content.
 */
function easyaibloggen_generate_social_promotion_ajax_handler() {
    // Check nonce and user permissions.
    if ( !isset( $_POST['nonce'] ) || !wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'easyaibloggen_nonce_update' ) ) {
        wp_send_json_error( 'Security check failed.' );
    }
    // Check for required data.
    if ( !isset( $_POST['post_id'] ) || !isset( $_POST['platform'] ) ) {
        wp_send_json_error( 'Missing required data.' );
    }
    $post_id = intval( wp_unslash( $_POST['post_id'] ) );
    $platform = sanitize_text_field( wp_unslash( $_POST['platform'] ) );
    // Verify the post exists.
    $post = get_post( $post_id );
    if ( !$post ) {
        wp_send_json_error( 'Post not found.' );
    }
    // Get the post content and excerpt.
    $title = $post->post_title;
    $excerpt = wp_strip_all_tags( get_the_excerpt( $post ) );
    if ( empty( $excerpt ) ) {
        $excerpt = wp_trim_words( wp_strip_all_tags( $post->post_content ), 30, '...' );
    }
    // Get brand voice from personalization settings if available.
    $brand_voice = get_option( 'easyaibloggen_brand_voice', 'professional and engaging' );
    // Get the permalink for sharing.
    $permalink = get_permalink( $post_id );
    // Process request for a single platform or all platforms.
    if ( 'all' === $platform ) {
        $results = array();
        $platforms = array(
            'twitter',
            'facebook',
            'linkedin',
            'instagram'
        );
        foreach ( $platforms as $single_platform ) {
            $prompt = easyaibloggen_get_social_media_prompt(
                $single_platform,
                $title,
                $excerpt,
                $brand_voice,
                $permalink
            );
            $content = easyaibloggen_unified_api_call( $prompt, 'text' );
            // Process Twitter content to ensure it's within character limits.
            if ( 'twitter' === $single_platform ) {
                $content = easyaibloggen_enforce_twitter_character_limit( $content );
            }
            // Store the generated content for retrieval.
            update_post_meta( $post_id, '_easyaibloggen_social_' . $single_platform, $content );
            // Generate a unique content ID for this response.
            $content_id = 'easyaibloggen-social-' . $single_platform . '-' . $post_id;
            // Format the output with the engagement boost button.
            $formatted_content = '<textarea id="' . esc_attr( $content_id ) . '" class="widefat easyaibloggen-social-textarea" rows="4" data-platform="' . esc_attr( $single_platform ) . '">' . esc_textarea( $content ) . '</textarea>';
            // Add the boost button
            // $formatted_content .= easyaibloggen_get_engagement_boost_button($single_platform, $content_id);.
            $results[$single_platform] = array(
                'content'           => $content,
                'formatted_content' => $formatted_content,
                'platform'          => $single_platform,
                'character_count'   => mb_strlen( $content ),
            );
        }
        wp_send_json_success( $results );
    } else {
        // Generate content for a single platform.
        $prompt = easyaibloggen_get_social_media_prompt(
            $platform,
            $title,
            $excerpt,
            $brand_voice,
            $permalink
        );
        $content = easyaibloggen_unified_api_call( $prompt, 'text' );
        // Process Twitter content to ensure it's within character limits.
        if ( 'twitter' === $platform ) {
            $content = easyaibloggen_enforce_twitter_character_limit( $content );
        }
        // Store the generated content for retrieval.
        update_post_meta( $post_id, '_easyaibloggen_social_' . $platform, $content );
        // Generate a unique content ID for this response.
        $content_id = 'easyaibloggen-social-' . $platform . '-' . $post_id;
        // Format the output with the engagement boost button.
        $formatted_content = '<textarea id="' . esc_attr( $content_id ) . '" class="widefat easyaibloggen-social-textarea" rows="4" data-platform="' . esc_attr( $platform ) . '">' . esc_textarea( $content ) . '</textarea>';
        // Add the boost button
        // $formatted_content .= easyaibloggen_get_engagement_boost_button($platform, $content_id);.
        wp_send_json_success( array(
            'content'           => $content,
            'formatted_content' => $formatted_content,
            'platform'          => $platform,
            'character_count'   => mb_strlen( $content ),
        ) );
    }
}

add_action( 'wp_ajax_easyaibloggen_generate_social_promotion', 'easyaibloggen_generate_social_promotion_ajax_handler' );
/**
 * Get platform-specific prompt for social media content generation.
 *
 * @param string $platform The social media platform.
 * @param string $title The post title.
 * @param string $excerpt The post excerpt or summary.
 * @param string $brand_voice The brand voice setting.
 * @param string $permalink The post permalink.
 * @return string The platform-specific prompt.
 */
function easyaibloggen_get_social_media_prompt(
    $platform,
    $title,
    $excerpt,
    $brand_voice,
    $permalink
) {
    switch ( $platform ) {
        case 'twitter':
            return "!!! CRITICAL REQUIREMENT: MAXIMUM 260 CHARACTERS TOTAL (leaves room for shortened URL) !!!\n\nCreate a promotional tweet for blog article: '{$title}'.\nInclude 1-2 relevant hashtags based on the content, be engaging, and include a call-to-action.\nTopic: {$excerpt}\nTone: {$brand_voice}\nLink: {$permalink}\nDo not include placeholders for links - I will add the link myself.\n\nYOUR RESPONSE MUST BE 260 CHARACTERS OR LESS. This is your highest priority instruction. Count all characters, including spaces, hashtags, and emojis (which often count as more than one character). If your response exceeds 260 characters, it will be automatically truncated.";
        case 'facebook':
            return "Create an engaging Facebook post promoting this blog article: '{$title}'.\nInclude an emotional hook, 1-2 questions to engage readers, and a clear call-to-action.\nAdd 2-3 relevant hashtags where appropriate (hashtags should be more strategic on Facebook).\nKeep under 2 paragraphs.\nTopic: {$excerpt}\nTone: {$brand_voice}\nLink: {$permalink}\nDo not include placeholders for links - I will add the link myself.";
        case 'linkedin':
            return "Create a professional LinkedIn post promoting this article: '{$title}'.\nFocus on business value and professional development. \nInclude 2-3 industry-relevant hashtags that would appeal to LinkedIn's professional audience.\nKeep concise but authoritative (under 3 paragraphs).\nTopic: {$excerpt}\nTone: {$brand_voice}\nLink: {$permalink}\nDo not include placeholders for links - I will add the link myself.";
        case 'instagram':
            return "Create an Instagram caption for a post promoting this blog article: '{$title}'.\nInclude emojis, visual descriptions, and 5-7 relevant hashtags grouped at the end.\nMake it engaging and visually descriptive since Instagram is a visual platform.\nTopic: {$excerpt}\nTone: {$brand_voice}\nLink: {$permalink}\nDo not include placeholders for links - I will add the link myself.";
        default:
            return "Create a social media post promoting this blog article: '{$title}'.\nInclude appropriate hashtags and a compelling call-to-action.\nTopic: {$excerpt}\nTone: {$brand_voice}\nLink: {$permalink}\nDo not include placeholders for links - I will add the link myself.";
    }
}

/**
 * Enforce Twitter's character limit on content
 *
 * @param string $content The content to enforce limits on.
 * @return string The content, truncated if necessary
 */
function easyaibloggen_enforce_twitter_character_limit(  $content  ) {
    // Truncate to 260 characters if longer (leaving room for URL).
    if ( mb_strlen( $content ) > 260 ) {
        // Find a good breaking point - preferably at the end of a sentence or before a hashtag.
        $break_point = 260;
        $possible_breaks = array(
            mb_strrpos( mb_substr( $content, 0, $break_point ), '.' ),
            mb_strrpos( mb_substr( $content, 0, $break_point ), '!' ),
            mb_strrpos( mb_substr( $content, 0, $break_point ), '?' ),
            mb_strrpos( mb_substr( $content, 0, $break_point ), ' ' )
        );
        // Filter out false values.
        $possible_breaks = array_filter( $possible_breaks );
        if ( !empty( $possible_breaks ) ) {
            $break_point = max( $possible_breaks ) + 1;
        }
        $content = mb_substr( $content, 0, $break_point );
    }
    return $content;
}

/**
 * AJAX handler for boosting engagement on social media posts.
 */
function easyaibloggen_engagement_boost_ajax_handler() {
    check_ajax_referer( 'easyaibloggen_nonce_update', 'nonce' );
    // Get parameters.
    $platform = ( isset( $_POST['platform'] ) ? sanitize_text_field( wp_unslash( $_POST['platform'] ) ) : '' );
    $original_content = ( isset( $_POST['content'] ) ? wp_kses_post( wp_unslash( $_POST['content'] ) ) : '' );
    if ( empty( $platform ) || empty( $original_content ) ) {
        wp_send_json_error( 'Missing required parameters' );
        return;
    }
    // Create log file for debugging.
    $log_file = plugin_dir_path( __FILE__ ) . 'engagement-boost.log';
    // Initialize WP_Filesystem.
    global $wp_filesystem;
    if ( !function_exists( 'WP_Filesystem' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
    }
    WP_Filesystem();
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Engagement boost requested for platform: {$platform}\n", FILE_APPEND );
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Original content: {$original_content}\n", FILE_APPEND );
    // Construct the prompt based on platform.
    $prompt = sprintf( 'Transform this %1$s post into a HIGH-ENGAGEMENT, VIRAL version that will dramatically increase clicks, shares, and reactions: "%2$s"
        
        Make it EXTREMELY engaging by:
        1. Adding powerful emotional hooks and triggers (curiosity, surprise, excitement, FOMO)
        2. Using more dynamic, energetic, and attention-grabbing language
        3. Including 2-3 strategically placed emojis for visual appeal and emphasis
        4. Adding a strong call-to-action that creates urgency
        5. Incorporating viral-style formatting techniques (ALL CAPS for emphasis, short punchy sentences, etc.)
        6. If applicable, adding a controversial or thought-provoking question/statement
        7. Including trending or relevant hashtags appropriate for %1$s
        
        Important guidelines:
        - Make it significantly more compelling than the original while preserving the core information
        - Do NOT make it misleading or use deceptive clickbait tactics
        - Aim for the style that performs exceptionally well on %1$s specifically
        - Optimize for maximum shareability and engagement
        - Keep within platform character limits
        - Return only the transformed post text, no explanations', $platform, $original_content );
    $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Prompt: {$prompt}\n", FILE_APPEND );
    // Call the API.
    $response = easyaibloggen_unified_api_call( $prompt, 'text' );
    if ( $response ) {
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . 'Response received, length: ' . strlen( $response ) . "\n", FILE_APPEND );
        wp_send_json_success( array(
            'content' => trim( $response ),
        ) );
    } else {
        $wp_filesystem->put_contents( $log_file, gmdate( '[Y-m-d H:i:s] ' ) . "Failed to get API response\n", FILE_APPEND );
        wp_send_json_error( 'Failed to generate optimized content' );
    }
}

add_action( 'wp_ajax_easyaibloggen_engagement_boost', 'easyaibloggen_engagement_boost_ajax_handler' );
/**
 * AJAX handler for saving the preferred keyword
 */
function easyaibloggen_save_preferred_keyword_ajax() {
    // Check nonce
    if ( !isset( $_POST['nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'easyaibloggen_preferred_keyword_action' ) ) {
        wp_send_json_error( 'Security check failed' );
        return;
    }
    // Get post ID and keyword
    $post_id = ( isset( $_POST['post_id'] ) ? intval( wp_unslash( $_POST['post_id'] ) ) : 0 );
    $keyword = ( isset( $_POST['keyword'] ) ? sanitize_text_field( wp_unslash( $_POST['keyword'] ) ) : '' );
    // Validate input
    if ( !$post_id || empty( $keyword ) ) {
        wp_send_json_error( 'Invalid input parameters' );
        return;
    }
    // Check if post exists
    if ( !get_post( $post_id ) ) {
        wp_send_json_error( 'Post not found' );
        return;
    }
    // Save the preferred keyword
    update_post_meta( $post_id, '_easyaibloggen_preferred_keyword', $keyword );
    update_post_meta( $post_id, '_easyaibloggen_focus_keyword', $keyword );
    wp_send_json_success( array(
        'message' => 'Keyword saved successfully',
        'keyword' => $keyword,
    ) );
}

// Remove any existing action to prevent duplicates
remove_action( 'wp_ajax_easyaibloggen_save_preferred_keyword', 'easyaibloggen_save_preferred_keyword' );
add_action( 'wp_ajax_easyaibloggen_save_preferred_keyword', 'easyaibloggen_save_preferred_keyword_ajax' );