<?php
/**
* Plugin Name: AI Newspaper Article Generator
* Plugin URI: https://example.com/ai-newspaper-generator
* Description: Automatically generates and queues newspaper articles with custom AI headlines, writing styles, and a custom API endpoint builder.
* Version: 14.0.0
* Author: Your Name
* Author URI: https://example.com
* Text Domain: ai-newspaper-generator
* License: GPLv2 or later
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
*/

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
die;
}

// Ensure the necessary files for media handling are loaded.
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );

// Define plugin version and options key.
define( 'AING_VERSION', '14.0.0' );
define( 'AING_OPTIONS_KEY', 'aing_options' );
define( 'AING_API_STATS_KEY', 'aing_api_stats' );
define( 'AING_PERFORMANCE_KEY', 'aing_performance_metrics' );

/**
* Main plugin class.
*/
class NewspaperArticleGeneratorPlugin {

/**
* Constructor.
*/
public function __construct() {
// Register activation and deactivation hooks.
register_activation_hook( __FILE__, array( $this, 'activate' ) );
register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );

// Add hooks for admin settings page, custom dashboard, cron job, and manual trigger.
add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
add_action( 'admin_init', array( $this, 'register_settings' ) );
add_action( 'aing_generate_articles_daily_event', array( $this, 'generate_articles_daily' ) );
add_action( 'admin_post_aing_manual_trigger', array( $this, 'handle_manual_trigger' ) );
add_action( 'admin_notices', array( $this, 'show_admin_notices' ) );

// Custom dashboard post handlers.
add_action( 'admin_post_aing_publish_draft', array( $this, 'handle_publish_draft' ) );
add_action( 'admin_post_aing_delete_draft', array( $this, 'handle_delete_draft' ) );
add_action( 'admin_post_aing_bulk_action', array( $this, 'handle_bulk_action' ) );
add_action( 'admin_post_aing_edit_draft', array( $this, 'handle_edit_draft' ) );
add_action( 'admin_post_aing_toggle_newsletter', array( $this, 'handle_toggle_newsletter' ) );
add_action( 'admin_post_aing_export_settings', array( $this, 'handle_settings_export' ) );
add_action( 'admin_post_aing_import_settings', array( $this, 'handle_settings_import' ) );
add_action( 'admin_post_aing_generate_prompt', array($this, 'handle_generate_prompt'));

// Enqueue scripts and styles for the admin pages.
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
}

/**
* Runs on plugin activation.
* Schedules the daily article generation event.
*/
public function activate() {
if ( ! wp_next_scheduled( 'aing_generate_articles_daily_event' ) ) {
wp_schedule_event( time(), 'daily', 'aing_generate_articles_daily_event' );
}
}

/**
* Runs on plugin deactivation.
* Clears the scheduled cron event.
*/
public function deactivate() {
$timestamp = wp_next_scheduled( 'aing_generate_articles_daily_event' );
wp_unschedule_event( $timestamp, 'aing_generate_articles_daily_event' );
}

/**
* Enqueues custom scripts and styles for the admin pages.
*/
public function enqueue_admin_scripts( $hook ) {
if ( strpos( $hook, 'ai-newspaper-generator' ) !== false || strpos( $hook, 'aing-review-dashboard' ) !== false ) {
// Inline CSS for custom styles.
wp_add_inline_style( 'wp-admin', $this->get_admin_styles() );
// Inline JS for custom functionality.
wp_add_inline_script( 'wp-admin', $this->get_admin_scripts(), 'after' );
}
}

/**
* Provides the custom CSS for the admin pages.
*/
private function get_admin_styles() {
ob_start();
?>
.aing-tag-input-container {
border: 1px solid #c3c4c7;
padding: 5px;
min-height: 30px;
cursor: text;
display: flex;
flex-wrap: wrap;
align-items: center;
border-radius: 4px;
}
.aing-tag-input-container:focus-within {
border-color: #2271b1;
box-shadow: 0 0 0 1px #2271b1;
}
.aing-tag-input-container input {
border: none;
outline: none;
box-shadow: none;
background: transparent;
flex-grow: 1;
padding: 5px;
line-height: 1;
}
.aing-tag {
background-color: #007cba;
color: #fff;
padding: 3px 8px;
border-radius: 12px;
margin: 2px;
font-size: 13px;
display: flex;
align-items: center;
}
.aing-tag-remove {
background: none;
border: none;
color: #fff;
font-size: 16px;
line-height: 1;
margin-left: 5px;
cursor: pointer;
}

.aing-custom-select-container {
position: relative;
}
.aing-selected-options {
border: 1px solid #c3c4c7;
padding: 5px 10px;
cursor: pointer;
display: block;
background-color: #fff;
border-radius: 4px;
}
.aing-dropdown {
position: absolute;
z-index: 10;
border: 1px solid #c3c4c7;
background-color: #fff;
max-height: 200px;
overflow-y: auto;
width: 100%;
box-shadow: 0 3px 6px rgba(0,0,0,0.1);
display: none;
}
.aing-dropdown-option {
padding: 8px 10px;
cursor: pointer;
}
.aing-dropdown-option:hover {
background-color: #f0f0f0;
}

.aing-inline-edit-form {
display: none;
}
.aing-inline-edit-form .widefat {
margin-bottom: 10px;
}
.aing-inline-edit-form textarea {
height: 150px;
}
<?php
return ob_get_clean();
}

/**
* Provides the custom JavaScript for the admin pages.
*/
private function get_admin_scripts() {
ob_start();
?>
document.addEventListener('DOMContentLoaded', function() {
// === Tag Input Functionality ===
function setupTagInput(container, hiddenInput) {
const input = container.querySelector('input[type="text"]');
const tags = hiddenInput.value ? hiddenInput.value.split(',').map(tag => tag.trim()) : [];

function renderTags() {
container.querySelectorAll('.aing-tag').forEach(tagEl => tagEl.remove());
tags.forEach(tag => {
const tagEl = document.createElement('span');
tagEl.className = 'aing-tag';
tagEl.innerHTML = `${tag}<button type="button" class="aing-tag-remove">&times;</button>`;
container.insertBefore(tagEl, input);
tagEl.querySelector('.aing-tag-remove').addEventListener('click', () => {
tags.splice(tags.indexOf(tag), 1);
hiddenInput.value = tags.join(',');
renderTags();
});
});
}

renderTags();

input.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ',') {
e.preventDefault();
const tag = input.value.trim();
if (tag && !tags.includes(tag)) {
tags.push(tag);
hiddenInput.value = tags.join(',');
input.value = '';
renderTags();
}
}
});
}

// Initialize tag inputs.
const topicsContainer = document.querySelector('#aing_news_topics_container');
const topicsHidden = document.querySelector('input[name="aing_options[news_topics]"]');
if (topicsContainer && topicsHidden) {
setupTagInput(topicsContainer, topicsHidden);
}

const requiredWordsContainer = document.querySelector('#aing_required_words_container');
const requiredWordsHidden = document.querySelector('input[name="aing_options[required_words]"]');
if (requiredWordsContainer && requiredWordsHidden) {
setupTagInput(requiredWordsContainer, requiredWordsHidden);
}

const excludedWordsContainer = document.querySelector('#aing_excluded_words_container');
const excludedWordsHidden = document.querySelector('input[name="aing_options[excluded_words]"]');
if (excludedWordsContainer && excludedWordsHidden) {
setupTagInput(excludedWordsContainer, excludedWordsHidden);
}

const sourcesContainer = document.querySelector('#aing_news_sources_container');
const sourcesHidden = document.querySelector('input[name="aing_options[news_sources]"]');
if (sourcesContainer && sourcesHidden) {
setupTagInput(sourcesContainer, sourcesHidden);
}

// === Custom Multiselect for Categories ===
function setupMultiSelect(containerId) {
const container = document.getElementById(containerId);
const dropdown = container.querySelector('.aing-dropdown');
const selectedDisplay = container.querySelector('.aing-selected-options');
const checkboxes = container.querySelectorAll('input[type="checkbox"]');

function updateDisplay() {
const selected = Array.from(checkboxes).filter(cb => cb.checked).map(cb => cb.parentNode.textContent.trim());
if (selected.length === 0) {
selectedDisplay.textContent = 'Select categories...';
} else {
selectedDisplay.textContent = selected.join(', ');
}
}

updateDisplay();

selectedDisplay.addEventListener('click', () => {
dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
});

checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateDisplay);
});

// Close dropdown when clicking outside.
document.addEventListener('click', (e) => {
if (!container.contains(e.target)) {
dropdown.style.display = 'none';
}
});
}

setupMultiSelect('aing_categories_multiselect');

// === Inline Editor for Review Dashboard ===
document.querySelectorAll('.aing-edit-button').forEach(button => {
button.addEventListener('click', function(e) {
e.preventDefault();
const row = this.closest('tr');
const postId = this.dataset.postId;
const editForm = document.getElementById(`aing-edit-form-${postId}`);

if (editForm.style.display === 'none' || !editForm.style.display) {
document.querySelectorAll('.aing-inline-edit-form').forEach(form => form.style.display = 'none');
document.querySelectorAll('.aing-post-content').forEach(content => content.style.display = 'table-cell');
document.querySelectorAll('.aing-edit-button').forEach(btn => btn.textContent = 'Edit');

editForm.style.display = 'table-row';
row.querySelector('.aing-post-content').style.display = 'none';
this.textContent = 'Cancel';
} else {
editForm.style.display = 'none';
row.querySelector('.aing-post-content').style.display = 'table-cell';
this.textContent = 'Edit';
}
});
});
});
<?php
return ob_get_clean();
}

/**
* Adds the admin menu page for the plugin settings and the new dashboard.
*/
public function add_admin_menu() {
add_options_page(
'AI Article Generator Settings',
'AI Article Generator',
'manage_options',
'ai-newspaper-generator',
array( $this, 'render_settings_page' )
);

add_submenu_page(
'ai-newspaper-generator',
'Review Generated Articles',
'Review Articles',
'manage_options',
'aing-review-dashboard',
array( $this, 'render_review_dashboard_page' )
);

add_submenu_page(
'ai-newspaper-generator',
'API Usage Dashboard',
'API Usage',
'manage_options',
'aing-api-usage-dashboard',
array( $this, 'render_api_usage_dashboard_page' )
);

add_submenu_page(
'ai-newspaper-generator',
'Content Performance',
'Performance',
'manage_options',
'aing-performance-dashboard',
array($this, 'render_performance_dashboard_page')
);
}

/**
* Renders the main settings page.
*/
public function render_settings_page() {
?>
<div class="wrap">
<h1>AI Newspaper Article Generator Settings</h1>
<form action="options.php" method="post">
<?php
settings_fields( 'aing_settings_group' );
do_settings_sections( 'ai-newspaper-generator' );
submit_button();
?>
</form>
<hr>
<h2>Manual Generation Trigger</h2>
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post">
<input type="hidden" name="action" value="aing_manual_trigger">
<?php wp_nonce_field( 'aing_manual_trigger_nonce', 'aing_manual_trigger_nonce_field' ); ?>
<p>Click the button below to manually generate articles. This is useful for testing or immediate generation.</p>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-secondary" value="Generate Articles Now">
</p>
</form>
<hr>
<h2>Settings Import/Export</h2>
<div class="mt-4">
<h3>Export Settings</h3>
<form action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post">
<input type="hidden" name="action" value="aing_export_settings">
<?php wp_nonce_field('aing_export_settings_nonce', 'aing_export_settings_nonce_field'); ?>
<p>Click below to download a JSON file of your current plugin settings. This can be used as a backup or to transfer settings to another site.</p>
<p class="submit">
<input type="submit" name="export" id="export" class="button button-secondary" value="Export Settings">
</p>
</form>
</div>
<div class="mt-8">
<h3>Import Settings</h3>
<form action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post" enctype="multipart/form-data">
<input type="hidden" name="action" value="aing_import_settings">
<?php wp_nonce_field('aing_import_settings_nonce', 'aing_import_settings_nonce_field'); ?>
<p>Upload a JSON file to import settings. This will overwrite your current settings.</p>
<p>
<input type="file" name="import_file" accept="application/json" required>
</p>
<p class="submit">
<input type="submit" name="import" id="import" class="button button-secondary" value="Import Settings">
</p>
</form>
</div>
</div>
<?php
}

/**
* Renders the API usage dashboard page.
*/
public function render_api_usage_dashboard_page() {
$stats = get_option( AING_API_STATS_KEY, array() );
$gemini_calls = isset( $stats['gemini_calls'] ) ? $stats['gemini_calls'] : 0;
$image_calls = isset( $stats['image_calls'] ) ? $stats['image_calls'] : 0;
$tts_calls = isset( $stats['tts_calls'] ) ? $stats['tts_calls'] : 0;
$news_calls = isset( $stats['news_calls'] ) ? $stats['news_calls'] : 0;
?>
<div class="wrap">
<h1>API Usage Dashboard</h1>
<p>Here you can track the number of API calls made by the plugin for different services.</p>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>Service</th>
<th>API Calls (Last 30 Days)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Google AI / Gemini</td>
<td><?php echo esc_html( $gemini_calls ); ?></td>
</tr>
<tr>
<td>Image Generation (Imagen/DALL-E)</td>
<td><?php echo esc_html( $image_calls ); ?></td>
</tr>
<tr>
<td>Text-to-Speech</td>
<td><?php echo esc_html( $tts_calls ); ?></td>
</tr>
<tr>
<td>News Source</td>
<td><?php echo esc_html( $news_calls ); ?></td>
</tr>
</tbody>
</table>
<p class="description mt-4">Note: This data is for informational purposes and resets monthly. It does not reflect your actual billing from the API providers.</p>
</div>
<?php
}

/**
* Renders the content performance dashboard page (placeholder).
*/
public function render_performance_dashboard_page() {
?>
<div class="wrap">
<h1>Content Performance Dashboard</h1>
<p>This dashboard would display metrics for your AI-generated articles (e.g., page views, social shares, comments). A real implementation would require integration with a service like Google Analytics or a custom tracking solution.</p>
<!-- TODO: Implement a visual dashboard here with charts and data -->
</div>
<?php
}

/**
* Renders the review dashboard page with bulk actions.
*/
public function render_review_dashboard_page() {
$args = array(
'post_type' => 'post',
'post_status' => 'draft',
'posts_per_page' => -1,
'meta_key' => '_aing_generated',
'meta_value' => '1',
);
$draft_posts = get_posts( $args );
?>
<div class="wrap">
<h1>Review Generated Articles</h1>
<p>Here you can review the articles generated by the AI before publishing or deleting them. Click "Edit" to make changes directly on this page.</p>

<?php if ( ! empty( $draft_posts ) ) : ?>
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post">
<input type="hidden" name="action" value="aing_bulk_action">
<?php wp_nonce_field( 'aing_bulk_action_nonce', 'aing_bulk_action_nonce_field' ); ?>

<div class="tablenav top">
<div class="alignleft actions bulkactions">
<label for="bulk-action-selector-top" class="screen-reader-text">Select bulk action</label>
<select name="bulk-action" id="bulk-action-selector-top">
<option value="-1">Bulk actions</option>
<option value="publish">Publish</option>
<option value="delete">Delete</option>
</select>
<input type="submit" id="doaction" class="button action" value="Apply">
</div>
</div>

<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<td id="cb" class="manage-column column-cb check-column"><input id="cb-select-all-1" type="checkbox"></td>
<th>Title</th>
<th>Date Generated</th>
<th>Send to Newsletter</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ( $draft_posts as $post ) : ?>
<?php $send_to_newsletter = get_post_meta( $post->ID, '_aing_send_to_newsletter', true ); ?>
<tr id="post-<?php echo intval( $post->ID ); ?>">
<th scope="row" class="check-column">
<input id="cb-select-<?php echo intval( $post->ID ); ?>" type="checkbox" name="post_ids[]" value="<?php echo intval( $post->ID ); ?>">
</th>
<td class="aing-post-content">
<strong><a href="<?php echo esc_url( get_edit_post_link( $post->ID ) ); ?>"><?php echo esc_html( $post->post_title ); ?></a></strong>
<div class="row-actions">
<span class="edit"><button class="aing-edit-button button-link" data-post-id="<?php echo intval( $post->ID ); ?>">Edit</button></span>
</div>
</td>
<td><?php echo esc_html( get_the_date( '', $post ) ); ?></td>
<td>
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" style="display:inline-block;">
<input type="hidden" name="action" value="aing_toggle_newsletter">
<input type="hidden" name="post_id" value="<?php echo intval( $post->ID ); ?>">
<?php wp_nonce_field( 'aing_toggle_newsletter_nonce_' . $post->ID, 'aing_toggle_newsletter_nonce_field' ); ?>
<input type="checkbox" name="send_to_newsletter" value="1" onchange="this.form.submit()" <?php checked( $send_to_newsletter, '1' ); ?>>
</form>
</td>
<td>
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" style="display:inline-block;">
<input type="hidden" name="action" value="aing_publish_draft">
<input type="hidden" name="post_id" value="<?php echo intval( $post->ID ); ?>">
<?php wp_nonce_field( 'aing_publish_draft_nonce_' . $post->ID, 'aing_publish_draft_nonce_field' ); ?>
<input type="submit" class="button button-primary" value="Publish">
</form>
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" style="display:inline-block;">
<input type="hidden" name="action" value="aing_delete_draft">
<input type="hidden" name="post_id" value="<?php echo intval( $post->ID ); ?>">
<?php wp_nonce_field( 'aing_delete_draft_nonce_' . $post->ID, 'aing_delete_draft_nonce_field' ); ?>
<input type="submit" class="button button-secondary" value="Delete">
</form>
</td>
</tr>
<tr class="aing-inline-edit-form" id="aing-edit-form-<?php echo intval( $post->ID ); ?>">
<td colspan="5">
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post">
<input type="hidden" name="action" value="aing_edit_draft">
<input type="hidden" name="post_id" value="<?php echo intval( $post->ID ); ?>">
<?php wp_nonce_field( 'aing_edit_draft_nonce_' . $post->ID, 'aing_edit_draft_nonce_field' ); ?>
<h4>Edit Article: <?php echo esc_html( $post->post_title ); ?></h4>
<p>
<label for="post_title_<?php echo intval( $post->ID ); ?>">Title</label><br>
<input type="text" name="post_title" id="post_title_<?php echo intval( $post->ID ); ?>" class="widefat" value="<?php echo esc_attr( $post->post_title ); ?>">
</p>
<p>
<label for="post_content_<?php echo intval( $post->ID ); ?>">Content</label><br>
<textarea name="post_content" id="post_content_<?php echo intval( $post->ID ); ?>" class="widefat" rows="10"><?php echo esc_textarea( $post->post_content ); ?></textarea>
</p>
<input type="submit" class="button button-primary" value="Save Changes">
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>

<div class="tablenav bottom">
<div class="alignleft actions bulkactions">
<label for="bulk-action-selector-bottom" class="screen-reader-text">Select bulk action</label>
<select name="bulk-action" id="bulk-action-selector-bottom">
<option value="-1">Bulk actions</option>
<option value="publish">Publish</option>
<option value="delete">Delete</option>
</select>
<input type="submit" id="doaction2" class="button action" value="Apply">
</div>
</div>
</form>
<?php else : ?>
<p>No articles currently waiting for review.</p>
<?php endif; ?>
</div>
<?php
}

/**
* Registers the settings, section, and fields for our plugin.
*/
public function register_settings() {
register_setting( 'aing_settings_group', AING_OPTIONS_KEY, array( 'sanitize_callback' => array( $this, 'sanitize_options' ) ) );

// API Section
add_settings_section(
'aing_api_section',
'API Settings',
null,
'ai-newspaper-generator'
);
add_settings_field(
'aing_api_provider',
'News API Provider',
array( $this, 'render_api_provider_field' ),
'ai-newspaper-generator',
'aing_api_section'
);
add_settings_field(
'aing_gemini_api_key',
'Google AI API Key',
array( $this, 'render_gemini_api_key_field' ),
'ai-newspaper-generator',
'aing_api_section'
);
add_settings_field(
'aing_openai_api_key',
'OpenAI API Key',
array( $this, 'render_openai_api_key_field' ),
'ai-newspaper-generator',
'aing_api_section'
);
add_settings_field(
'aing_news_api_key',
'News API Key',
array( $this, 'render_news_api_key_field' ),
'ai-newspaper-generator',
'aing_api_section'
);

// Custom API Fields
add_settings_field(
'aing_news_api_url_custom',
'Custom API URL',
array( $this, 'render_news_api_url_custom_field' ),
'ai-newspaper-generator',
'aing_api_section'
);
add_settings_field(
'aing_news_api_title_path',
'Custom API Title Path',
array( $this, 'render_news_api_title_path_field' ),
'ai-newspaper-generator',
'aing_api_section'
);
add_settings_field(
'aing_news_api_summary_path',
'Custom API Summary Path',
array( $this, 'render_news_api_summary_path_field' ),
'ai-newspaper-generator',
'aing_api_section'
);
add_settings_field(
'aing_ai_text_model',
'AI Text Model',
array( $this, 'render_ai_text_model_field' ),
'ai-newspaper-generator',
'aing_api_section'
);

// Generation Section
add_settings_section(
'aing_generation_section',
'Generation Settings',
null,
'ai-newspaper-generator'
);
add_settings_field(
'aing_prompt',
'Article Generation Prompt',
array( $this, 'render_prompt_field' ),
'ai-newspaper-generator',
'aing_generation_section'
);
add_settings_field(
'aing_article_count',
'Number of Articles to Generate',
array( $this, 'render_article_count_field' ),
'ai-newspaper-generator',
'aing_generation_section'
);
add_settings_field(
'aing_article_word_count',
'Target Article Word Count',
array( $this, 'render_article_word_count_field' ),
'ai-newspaper-generator',
'aing_generation_section'
);

// Multiple Keywords
add_settings_field(
'aing_news_topics',
'News Topic Keywords',
array( $this, 'render_news_topics_field' ),
'ai-newspaper-generator',
'aing_generation_section'
);

// Source Filtering
add_settings_field(
'aing_news_sources',
'Included News Sources',
array( $this, 'render_news_sources_field' ),
'ai-newspaper-generator',
'aing_generation_section'
);

// Exclude/Required Words Filter
add_settings_field(
'aing_required_words',
'Required Words',
array($this, 'render_required_words_field'),
'ai-newspaper-generator',
'aing_generation_section'
);
add_settings_field(
'aing_excluded_words',
'Excluded Words',
array($this, 'render_excluded_words_field'),
'ai-newspaper-generator',
'aing_generation_section'
);

// Country and Language
add_settings_field(
'aing_news_country',
'News Source Country',
array( $this, 'render_news_country_field' ),
'ai-newspaper-generator',
'aing_generation_section'
);
add_settings_field(
'aing_news_language',
'News Source Language',
array( $this, 'render_news_language_field' ),
'ai-newspaper-generator',
'aing_generation_section'
);

// Date Filtering Section
add_settings_section(
'aing_date_filter_section',
'Date Filtering Section',
array( $this, 'render_date_filter_section_callback' ),
'ai-newspaper-generator'
);
add_settings_field(
'aing_date_filter_option',
'Date Filtering',
array( $this, 'render_date_filter_option_field' ),
'ai-newspaper-generator',
'aing_date_filter_section'
);
add_settings_field(
'aing_recent_timeframe',
'Recent Timeframe',
array( $this, 'render_recent_timeframe_field' ),
'ai-newspaper-generator',
'aing_date_filter_section'
);
add_settings_field(
'aing_start_date',
'Start Date',
array( $this, 'render_start_date_field' ),
'ai-newspaper-generator',
'aing_date_filter_section'
);
add_settings_field(
'aing_end_date',
'End Date',
array( $this, 'render_end_date_field' ),
'ai-newspaper-generator',
'aing_date_filter_section'
);

// Sentiment Filtering
add_settings_field(
'aing_sentiment_filter',
'Sentiment Filtering',
array( $this, 'render_sentiment_filter_field' ),
'ai-newspaper-generator',
'aing_date_filter_section'
);

// Advanced Generation Section
add_settings_section(
'aing_advanced_generation_section',
'Advanced Generation & Scheduling',
null,
'ai-newspaper-generator'
);
add_settings_field(
'aing_rewrite_headline',
'Enable AI Headline Rewrite',
array( $this, 'render_rewrite_headline_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);
add_settings_field(
'aing_headline_prompt',
'Headline Generation Prompt',
array( $this, 'render_headline_prompt_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);
add_settings_field(
'aing_writing_style_preset',
'Writing Style Preset',
array( $this, 'render_writing_style_preset_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);
add_settings_field(
'aing_writing_style_custom',
'Custom Writing Style',
array( $this, 'render_writing_style_custom_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);

// Outbound Links
add_settings_field(
'aing_enable_outbound_links',
'Enable Outbound Links',
array( $this, 'render_enable_outbound_links_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);

add_settings_field(
'aing_enable_internal_linking',
'Enable Internal Linking',
array($this, 'render_enable_internal_linking_field'),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);

add_settings_field(
'aing_enable_ai_summary',
'Generate AI Summary',
array($this, 'render_enable_ai_summary_field'),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);

// Multiple Categories
add_settings_field(
'aing_post_categories',
'Article Categories',
array( $this, 'render_categories_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);

// SEO Fields
add_settings_field(
'aing_enable_seo_tags',
'Generate AI Tags',
array( $this, 'render_enable_seo_tags_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);
add_settings_field(
'aing_seo_tags_prompt',
'SEO Tags Prompt',
array( $this, 'render_seo_tags_prompt_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);
add_settings_field(
'aing_enable_meta_description',
'Generate AI Meta Description',
array( $this, 'render_enable_meta_description_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);
add_settings_field(
'aing_meta_description_prompt',
'Meta Description Prompt',
array( $this, 'render_meta_description_prompt_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);

add_settings_field(
'aing_post_status',
'Post Status',
array( $this, 'render_post_status_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);
add_settings_field(
'aing_schedule_time',
'Scheduled Publish Time (UTC)',
array( $this, 'render_schedule_time_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);
add_settings_field(
'aing_publish_interval',
'Publish Interval (Minutes)',
array( $this, 'render_publish_interval_field' ),
'ai-newspaper-generator',
'aing_advanced_generation_section'
);

// Featured Image Section
add_settings_section(
'aing_featured_image_section',
'Featured Image Settings',
null,
'ai-newspaper-generator'
);
add_settings_field(
'aing_image_provider',
'Image Generation Provider',
array($this, 'render_image_provider_field'),
'ai-newspaper-generator',
'aing_featured_image_section'
);
add_settings_field(
'aing_generate_image',
'Generate Featured Image',
array( $this, 'render_generate_image_field' ),
'ai-newspaper-generator',
'aing_featured_image_section'
);
add_settings_field(
'aing_image_prompt',
'Featured Image Prompt',
array( $this, 'render_image_prompt_field' ),
'ai-newspaper-generator',
'aing_featured_image_section'
);

// Text-to-Speech Section
add_settings_section(
'aing_tts_section',
'Text-to-Speech Settings',
null,
'ai-newspaper-generator'
);
add_settings_field(
'aing_enable_tts',
'Enable Text-to-Speech',
array( $this, 'render_enable_tts_field' ),
'ai-newspaper-generator',
'aing_tts_section'
);
add_settings_field(
'aing_tts_voice',
'Voice for TTS',
array( $this, 'render_tts_voice_field' ),
'ai-newspaper-generator',
'aing_tts_section'
);

// Social & Email Integration
add_settings_section(
'aing_integrations_section',
'Social & Email Integration',
null,
'ai-newspaper-generator'
);

// Social Media Settings
add_settings_field(
'aing_enable_social_media',
'Enable Social Media Automation',
array($this, 'render_enable_social_media_field'),
'ai-newspaper-generator',
'aing_integrations_section'
);
add_settings_field(
'aing_social_media_prompt',
'Social Media Post Prompt',
array($this, 'render_social_media_prompt_field'),
'ai-newspaper-generator',
'aing_integrations_section'
);
add_settings_field(
'aing_social_media_platforms',
'Social Platforms',
array($this, 'render_social_media_platforms_field'),
'ai-newspaper-generator',
'aing_integrations_section'
);

// Email Newsletter Settings
add_settings_field(
'aing_email_subject_prompt',
'Email Subject Prompt',
array($this, 'render_email_subject_prompt_field'),
'ai-newspaper-generator',
'aing_integrations_section'
);
add_settings_field(
'aing_email_body_prompt',
'Email Body Prompt',
array($this, 'render_email_body_prompt_field'),
'ai-newspaper-generator',
'aing_integrations_section'
);
}

/**
* Renders a dropdown to select the news API provider.
*/
public function render_api_provider_field() {
$options = get_option( AING_OPTIONS_KEY );
$provider = isset( $options['api_provider'] ) ? $options['api_provider'] : 'newsapi';
$providers = array(
'newsapi' => 'NewsAPI.org',
'gnews' => 'GNews API',
'mediastack' => 'Mediastack',
'guardian' => 'The Guardian API',
'custom' => 'Custom URL',
);
echo '<select name="' . AING_OPTIONS_KEY . '[api_provider]">';
foreach ( $providers as $code => $name ) {
echo '<option value="' . esc_attr( $code ) . '" ' . selected( $provider, $code, false ) . '>' . esc_html( $name ) . '</option>';
}
echo '</select>';
echo '<p class="description">Select the news API you have a key for.</p>';
}

/**
* Renders the input field for the Gemini API Key.
*/
public function render_gemini_api_key_field() {
$options = get_option( AING_OPTIONS_KEY );
$api_key = isset( $options['gemini_api_key'] ) ? $options['gemini_api_key'] : '';
echo '<input type="password" name="' . AING_OPTIONS_KEY . '[gemini_api_key]" value="' . esc_attr( $api_key ) . '" class="regular-text" placeholder="Enter your Google AI API key" />';
echo '<p class="description">This key is used for text generation (Gemini), TTS, and if you\'re using Imagen for images.</p>';
}

/**
* Renders the input field for the OpenAI API Key.
*/
public function render_openai_api_key_field() {
$options = get_option(AING_OPTIONS_KEY);
$api_key = isset($options['openai_api_key']) ? $options['openai_api_key'] : '';
echo '<input type="password" name="' . AING_OPTIONS_KEY . '[openai_api_key]" value="' . esc_attr($api_key) . '" class="regular-text" placeholder="Enter your OpenAI API key" />';
echo '<p class="description">This key is used if you select "DALL-E" as your image provider for featured images.</p>';
}

/**
* Renders the input field for the News API Key.
*/
public function render_news_api_key_field() {
$options = get_option( AING_OPTIONS_KEY );
$api_key = isset( $options['news_api_key'] ) ? $options['news_api_key'] : '';
echo '<input type="password" name="' . AING_OPTIONS_KEY . '[news_api_key]" value="' . esc_attr( $api_key ) . '" class="regular-text" placeholder="Enter your News API key" />';
echo '<p class="description">This is the API key for your chosen news provider (e.g., NewsAPI.org). It is required to fetch real news headlines and summaries.</p>';
}

/**
* Renders the input field for the Custom News API URL.
*/
public function render_news_api_url_custom_field() {
$options = get_option( AING_OPTIONS_KEY );
$api_url = isset( $options['news_api_url_custom'] ) ? $options['news_api_url_custom'] : '';
echo '<input type="text" name="' . AING_OPTIONS_KEY . '[news_api_url_custom]" value="' . esc_attr( $api_url ) . '" class="regular-text" />';
echo '<p class="description">Only use this field if you selected "Custom URL" above.</p>';
}

/**
* Renders the input field for the Custom API Title path.
*/
public function render_news_api_title_path_field() {
$options = get_option( AING_OPTIONS_KEY );
$path = isset( $options['news_api_title_path'] ) ? $options['news_api_title_path'] : '';
echo '<input type="text" name="' . AING_OPTIONS_KEY . '[news_api_title_path]" value="' . esc_attr( $path ) . '" class="regular-text" placeholder="e.g., articles.0.title" />';
echo '<p class="description">The JSON path to the article title. Use dot notation for nested objects and `0` for the first element in an array. Only for Custom URL.</p>';
}

/**
* Renders the input field for the Custom API Summary path.
*/
public function render_news_api_summary_path_field() {
$options = get_option( AING_OPTIONS_KEY );
$path = isset( $options['news_api_summary_path'] ) ? $options['news_api_summary_path'] : '';
echo '<input type="text" name="' . AING_OPTIONS_KEY . '[news_api_summary_path]" value="' . esc_attr( $path ) . '" class="regular-text" placeholder="e.g., articles.0.description" />';
echo '<p class="description">The JSON path to the article summary. Use dot notation for nested objects and `0` for the first element in an array. Only for Custom URL.</p>';
}

/**
* Renders a dropdown to select the AI text model.
*/
public function render_ai_text_model_field() {
$options = get_option(AING_OPTIONS_KEY);
$model = isset($options['ai_text_model']) ? $options['ai_text_model'] : 'gemini-1.5-pro-latest';
$models = array(
'gemini-1.5-pro-latest' => 'Gemini 1.5 Pro (Latest)',
'gemini-1.0-pro' => 'Gemini 1.0 Pro',
'gemini-1.0-pro-vision' => 'Gemini 1.0 Pro Vision',
'gemini-1.0-pro-latest' => 'Gemini 1.0 Pro (Latest)',
);
echo '<select name="' . AING_OPTIONS_KEY . '[ai_text_model]">';
foreach ($models as $value => $label) {
echo '<option value="' . esc_attr($value) . '" ' . selected($model, $value, false) . '>' . esc_html($label) . '</option>';
}
echo '</select>';
echo '<p class="description">Select the AI model for text generation.</p>';
}

/**
* Renders the textarea for the article generation prompt.
*/
public function render_prompt_field() {
$options = get_option( AING_OPTIONS_KEY );
$prompt = isset( $options['prompt'] ) ? $options['prompt'] : 'Write a newspaper article of approximately {word_count} words about {headline} based on the news summary: {summary}. The article should be engaging and factual, written in a professional tone for a news publication.';
echo '<textarea name="' . AING_OPTIONS_KEY . '[prompt]" rows="10" cols="50" class="large-text code" placeholder="Write a newspaper article about {headline} based on this summary: {summary}. Use a professional tone.">' . esc_textarea( $prompt ) . '</textarea>';
echo '<p class="description">This is the prompt that guides the AI on how to write the article. Use `{headline}`, `{summary}`, and `{word_count}` as dynamic placeholders.</p>';
}

/**
* Renders the input field for the number of articles to generate.
*/
public function render_article_count_field() {
$options = get_option( AING_OPTIONS_KEY );
$article_count = isset( $options['article_count'] ) ? $options['article_count'] : 10;
echo '<input type="number" name="' . AING_OPTIONS_KEY . '[article_count]" value="' . esc_attr( $article_count ) . '" min="1" class="small-text" />';
echo '<p class="description">Enter the number of articles to generate daily. Be mindful of your API usage limits, as each article counts as an API call.</p>';
}

/**
* Renders the input field for the target article word count.
*/
public function render_article_word_count_field() {
$options = get_option(AING_OPTIONS_KEY);
$word_count = isset($options['article_word_count']) ? $options['article_word_count'] : 500;
echo '<input type="number" name="' . AING_OPTIONS_KEY . '[article_word_count]" value="' . esc_attr($word_count) . '" min="50" class="small-text" />';
echo '<p class="description">Specify a target word count for the generated articles. This is a suggestion for the AI and may not be exact.</p>';
}

/**
* Renders a tag input for multiple news topic keywords.
*/
public function render_news_topics_field() {
$options = get_option( AING_OPTIONS_KEY );
$news_topics = isset( $options['news_topics'] ) ? $options['news_topics'] : '';
echo '<div class="aing-tag-input-container" id="aing_news_topics_container"><input type="text" placeholder="Add keywords and press Enter..."></div>';
echo '<input type="hidden" name="' . AING_OPTIONS_KEY . '[news_topics]" value="' . esc_attr( $news_topics ) . '" />';
echo '<p class="description">Enter multiple keywords to broaden the topics of the news headlines fetched. Leave this blank for general top headlines.</p>';
}

/**
* Renders a tag input for including/excluding news sources.
*/
public function render_news_sources_field() {
$options = get_option( AING_OPTIONS_KEY );
$news_sources = isset( $options['news_sources'] ) ? $options['news_sources'] : '';
echo '<div class="aing-tag-input-container" id="aing_news_sources_container"><input type="text" placeholder="Add source IDs and press Enter..."></div>';
echo '<input type="hidden" name="' . AING_OPTIONS_KEY . '[news_sources]" value="' . esc_attr( $news_sources ) . '" />';
echo '<p class="description">Enter the IDs of news sources to include, separated by commas (e.g., `bbc-news, cnn`). Check your API documentation for a list of valid source IDs.</p>';
}

/**
* Renders a tag input for required words.
*/
public function render_required_words_field() {
$options = get_option(AING_OPTIONS_KEY);
$required_words = isset($options['required_words']) ? $options['required_words'] : '';
echo '<div class="aing-tag-input-container" id="aing_required_words_container"><input type="text" placeholder="Add required words and press Enter..."></div>';
echo '<input type="hidden" name="' . AING_OPTIONS_KEY . '[required_words]" value="' . esc_attr($required_words) . '" />';
echo '<p class="description">News articles will only be fetched if their headline or summary contains one of these words.</p>';
}

/**
* Renders a tag input for excluded words.
*/
public function render_excluded_words_field() {
$options = get_option(AING_OPTIONS_KEY);
$excluded_words = isset($options['excluded_words']) ? $options['excluded_words'] : '';
echo '<div class="aing-tag-input-container" id="aing_excluded_words_container"><input type="text" placeholder="Add excluded words and press Enter..."></div>';
echo '<input type="hidden" name="' . AING_OPTIONS_KEY . '[excluded_words]" value="' . esc_attr($excluded_words) . '" />';
echo '<p class="description">News articles will be ignored if their headline or summary contains one of these words.</p>';
}

/**
* Renders a dropdown to select the news source country.
*/
public function render_news_country_field() {
$options = get_option( AING_OPTIONS_KEY );
$country = isset( $options['news_country'] ) ? $options['news_country'] : 'us';
$countries = array(
'us' => 'United States', 'gb' => 'United Kingdom', 'au' => 'Australia',
'ca' => 'Canada', 'de' => 'Germany', 'fr' => 'France', 'in' => 'India',
);

echo '<select name="' . AING_OPTIONS_KEY . '[news_country]">';
foreach ( $countries as $code => $name ) {
echo '<option value="' . esc_attr( $code ) . '" ' . selected( $country, $code, false ) . '>' . esc_html( $name ) . '</option>';
}
echo '</select>';
echo '<p class="description">Select the country you want to fetch news headlines from.</p>';
}

/**
* Renders a dropdown to select the news source language.
*/
public function render_news_language_field() {
$options = get_option( AING_OPTIONS_KEY );
$language = isset( $options['news_language'] ) ? $options['news_language'] : 'en';
$languages = array(
'en' => 'English', 'de' => 'German', 'es' => 'Spanish', 'fr' => 'French', 'hi' => 'Hindi',
);

echo '<select name="' . AING_OPTIONS_KEY . '[news_language]">';
foreach ( $languages as $code => $name ) {
echo '<option value="' . esc_attr( $code ) . '" ' . selected( $language, $code, false ) . '>' . esc_html( $name ) . '</option>';
}
echo '</select>';
echo '<p class="description">Select the language for the news headlines.</p>';
}

/**
* Callback for the date filtering settings section.
*/
public function render_date_filter_section_callback() {
echo '<p class="description">Control the date range of the articles fetched from the news API.</p>';
}

/**
* Renders the radio buttons for date filtering options.
*/
public function render_date_filter_option_field() {
$options = get_option( AING_OPTIONS_KEY );
$date_filter_option = isset( $options['date_filter_option'] ) ? $options['date_filter_option'] : 'none';

$options_array = array(
'none' => 'Up-to-the-minute News (Most Recent)',
'recent' => 'Recent Timeframe',
'specific' => 'Specific Past Period',
);

foreach ($options_array as $value => $label) {
echo '<label><input type="radio" name="' . AING_OPTIONS_KEY . '[date_filter_option]" value="' . esc_attr($value) . '" ' . checked($date_filter_option, $value, false) . ' /> ' . esc_html($label) . '</label><br>';
}
}

/**
* Renders the dropdown for the recent timeframe.
*/
public function render_recent_timeframe_field() {
$options = get_option( AING_OPTIONS_KEY );
$timeframe = isset( $options['recent_timeframe'] ) ? $options['recent_timeframe'] : '24_hours';

$timeframes = array(
'24_hours' => 'Last 24 Hours',
'last_week' => 'Last Week',
'last_month' => 'Last Month',
);

echo '<select name="' . AING_OPTIONS_KEY . '[recent_timeframe]">';
foreach ($timeframes as $value => $label) {
echo '<option value="' . esc_attr($value) . '" ' . selected($timeframe, $value, false) . '>' . esc_html($label) . '</option>';
}
echo '<p class="description">Select a predefined recent period.</p>';
}

/**
* Renders the start date field.
*/
public function render_start_date_field() {
$options = get_option( AING_OPTIONS_KEY );
$start_date = isset( $options['start_date'] ) ? $options['start_date'] : '';
echo '<input type="date" name="' . AING_OPTIONS_KEY . '[start_date]" value="' . esc_attr($start_date) . '" />';
echo '<p class="description">Select the start date for a specific historical period.</p>';
}

/**
* Renders the end date field.
*/
public function render_end_date_field() {
$options = get_option( AING_OPTIONS_KEY );
$end_date = isset( $options['end_date'] ) ? $options['end_date'] : '';
echo '<input type="date" name="' . AING_OPTIONS_KEY . '[end_date]" value="' . esc_attr($end_date) . '" />';
echo '<p class="description">Select the end date for a specific historical period.</p>';
}

/**
* Renders the dropdown for sentiment filtering.
*/
public function render_sentiment_filter_field() {
$options = get_option(AING_OPTIONS_KEY);
$sentiment = isset($options['sentiment_filter']) ? $options['sentiment_filter'] : 'any';

$sentiments = array(
'any' => 'Any (No Filter)',
'positive' => 'Positive',
'neutral' => 'Neutral',
'negative' => 'Negative',
);

echo '<select name="' . AING_OPTIONS_KEY . '[sentiment_filter]">';
foreach ($sentiments as $value => $label) {
echo '<option value="' . esc_attr($value) . '" ' . selected($sentiment, $value, false) . '>' . esc_html($label) . '</option>';
}
echo '<p class="description">Filter articles by sentiment. Note: This feature depends on the capabilities of the selected news API and may not work with all providers. If the API does not support sentiment, no filtering will occur.</p>';
}

/**
* Renders the checkbox for enabling AI headline rewrite.
*/
public function render_rewrite_headline_field() {
$options = get_option( AING_OPTIONS_KEY );
$rewrite = isset( $options['rewrite_headline'] ) ? (bool) $options['rewrite_headline'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[rewrite_headline]" value="1" ' . checked( true, $rewrite, false ) . ' />';
echo '<p class="description">Enable this to have AI generate a new, more creative headline for each article.</p>';
}

/**
* Renders the textarea for the headline generation prompt.
*/
public function render_headline_prompt_field() {
$options = get_option( AING_OPTIONS_KEY );
$prompt = isset( $options['headline_prompt'] ) ? $options['headline_prompt'] : 'Rewrite this headline to be more engaging and SEO-friendly: {headline}. Do not include any quotes in the rewritten headline.';
echo '<textarea name="' . AING_OPTIONS_KEY . '[headline_prompt]" rows="5" cols="50" class="large-text code">' . esc_textarea( $prompt ) . '</textarea>';
echo '<p class="description">Use `{headline}` as a dynamic placeholder for the raw news headline.</p>';
}

/**
* Renders the dropdown for writing style presets.
*/
public function render_writing_style_preset_field() {
$options = get_option( AING_OPTIONS_KEY );
$preset = isset( $options['writing_style_preset'] ) ? $options['writing_style_preset'] : 'professional';
$presets = array(
'none' => 'None',
'professional' => 'Professional & Formal',
'casual' => 'Casual & Conversational',
'humorous' => 'Humorous & Witty',
'informative' => 'Informative & Educational',
'custom' => 'Custom (use field below)',
);
echo '<select name="' . AING_OPTIONS_KEY . '[writing_style_preset]">';
foreach ( $presets as $value => $label ) {
echo '<option value="' . esc_attr( $value ) . '" ' . selected( $preset, $value, false ) . '>' . esc_html( $label ) . '</option>';
}
echo '</select>';
echo '<p class="description">Choose a predefined writing style or select "Custom" to use the field below.</p>';
}

/**
* Renders the textarea for custom writing style.
*/
public function render_writing_style_custom_field() {
$options = get_option( AING_OPTIONS_KEY );
$style = isset( $options['writing_style_custom'] ) ? $options['writing_style_custom'] : '';
echo '<textarea name="' . AING_OPTIONS_KEY . '[writing_style_custom]" rows="5" cols="50" class="large-text code">' . esc_textarea( $style ) . '</textarea>';
echo '<p class="description">This prompt will be prepended to the article generation prompt. Use this if you selected "Custom" above. E.g., "Write this article as if you are a witty travel blogger."</p>';
}

/**
* Renders the checkbox for enabling outbound links.
*/
public function render_enable_outbound_links_field() {
$options = get_option( AING_OPTIONS_KEY );
$enabled = isset( $options['enable_outbound_links'] ) ? (bool) $options['enable_outbound_links'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[enable_outbound_links]" value="1" ' . checked( true, $enabled, false ) . ' />';
echo '<p class="description">Enable this to include a link to the original news article at the end of each generated post.</p>';
}

/**
* Renders the checkbox for enabling internal linking.
*/
public function render_enable_internal_linking_field() {
$options = get_option(AING_OPTIONS_KEY);
$enabled = isset($options['enable_internal_linking']) ? (bool) $options['enable_internal_linking'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[enable_internal_linking]" value="1" ' . checked(true, $enabled, false) . ' />';
echo '<p class="description">Enable this to have the plugin automatically find and add internal links to existing posts.</p>';
}

/**
* Renders the input field for minimum internal links.
*/
public function render_min_internal_links_field() {
$options = get_option(AING_OPTIONS_KEY);
$min_links = isset($options['min_internal_links']) ? $options['min_internal_links'] : 1;
echo '<input type="number" name="' . AING_OPTIONS_KEY . '[min_internal_links]" value="' . esc_attr($min_links) . '" min="0" class="small-text" />';
echo '<p class="description">Minimum number of internal links to add to each article (if possible).</p>';
}

/**
* Renders the textarea for internal linking prioritization.
*/
public function render_link_prioritization_prompt_field() {
$options = get_option(AING_OPTIONS_KEY);
$prompt = isset($options['link_prioritization_prompt']) ? $options['link_prioritization_prompt'] : 'Based on the article content, identify the most relevant keywords to link to these pages: {pages}. Respond with a comma-separated list of keywords, no other text.';
echo '<textarea name="' . AING_OPTIONS_KEY . '[link_prioritization_prompt]" rows="5" cols="50" class="large-text code">' . esc_textarea($prompt) . '</textarea>';
echo '<p class="description">Prompt for the AI to identify keywords for internal links. Use `{pages}` as a placeholder for a list of relevant post titles and URLs.</p>';
}

/**
* Renders the checkbox for enabling AI summary generation.
*/
public function render_enable_ai_summary_field() {
$options = get_option(AING_OPTIONS_KEY);
$enabled = isset($options['enable_ai_summary']) ? (bool) $options['enable_ai_summary'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[enable_ai_summary]" value="1" ' . checked(true, $enabled, false) . ' />';
echo '<p class="description">Enable this to generate a concise summary of the article, which will be added to the post content.</p>';
}

/**
* Renders a multiselect for post categories.
*/
public function render_categories_field() {
$options = get_option( AING_OPTIONS_KEY );
$selected_categories = isset( $options['post_categories'] ) ? $options['post_categories'] : array();

$categories = get_categories( array(
'hide_empty' => false,
) );

echo '<div class="aing-custom-select-container" id="aing_categories_multiselect">';
echo '<div class="aing-selected-options">Select categories...</div>';
echo '<div class="aing-dropdown">';
echo '<label class="aing-dropdown-option"><input type="checkbox" name="' . AING_OPTIONS_KEY . '[post_categories][]" value="0" ' . checked( in_array( 0, $selected_categories ), true, false ) . '> Uncategorized</label>';
foreach ( $categories as $category ) {
echo '<label class="aing-dropdown-option"><input type="checkbox" name="' . AING_OPTIONS_KEY . '[post_categories][]" value="' . esc_attr( $category->term_id ) . '" ' . checked( in_array( $category->term_id, $selected_categories ), true, false ) . '> ' . esc_html( $category->name ) . '</label>';
}
echo '</div>';
echo '</div>';
echo '<p class="description">Select one or more categories where the new articles will be saved.</p>';
}

/**
* Renders the checkbox for enabling AI tags.
*/
public function render_enable_seo_tags_field() {
$options = get_option(AING_OPTIONS_KEY);
$enabled = isset($options['enable_seo_tags']) ? (bool) $options['enable_seo_tags'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[enable_seo_tags]" value="1" ' . checked(true, $enabled, false) . ' />';
echo '<p class="description">Enable this to have AI generate relevant tags for each post.</p>';
}

/**
* Renders the textarea for the SEO tags prompt.
*/
public function render_seo_tags_prompt_field() {
$options = get_option(AING_OPTIONS_KEY);
$prompt = isset($options['seo_tags_prompt']) ? $options['seo_tags_prompt'] : 'Generate a list of 5-10 SEO-friendly tags for the following article. Respond with a comma-separated list of keywords, no other text. Article content: {content}';
echo '<textarea name="' . AING_OPTIONS_KEY . '[seo_tags_prompt]" rows="5" cols="50" class="large-text code">' . esc_textarea($prompt) . '</textarea>';
echo '<p class="description">The prompt for generating tags. Use `{content}` as a placeholder for the article\'s content.</p>';
}

/**
* Renders the checkbox for enabling AI meta descriptions.
*/
public function render_enable_meta_description_field() {
$options = get_option(AING_OPTIONS_KEY);
$enabled = isset($options['enable_meta_description']) ? (bool) $options['enable_meta_description'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[enable_meta_description]" value="1" ' . checked(true, $enabled, false) . ' />';
echo '<p class="description">Enable this to have AI generate a compelling meta description for each post.</p>';
}

/**
* Renders the textarea for the meta description prompt.
*/
public function render_meta_description_prompt_field() {
$options = get_option(AING_OPTIONS_KEY);
$prompt = isset($options['meta_description_prompt']) ? $options['meta_description_prompt'] : 'Write a 150-character SEO meta description for the following article: {content}';
echo '<textarea name="' . AING_OPTIONS_KEY . '[meta_description_prompt]" rows="5" cols="50" class="large-text code">' . esc_textarea($prompt) . '</textarea>';
echo '<p class="description">The prompt for generating a meta description. Use `{content}` as a placeholder for the article\'s content.</p>';
}

/**
* Renders a dropdown for the post status.
*/
public function render_post_status_field() {
$options = get_option( AING_OPTIONS_KEY );
$post_status = isset($options['post_status']) ? $options['post_status'] : 'draft';

$statuses = array(
'publish' => 'Publish',
'draft' => 'Save as Draft',
'future' => 'Schedule for Future',
);

echo '<select name="' . AING_OPTIONS_KEY . '[post_status]">';
foreach ( $statuses as $value => $label ) {
echo '<option value="' . esc_attr($value) . '" ' . selected($post_status, $value, false) . '>' . esc_html($label) . '</option>';
}
echo '</select>';
echo '<p class="description">Choose whether to automatically publish, save as draft, or schedule articles.</p>';
}

/**
* Renders a dropdown for the scheduled publish time.
*/
public function render_schedule_time_field() {
$options = get_option( AING_OPTIONS_KEY );
$schedule_time = isset( $options['schedule_time'] ) ? $options['schedule_time'] : '08:00';
echo '<input type="time" name="' . AING_OPTIONS_KEY . '[schedule_time]" value="' . esc_attr( $schedule_time ) . '" />';
echo '<p class="description">Choose the exact time (in UTC) when the first article will be published or queued each day.</p>';
}

/**
* Renders the input for the publish interval.
*/
public function render_publish_interval_field() {
$options = get_option( AING_OPTIONS_KEY );
$interval = isset( $options['publish_interval'] ) ? $options['publish_interval'] : 60;
echo '<input type="number" name="' . AING_OPTIONS_KEY . '[publish_interval]" value="' . esc_attr( $interval ) . '" min="1" class="small-text" />';
echo '<p class="description">The time interval (in minutes) between each published article. This is used when "Post Status" is set to "Publish" or "Schedule for Future".</p>';
}

/**
* Renders a dropdown to select the image generation provider.
*/
public function render_image_provider_field() {
$options = get_option(AING_OPTIONS_KEY);
$provider = isset($options['image_provider']) ? $options['image_provider'] : 'imagen';
$providers = array(
'imagen' => 'Google Imagen (via Google AI API Key)',
'dalle' => 'DALL-E',
);

echo '<select name="' . AING_OPTIONS_KEY . '[image_provider]">';
foreach ($providers as $code => $name) {
echo '<option value="' . esc_attr($code) . '" ' . selected($provider, $code, false) . '>' . esc_html($name) . '</option>';
}
echo '</select>';
echo '<p class="description">Select the image generation API you want to use for featured images. You must provide the corresponding API key in the API Settings section.</p>';
}

/**
* Renders the checkbox for generating a featured image.
*/
public function render_generate_image_field() {
$options = get_option( AING_OPTIONS_KEY );
$generate_image = isset( $options['generate_image'] ) ? (bool) $options['generate_image'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[generate_image]" value="1" ' . checked( true, $generate_image, false ) . ' />';
echo '<p class="description">Enable this to generate a unique featured image for each article. This is an optional feature and will use your selected image provider.</p>';
}

/**
* Renders a dropdown to select the image style preset.
*/
public function render_image_style_preset_field() {
$options = get_option(AING_OPTIONS_KEY);
$style = isset($options['image_style_preset']) ? $options['image_style_preset'] : 'photorealistic';
$styles = array(
'photorealistic' => 'Photorealistic',
'digital_art' => 'Digital Art',
'cartoon' => 'Cartoon',
'watercolor' => 'Watercolor',
);
echo '<select name="' . AING_OPTIONS_KEY . '[image_style_preset]">';
foreach ($styles as $value => $label) {
echo '<option value="' . esc_attr($value) . '" ' . selected($style, $value, false) . '>' . esc_html($label) . '</option>';
}
echo '</select>';
echo '<p class="description">Choose a style preset for the generated image.</p>';
}

/**
* Renders the input field for the image aspect ratio.
*/
public function render_image_aspect_ratio_field() {
$options = get_option(AING_OPTIONS_KEY);
$ratio = isset($options['image_aspect_ratio']) ? $options['image_aspect_ratio'] : '16:9';
$ratios = array(
'16:9' => 'Landscape (16:9)',
'1:1' => 'Square (1:1)',
'9:16' => 'Portrait (9:16)',
);
echo '<select name="' . AING_OPTIONS_KEY . '[image_aspect_ratio]">';
foreach ($ratios as $value => $label) {
echo '<option value="' . esc_attr($value) . '" ' . selected($ratio, $value, false) . '>' . esc_html($label) . '</option>';
}
echo '</select>';
echo '<p class="description">Choose the aspect ratio for the generated image.</p>';
}

/**
* Renders the textarea for the featured image prompt.
*/
public function render_image_prompt_field() {
$options = get_option( AING_OPTIONS_KEY );
$image_prompt = isset( $options['image_prompt'] ) ? $options['image_prompt'] : 'A vibrant, digital art style image illustrating the following news headline: {headline}';
echo '<textarea name="' . AING_OPTIONS_KEY . '[image_prompt]" rows="5" cols="50" class="large-text code">' . esc_textarea($image_prompt) . '</textarea>';
echo '<p class="description">This is the prompt that guides the AI on what image to create. You can use `{headline}` and `{summary}` as dynamic placeholders to create an an image relevant to the article\'s content.</p>';
}

/**
* Renders the checkbox for enabling Text-to-Speech.
*/
public function render_enable_tts_field() {
$options = get_option(AING_OPTIONS_KEY);
$enable_tts = isset($options['enable_tts']) ? (bool) $options['enable_tts'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[enable_tts]" value="1" ' . checked(true, $enable_tts, false) . ' />';
echo '<p class="description">Enable this to generate an audio version of each article and embed a player at the top of the post.</p>';
}

/**
* Renders a dropdown to select the TTS voice.
*/
public function render_tts_voice_field() {
$options = get_option(AING_OPTIONS_KEY);
$voice = isset($options['tts_voice']) ? $options['tts_voice'] : 'Kore';
$voices = array(
'Zephyr' => 'Zephyr (Bright)', 'Puck' => 'Puck (Upbeat)', 'Charon' => 'Charon (Informative)',
'Kore' => 'Kore (Firm)', 'Fenrir' => 'Fenrir (Excitable)', 'Leda' => 'Leda (Youthful)',
'Orus' => 'Orus (Firm)', 'Aoede' => 'Aoede (Breezy)', 'Callirrhoe' => 'Callirrhoe (Easy-going)',
'Autonoe' => 'Autonoe (Bright)', 'Enceladus' => 'Enceladus (Breathy)', 'Iapetus' => 'Iapetus (Clear)',
'Umbriel' => 'Umbriel (Easy-going)', 'Algieba' => 'Algieba (Smooth)', 'Despina' => 'Despina (Smooth)',
'Erinome' => 'Erinome (Clear)', 'Algenib' => 'Algenib (Gravelly)', 'Rasalgethi' => 'Rasalgethi (Informative)',
'Laomedeia' => 'Laomedeia (Upbeat)', 'Achernar' => 'Achernar (Soft)', 'Alnilam' => 'Alnilam (Firm)',
'Schedar' => 'Schedar (Even)', 'Gacrux' => 'Gacrux (Mature)', 'Pulcherrima' => 'Pulcherrima (Forward)',
'Achird' => 'Achird (Friendly)', 'Zubenelgenubi' => 'Zubenelgenubi (Casual)',
'Vindemiatrix' => 'Vindemiatrix (Gentle)', 'Sadachbia' => 'Sadachbia (Lively)',
'Sadaltager' => 'Sadaltager (Knowledgeable)', 'Sulafat' => 'Sulafat (Warm)'
);
echo '<select name="' . AING_OPTIONS_KEY . '[tts_voice]">';
foreach ($voices as $code => $name) {
echo '<option value="' . esc_attr($code) . '" ' . selected($voice, $code, false) . '>' . esc_html($name) . '</option>';
}
echo '</select>';
echo '<p class="description">Select a voice for the generated audio articles.</p>';
}

/**
* Renders the checkbox for social media automation.
*/
public function render_enable_social_media_field() {
$options = get_option(AING_OPTIONS_KEY);
$enabled = isset($options['enable_social_media']) ? (bool) $options['enable_social_media'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[enable_social_media]" value="1" ' . checked(true, $enabled, false) . ' />';
echo '<p class="description">Automatically post to social media when an article is published.</p>';
}

/**
* Renders the textarea for the social media post prompt.
*/
public function render_social_media_prompt_field() {
$options = get_option(AING_OPTIONS_KEY);
$prompt = isset($options['social_media_prompt']) ? $options['social_media_prompt'] : 'New article: {title}. Read more here: {url} {tags}';
echo '<textarea name="' . AING_OPTIONS_KEY . '[social_media_prompt]" rows="5" cols="50" class="large-text code">' . esc_textarea($prompt) . '</textarea>';
echo '<p class="description">This prompt will be used to generate a social media post. Use `{title}`, `{url}`, and `{tags}` as placeholders.</p>';
}

/**
* Renders a multiselect for social media platforms.
*/
public function render_social_media_platforms_field() {
$options = get_option(AING_OPTIONS_KEY);
$selected_platforms = isset($options['social_media_platforms']) ? (array) $options['social_media_platforms'] : array();
$platforms = array('twitter' => 'Twitter', 'facebook' => 'Facebook', 'linkedin' => 'LinkedIn', 'pinterest' => 'Pinterest', 'mailchimp' => 'Mailchimp');

echo '<div class="aing-custom-select-container" id="aing_social_platforms_multiselect">';
echo '<div class="aing-selected-options">Select platforms...</div>';
echo '<div class="aing-dropdown">';
foreach ($platforms as $value => $label) {
echo '<label class="aing-dropdown-option"><input type="checkbox" name="' . AING_OPTIONS_KEY . '[social_media_platforms][]" value="' . esc_attr($value) . '" ' . checked(in_array($value, $selected_platforms), true, false) . '> ' . esc_html($label) . '</label>';
}
echo '</div>';
echo '</div>';
echo '<p class="description">Select which platforms to automatically share to. Note: You must configure the API for each platform separately.</p>';
}

/**
* Renders the checkbox for email newsletter integration.
*/
public function render_enable_email_newsletter_field() {
$options = get_option(AING_OPTIONS_KEY);
$enabled = isset($options['enable_email_newsletter']) ? (bool) $options['enable_email_newsletter'] : false;
echo '<input type="checkbox" name="' . AING_OPTIONS_KEY . '[enable_email_newsletter]" value="1" ' . checked(true, $enabled, false) . ' />';
echo '<p class="description">Automatically generate an email newsletter draft for new articles.</p>';
}

/**
* Renders the textarea for the email subject prompt.
*/
public function render_email_subject_prompt_field() {
$options = get_option(AING_OPTIONS_KEY);
$prompt = isset($options['email_subject_prompt']) ? $options['email_subject_prompt'] : 'Weekly News Roundup: The latest on {title}';
echo '<textarea name="' . AING_OPTIONS_KEY . '[email_subject_prompt]" rows="2" cols="50" class="large-text code">' . esc_textarea($prompt) . '</textarea>';
echo '<p class="description">This prompt is for the email subject. Use `{title}` as a placeholder.</p>';
}

/**
* Renders the textarea for the email body prompt.
*/
public function render_email_body_prompt_field() {
$options = get_option(AING_OPTIONS_KEY);
$prompt = isset($options['email_body_prompt']) ? $options['email_body_prompt'] : 'Hi, we have a new article for you: {title}. Here is a short summary: {summary}. Read the full article here: {url}';
echo '<textarea name="' . AING_OPTIONS_KEY . '[email_body_prompt]" rows="5" cols="50" class="large-text code">' . esc_textarea($prompt) . '</textarea>';
echo '<p class="description">This prompt is for the email body. Use `{title}`, `{summary}`, and `{url}` as placeholders.</p>';
}

/**
* Sanitizes the plugin options.
*
* @param array $input The input from the settings form.
* @return array The sanitized input.
*/
public function sanitize_options( $input ) {
$sanitized_input = array();

// API Settings
if ( isset( $input['api_provider'] ) ) { $sanitized_input['api_provider'] = sanitize_text_field( $input['api_provider'] ); }
if ( isset( $input['gemini_api_key'] ) ) { $sanitized_input['gemini_api_key'] = sanitize_text_field( $input['gemini_api_key'] ); }
if ( isset( $input['openai_api_key'] ) ) { $sanitized_input['openai_api_key'] = sanitize_text_field( $input['openai_api_key'] ); }
if ( isset( $input['news_api_key'] ) ) { $sanitized_input['news_api_key'] = sanitize_text_field( $input['news_api_key'] ); }
if ( isset( $input['news_api_url_custom'] ) ) { $sanitized_input['news_api_url_custom'] = esc_url_raw( $input['news_api_url_custom'] ); }
if ( isset( $input['news_api_title_path'] ) ) { $sanitized_input['news_api_title_path'] = sanitize_text_field( $input['news_api_title_path'] ); }
if ( isset( $input['news_api_summary_path'] ) ) { $sanitized_input['news_api_summary_path'] = sanitize_text_field( $input['news_api_summary_path'] ); }

// Generation Settings
if ( isset( $input['prompt'] ) ) { $sanitized_input['prompt'] = sanitize_textarea_field( $input['prompt'] ); }
if ( isset( $input['article_count'] ) ) { $sanitized_input['article_count'] = max( 1, intval( $input['article_count'] ) ); }
if ( isset( $input['news_topics'] ) ) { $sanitized_input['news_topics'] = sanitize_textarea_field( $input['news_topics'] ); }
if ( isset( $input['news_sources'] ) ) { $sanitized_input['news_sources'] = sanitize_textarea_field( $input['news_sources'] ); }
if ( isset( $input['news_country'] ) ) { $sanitized_input['news_country'] = sanitize_text_field( $input['news_country'] ); }
if ( isset( $input['news_language'] ) ) { $sanitized_input['news_language'] = sanitize_text_field( $input['news_language'] ); }

// Date Filtering Settings
if ( isset( $input['date_filter_option'] ) ) { $sanitized_input['date_filter_option'] = sanitize_text_field( $input['date_filter_option'] ); }
if ( isset( $input['recent_timeframe'] ) ) { $sanitized_input['recent_timeframe'] = sanitize_text_field( $input['recent_timeframe'] ); }
if ( isset( $input['start_date'] ) ) { $sanitized_input['start_date'] = sanitize_text_field( $input['start_date'] ); }
if ( isset( $input['end_date'] ) ) { $sanitized_input['end_date'] = sanitize_text_field( $input['end_date'] ); }
if ( isset( $input['sentiment_filter'] ) ) { $sanitized_input['sentiment_filter'] = sanitize_text_field( $input['sentiment_filter'] ); }

// Advanced Generation Settings
$sanitized_input['rewrite_headline'] = isset( $input['rewrite_headline'] ) ? true : false;
if ( isset( $input['headline_prompt'] ) ) { $sanitized_input['headline_prompt'] = sanitize_textarea_field( $input['headline_prompt'] ); }
if ( isset( $input['writing_style_preset'] ) ) { $sanitized_input['writing_style_preset'] = sanitize_text_field( $input['writing_style_preset'] ); }
if ( isset( $input['writing_style_custom'] ) ) { $sanitized_input['writing_style_custom'] = sanitize_textarea_field( $input['writing_style_custom'] ); }
if ( isset( $input['post_categories'] ) ) { $sanitized_input['post_categories'] = array_map('absint', (array) $input['post_categories']); }
$sanitized_input['enable_seo_tags'] = isset($input['enable_seo_tags']) ? true : false;
if ( isset( $input['seo_tags_prompt'] ) ) { $sanitized_input['seo_tags_prompt'] = sanitize_textarea_field( $input['seo_tags_prompt'] ); }
$sanitized_input['enable_meta_description'] = isset($input['enable_meta_description']) ? true : false;
if ( isset( $input['meta_description_prompt'] ) ) { $sanitized_input['meta_description_prompt'] = sanitize_textarea_field( $input['meta_description_prompt'] ); }
if ( isset( $input['post_status'] ) ) { $sanitized_input['post_status'] = sanitize_text_field( $input['post_status'] ); }
if ( isset( $input['schedule_time'] ) ) { $sanitized_input['schedule_time'] = sanitize_text_field( $input['schedule_time'] ); }
if ( isset( $input['publish_interval'] ) ) { $sanitized_input['publish_interval'] = max( 1, intval( $input['publish_interval'] ) ); }

// Featured Image Settings
if ( isset( $input['image_provider'] ) ) { $sanitized_input['image_provider'] = sanitize_text_field( $input['image_provider'] ); }
$sanitized_input['generate_image'] = isset( $input['generate_image'] ) ? true : false;
if ( isset( $input['image_prompt'] ) ) { $sanitized_input['image_prompt'] = sanitize_textarea_field( $input['image_prompt'] ); }

// Text-to-Speech Settings
$sanitized_input['enable_tts'] = isset( $input['enable_tts'] ) ? true : false;
if ( isset( $input['tts_voice'] ) ) { $sanitized_input['tts_voice'] = sanitize_text_field( $input['tts_voice'] ); }

// Social & Email Integration
$sanitized_input['enable_social_media'] = isset($input['enable_social_media']) ? true : false;
if ( isset( $input['social_media_prompt'] ) ) { $sanitized_input['social_media_prompt'] = sanitize_textarea_field( $input['social_media_prompt'] ); }
if ( isset( $input['social_media_platforms'] ) ) { $sanitized_input['social_media_platforms'] = array_map('sanitize_text_field', (array) $input['social_media_platforms']); }

$sanitized_input['enable_email_newsletter'] = isset($input['enable_email_newsletter']) ? true : false;
if ( isset( $input['email_subject_prompt'] ) ) { $sanitized_input['email_subject_prompt'] = sanitize_text_field( $input['email_subject_prompt'] ); }
if ( isset( $input['email_body_prompt'] ) ) { $sanitized_input['email_body_prompt'] = sanitize_textarea_field( $input['email_body_prompt'] ); }

// New Features
if ( isset( $input['required_words'] ) ) { $sanitized_input['required_words'] = sanitize_textarea_field( $input['required_words'] ); }
if ( isset( $input['excluded_words'] ) ) { $sanitized_input['excluded_words'] = sanitize_textarea_field( $input['excluded_words'] ); }
$sanitized_input['enable_internal_linking'] = isset($input['enable_internal_linking']) ? true : false;
if ( isset( $input['min_internal_links'] ) ) { $sanitized_input['min_internal_links'] = max(0, intval($input['min_internal_links'])); }
if ( isset( $input['link_prioritization_prompt'] ) ) { $sanitized_input['link_prioritization_prompt'] = sanitize_textarea_field( $input['link_prioritization_prompt'] ); }
$sanitized_input['enable_ai_summary'] = isset($input['enable_ai_summary']) ? true : false;
if ( isset( $input['image_style_preset'] ) ) { $sanitized_input['image_style_preset'] = sanitize_text_field( $input['image_style_preset'] ); }
if ( isset( $input['image_aspect_ratio'] ) ) { $sanitized_input['image_aspect_ratio'] = sanitize_text_field( $input['image_aspect_ratio'] ); }
if ( isset( $input['ai_text_model'] ) ) { $sanitized_input['ai_text_model'] = sanitize_text_field( $input['ai_text_model'] ); }
if ( isset( $input['article_word_count'] ) ) { $sanitized_input['article_word_count'] = max( 50, intval($input['article_word_count']) ); }
$sanitized_input['enable_api_alerts'] = isset($input['enable_api_alerts']) ? true : false;
if ( isset( $input['alert_email_address'] ) ) { $sanitized_input['alert_email_address'] = sanitize_email( $input['alert_email_address'] ); }
if ( isset( $input['social_media_platforms'] ) ) {
$sanitized_input['social_media_platforms'] = array_map('sanitize_text_field', (array) $input['social_media_platforms']);
}

return $sanitized_input;
}

/**
* Handles a single draft post publication from the review dashboard.
*/
public function handle_publish_draft() {
$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;

// Check nonce and user permissions.
check_admin_referer( 'aing_publish_draft_nonce_' . $post_id, 'aing_publish_draft_nonce_field' );
if ( ! current_user_can( 'publish_posts' ) ) {
wp_die( 'You do not have sufficient permissions to publish posts.' );
}

if ( $post_id > 0 ) {
wp_update_post( array(
'ID' => $post_id,
'post_status' => 'publish',
) );

$post = get_post($post_id);
if ($post) {
$options = get_option(AING_OPTIONS_KEY);
if (isset($options['enable_social_media']) && $options['enable_social_media']) {
$this->share_on_social_media($options, $post_id, $post->post_title);
}
if (get_post_meta($post_id, '_aing_send_to_newsletter', true)) {
$this->add_to_email_newsletter($options, $post_id, $post->post_title);
}
}
}

wp_redirect( add_query_arg( 'aing_message', 'publish_success', admin_url( 'options-general.php?page=aing-review-dashboard' ) ) );
exit;
}

/**
* Handles deleting a single draft from the review dashboard.
*/
public function handle_delete_draft() {
$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;

// Check nonce and user permissions.
check_admin_referer( 'aing_delete_draft_nonce_' . $post_id, 'aing_delete_draft_nonce_field' );
if ( ! current_user_can( 'delete_posts' ) ) {
wp_die( 'You do not have sufficient permissions to delete posts.' );
}

if ( $post_id > 0 ) {
wp_delete_post( $post_id, true );
}

wp_redirect( add_query_arg( 'aing_message', 'delete_success', admin_url( 'options-general.php?page=aing-review-dashboard' ) ) );
exit;
}

/**
* Handles bulk actions (publish or delete) from the review dashboard.
*/
public function handle_bulk_action() {
check_admin_referer( 'aing_bulk_action_nonce', 'aing_bulk_action_nonce_field' );

if ( ! isset( $_POST['post_ids'] ) || empty( $_POST['post_ids'] ) ) {
wp_redirect( admin_url( 'options-general.php?page=aing-review-dashboard' ) );
exit;
}

$post_ids = array_map( 'absint', $_POST['post_ids'] );
$action = isset( $_POST['bulk-action'] ) ? sanitize_text_field( $_POST['bulk-action'] ) : -1;

if ( $action === 'publish' && current_user_can( 'publish_posts' ) ) {
foreach ( $post_ids as $post_id ) {
wp_update_post( array(
'ID' => $post_id,
'post_status' => 'publish',
) );
$post = get_post($post_id);
if ($post) {
$options = get_option(AING_OPTIONS_KEY);
if (isset($options['enable_social_media']) && $options['enable_social_media']) {
$this->share_on_social_media($options, $post_id, $post->post_title);
}
if (get_post_meta($post_id, '_aing_send_to_newsletter', true)) {
$this->add_to_email_newsletter($options, $post_id, $post->post_title);
}
}
}
wp_redirect( add_query_arg( 'aing_message', 'bulk_publish_success', admin_url( 'options-general.php?page=aing-review-dashboard' ) ) );
} elseif ( $action === 'delete' && current_user_can( 'delete_posts' ) ) {
foreach ( $post_ids as $post_id ) {
wp_delete_post( $post_id, true );
}
wp_redirect( add_query_arg( 'aing_message', 'bulk_delete_success', admin_url( 'options-general.php?page=aing-review-dashboard' ) ) );
}

exit;
}

/**
* Handles inline editing a draft from the review dashboard.
*/
public function handle_edit_draft() {
$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
$post_title = isset( $_POST['post_title'] ) ? sanitize_text_field( $_POST['post_title'] ) : '';
$post_content = isset( $_POST['post_content'] ) ? wp_kses_post( $_POST['post_content'] ) : '';

// Check nonce and user permissions.
check_admin_referer( 'aing_edit_draft_nonce_' . $post_id, 'aing_edit_draft_nonce_field' );
if ( ! current_user_can( 'edit_post', $post_id ) ) {
wp_die( 'You do not have sufficient permissions to edit this post.' );
}

if ( $post_id > 0 ) {
wp_update_post( array(
'ID' => $post_id,
'post_title' => $post_title,
'post_content' => $post_content,
) );
}

wp_redirect( add_query_arg( 'aing_message', 'edit_success', admin_url( 'options-general.php?page=aing-review-dashboard' ) ) );
exit;
}

/**
* Toggles the '_aing_send_to_newsletter' meta key for a post.
*/
public function handle_toggle_newsletter() {
$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;

// Check nonce and user permissions.
check_admin_referer( 'aing_toggle_newsletter_nonce_' . $post_id, 'aing_toggle_newsletter_nonce_field' );
if ( ! current_user_can( 'edit_post', $post_id ) ) {
wp_die( 'You do not have sufficient permissions to edit this post.' );
}

$current_value = get_post_meta($post_id, '_aing_send_to_newsletter', true);
if ($current_value) {
delete_post_meta($post_id, '_aing_send_to_newsletter');
} else {
add_post_meta($post_id, '_aing_send_to_newsletter', 1, true);
}

wp_safe_redirect( wp_get_referer() );
exit;
}

/**
* Shows admin notices for success or failure messages.
*/
public function show_admin_notices() {
if ( isset( $_GET['aing_message'] ) ) {
$message = sanitize_text_field( $_GET['aing_message'] );

if ( 'manual_trigger_success' === $message ) {
echo '<div class="notice notice-success is-dismissible"><p>Article generation process has been triggered! Please check the "Review Articles" dashboard for new drafts.</p></div>';
} elseif ( 'publish_success' === $message ) {
echo '<div class="notice notice-success is-dismissible"><p>Article published successfully!</p></div>';
} elseif ( 'delete_success' === $message ) {
echo '<div class="notice notice-success is-dismissible"><p>Article deleted successfully!</p></div>';
} elseif ( 'bulk_publish_success' === $message ) {
echo '<div class="notice notice-success is-dismissible"><p>Selected articles published successfully!</p></div>';
} elseif ( 'bulk_delete_success' === $message ) {
echo '<div class="notice notice-success is-dismissible"><p>Selected articles deleted successfully!</p></div>';
} elseif ( 'edit_success' === $message ) {
echo '<div class="notice notice-success is-dismissible"><p>Article saved successfully!</p></div>';
} elseif ( 'api_error' === $message ) {
echo '<div class="notice notice-error is-dismissible"><p>There was an error communicating with one of the APIs. Please check your API keys and the debug logs.</p></div>';
}
}
}

/**
* Handles exporting plugin settings.
*/
public function handle_settings_export() {
check_admin_referer('aing_export_settings_nonce', 'aing_export_settings_nonce_field');
if (!current_user_can('manage_options')) {
wp_die('You do not have sufficient permissions to perform this action.');
}

$options = get_option(AING_OPTIONS_KEY);
$filename = 'aing-settings-' . date('Y-m-d') . '.json';

header('Content-Type: application/json');
header('Content-Disposition: attachment; filename="' . $filename . '"');
echo json_encode($options, JSON_PRETTY_PRINT);
exit;
}

/**
* Handles importing plugin settings.
*/
public function handle_settings_import() {
check_admin_referer('aing_import_settings_nonce', 'aing_import_settings_nonce_field');
if (!current_user_can('manage_options')) {
wp_die('You do not have sufficient permissions to perform this action.');
}

if (!empty($_FILES['import_file']['tmp_name'])) {
$file_path = $_FILES['import_file']['tmp_name'];
$settings_json = file_get_contents($file_path);
$settings = json_decode($settings_json, true);

if (is_array($settings)) {
update_option(AING_OPTIONS_KEY, $settings);
wp_redirect(add_query_arg('aing_message', 'import_success', admin_url('options-general.php?page=ai-newspaper-generator')));
exit;
}
}

wp_redirect(add_query_arg('aing_message', 'import_fail', admin_url('options-general.php?page=ai-newspaper-generator')));
exit;
}

/**
* The main function to generate articles daily.
*/
public function generate_articles_daily() {
$options = get_option( AING_OPTIONS_KEY );
$article_count = isset( $options['article_count'] ) ? $options['article_count'] : 1;
$post_status = isset( $options['post_status'] ) ? $options['post_status'] : 'draft';
$post_categories = isset( $options['post_categories'] ) ? $options['post_categories'] : array(0);
$publish_interval = isset( $options['publish_interval'] ) ? $options['publish_interval'] : 60;
$article_word_count = isset($options['article_word_count']) ? $options['article_word_count'] : 500;
$ai_text_model = isset($options['ai_text_model']) ? $options['ai_text_model'] : 'gemini-1.5-pro-latest';
$enable_outbound_links = isset($options['enable_outbound_links']) ? (bool) $options['enable_outbound_links'] : false;

// 1. Fetch news articles.
$news_articles = $this->fetch_news_articles( $options );

if ( is_wp_error( $news_articles ) ) {
// Log the error and return.
error_log( 'AI Newspaper Generator Error: ' . $news_articles->get_error_message() );
return;
}

// 2. Loop through the fetched articles and generate posts.
$articles_to_generate = array_slice( $news_articles, 0, $article_count );
foreach ( $articles_to_generate as $index => $news_item ) {
$headline = $news_item['headline'];
$summary = $news_item['summary'];
$original_url = $news_item['original_url'];

// Optional: Rewrite headline with AI.
if ( isset( $options['rewrite_headline'] ) && $options['rewrite_headline'] ) {
$headline = $this->call_ai_api( $options, $options['headline_prompt'], array( 'headline' => $headline, 'summary' => $summary ), $ai_text_model );
$this->log_api_call('gemini_calls');
}

// Optional: Add custom writing style to the main prompt.
$prompt_prefix = '';
if ( 'custom' === $options['writing_style_preset'] && ! empty( $options['writing_style_custom'] ) ) {
$prompt_prefix = $options['writing_style_custom'] . ' ';
} else {
$prompts = array(
'professional' => 'Write this article in a professional and formal tone. ',
'casual' => 'Write this article in a casual, conversational, and friendly tone. ',
'humorous' => 'Write this article in a humorous and witty style. ',
'informative' => 'Write this article in an educational and highly informative manner. ',
);
if ( isset( $prompts[ $options['writing_style_preset'] ] ) ) {
$prompt_prefix = $prompts[ $options['writing_style_preset'] ];
}
}

// Generate AI summary if enabled
$ai_summary = '';
if ( isset($options['enable_ai_summary']) && $options['enable_ai_summary']) {
$summary_prompt = 'Generate a concise, 200-character summary of the article about {headline} and {summary}.';
$ai_summary = $this->call_ai_api($options, $summary_prompt, array('headline' => $headline, 'summary' => $summary), $ai_text_model);
$this->log_api_call('gemini_calls');
}

$article_prompt = str_replace(
array( '{headline}', '{summary}', '{word_count}' ),
array( $headline, $summary, $article_word_count ),
$options['prompt']
);
$article_content = $this->call_ai_api( $options, $prompt_prefix . $article_prompt, array(), $ai_text_model );
$this->log_api_call('gemini_calls');

// Check for errors from AI API.
if ( is_wp_error( $article_content ) ) {
error_log( 'AI Newspaper Generator Error: ' . $article_content->get_error_message() );
continue;
}

// Prepend AI summary to content if enabled
if ( !empty($ai_summary) ) {
$article_content = '<p><strong>Summary:</strong> ' . esc_html($ai_summary) . '</p>' . $article_content;
}

// Add outbound link to the article if enabled
if ($enable_outbound_links && !empty($original_url)) {
$article_content .= '<p>Read the original article here: <a href="' . esc_url($original_url) . '" target="_blank" rel="noopener noreferrer">' . esc_html($headline) . '</a></p>';
}

// Add internal links to the article content.
if ( isset($options['enable_internal_linking']) && $options['enable_internal_linking'] ) {
$article_content = $this->suggest_internal_links($article_content);
}

// Prepare post data.
$post_data = array(
'post_title' => wp_strip_all_tags( $headline ),
'post_content' => $article_content,
'post_status' => $post_status,
'post_category' => $post_categories,
'meta_input' => array(
'_aing_generated' => true,
'_aing_send_to_newsletter' => 0, // Default to unchecked
),
);

// Handle scheduling for future posts.
if ( 'future' === $post_status ) {
$time_to_publish = strtotime( 'today ' . $options['schedule_time'] . ' UTC' ) + ( $index * $publish_interval * 60 );
$post_data['post_date'] = date( 'Y-m-d H:i:s', $time_to_publish );
}

$post_id = wp_insert_post( $post_data );

if ( $post_id ) {
// Handle SEO metadata generation.
if ( isset( $options['enable_seo_tags'] ) && $options['enable_seo_tags'] ) {
$this->generate_seo_tags( $options, $post_id, $article_content );
}
if ( isset( $options['enable_meta_description'] ) && $options['enable_meta_description'] ) {
$this->generate_meta_description( $options, $post_id, $article_content );
}

// Handle featured image generation.
if ( isset( $options['generate_image'] ) && $options['generate_image'] ) {
$image_prompt = str_replace(
array( '{headline}', '{summary}' ),
array( $headline, $summary ),
$options['image_prompt']
);
$image_id = $this->call_image_api( $options, $image_prompt );
$this->log_api_call('image_calls');

if ( $image_id && ! is_wp_error( $image_id ) ) {
set_post_thumbnail( $post_id, $image_id );
}
}

// Handle TTS generation.
if ( isset( $options['enable_tts'] ) && $options['enable_tts'] ) {
$audio_url = $this->call_tts_api( $options, $article_content, $options['tts_voice'] );
$this->log_api_call('tts_calls');

if ( ! is_wp_error( $audio_url ) ) {
update_post_meta( $post_id, '_aing_tts_audio_url', esc_url_raw( $audio_url ) );
}
}
}
}
}

/**
* Helper function to fetch news from a chosen API provider.
*
* @param array $options Plugin options.
* @return array|WP_Error An array of news items or a WP_Error object on failure.
*/
private function fetch_news_articles( $options ) {
$provider = isset( $options['api_provider'] ) ? $options['api_provider'] : 'newsapi';
$api_key = isset( $options['news_api_key'] ) ? $options['news_api_key'] : '';
$news_topics = isset( $options['news_topics'] ) ? array_map( 'trim', explode( ',', $options['news_topics'] ) ) : array();
$news_sources = isset( $options['news_sources'] ) ? array_map( 'trim', explode( ',', $options['news_sources'] ) ) : array();
$date_filter_option = isset( $options['date_filter_option'] ) ? $options['date_filter_option'] : 'none';
$sentiment_filter = isset( $options['sentiment_filter'] ) ? $options['sentiment_filter'] : 'any';
$required_words = isset( $options['required_words'] ) ? array_map( 'trim', explode( ',', $options['required_words'] ) ) : array();
$excluded_words = isset( $options['excluded_words'] ) ? array_map( 'trim', explode( ',', $options['excluded_words'] ) ) : array();

// A proper date range and sentiment filtering implementation would be added here
// based on the specific capabilities of each news API.

if ( empty( $api_key ) && 'custom' !== $provider ) {
return new WP_Error( 'api_key_missing', 'News API key is not set.' );
}

$url = '';
$args = array(
'headers' => array(),
);
$json_path_title = '';
$json_path_summary = '';

switch ( $provider ) {
case 'newsapi':
$url = 'https://newsapi.org/v2/top-headlines';
$args['headers']['X-Api-Key'] = $api_key;
$args['country'] = $options['news_country'];
$args['language'] = $options['news_language'];
if ( ! empty( $news_topics ) ) {
$args['q'] = implode( ' OR ', $news_topics );
}
if ( ! empty( $news_sources ) ) {
$args['sources'] = implode( ',', $news_sources );
}
// TODO: Add date filtering parameters for newsapi.org
// e.g., $args['from'] = 'YYYY-MM-DD', $args['to'] = 'YYYY-MM-DD'
// TODO: Add required/excluded word filters for newsapi.org
$json_path_title = 'articles.0.title';
$json_path_summary = 'articles.0.description';
break;
case 'gnews':
$url = 'https://gnews.io/api/v4/top-headlines';
$args['token'] = $api_key;
$args['lang'] = $options['news_language'];
$args['country'] = $options['news_country'];
if ( ! empty( $news_topics ) ) {
$args['q'] = implode( ' OR ', $news_topics );
}
// TODO: Add date and source filtering for gnews.io
// TODO: Add required/excluded word filters for gnews.io
$json_path_title = 'articles.0.title';
$json_path_summary = 'articles.0.description';
break;
case 'mediastack':
$url = 'http://api.mediastack.com/v1/news';
$args['access_key'] = $api_key;
$args['countries'] = $options['news_country'];
$args['languages'] = $options['news_language'];
if ( ! empty( $news_topics ) ) {
$args['keywords'] = implode( ',', $news_topics );
}
// TODO: Add date and source filtering for mediastack
// TODO: Add required/excluded word filters for mediastack
$json_path_title = 'data.0.title';
$json_path_summary = 'data.0.description';
break;
case 'guardian':
$url = 'https://content.guardianapis.com/search';
$args['api-key'] = $api_key;
if ( ! empty( $news_topics ) ) {
$args['q'] = implode( ' AND ', $news_topics );
}
$args['show-fields'] = 'headline,trailText';
// TODO: Add date filtering for theguardian.com
// TODO: Add required/excluded word filters for theguardian.com
$json_path_title = 'response.results.0.fields.headline';
$json_path_summary = 'response.results.0.fields.trailText';
break;
case 'custom':
$url = $options['news_api_url_custom'];
$json_path_title = $options['news_api_title_path'];
$json_path_summary = $options['news_api_summary_path'];
if ( empty( $url ) || empty( $json_path_title ) || empty( $json_path_summary ) ) {
return new WP_Error( 'custom_api_config_missing', 'Custom API URL or JSON paths are not set.' );
}
// TODO: No standard way to apply filters to a custom URL, a note on this in the UI might be good.
break;
default:
return new WP_Error( 'invalid_provider', 'Invalid news API provider selected.' );
}

$this->log_api_call('news_calls');
// This is just a placeholder, a proper API call would be here.
// For the purpose of this code, we'll return mock data.
return array(
array( 'headline' => 'Mock Headline 1', 'summary' => 'This is a mock summary for article 1.', 'original_url' => 'https://example.com/mock-article-1'),
array( 'headline' => 'Mock Headline 2', 'summary' => 'This is a mock summary for article 2.', 'original_url' => 'https://example.com/mock-article-2'),
array( 'headline' => 'Mock Headline 3', 'summary' => 'This is a mock summary for article 3.', 'original_url' => 'https://example.com/mock-article-3'),
);
}

/**
* Helper function to call the AI API for text generation.
*
* @param array $options Plugin options.
* @param string $prompt The prompt to send to the AI.
* @param array $replacements An array of placeholders to replace in the prompt (e.g., 'headline', 'summary').
* @return string|WP_Error Generated text or a WP_Error object.
*/
private function call_ai_api( $options, $prompt, $replacements = array(), $model = 'gemini-1.5-pro-latest' ) {
// Mock AI response for demonstration.
$final_prompt = str_replace(
array_keys($replacements),
array_values($replacements),
$prompt
);
return 'This is a mock generated text based on the prompt: ' . esc_html( $final_prompt ) . ' using model ' . esc_html($model) . '.';

// TODO: Implement real API call logic using the Gemini or other AI API.
}

/**
* Helper function to generate a short summary for social and email.
*
* @param array $options Plugin options.
* @param array $replacements An array of placeholders to replace in the prompt.
* @return string|WP_Error Generated summary or a WP_Error object.
*/
private function generate_short_summary($options, $replacements) {
$prompt = 'Generate a short, 200-character summary of the article content for use in a social media post or email newsletter. Content: {content}';
$summary = $this->call_ai_api($options, $prompt, $replacements);
$this->log_api_call('gemini_calls');
return $summary;
}

/**
* Helper function to generate and set SEO tags for a post.
*
* @param array $options Plugin options.
* @param int $post_id The ID of the post.
* @param string $content The content of the article.
* @return bool True on success, false on failure.
*/
private function generate_seo_tags($options, $post_id, $content) {
$prompt = str_replace('{content}', $content, $options['seo_tags_prompt']);
$tags_string = $this->call_ai_api($options, $prompt);
$this->log_api_call('gemini_calls');

if (is_wp_error($tags_string)) {
error_log('AI SEO Tags Error: ' . $tags_string->get_error_message());
return false;
}

$tags_array = array_map('trim', explode(',', $tags_string));
wp_set_post_tags($post_id, $tags_array, false);
return true;
}

/**
* Helper function to generate and set a meta description for a post.
*
* @param array $options Plugin options.
* @param int $post_id The ID of the post.
* @param string $content The content of the article.
* @return bool True on success, false on failure.
*/
private function generate_meta_description($options, $post_id, $content) {
$prompt = str_replace('{content}', $content, $options['meta_description_prompt']);
$meta_description = $this->call_ai_api($options, $prompt);
$this->log_api_call('gemini_calls');

if (is_wp_error($meta_description)) {
error_log('AI Meta Description Error: ' . $meta_description->get_error_message());
return false;
}

// A proper implementation would update a meta field for an SEO plugin like Yoast or Rank Math.
// For now, we'll just add a custom field.
update_post_meta($post_id, '_ai_meta_description', sanitize_text_field($meta_description));
return true;
}

/**
* Helper function to call the image generation API.
*
* @param array $options Plugin options.
* @param string $prompt The image generation prompt.
* @return int|WP_Error Attachment ID or a WP_Error object.
*/
private function call_image_api( $options, $prompt ) {
// Mock image generation.
// In a real scenario, you'd call the API, get a base64 or URL, download it, and create an attachment.
$image_url = 'https://placehold.co/1200x600/E5E7EB/1F2937?text=AI+Generated+Image';
$upload_dir = wp_upload_dir();
$image_data = file_get_contents( $image_url );
$filename = basename( $image_url );

if ( wp_mkdir_p( $upload_dir['path'] ) ) {
$file = $upload_dir['path'] . '/' . $filename;
} else {
$file = $upload_dir['basedir'] . '/' . $filename;
}

file_put_contents( $file, $image_data );
$wp_filetype = wp_check_filetype( $filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name( $filename ),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $file );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
wp_update_attachment_metadata( $attach_id, $attach_data );

return $attach_id;
}

/**
* Helper function to call the TTS API.
*
* @param array $options Plugin options.
* @param string $text The text to convert to speech.
* @param string $voice The voice to use.
* @return string|WP_Error URL to the audio file or a WP_Error object.
*/
private function call_tts_api( $options, $text, $voice ) {
// Mock TTS generation.
// In a real scenario, you'd call the API, get the audio data, and save it as an attachment.
return 'https://example.com/mock-audio.mp3';
}

/**
* Helper function to add internal links to a post's content.
*
* @param string $content The content of the article.
* @return string The content with internal links added.
*/
private function suggest_internal_links($content) {
// TODO: Implement the actual logic for finding relevant posts and inserting links.
// This is a placeholder for the functionality.
return $content;
}

/**
* Shares the article on social media.
* @param array $options Plugin options.
* @param int $post_id The ID of the post.
* @param string $headline The article headline.
*/
private function share_on_social_media($options, $post_id, $headline) {
$post_url = get_permalink($post_id);
$post_content = get_post_field('post_content', $post_id);
$post_tags = wp_get_post_tags($post_id, array('fields' => 'names'));
$tags_string = !empty($post_tags) ? '#' . implode(' #', $post_tags) : '';

$summary = $this->generate_short_summary($options, array('content' => $post_content));

$prompt = str_replace(
array('{title}', '{summary}', '{url}', '{tags}'),
array($headline, $summary, $post_url, $tags_string),
$options['social_media_prompt']
);

error_log('AING: Generated social media post: ' . $prompt);

// TODO: Implement real social media API calls for each selected platform.
}

/**
* Adds the article to a newsletter draft.
* @param array $options Plugin options.
* @param int $post_id The ID of the post.
* @param string $headline The article headline.
*/
private function add_to_email_newsletter($options, $post_id, $headline) {
$post_url = get_permalink($post_id);
$post_content = get_post_field('post_content', $post_id);
$summary = $this->generate_short_summary($options, array('content' => $post_content));

$subject = str_replace(
array('{title}'),
array($headline),
$options['email_subject_prompt']
);
$body = str_replace(
array('{title}', '{summary}', '{url}'),
array($headline, $summary, $post_url),
$options['email_body_prompt']
);

error_log('AING: Generated email newsletter draft. Subject: ' . $subject . ' | Body: ' . $body);

// TODO: Implement real email marketing API calls (e.g., Mailchimp, etc.).
}

/**
* Increments the API call counter for a specific service.
* @param string $service The service name (e.g., 'gemini_calls', 'image_calls').
*/
private function log_api_call($service) {
$stats = get_option(AING_API_STATS_KEY, array());
if (!isset($stats[$service])) {
$stats[$service] = 0;
}
$stats[$service]++;
update_option(AING_API_STATS_KEY, $stats);
}
}

// Instantiate the main plugin class.
new NewspaperArticleGeneratorPlugin();

https://www.cphtimes.com/microplastics-soil/ en 2025-08-09T17:10:58+00:00 https://www.cphtimes.com/discovery-fossil-reptile/ en 2025-08-09T17:05:30+00:00 https://www.cphtimes.com/trump_announces_summit_with_putin/ en 2025-08-09T16:58:04+00:00 https://www.cphtimes.com/mexico_president_firmly_rejects/ en 2025-08-09T16:38:22+00:00 https://www.cphtimes.com/ukranians_favor_negotiation/ en 2025-08-09T16:22:55+00:00