<?php
/**
 * This file is part of the Wisewand WordPress plugin.
 *
 * @package Wisewand
 * @since 1.0.0
 * @license GPL-2.0-or-later
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
namespace Wisewand\Admin;

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

use Wisewand\Utils\Options;
use Wisewand\Logging\Logger;
use Wisewand\Utils\Wisewand_API_Client;
use Wisewand\Utils\Publish_Mode_Migrator;
use Wisewand\RSS\RSS_Feed_Manager;
use Wisewand\RSS\RSS_Article_Manager;
use Wisewand\RSS\RSS_Sync_Engine;
use Wisewand\Content\Content_Manager;
use Wisewand\Admin\Traits\AJAX_Security;

// phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_error_log -- error_log() is only used within WP_DEBUG conditionals for debugging

class Wisewand_RSS_Page {

	use AJAX_Security;

	private $options;
	private $logger;
	private $api_client;
	private $feed_manager;
	private $article_manager;
	private $sync_engine;

	public function __construct( Options $options, Logger $logger ) {
		$this->options = $options;
		$this->logger  = $logger;

		// Initialize API client with API key STRING (not Options object!)
		$api_key          = $options->get( 'wisewand_api_key' );
		$this->api_client = new Wisewand_API_Client( $api_key, $logger );

		// Initialize Repository
		$rss_repository = new \Wisewand\Repositories\RSS_Repository();

		// Initialize RSS managers with Repository injection
		$this->feed_manager    = new RSS_Feed_Manager( $logger, $rss_repository );
		$this->article_manager = new RSS_Article_Manager( $logger, $rss_repository );

		// Note: sync_engine is lazy-loaded when first needed (see get_sync_engine method)
		// This avoids initialization order issues with Content_Manager
	}

	/**
	 * Enqueue RSS page assets
	 */
	private function enqueue_assets() {
		wp_enqueue_style(
			'wisewand-rss-admin',
			WISEWAND_PLUGIN_URL . 'assets/css/admin/wisewand-rss-admin.css',
			array(),
			WISEWAND_PLUGIN_VERSION
		);

		wp_enqueue_script(
			'wisewand-rss-admin',
			WISEWAND_PLUGIN_URL . 'assets/js/admin/wisewand-rss-admin.js',
			array( 'jquery' ),
			WISEWAND_PLUGIN_VERSION,
			true
		);

		wp_localize_script(
			'wisewand-rss-admin',
			'wisewandRSS',
			array(
				'ajaxUrl'                 => admin_url( 'admin-ajax.php' ),
				'nonce'                   => wp_create_nonce( 'wisewand_rss' ),
				'isWPMLActive'            => $this->options->is_wpml_active(),
				'globalPublishMode'       => $this->feed_manager->get_global_publish_mode(),
				'publishModeLabels'       => array(
					'global'   => __( 'Use Global Default', 'wisewand-ai-content-writer-seo-content-generator' ),
					'schedule' => __( 'Schedule for Later', 'wisewand-ai-content-writer-seo-content-generator' ),
					'publish'  => __( 'Publish Immediately', 'wisewand-ai-content-writer-seo-content-generator' ),
					'draft'    => __( 'Save as Draft', 'wisewand-ai-content-writer-seo-content-generator' ),
				),
				'publishModeHelp'         => __( 'How articles from this feed should be published', 'wisewand-ai-content-writer-seo-content-generator' ),
				'publishModeGlobalPrefix' => __( 'Using global default', 'wisewand-ai-content-writer-seo-content-generator' ),
				'globalDefaults'          => array(
					'auto_import'          => $this->options->get( 'wisewand_rss_default_auto_import', true ),
					'import_frequency'     => $this->options->get( 'wisewand_rss_default_import_frequency', 'every_6_hours' ),
					'max_articles'         => $this->options->get( 'wisewand_rss_default_max_articles', 5 ),
					'publish_mode'         => Publish_Mode_Migrator::get_publish_mode_with_fallback( 'wisewand_rss_default_publish_mode', 'draft' ),
					'target_author'        => $this->options->get( 'wisewand_rss_default_target_author', get_current_user_id() ),
					'ai_category_matching' => $this->options->get( 'wisewand_rss_default_ai_category_matching', false ),
				),
			)
		);
	}

	/**
	 * Get or create sync engine (lazy loading)
	 * Prevents initialization order issues
	 *
	 * @return RSS_Sync_Engine|null
	 */
	private function get_sync_engine() {
		if ( ! $this->sync_engine ) {
			try {
				$plugin = \Wisewand\Core\Plugin::instance();

				if ( ! $plugin ) {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Plugin instance not available' );
					}
					return null;
				}

				$content_manager = $plugin->get_content_manager();

				if ( ! $content_manager ) {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Content Manager not available yet' );
					}
					return null;
				}

				// Initialize Calendar Entry Manager for RSS calendar integration
				if ( ! class_exists( 'Wisewand\\Utils\\Wisewand_Payload_Builder' ) ) {
					require_once WISEWAND_PLUGIN_DIR . 'includes/Utils/Wisewand_Payload_Builder.php';
				}
				if ( ! class_exists( 'Wisewand\\Calendar\\Calendar_Entry_Manager' ) ) {
					require_once WISEWAND_PLUGIN_DIR . 'includes/Calendar/Calendar_Entry_Manager.php';
				}

				$payload_builder  = new \Wisewand\Utils\Wisewand_Payload_Builder( $this->options, $this->logger );
				$calendar_manager = new \Wisewand\Calendar\Calendar_Entry_Manager( $this->options, $this->logger, $payload_builder );

				// Initialize RSS Calendar Bridge for calendar integration
				if ( ! class_exists( 'Wisewand\\RSS\\RSS_Calendar_Bridge' ) ) {
					require_once WISEWAND_PLUGIN_DIR . 'includes/RSS/RSS_Calendar_Bridge.php';
				}

				$calendar_bridge = new \Wisewand\RSS\RSS_Calendar_Bridge(
					$calendar_manager,
					$this->article_manager,
					$this->feed_manager,
					$this->logger
				);

				// Initialize sync engine with all required dependencies
				$this->sync_engine = new RSS_Sync_Engine(
					$this->api_client,
					$this->feed_manager,
					$this->article_manager,
					$content_manager,
					$calendar_manager,
					$calendar_bridge,
					$this->logger,
					$this->options
				);
			} catch ( \Exception $e ) {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( 'RSS_PAGE: Failed to create sync_engine: ' . $e->getMessage() );
				}
				return null;
			} catch ( \Error $e ) {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( 'RSS_PAGE: Fatal error creating sync_engine: ' . $e->getMessage() );
				}
				return null;
			}
		}

		return $this->sync_engine;
	}

	/**
	 * Render main RSS Feeds page
	 */
	public function render_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wisewand-ai-content-writer-seo-content-generator' ) );
		}

		$this->enqueue_assets();

		?>
		<div class="wrap wisewand-rss-feeds-page">
			<h1><?php esc_html_e( '📡 RSS Feeds', 'wisewand-ai-content-writer-seo-content-generator' ); ?></h1>

			<div class="wisewand-notice-info" style="margin: 20px 0; padding: 16px; background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(0, 188, 212, 0.1) 100%); border-left: 4px solid #3b82f6; border-radius: 8px;">
				<p style="margin: 0; color: #1f2937; font-size: 14px;">
					<strong>💡 <?php esc_html_e( 'How it works:', 'wisewand-ai-content-writer-seo-content-generator' ); ?></strong>
					<?php esc_html_e( 'Feeds are created and managed in Wisewand. WordPress automatically imports articles using your enhanced import pipeline (images, AI metadata, categories).', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
				</p>
				<p style="margin: 8px 0 0 0;">
					<a href="https://app.wisewand.ai/feeds" target="_blank" rel="noopener noreferrer" class="button button-primary" style="margin-top: 8px;">
						🚀 <?php esc_html_e( 'Create New Feed in Wisewand', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
					</a>
					<button type="button" id="refresh-feeds" class="button" style="margin-left: 8px;">
						🔄 <?php esc_html_e( 'Refresh Feeds', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
					</button>
					<button type="button" id="test-rss-connection" class="button" style="margin-left: 8px;">
						🔍 <?php esc_html_e( 'Test Connection', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
					</button>
					<button type="button" id="sync-all-feeds" class="button button-primary" style="margin-left: 8px;">
						⚡ <?php esc_html_e( 'Sync All Feeds', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
					</button>
					<button type="button" id="cleanup-rss-data" class="button" style="margin-left: 8px; background: #dc2626; color: white; border-color: #dc2626;">
						🗑️ <?php esc_html_e( 'Cleanup RSS Data', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
					</button>
				</p>
			</div>


			<!-- RSS v2.0: Auto-Import Status Widget -->
			<div id="auto-import-status-widget" style="margin: 20px 0; padding: 20px; background: linear-gradient(135deg, #10b981 0%, #3b82f6 100%); border-radius: 8px; color: white; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
				<h3 style="margin: 0 0 16px 0; color: white;">🤖 Auto-Import Status</h3>
				<div id="widget-content" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px;">
					<div>
						<div style="font-size: 32px; font-weight: 700;" id="activated-feeds-count">-</div>
						<div style="opacity: 0.9; font-size: 14px;">Feeds Activated</div>
					</div>
					<div>
						<div style="font-size: 32px; font-weight: 700;" id="next-sync-time">-</div>
						<div style="opacity: 0.9; font-size: 14px;">Next Sync</div>
					</div>
					<div>
						<div style="font-size: 32px; font-weight: 700;" id="last-24h-imported">-</div>
						<div style="opacity: 0.9; font-size: 14px;">Last 24h Imported</div>
					</div>
				</div>
				<button type="button" id="open-global-publication-settings" class="button" style="margin-top: 16px; background: rgba(255,255,255,0.2); border: none; color: white; cursor: pointer;">
					⚙️ <?php esc_html_e( 'Global Publication Settings', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
				</button>
			</div>

			<div id="diagnostic-info" style="margin-bottom: 20px;"></div>

			<!-- RSS v2.0: Bulk Actions Bar -->
			<div id="bulk-actions-bar" style="display: none; padding: 12px 16px; background: #f0f9ff; border-left: 4px solid #3b82f6; margin-bottom: 16px; border-radius: 4px;">
				<strong id="selected-count" style="color: #1e40af; margin-right: 16px;">0 feeds selected</strong>
				<button type="button" id="bulk-activate-feeds" class="button" style="margin-right: 8px;">
					⚡ <?php esc_html_e( 'Activate Selected', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
				</button>
				<button type="button" id="bulk-deactivate-feeds" class="button" style="margin-right: 8px;">
					⏸️ <?php esc_html_e( 'Deactivate Selected', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
				</button>
				<button type="button" id="bulk-configure-feeds" class="button">
					⚙️ <?php esc_html_e( 'Bulk Configure', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
				</button>
				<button type="button" id="bulk-sync-selected" class="button button-primary" style="margin-left: 8px;">
					🔄 <?php esc_html_e( 'Sync Selected', 'wisewand-ai-content-writer-seo-content-generator' ); ?>
				</button>
			</div>

			<div id="feeds-container">
				<div class="loading-spinner" style="text-align: center; padding: 60px;">
					<div class="spinner is-active" style="float: none; margin: 0 auto;"></div>
					<p><?php esc_html_e( 'Loading feeds from Wisewand...', 'wisewand-ai-content-writer-seo-content-generator' ); ?></p>
				</div>
			</div>
		</div>
		<?php
	}

	// AJAX Handlers

	/**
	 * AJAX handler: Test RSS connection (diagnostic endpoint)
	 */
	public function ajax_test_rss_connection() {
		$this->verify_ajax_request( 'wisewand_rss', 'manage_options' );

		wp_send_json_success(
			array(
				'message'            => 'RSS AJAX handler is working',
				'api_key_configured' => Wisewand_API_Client::is_api_key_configured(),
				'classes_loaded'     => array(
					'RSS_Feed_Manager'    => class_exists( 'Wisewand\\RSS\\RSS_Feed_Manager' ),
					'RSS_Article_Manager' => class_exists( 'Wisewand\\RSS\\RSS_Article_Manager' ),
					'RSS_Sync_Engine'     => class_exists( 'Wisewand\\RSS\\RSS_Sync_Engine' ),
					'Content_Manager'     => class_exists( 'Wisewand\\Content\\Content_Manager' ),
					'Wisewand_API_Client' => class_exists( 'Wisewand\\Utils\\Wisewand_API_Client' ),
				),
			)
		);
	}

	public function ajax_list_feeds() {
		// CRITICAL: Prevent ANY output from corrupting JSON response
		// Clear any previous output (theme/plugin notices)
		if ( ob_get_length() ) {
			ob_clean();
		}

		// Start fresh output buffer
		ob_start();

		// Suppress error display temporarily for clean JSON

		$this->verify_ajax_request( 'wisewand_rss' );

		try {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: ajax_list_feeds called' );
			}

			// Check if API key is configured
			if ( ! Wisewand_API_Client::is_api_key_configured() ) {
				throw new \Exception( __( 'Wisewand API key not configured. Please configure it in Settings → API Configuration.', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: API key configured, calling list_feeds()' );
			}

			// Get default project ID for filtering (RSS v2.0)
	
		// Retrieve Configured Project ID (Robust Fallback logic)
		$default_project = $this->options->get( 'wisewand_default_project_id' );
		if ( empty( $default_project ) ) {
			$default_project = $this->options->get( 'wisewand_project_id' );
		}

		// Ensure we pass a string, not null
		$default_project = (string) $default_project;
		
		/**
		 * Filter: Should we strictly hide feeds from other projects?
		 * Default: true (Hide unrelated feeds).
		 */
		$strict_project_isolation = apply_filters( 'wisewand_rss_strict_project_isolation', true );

		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			// error_log( sprintf( 'RSS_PAGE: Default project ID resolved to: "%s"', $default_project ) );
		}	

			// Fetch ALL feeds from Wisewand API (no projectId filter)
			// IMPORTANT: project_id is nested in config.project_id, not at root level!
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: Fetching all feeds from API (skip=0, take=50)' );
			}

			// Use centralized API client for security and consistency
			$all_feeds_response = $this->api_client->list_feeds( 0, 50 );

			if ( is_wp_error( $all_feeds_response ) ) {
				throw new \Exception( 'API request failed: ' . $all_feeds_response->get_error_message() );
			}

			if ( ! $all_feeds_response || ! isset( $all_feeds_response['items'] ) ) {
				throw new \Exception( 'Invalid API response format' );
			}

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: Received ' . count( $all_feeds_response['items'] ) . ' total feeds from API' );
			}

			// Filter feeds in PHP based on config.project_id (RSS v2.0)
			// CRITICAL FIX: project_id is at feed.config.project_id, not feed.project_id!
			$all_wisewand_feeds = array();

			foreach ( $all_feeds_response['items'] as $feed ) {
				// Extract project_id from config (nested location!)
				$feed_project_id = isset( $feed['config']['project_id'] ) ? $feed['config']['project_id'] : null;

				// STRICT PROJECT ENFORCEMENT (RSS v2.1)
				// Only allow feeds that explicitly match the configured project ID.
				// Unassigned feeds or mismatched feeds are completely hidden.

				if ( ! empty( $default_project ) && $feed_project_id === $default_project ) {
					// Project feed matching our configured project
					$feed['_feed_type']   = 'project';
					$all_wisewand_feeds[] = $feed;

					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						// error_log( 'RSS_PAGE: ➜ Marked as PROJECT (matches default project)' ); 
					}
				} elseif ( empty( $default_project ) ) {
					// ...
					$feed['_feed_type']   = 'project';
					$all_wisewand_feeds[] = $feed;
				} else {
					// Feed belongs to different project OR is unassigned - skip it
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( sprintf( 
							'RSS_PAGE: ➜ SKIPPED Feed "%s". Feed Project: "%s" != Config Project: "%s"',
							$feed['title'] ?? 'Unknown',
							$feed_project_id ?: 'NULL',
							$default_project
						) );
					}
				}
			}

			if ( empty( $all_wisewand_feeds ) ) {
				throw new \Exception( 'No feeds found matching your project. Check your default project ID in Settings.' );
			}

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: After filtering: ' . count( $all_wisewand_feeds ) . ' feeds match project or are unassigned' );
			}

			$feeds = array();
			foreach ( $all_wisewand_feeds as $index => $wisewand_feed ) {
				try {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Processing feed ' . ( $index + 1 ) . ': ' . ( $wisewand_feed['title'] ?? 'unknown' ) );
					}

					$feed_id = $this->feed_manager->sync_feed_from_wisewand( $wisewand_feed );

					if ( is_wp_error( $feed_id ) ) {
						if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
							error_log( 'RSS_PAGE: Failed to sync feed: ' . $feed_id->get_error_message() );
						}
						continue; // Skip this feed
					}

					$local_feed = $this->feed_manager->get_feed( $feed_id );

					if ( ! $local_feed ) {
						if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
							error_log( 'RSS_PAGE: Could not retrieve feed from database' );
						}
						continue;
					}

					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Feed synced, database ID: ' . $feed_id );
					}

					// Get article counts from Wisewand API
					$wisewand_feed_id = $local_feed['wisewand_feed_id'];
					$feed_type        = $local_feed['feed_type'] ?? 'articles';

					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Fetching article count for feed ' . $wisewand_feed_id . ' (type: ' . $feed_type . ')' );
					}

					// Use API Client to fetch counts based on feed type
					if ( $feed_type === 'discoverarticles' ) {
						$count_result = $this->api_client->get_feed_discoverarticles( $wisewand_feed_id, 0, 1 );
					} else {
						$count_result = $this->api_client->get_feed_articles( $wisewand_feed_id, 0, 1 );
					}

					if ( ! is_wp_error( $count_result ) && isset( $count_result['count'] ) ) {
						$local_feed['total_articles'] = (int) $count_result['count'];

						if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
							error_log( 'RSS_PAGE: Count response for feed ' . $wisewand_feed_id . ': count=' . $count_result['count'] );
						}

						// Quick filter for success articles
						if ( $feed_type === 'discoverarticles' ) {
							$success_result = $this->api_client->get_feed_discoverarticles(
								$wisewand_feed_id,
								0,
								1,
								array( 'status' => 'success' )
							);
						} else {
							$success_result = $this->api_client->get_feed_articles(
								$wisewand_feed_id,
								0,
								1,
								array( 'status' => 'success' )
							);
						}

						if ( ! is_wp_error( $success_result ) && isset( $success_result['count'] ) ) {
							$local_feed['articles_success'] = (int) $success_result['count'];
						}
					}

					// Get imported count from local database
					$imported_stats                  = $this->article_manager->get_feed_statistics( $feed_id );
					$local_feed['articles_imported'] = $imported_stats['imported'] ?? 0;

					// Sync info
					$local_feed['sync_status']    = $local_feed['auto_import_enabled'] ? 'enabled' : 'disabled';
					$local_feed['last_sync_text'] = $local_feed['last_sync_at'] ? human_time_diff( strtotime( $local_feed['last_sync_at'] ) ) . ' ago' : 'Never';
					
					// DEBUG TIMEZONE LOGIC
					$next_sync_ts = $local_feed['next_sync_at'] ? strtotime( $local_feed['next_sync_at'] ) : 0;
					$now_ts       = time();
					$diff         = $next_sync_ts - $now_ts;
					
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG && $local_feed['next_sync_at'] ) {
						error_log( sprintf( 
							'RSS_PAGE: Feed "%s" NextSyncDB: "%s" | TS: %d | Now: %d | Diff: %ds (%.1fh)', 
							$local_feed['feed_name'], 
							$local_feed['next_sync_at'], 
							$next_sync_ts, 
							$now_ts, 
							$diff,
							$diff / 3600
						) );
					}

					$local_feed['next_sync_text'] = $local_feed['next_sync_at'] ? 'in ' . human_time_diff( $now_ts, $next_sync_ts ) : 'Not scheduled';

					// Add boolean is_active for JavaScript (JavaScript checks this field)
					// Debug: Check what wisewand_status actually contains
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Feed ' . $local_feed['feed_name'] . ' - wisewand_status: "' . $local_feed['wisewand_status'] . '"' );
					}

					$local_feed['is_active'] = ( $local_feed['wisewand_status'] === 'active' );

					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Feed ' . $local_feed['feed_name'] . ' - is_active: ' . ( $local_feed['is_active'] ? 'true' : 'false' ) );
					}

					// Preserve feed type marker for UI separation (RSS v2.0)
					$local_feed['feed_type'] = $wisewand_feed['_feed_type'] ?? 'project';

                    // Fix for JS timezone calculation: Provide unambiguous UNIX timestamp
                    if ( ! empty( $local_feed['next_sync_at'] ) ) {
                        $local_feed['next_sync_ts'] = strtotime( $local_feed['next_sync_at'] );
                    }

					$feeds[] = $local_feed;

				} catch ( \Exception $e ) {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Exception processing feed ' . ( $index + 1 ) . ': ' . $e->getMessage() );
					}
					// Skip this feed and continue with next
					continue;
				} catch ( \Error $e ) {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_PAGE: Fatal error processing feed ' . ( $index + 1 ) . ': ' . $e->getMessage() );
					}
					// Skip this feed and continue with next
					continue;
				}
			}

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: Returning ' . count( $feeds ) . ' feeds to frontend' );
			}

			// Sanitize feeds array for JSON encoding (remove any object references)
			$feeds_clean = array();
			foreach ( $feeds as $feed ) {
				$feed_clean = array();
				foreach ( $feed as $key => $value ) {
					// Skip if value is an object (can't JSON encode)
					if ( is_object( $value ) ) {
						if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
							error_log( "RSS_PAGE: Skipping object in feed data: key={$key}, class=" . get_class( $value ) );
						}
						continue;
					}
					$feed_clean[ $key ] = $value;
				}
				$feeds_clean[] = $feed_clean;
			}

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: Cleaned feeds for JSON: ' . count( $feeds_clean ) . ' feeds' );
			}

			// Separate project feeds from unassigned feeds (RSS v2.0)
			$project_feeds    = array();
			$unassigned_feeds = array();

			foreach ( $feeds_clean as $feed ) {
				if ( isset( $feed['feed_type'] ) && $feed['feed_type'] === 'unassigned' ) {
					$unassigned_feeds[] = $feed;
				} else {
					$project_feeds[] = $feed;
				}
			}

			// Restore error reporting

			ob_clean(); // Clear any notices/warnings before JSON
			wp_send_json_success(
				array(
					'feeds'            => $project_feeds,
					'unassigned_feeds' => $unassigned_feeds,
					'project_id'       => $default_project,
				)
			);

		} catch ( \Exception $e ) {
			$this->logger->error(
				'RSS ajax_list_feeds failed',
				array(
					'error' => $e->getMessage(),
					'trace' => $e->getTraceAsString(),
				)
			);

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: Exception in ajax_list_feeds: ' . $e->getMessage() );
				error_log( 'RSS_PAGE: Stack trace: ' . $e->getTraceAsString() );
			}

			// Restore error reporting

			ob_clean(); // Clear any notices/warnings before JSON
			wp_send_json_error(
				array(
					'message'    => esc_html( $e->getMessage() ),
					'debug_info' => WP_DEBUG ? $e->getTraceAsString() : null,
				)
			);
		} catch ( \Error $e ) {
			$this->logger->error(
				'RSS ajax_list_feeds fatal error',
				array(
					'error' => $e->getMessage(),
					'type'  => get_class( $e ),
				)
			);

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: Fatal error in ajax_list_feeds: ' . $e->getMessage() );
			}

			// Restore error reporting

			ob_clean(); // Clear any notices/warnings before JSON
			wp_send_json_error(
				array(
					'message'    => __( 'Critical server error. Check PHP error logs for details.', 'wisewand-ai-content-writer-seo-content-generator' ),
					'error_type' => get_class( $e ),
				)
			);
		}
	}

	public function ajax_sync_feed() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		$feed_id = absint( $_POST['feed_id'] ?? 0 );
		if ( ! $feed_id ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'Invalid feed ID', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		try {
			$sync_engine = $this->get_sync_engine();
			if ( ! $sync_engine ) {
				throw new \Exception( __( 'Sync engine not available', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			$result = $sync_engine->sync_feed( $feed_id, true );

			if ( is_wp_error( $result ) ) {
				throw new \Exception( $result->get_error_message() );
			}

			// v1.2.0: Include sync logs for live UI display.
			$sync_logs = method_exists( $sync_engine, 'get_sync_logs' ) ? $sync_engine->get_sync_logs() : array();

			// Prepare response with logs.
			$response = array_merge(
				$result,
				array( 'logs' => $sync_logs )
			);

			ob_clean();
			wp_send_json_success( $response );

		} catch ( \Exception $e ) {
			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	/**
	 * AJAX handler: Bulk sync multiple feeds
	 *
	 * @since 1.0.3
	 */
	public function ajax_bulk_sync() {
		// Log entry BEFORE any checks (debugging).
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			error_log( 'Wisewand RSS: ajax_bulk_sync called' );
			error_log( 'Wisewand RSS: POST keys: ' . implode( ', ', array_keys( $_POST ) ) );
		}

		try {
			// Prevent output corruption.
			if ( ob_get_length() ) {
				ob_clean();
			}
			ob_start();

			// Check nonce (don't die, return boolean).
			if ( ! check_ajax_referer( 'wisewand_rss', 'nonce', false ) ) {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( 'Wisewand RSS: Nonce verification FAILED' );
				}

				ob_clean();
				wp_send_json_error(
					array(
						'message' => __( 'Security check failed. Please reload the page.', 'wisewand-ai-content-writer-seo-content-generator' ),
					)
				);
				return;
			}

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'Wisewand RSS: Nonce verified successfully' );
			}

			// Check capability.
			if ( ! current_user_can( 'edit_posts' ) ) {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( 'Wisewand RSS: Permission denied for current user' );
				}

				ob_clean();
				wp_send_json_error(
					array(
						'message' => __( 'Insufficient permissions', 'wisewand-ai-content-writer-seo-content-generator' ),
					)
				);
				return;
			}

			// Get feed IDs (empty = all feeds).
			$feed_ids     = isset( $_POST['feed_ids'] ) ? array_map( 'absint', (array) $_POST['feed_ids'] ) : array();
			$force_import = ! empty( $_POST['force_import'] );

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'Wisewand RSS: Starting bulk sync - feed_ids: ' . implode( ', ', $feed_ids ) . ', force: ' . ( $force_import ? 'yes' : 'no' ) );
			}

			// Get sync engine.
			$sync_engine = $this->get_sync_engine();
			if ( ! $sync_engine ) {
				throw new \Exception( __( 'Sync engine not available', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			// Load dependencies.
			if ( ! class_exists( 'Wisewand\\Utils\\Rate_Limiter' ) ) {
				require_once WISEWAND_PLUGIN_DIR . 'includes/Utils/Rate_Limiter.php';
			}
			if ( ! class_exists( 'Wisewand\\RSS\\Bulk_Sync_Manager' ) ) {
				require_once WISEWAND_PLUGIN_DIR . 'includes/RSS/Bulk_Sync_Manager.php';
			}

			// Create bulk sync manager.
			$rate_limiter = new \Wisewand\Utils\Rate_Limiter( $this->logger );
			$bulk_manager = new \Wisewand\RSS\Bulk_Sync_Manager(
				$sync_engine,
				$this->feed_manager,
				$rate_limiter,
				$this->logger
			);

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'Wisewand RSS: Bulk sync manager created, running batch' );
			}

			// Run bulk sync.
			$results = $bulk_manager->sync_feeds_batch( $feed_ids, $force_import );

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'Wisewand RSS: Bulk sync completed - succeeded: ' . $results['succeeded'] . ', failed: ' . $results['failed'] );
			}

			// Build user-friendly message with guidance.
			$message = sprintf(
				/* translators: 1: succeeded count, 2: total count */
				__( 'Synced %1$d of %2$d feeds successfully', 'wisewand-ai-content-writer-seo-content-generator' ),
				$results['succeeded'],
				$results['total_feeds']
			);

			// Add guidance if timeout protection triggered.
			if ( ! empty( $results['timeout_reached'] ) ) {
				$message .= ' ' . sprintf(
					/* translators: %d: remaining feeds count */
					__( '(%d feeds remaining due to timeout protection - click "Sync All" again to continue)', 'wisewand-ai-content-writer-seo-content-generator' ),
					$results['remaining_feeds']
				);
			}

			// Clear output buffer before sending response.
			ob_clean();

			// DON'T clear rate limits after sync - let them decay naturally via transient TTL.
			// Clearing limits allows rapid subsequent operations which trigger API server-side rate limiting.
			// Natural decay via 60s transient TTL provides better rate limit compliance.
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'Wisewand RSS: Bulk sync completed, rate limits will decay naturally (60s TTL)' );
			}

			// v1.2.0: Build feed summaries for beautiful progress UI.
			$feed_summaries = array();
			if ( ! empty( $results['feed_results'] ) ) {
				foreach ( $results['feed_results'] as $feed_result ) {
					$feed_name  = $feed_result['feed_name'] ?? 'Unknown Feed';
					$discovered = $feed_result['articles_discovered'] ?? 0;
					$imported   = $feed_result['articles_imported'] ?? 0;
					$failed     = $feed_result['articles_failed'] ?? 0;

					// Determine status.
					$status = 'success';
					if ( $failed > 0 && $imported === 0 ) {
						$status = 'failed';
					} elseif ( $failed > 0 ) {
						$status = 'partial';
					}

					$feed_summaries[] = array(
						'feed_name'  => $feed_name,
						'discovered' => $discovered,
						'imported'   => $imported,
						'failed'     => $failed,
						'status'     => $status,
					);
				}
			}

			wp_send_json_success(
				array(
					'message'         => $message,
					'results'         => $results,
					'feed_summaries'  => $feed_summaries, // v1.2.0: For beautiful progress UI.
					'timeout_reached' => ! empty( $results['timeout_reached'] ),
					'remaining'       => $results['remaining_feeds'] ?? 0,
				)
			);

		} catch ( \Exception $e ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'Wisewand RSS: EXCEPTION in ajax_bulk_sync: ' . $e->getMessage() );
				error_log( 'Wisewand RSS: Stack trace: ' . $e->getTraceAsString() );
			}

			$this->logger->error(
				'Bulk sync failed',
				array( 'error' => $e->getMessage() )
			);

			ob_clean();
			wp_send_json_error(
				array(
					'message' => __( 'Sync failed: ', 'wisewand-ai-content-writer-seo-content-generator' ) . esc_html( $e->getMessage() ),
				)
			);
		}
	}

	public function ajax_get_articles() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		$feed_id = absint( $_POST['feed_id'] ?? 0 );
		if ( ! $feed_id ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'Invalid feed ID', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		try {
			// Get feed info to know Wisewand feed ID
			$feed = $this->feed_manager->get_feed( $feed_id );
			if ( ! $feed ) {
				throw new \Exception( __( 'Feed not found', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			$wisewand_feed_id = $feed['wisewand_feed_id'];

			// Fetch articles from Wisewand API using API Client (respects feed type)
			$feed_type = $feed['feed_type'] ?? 'articles';

			if ( $feed_type === 'discoverarticles' ) {
				$wisewand_articles = $this->api_client->get_feed_discoverarticles( $wisewand_feed_id, 0, 50 );
			} else {
				$wisewand_articles = $this->api_client->get_feed_articles( $wisewand_feed_id, 0, 50 );
			}

			if ( is_wp_error( $wisewand_articles ) ) {
				throw new \Exception( 'API request failed: ' . $wisewand_articles->get_error_message() );
			}

			if ( ! $wisewand_articles || ! isset( $wisewand_articles['items'] ) ) {
				throw new \Exception( 'Invalid API response' );
			}

			// Merge with local tracking status
			$articles = array();
			foreach ( $wisewand_articles['items'] as $wisewand_article ) {
				// Check if article is tracked locally
				$tracked = $this->article_manager->get_article_by_wisewand_id( $wisewand_article['id'] );

				$article_data = array(
					'wisewand_article_id' => $wisewand_article['id'],
					'article_title'       => $wisewand_article['title'] ?? $wisewand_article['subject'],
					'article_subject'     => $wisewand_article['subject'] ?? '',
					'import_status'       => $tracked ? $tracked['import_status'] : 'pending',
					'wordpress_post_id'   => $tracked ? $tracked['wordpress_post_id'] : null,
					'id'                  => $tracked ? $tracked['id'] : null,
				);

				$articles[] = $article_data;
			}

			ob_clean();
			wp_send_json_success( array( 'articles' => $articles ) );

		} catch ( \Exception $e ) {
			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	public function ajax_import_article() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		$wisewand_article_id = isset( $_POST['wisewand_article_id'] ) ? sanitize_text_field( wp_unslash( $_POST['wisewand_article_id'] ) ) : '';
		$feed_id             = absint( $_POST['feed_id'] ?? 0 );

		if ( empty( $wisewand_article_id ) || ! $feed_id ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'Invalid parameters', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		// PHASE 1: Add entry point logging
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			error_log( '🔵 AJAX_IMPORT: Entry point - article_id: ' . $wisewand_article_id . ', feed_id: ' . $feed_id );
		}

		try {
			// phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- Required for RSS article import operations which may involve multiple images
			@set_time_limit( 300 );

			$sync_engine = $this->get_sync_engine();
			if ( ! $sync_engine ) {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( '❌ AJAX_IMPORT: Sync engine not available' );
				}
				throw new \Exception( __( 'Sync engine not available', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'AJAX_IMPORT: Calling sync_engine->import_article_manual()...' );
			}

			$post_id = $sync_engine->import_article_manual( $wisewand_article_id, $feed_id );

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'AJAX_IMPORT: import_article_manual() returned - type: ' . ( is_wp_error( $post_id ) ? 'WP_Error' : ( is_int( $post_id ) ? 'int' : ( is_null( $post_id ) ? 'NULL' : gettype( $post_id ) ) ) ) );
			}

			// PHASE 1: Explicit validation of return value
			if ( is_null( $post_id ) ) {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( '❌ AJAX_IMPORT: CRITICAL - import_article_manual() returned NULL!' );
				}
				throw new \Exception( __( 'Import failed: No post ID returned (internal error)', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			if ( $post_id === false ) {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( '❌ AJAX_IMPORT: CRITICAL - import_article_manual() returned FALSE!' );
				}
				throw new \Exception( __( 'Import failed: Function returned false (internal error)', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			if ( is_wp_error( $post_id ) ) {
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( '❌ AJAX_IMPORT: import_article_manual() returned WP_Error: ' . $post_id->get_error_message() );
				}

				if ( $post_id->get_error_code() === 'already_imported' ) {
					$data = $post_id->get_error_data();
					ob_clean();
					wp_send_json_success(
						array(
							'post_id'          => $data['post_id'],
							'message'          => __( 'Article already imported', 'wisewand-ai-content-writer-seo-content-generator' ),
							'already_imported' => true,
						)
					);
					return;
				}
				throw new \Exception( $post_id->get_error_message() );
			}

			if ( ! is_int( $post_id ) || $post_id <= 0 ) {

				throw new \Exception( __( 'Import failed: Invalid post ID returned', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			// PHASE 1: Success!
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( '✅ AJAX_IMPORT: Success - post_id: ' . $post_id );
			}

			ob_clean();
			wp_send_json_success(
				array(
					'post_id' => $post_id,
					'message' => __( 'Article imported successfully', 'wisewand-ai-content-writer-seo-content-generator' ),
				)
			);

		} catch ( \Exception $e ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( '❌ AJAX_IMPORT: Exception caught: ' . $e->getMessage() );
			}
			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	public function ajax_bulk_import() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		$article_ids = isset( $_POST['article_ids'] ) ? array_map( 'sanitize_text_field', wp_unslash( (array) $_POST['article_ids'] ) ) : array();
		$feed_id     = absint( $_POST['feed_id'] ?? 0 );

		if ( empty( $article_ids ) || ! $feed_id ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'Invalid parameters', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		try {
			// phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- Required for bulk RSS feed synchronization operations
			@set_time_limit( 600 );

			$sync_engine = $this->get_sync_engine();
			if ( ! $sync_engine ) {
				throw new \Exception( __( 'Sync engine not available', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			$imported = 0;
			$failed   = 0;

			foreach ( $article_ids as $wisewand_article_id ) {
				$result = $sync_engine->import_article_manual( $wisewand_article_id, $feed_id );

				if ( is_wp_error( $result ) && $result->get_error_code() !== 'already_imported' ) {
					++$failed;
				} else {
					++$imported;
				}
			}

			ob_clean();
			wp_send_json_success(
				array(
					'imported' => $imported,
					'failed'   => $failed,
					'total'    => count( $article_ids ),
				)
			);

		} catch ( \Exception $e ) {
			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	public function ajax_get_feed_settings() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		$feed_id = absint( $_POST['feed_id'] ?? 0 );
		if ( ! $feed_id ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'Invalid feed ID', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		try {
			$feed = $this->feed_manager->get_feed( $feed_id );
			if ( ! $feed ) {
				throw new \Exception( __( 'Feed not found', 'wisewand-ai-content-writer-seo-content-generator' ) );
			}

			// Get WordPress authors (fixed: 'who' deprecated since WP 5.9, use 'capability')
			$authors_raw = get_users(
				array(
					'capability' => 'edit_posts',
					'orderby'    => 'display_name',
				)
			);

			// v1.2.8: Format authors for JSON serialization (WP_User objects don't serialize display_name)
			$authors = array();
			foreach ( $authors_raw as $user ) {
				$authors[] = array(
					'ID'           => $user->ID,
					'display_name' => $user->display_name,
					'user_login'   => $user->user_login,
					'user_email'   => $user->user_email,
				);
			}

			// Get WordPress categories
			$categories = get_categories(
				array(
					'hide_empty' => false,
					'orderby'    => 'name',
				)
			);

			// Check if OpenAI is configured
			$openai_configured = class_exists( 'Wisewand\\Utils\\OpenAI_Client' ) && \Wisewand\Utils\OpenAI_Client::is_configured();

			// WPML: Get available languages if WPML is active
			$wpml_languages = array();
			$wpml_active    = $this->options->is_wpml_active();
			if ( $wpml_active && class_exists( '\Wisewand\WPML\WPML_Manager' ) ) {
				$wpml_manager   = new \Wisewand\WPML\WPML_Manager( $this->options );
				$wpml_languages = $wpml_manager->get_active_languages();
			}

			// Phase 1: Get global settings for inheritance display
			$global_settings = array(
				'import_frequency' => $this->options->get( 'wisewand_rss_default_import_frequency', 'every_6_hours' ),
				'max_articles'     => $this->options->get( 'wisewand_rss_default_max_articles', 10 ),
				'publish_mode'     => $this->options->get( 'wisewand_rss_publish_mode', 'schedule' ),
				'author'           => $this->options->get( 'wisewand_rss_default_target_author', 0 ),
				'ai_categories'    => $this->options->get( 'wisewand_rss_default_ai_category_matching', false ),
			);

			// Get author name for display
			if ( $global_settings['author'] > 0 ) {
				$author_obj                       = get_user_by( 'ID', $global_settings['author'] );
				$global_settings['author_name'] = $author_obj ? $author_obj->display_name : 'default';
			} else {
				$global_settings['author_name'] = 'default';
			}

			ob_clean();
			wp_send_json_success(
				array(
					'feed'              => $feed,
					'authors'           => $authors,
					'categories'        => $categories,
					'openai_configured' => $openai_configured,
					'wpml_active'       => $wpml_active,
					'wpml_languages'    => $wpml_languages,
					'global_settings'   => $global_settings,
				)
			);

		} catch ( \Exception $e ) {
			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	public function ajax_save_feed_settings() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		$feed_id = absint( $_POST['feed_id'] ?? 0 );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Settings array is sanitized field-by-field in the $sanitized_settings array below (lines 934-950)
		$settings = isset( $_POST['settings'] ) ? wp_unslash( (array) $_POST['settings'] ) : array();

		if ( ! $feed_id || empty( $settings ) ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'Invalid parameters', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		try {
			// Sanitize settings
			$sanitized_settings = array(
				'auto_import_enabled'             => ! empty( $settings['auto_import_enabled'] ) ? 1 : 0,
				'import_schedule_type'            => sanitize_text_field( $settings['import_schedule_type'] ?? 'every_6_hours' ),
				'import_schedule_time'            => ! empty( $settings['import_schedule_time'] ) ? sanitize_text_field( $settings['import_schedule_time'] ) : null,
				'import_schedule_days'            => ! empty( $settings['import_schedule_days'] ) ? sanitize_text_field( $settings['import_schedule_days'] ) : null,
				'max_articles_per_sync'           => absint( $settings['max_articles_per_sync'] ?? 10 ),
				'target_post_status'              => sanitize_text_field( $settings['target_post_status'] ?? 'draft' ),
				'target_author'                   => absint( $settings['target_author'] ?? 0 ),
				'target_categories'               => $this->validate_and_sanitize_categories( $settings['target_categories'] ?? '' ),
				'use_ai_category_matching'        => ! empty( $settings['use_ai_category_matching'] ) ? 1 : 0,
				// RSS v2.0: Custom interval
				'custom_interval_hours'           => absint( $settings['custom_interval_hours'] ?? 12 ),
				// RSS v2.2: Inheritance flags for global settings
				// Note: Using ! empty() instead of isset() because isset() returns true for 0,
				// which would incorrectly save unchecked checkboxes as 1.
				'inherit_import_frequency'        => ! empty( $settings['inherit_import_frequency'] ) ? 1 : 0,
				'inherit_author'                  => ! empty( $settings['inherit_author'] ) ? 1 : 0,
				'inherit_categories'              => ! empty( $settings['inherit_categories'] ) ? 1 : 0,
				'inherit_max_articles'            => ! empty( $settings['inherit_max_articles'] ) ? 1 : 0,
				'inherit_ai_categories'           => ! empty( $settings['inherit_ai_categories'] ) ? 1 : 0,
			);

			// v2.4.0: Map new feed_publish_mode dropdown to database fields
			$publish_mode = sanitize_text_field( $settings['feed_publish_mode'] ?? 'inherit' );

			switch ( $publish_mode ) {
				case 'inherit':
					$sanitized_settings['inherit_publish_mode']            = 1;
					$sanitized_settings['schedule_mode']                   = null;
					$sanitized_settings['publish_mode']                    = 'schedule';
					$sanitized_settings['use_custom_publication_schedule'] = 0;
					break;

				case 'specific_time':
					$sanitized_settings['inherit_publish_mode']            = 0;
					$sanitized_settings['schedule_mode']                   = 'custom';
					$sanitized_settings['schedule_time']                   = sanitize_text_field( $settings['feed_schedule_time'] ?? '18:03:00' );
					$sanitized_settings['publication_allowed_days']        = ! empty( $settings['feed_publish_days'] )
						? wp_json_encode( array_map( 'sanitize_text_field', (array) $settings['feed_publish_days'] ) )
						: wp_json_encode( array( '1', '2', '3', '4', '5', '6', '7' ) );
					$sanitized_settings['use_custom_publication_schedule'] = 1;
					$sanitized_settings['publish_mode']                    = 'schedule';
					break;

				case 'time_range':
					$sanitized_settings['inherit_publish_mode']            = 0;
					$sanitized_settings['schedule_mode']                   = null;
					$sanitized_settings['publication_time_range']          = sanitize_text_field( $settings['feed_time_range'] ?? 'evening' );
					$sanitized_settings['use_custom_publication_schedule'] = 1;
					$sanitized_settings['publish_mode']                    = 'schedule';
					break;

				case 'immediate':
					$sanitized_settings['inherit_publish_mode']            = 0;
					$sanitized_settings['publish_mode']                    = 'publish';
					$sanitized_settings['use_custom_publication_schedule'] = 0;
					break;

				case 'draft':
					$sanitized_settings['inherit_publish_mode']            = 0;
					$sanitized_settings['publish_mode']                    = 'draft';
					$sanitized_settings['use_custom_publication_schedule'] = 0;
					break;

				default:
					// Fallback to inherit
					$sanitized_settings['inherit_publish_mode']            = 1;
					$sanitized_settings['publish_mode']                    = 'schedule';
					$sanitized_settings['use_custom_publication_schedule'] = 0;
					break;
			}

			// Update settings
			$result = $this->feed_manager->update_feed_settings( $feed_id, $sanitized_settings );

			if ( is_wp_error( $result ) ) {
				throw new \Exception( $result->get_error_message() );
			}



			$this->logger->info(
				'Feed settings saved',
				array(
					'feed_id'     => $feed_id,
					'auto_import' => $sanitized_settings['auto_import_enabled'],
					'schedule'    => $sanitized_settings['import_schedule_type'],
				)
			);

			// Layer 3: Server-side verification - Echo back saved values for client verification
			// This creates a complete audit trail: client sends → server saves → server echoes → client verifies
			$saved_values = array(
				'auto_import_enabled'             => $sanitized_settings['auto_import_enabled'],
				'use_ai_category_matching'        => $sanitized_settings['use_ai_category_matching'],
				'use_custom_publication_schedule' => $sanitized_settings['use_custom_publication_schedule'],
				'custom_interval_hours'           => $sanitized_settings['custom_interval_hours'],
				'publication_time_range'          => $sanitized_settings['publication_time_range'] ?? null,
				'publication_allowed_days'        => $sanitized_settings['publication_allowed_days'],
				'import_schedule_type'            => $sanitized_settings['import_schedule_type'],
				'target_post_status'              => $sanitized_settings['target_post_status'],
				'publish_mode'                    => $sanitized_settings['publish_mode'],
				'target_categories'               => $sanitized_settings['target_categories'],
			);

			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_PAGE: Layer 3 - Server echoing saved values for verification: ' . wp_json_encode( $saved_values ) );
			}

			ob_clean();
			wp_send_json_success(
				array(
					'message'      => __( 'Settings saved successfully', 'wisewand-ai-content-writer-seo-content-generator' ),
					'saved_values' => $saved_values, // Echo back for client verification
				)
			);

		} catch ( \Exception $e ) {
			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	/**
	 * Validate and sanitize category array
	 *
	 * Ensures only valid category IDs are stored in JSON format.
	 *
	 * @since 1.2.0
	 * @param mixed $input Raw input (could be string, array, or anything).
	 * @return string JSON-encoded array of valid category IDs, or '[]' if invalid.
	 */
	private function validate_and_sanitize_categories( $input ) {
		// Handle empty input
		if ( empty( $input ) ) {
			return '[]';
		}

		// If it's a string, try to decode it
		if ( is_string( $input ) ) {
			$decoded = json_decode( $input, true );
			if ( json_last_error() !== JSON_ERROR_NONE ) {
				// Invalid JSON - return empty array
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( 'RSS_PAGE: Invalid JSON for categories: ' . $input );
				}
				return '[]';
			}
			$input = $decoded;
		}

		// Ensure it's an array
		if ( ! is_array( $input ) ) {
			return '[]';
		}

		// Sanitize: filter out non-numeric values, convert to integers
		$valid_ids = array_filter(
			array_map( 'absint', $input ),
			function ( $id ) {
				return $id > 0;
			}
		);

		// Re-index array (remove gaps from filtering)
		$valid_ids = array_values( $valid_ids );

		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			error_log( 'RSS_PAGE: Validated categories: ' . wp_json_encode( $valid_ids ) );
		}

		// Return JSON-encoded array
		return wp_json_encode( $valid_ids );
	}

	/**
	 * Sanitize publish mode value
	 *
	 * Validates publish mode against allowed values and returns
	 * safe default if invalid input provided.
	 *
	 * @since 1.4.0
	 * @param string $mode Publish mode input.
	 * @return string Sanitized publish mode (global, schedule, publish, or draft).
	 */
	private function sanitize_publish_mode( $mode ) {
		$allowed_modes = array( 'global', 'schedule', 'publish', 'draft' );

		$mode = sanitize_text_field( $mode );

		if ( ! in_array( $mode, $allowed_modes, true ) ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log(
					sprintf(
						'Wisewand RSS: Invalid publish mode "%s", defaulting to "global"',
						$mode
					)
				);
			}
			return 'global'; // Safe default.
		}

		return $mode;
	}

	/**
	 * AJAX handler for bulk activating feeds (RSS v2.0)
	 */
	public function ajax_bulk_activate() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		$feed_ids = isset( $_POST['feed_ids'] ) ? array_map( 'absint', (array) $_POST['feed_ids'] ) : array();

		if ( empty( $feed_ids ) ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'No feeds selected', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		try {
			// Clear any WordPress caches that might interfere
			wp_cache_flush();
			if ( function_exists( 'wp_cache_delete' ) ) {
				wp_cache_delete( 'wisewand_rss_feeds', 'wisewand-ai-content-writer-seo-content-generator' );
			}
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_BULK_ACTIVATE: Cleared WordPress caches' );
			}

			$success_count = 0;
			$failed_count  = 0;

			foreach ( $feed_ids as $feed_id ) {
				if ( $feed_id <= 0 ) {
					continue;
				}

				// RSS v2.0: Simplified activation - enable both activation AND auto-import
				// VERSION CHECK: Ensure we're using the correct code version
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( 'RSS_BULK_ACTIVATE: ====== Processing feed ID: ' . $feed_id . ' ======' );
				}

				// Verify feed exists in database
				global $wpdb;
				$table_name  = $wpdb->prefix . 'wisewand_rss_feeds';
				$feed_exists = $wpdb->get_var(
					$wpdb->prepare(
						'SELECT COUNT(*) FROM %i WHERE id = %d',
						$table_name,
						$feed_id
					)
				);
				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
					error_log( 'RSS_BULK_ACTIVATE: Feed ' . $feed_id . ' exists in DB: ' . ( $feed_exists ? 'YES' : 'NO' ) );
				}

				if ( ! $feed_exists ) {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_BULK_ACTIVATE: ERROR - Feed ' . $feed_id . ' not found in database!' );
					}
					++$failed_count;
					continue;
				}

				// Build settings array explicitly
				$settings_to_update                         = array();
				$settings_to_update['sync_status']          = 'enabled';  // Use actual database field
				$settings_to_update['enabled_for_site']     = 1;    // Keep for backwards compatibility
				$settings_to_update['auto_import_enabled']  = 1;
				$settings_to_update['import_schedule_type'] = 'every_6_hours';

				// Call update method
				$result = $this->feed_manager->update_feed_settings( $feed_id, $settings_to_update );

				if ( is_wp_error( $result ) ) {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_BULK_ACTIVATE: Normal update failed for feed ' . $feed_id . ': ' . $result->get_error_message() );
					}

					// FALLBACK: Direct database update
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_BULK_ACTIVATE: Attempting fallback direct database update for feed ' . $feed_id );
					}

					$direct_result = $wpdb->update(
						$table_name,
						array(
							'sync_status'          => 'enabled',  // Use actual database field
							'auto_import_enabled'  => 1,
							'import_schedule_type' => 'every_6_hours',
							'updated_at'           => current_time( 'mysql' ),
						),
						array( 'id' => $feed_id ),
						array( '%s', '%d', '%s', '%s' ),  // sync_status is string
						array( '%d' )
					);

					if ( $direct_result !== false ) {
						if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
							error_log( 'RSS_BULK_ACTIVATE: Fallback direct update SUCCEEDED for feed ' . $feed_id );
						}
						// Calculate next sync time for auto-import (allow catchup)
						$this->feed_manager->calculate_next_sync_time( $feed_id, true );
						++$success_count;
					} else {
						if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
							error_log( 'RSS_BULK_ACTIVATE: Fallback direct update FAILED for feed ' . $feed_id . ' - DB error: ' . $wpdb->last_error );
						}
						++$failed_count;
					}
				} else {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_BULK_ACTIVATE: Successfully activated feed ' . $feed_id );
					}
					// Calculate next sync time for auto-import (allow catchup for immediate run)
					$this->feed_manager->calculate_next_sync_time( $feed_id, true );
					++$success_count;
				}
			}

			$this->logger->info(
				'Bulk activate feeds',
				array(
					'feed_ids' => $feed_ids,
					'success'  => $success_count,
					'failed'   => $failed_count,
				)
			);

			// RSS v2.0: Trigger immediate sync for activated feeds
			if ( $success_count > 0 ) {
				// Schedule immediate CRON run (within next minute)
				if ( wp_next_scheduled( 'wisewand_rss_sync' ) ) {
					wp_unschedule_hook( 'wisewand_rss_sync' );
				}
				wp_schedule_single_event( time() + 30, 'wisewand_rss_sync' );

				$this->logger->info( 'Scheduled immediate RSS sync after bulk activation' );
			}

			ob_clean();
			wp_send_json_success(
				array(
					/* translators: %d: number of RSS feeds activated */
					'message'       => sprintf( __( '✅ Activated %d feed(s) with auto-import. Sync will start in 30 seconds!', 'wisewand-ai-content-writer-seo-content-generator' ), $success_count ),
					'success_count' => $success_count,
					'failed_count'  => $failed_count,
				)
			);

		} catch ( \Exception $e ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_BULK_ACTIVATE: Exception: ' . $e->getMessage() );
			}

			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	/**
	 * AJAX handler for bulk deactivating feeds (RSS v2.0)
	 */
	public function ajax_bulk_deactivate() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		$feed_ids = isset( $_POST['feed_ids'] ) ? array_map( 'absint', (array) $_POST['feed_ids'] ) : array();

		if ( empty( $feed_ids ) ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'No feeds selected', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		try {
			$success_count = 0;
			$failed_count  = 0;

			foreach ( $feed_ids as $feed_id ) {
				if ( $feed_id <= 0 ) {
					continue;
				}

				// Deactivate feed and also disable auto-import
				$result = $this->feed_manager->update_feed_settings(
					$feed_id,
					array(
						'sync_status'         => 'disabled',  // Use actual database field
						'enabled_for_site'    => 0,      // Keep for backwards compatibility
						'auto_import_enabled' => 0,
					)
				);

				if ( is_wp_error( $result ) ) {
					++$failed_count;
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						error_log( 'RSS_BULK_DEACTIVATE: Failed to deactivate feed ' . $feed_id . ': ' . $result->get_error_message() );
					}
				} else {
					++$success_count;
				}
			}

			$this->logger->info(
				'Bulk deactivate feeds',
				array(
					'feed_ids' => $feed_ids,
					'success'  => $success_count,
					'failed'   => $failed_count,
				)
			);

			ob_clean();
			wp_send_json_success(
				array(
					/* translators: %d: number of RSS feeds deactivated */
					'message'       => sprintf( __( 'Deactivated %d feed(s) successfully', 'wisewand-ai-content-writer-seo-content-generator' ), $success_count ),
					'success_count' => $success_count,
					'failed_count'  => $failed_count,
				)
			);

		} catch ( \Exception $e ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				error_log( 'RSS_BULK_DEACTIVATE: Exception: ' . $e->getMessage() );
			}

			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	/**
	 * AJAX handler for cleanup RSS database tables
	 *
	 * Removes all RSS feeds, articles, and resets auto-increment.
	 * Includes confirmation requirement for safety.
	 *
	 * @since 1.1.0
	 */
	public function ajax_cleanup_rss_data() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss', 'manage_options' );

		// Require confirmation parameter
		$confirmed = isset( $_POST['confirmed'] ) && $_POST['confirmed'] === 'true';

		if ( ! $confirmed ) {
			ob_clean();
			wp_send_json_error( array( 'message' => __( 'Confirmation required', 'wisewand-ai-content-writer-seo-content-generator' ) ) );
		}

		try {
			global $wpdb;

			$feeds_table    = $wpdb->prefix . 'wisewand_rss_feeds';
			$articles_table = $wpdb->prefix . 'wisewand_rss_articles';
			$calendar_table = $wpdb->prefix . 'wisewand_calendar';

			// v1.2.3: Enhanced cleanup with complete WordPress post deletion
			// Get counts before deletion for user feedback
			$feeds_count    = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', $feeds_table ) );
			$articles_count = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', $articles_table ) );

			// STEP 1: Query wordpress_post_id from articles BEFORE deleting table
			$wordpress_post_ids = $wpdb->get_col(
				$wpdb->prepare(
					'SELECT wordpress_post_id FROM %i WHERE wordpress_post_id IS NOT NULL AND wordpress_post_id > 0',
					$articles_table
				)
			);

			$posts_deleted = 0;
			$posts_failed  = 0;

			// STEP 2: Delete each WordPress post using wp_delete_post($id, true)
			if ( ! empty( $wordpress_post_ids ) ) {
				foreach ( $wordpress_post_ids as $post_id ) {
					// Verify post exists before attempting deletion
					if ( get_post( $post_id ) ) {
						$result = wp_delete_post( $post_id, true ); // true = force delete, bypass trash

						if ( $result ) {
							++$posts_deleted;

							if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
								error_log( "RSS_CLEANUP: ✅ Deleted WordPress post ID: {$post_id}" );
							}
						} else {
							++$posts_failed;

							if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
								error_log( "RSS_CLEANUP: ❌ Failed to delete WordPress post ID: {$post_id}" );
							}
						}
					} elseif ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
							error_log( "RSS_CLEANUP: ⚠️ WordPress post ID {$post_id} does not exist (already deleted or invalid)" );
					}
				}
			}

			// STEP 3: Delete calendar entries where rss_feed_id matches any feed
			$calendar_entries_deleted = 0;

			// Get all feed IDs before deleting feeds table
			$feed_ids = $wpdb->get_col( $wpdb->prepare( 'SELECT id FROM %i', $feeds_table ) );

			if ( ! empty( $feed_ids ) ) {
				// Delete calendar entries for all RSS feeds
				foreach ( $feed_ids as $feed_id ) {
					$deleted = $wpdb->delete(
						$calendar_table,
						array( 'rss_feed_id' => $feed_id ),
						array( '%d' )
					);

					if ( $deleted !== false ) {
						$calendar_entries_deleted += $deleted;

						if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
							error_log( "RSS_CLEANUP: 📅 Deleted {$deleted} calendar entries for feed ID: {$feed_id}" );
						}
					}
				}
			}

			// STEP 4: Delete RSS tracking tables (existing logic)
			$wpdb->query( $wpdb->prepare( 'DELETE FROM %i', $articles_table ) );
			$wpdb->query( $wpdb->prepare( 'DELETE FROM %i', $feeds_table ) );

			// Reset auto-increment
			$wpdb->query( $wpdb->prepare( 'ALTER TABLE %i AUTO_INCREMENT = 1', $articles_table ) );
			$wpdb->query( $wpdb->prepare( 'ALTER TABLE %i AUTO_INCREMENT = 1', $feeds_table ) );

			// STEP 5: Return detailed statistics
			$this->logger->info(
				'RSS cleanup completed',
				array(
					'feeds_deleted'            => $feeds_count,
					'articles_deleted'         => $articles_count,
					'posts_deleted'            => $posts_deleted,
					'posts_failed'             => $posts_failed,
					'calendar_entries_deleted' => $calendar_entries_deleted,
				)
			);

			ob_clean();
			wp_send_json_success(
				array(
					'message'                  => sprintf(
						/* translators: 1: feeds deleted, 2: articles deleted, 3: WordPress posts deleted, 4: calendar entries deleted */
						__( 'Cleanup complete! Removed %1$d feeds, %2$d articles, %3$d WordPress posts, and %4$d calendar entries.', 'wisewand-ai-content-writer-seo-content-generator' ),
						$feeds_count,
						$articles_count,
						$posts_deleted,
						$calendar_entries_deleted
					),
					'feeds_deleted'            => $feeds_count,
					'articles_deleted'         => $articles_count,
					'posts_deleted'            => $posts_deleted,
					'posts_failed'             => $posts_failed,
					'calendar_entries_deleted' => $calendar_entries_deleted,
				)
			);

		} catch ( \Exception $e ) {
			$this->logger->error(
				'RSS cleanup failed',
				array( 'error' => $e->getMessage() )
			);

			ob_clean();
			wp_send_json_error( array( 'message' => __( 'Cleanup failed: ', 'wisewand-ai-content-writer-seo-content-generator' ) . esc_html( $e->getMessage() ) ) );
		}
	}

	/**
	 * AJAX handler to get global publication settings (RSS v2.0)
	 * Returns Calendar publication settings for display in feed settings modal
	 */
	public function ajax_get_global_publication_settings() {
		// Prevent output corruption
		if ( ob_get_length() ) {
			ob_clean();
		}
		ob_start();

		$this->verify_ajax_request( 'wisewand_rss' );

		try {
			$time_range   = $this->options->get( 'wisewand_calendar_time_range', 'random' );
			$allowed_days = $this->options->get( 'wisewand_allowed_publication_days', array( '1', '2', '3', '4', '5' ) );

			ob_clean();
			wp_send_json_success(
				array(
					'time_range'   => $time_range,
					'allowed_days' => $allowed_days,
				)
			);

		} catch ( \Exception $e ) {
			ob_clean();
			wp_send_json_error( array( 'message' => esc_html( $e->getMessage() ) ) );
		}
	}

	/**
	 * AJAX handler: Save global schedule settings
	 *
	 * Saves wisewand_rss_publish_mode and wisewand_rss_publish_time options.
	 * Validates inputs via Schedule_Validator utility.
	 *
	 * @since 2.1.3
	 * @return void
	 */
}
