<?php
/**
 * Settings Class for WPStack AI ALT Genius
 *
 * @package WPStack_AI_ALT_Genius
 */

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Handles plugin settings and admin menu.
 */
class Aialtg_Settings {

	/**
	 * Option key for API settings.
	 *
	 * @var string
	 */
	public static $option_name = 'aialtg_settings';

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
		add_action( 'admin_init', array( $this, 'redirect_legacy_settings_url' ) );
		add_action( 'admin_init', array( $this, 'register_settings' ) );
	}

	/**
	 * Redirect old Settings → AI ALT Genius URL to the top-level menu page.
	 */
	public function redirect_legacy_settings_url() {
		global $pagenow;
		if ( 'options-general.php' === $pagenow && isset( $_GET['page'] ) && AIALTG_SLUG === sanitize_text_field( wp_unslash( $_GET['page'] ) ) ) {
			wp_safe_redirect( admin_url( 'admin.php?page=' . AIALTG_SLUG ) );
			exit;
		}
	}

	/**
	 * Adds the top-level admin menu with custom plugin icon.
	 */
	public function add_admin_menu() {
		$icon_url = AIALTG_PLUGIN_URL . 'assets/images/icon-256x256.png';

		add_menu_page(
			__( 'WPStack AI ALT Genius', AIALTG_TEXT_DOMAIN ),
			__( 'AI ALT Genius', AIALTG_TEXT_DOMAIN ),
			'manage_options',
			AIALTG_SLUG,
			array( $this, 'render_settings_page' ),
			$icon_url,
			80
		);
	}

	/**
	 * Registers plugin settings.
	 */
	public function register_settings() {
		register_setting( 'aialtg_plugin_options', self::$option_name, array( $this, 'sanitize_settings' ) );

		// --- API Section ---
		add_settings_section(
			'aialtg_api_section',
			__( 'API Configuration', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_section_info' ),
			AIALTG_SLUG
		);

		add_settings_field(
			'provider',
			__( 'AI Provider', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_provider_field' ),
			AIALTG_SLUG,
			'aialtg_api_section'
		);

		add_settings_field(
			'api_key',
			__( 'API Key', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_api_key_field' ),
			AIALTG_SLUG,
			'aialtg_api_section'
		);

		add_settings_field(
			'nvidia_api_keys',
			__( 'NVIDIA API Keys (x3)', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_nvidia_api_keys_field' ),
			AIALTG_SLUG,
			'aialtg_api_section'
		);

		add_settings_field(
			'model',
			__( 'AI Model', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_model_field' ),
			AIALTG_SLUG,
			'aialtg_api_section'
		);

		// --- Options Section ---
		add_settings_section(
			'aialtg_options_section',
			__( 'Generation Options', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_options_section_info' ),
			AIALTG_SLUG
		);

		// New Global Context Field.
		add_settings_field(
			'global_context',
			__( 'Global Context', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_global_context_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'allowed_formats',
			__( 'Supported Image Formats', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_allowed_formats_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'enable_alt',
			__( 'Generate Alt Text', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_enable_alt_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'prompt',
			__( 'Alt Text Prompt', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_alt_prompt_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'enable_title',
			__( 'Generate Title', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_enable_title_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'title_prompt',
			__( 'Title Prompt', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_title_prompt_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'enable_caption',
			__( 'Generate Caption', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_enable_caption_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'caption_prompt',
			__( 'Caption Prompt', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_caption_prompt_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'enable_description',
			__( 'Generate Description', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_enable_description_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'description_prompt',
			__( 'Description Prompt', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_description_prompt_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		add_settings_field(
			'save_gen_meta',
			__( 'Save Generation Info', AIALTG_TEXT_DOMAIN ),
			array( $this, 'render_save_gen_meta_field' ),
			AIALTG_SLUG,
			'aialtg_options_section'
		);

		// --- Cron / Bulk Section (Conditional) ---
		// Only check for class existence. The main plugin file loads the class if the file exists.
		if ( class_exists( 'Aialtg_Cron' ) ) {
			add_settings_section(
				'aialtg_cron_section',
				__( 'Bulk Generation (Cron)', AIALTG_TEXT_DOMAIN ),
				array( $this, 'render_cron_section_info' ),
				AIALTG_SLUG
			);

			add_settings_field(
				'cron_enabled',
				__( 'Enable Background Processing', AIALTG_TEXT_DOMAIN ),
				array( $this, 'render_cron_enabled_field' ),
				AIALTG_SLUG,
				'aialtg_cron_section'
			);

			add_settings_field(
				'cron_batch_size',
				__( 'Batch Size (Images per run)', AIALTG_TEXT_DOMAIN ),
				array( $this, 'render_cron_batch_field' ),
				AIALTG_SLUG,
				'aialtg_cron_section'
			);

			add_settings_field(
				'cron_interval',
				__( 'Interval (Minutes)', AIALTG_TEXT_DOMAIN ),
				array( $this, 'render_cron_interval_field' ),
				AIALTG_SLUG,
				'aialtg_cron_section'
			);
		}
	}

	/**
	 * Sanitizes setting inputs.
	 */
	public function sanitize_settings( $input ) {
		$old_options = get_option( self::$option_name );
		$old_options = is_array( $old_options ) ? $old_options : array();
		$new_input   = array();

		// API Settings.
		if ( isset( $input['provider'] ) ) {
			$allowed_providers = array( 'openrouter', 'openai', 'nvidia', 'minimax' );
			$new_input['provider'] = in_array( $input['provider'], $allowed_providers, true ) ? $input['provider'] : 'openrouter';
		}
		if ( isset( $input['api_key'] ) ) {
			$new_input['api_key'] = Aialtg_Helpers::preserve_secret_field(
				$input['api_key'],
				isset( $old_options['api_key'] ) ? $old_options['api_key'] : ''
			);
		}
		// NVIDIA multi-key support (3 keys for round-robin parallel processing).
		$old_nvidia = isset( $old_options['nvidia_api_keys'] ) ? $old_options['nvidia_api_keys'] : array();
		$old_nvidia = is_array( $old_nvidia ) ? $old_nvidia : array();
		$nvidia_keys = array();
		for ( $i = 1; $i <= 3; $i++ ) {
			$submitted = isset( $input[ 'nvidia_key_' . $i ] ) ? $input[ 'nvidia_key_' . $i ] : '';
			$existing  = isset( $old_nvidia[ $i - 1 ] ) ? $old_nvidia[ $i - 1 ] : '';
			$resolved  = Aialtg_Helpers::preserve_secret_field( $submitted, $existing );
			if ( '' !== $resolved ) {
				$nvidia_keys[] = $resolved;
			}
		}
		$new_input['nvidia_api_keys'] = $nvidia_keys;
		if ( isset( $input['model'] ) ) {
			$new_input['model'] = sanitize_text_field( $input['model'] );
		}

		// Feature Toggles.
		$new_input['enable_alt']        = isset( $input['enable_alt'] ) ? '1' : '0';
		$new_input['enable_title']      = isset( $input['enable_title'] ) ? '1' : '0';
		$new_input['enable_caption']    = isset( $input['enable_caption'] ) ? '1' : '0';
		$new_input['enable_description'] = isset( $input['enable_description'] ) ? '1' : '0';
		$new_input['save_gen_meta']     = isset( $input['save_gen_meta'] ) ? '1' : '0';

		// Prompts & Formats.
		if ( isset( $input['global_context'] ) ) {
			$new_input['global_context'] = wp_strip_all_tags( $input['global_context'] );
		}
		if ( isset( $input['allowed_formats'] ) ) {
			$new_input['allowed_formats'] = sanitize_text_field( $input['allowed_formats'] );
		}
		if ( isset( $input['prompt'] ) ) {
			$new_input['prompt'] = wp_strip_all_tags( $input['prompt'] );
		}
		if ( isset( $input['title_prompt'] ) ) {
			$new_input['title_prompt'] = wp_strip_all_tags( $input['title_prompt'] );
		}
		if ( isset( $input['caption_prompt'] ) ) {
			$new_input['caption_prompt'] = wp_strip_all_tags( $input['caption_prompt'] );
		}
		if ( isset( $input['description_prompt'] ) ) {
			$new_input['description_prompt'] = wp_strip_all_tags( $input['description_prompt'] );
		}

		// Cron Settings (Only process if available).
		if ( class_exists( 'Aialtg_Cron' ) ) {
			$new_input['cron_enabled']    = isset( $input['cron_enabled'] ) ? '1' : '0';
			$new_input['cron_batch_size'] = isset( $input['cron_batch_size'] ) ? absint( $input['cron_batch_size'] ) : 1;
			$new_input['cron_interval']   = isset( $input['cron_interval'] ) ? absint( $input['cron_interval'] ) : 5;

			// --- Cron Logic Trigger ---
			$old_enabled  = isset( $old_options['cron_enabled'] ) ? $old_options['cron_enabled'] : '0';
			$old_interval = isset( $old_options['cron_interval'] ) ? $old_options['cron_interval'] : 5;

			$needs_reschedule = false;

			if ( $new_input['cron_enabled'] !== $old_enabled ) {
				$needs_reschedule = true;
			}
			if ( '1' === $new_input['cron_enabled'] && $new_input['cron_interval'] !== $old_interval ) {
				$needs_reschedule = true;
			}

			// Check if the event is actually currently scheduled.
			// Access constants via class.
			$cron_hook    = Aialtg_Cron::CRON_HOOK;
			$is_scheduled = wp_next_scheduled( $cron_hook );

			// Logic:
			// 1. If we are disabling it, clear the schedule.
			// 2. If we are enabling it, schedule it IF it's missing OR if we explicitly changed settings (reschedule).
			if ( '0' === $new_input['cron_enabled'] ) {
				if ( $is_scheduled ) {
					wp_clear_scheduled_hook( $cron_hook );
				}
			} elseif ( '1' === $new_input['cron_enabled'] ) {
				// If it's not scheduled in WP (even if enabled in settings), OR we need to reschedule due to changes.
				if ( ! $is_scheduled || $needs_reschedule ) {
					// Clear first to be safe (remove duplicates or old intervals).
					wp_clear_scheduled_hook( $cron_hook );
					wp_schedule_event( time() + 10, Aialtg_Cron::INTERVAL_NAME, $cron_hook );
				}
			}
		} else {
			// Maintain old values if cron file was removed so settings aren't lost on save.
			if ( isset( $old_options['cron_enabled'] ) ) {
				$new_input['cron_enabled'] = $old_options['cron_enabled'];
			}
			if ( isset( $old_options['cron_batch_size'] ) ) {
				$new_input['cron_batch_size'] = $old_options['cron_batch_size'];
			}
			if ( isset( $old_options['cron_interval'] ) ) {
				$new_input['cron_interval'] = $old_options['cron_interval'];
			}
		}

		// Clear stats cache whenever settings are saved so counts update immediately.
		delete_transient( 'aialtg_stats' );

		return $new_input;
	}

	/**
	 * Helper: Get allowed MIME types based on settings.
	 *
	 * @return array|string Array of mime types or 'image' string if default.
	 */
	public static function get_allowed_mimes() {
		$options = get_option( self::$option_name );
		$input   = isset( $options['allowed_formats'] ) ? $options['allowed_formats'] : 'jpg,jpeg,png,webp';

		// If user cleared the field, fallback to all images? Or strictly nothing?
		// Let's fallback to 'image' (all sub-types) to prevent breakage.
		if ( empty( trim( $input ) ) ) {
			return 'image';
		}

		$exts = array_map( 'trim', explode( ',', strtolower( $input ) ) );

		$mimes    = array();
		$wp_mimes = wp_get_mime_types();

		foreach ( $wp_mimes as $pattern => $type ) {
			// Pattern matches extensions (e.g. 'jpg|jpeg|jpe').
			$type_exts = explode( '|', $pattern );
			// Check if any of the user's allowed extensions match this mime type group.
			if ( array_intersect( $exts, $type_exts ) ) {
				$mimes[] = $type;
			}
		}

		if ( empty( $mimes ) ) {
			return 'image';
		}

		return array_unique( $mimes );
	}

	/**
	 * Renders Cron section info with STATS (Cached) and Reset Button.
	 */
	public function render_cron_section_info() {
		// Use transients to cache the query results (1 hour).
		$stats = get_transient( 'aialtg_stats' );

		if ( false === $stats ) {
			// We must use allowed mime types for accurate stats.
			$allowed_mimes = self::get_allowed_mimes();

			// 1. Total Images (matching allowed types).
			$args_total   = array(
				'post_type'      => 'attachment',
				'post_status'    => 'inherit',
				'post_mime_type' => $allowed_mimes,
				'posts_per_page' => 1,
				'fields'         => 'ids',
				'no_found_rows'  => false,
			);
			$query_total  = new WP_Query( $args_total );
			$total_images = $query_total->found_posts;

			// 2. Processed Successfully (value = '1').
			$args_processed   = array(
				'post_type'      => 'attachment',
				'post_status'    => 'inherit',
				'post_mime_type' => $allowed_mimes,
				'posts_per_page' => 1,
				'fields'         => 'ids',
				'no_found_rows'  => false,
				// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
				'meta_query'     => array(
					array(
						'key'   => '_aialtg_processed',
						'value' => '1',
					),
				),
			);
			$query_processed  = new WP_Query( $args_processed );
			$processed_images = $query_processed->found_posts;

			// 3. Failed (value = 'failed').
			$args_failed    = array(
				'post_type'      => 'attachment',
				'post_status'    => 'inherit',
				'post_mime_type' => $allowed_mimes,
				'posts_per_page' => 1,
				'fields'         => 'ids',
				'no_found_rows'  => false,
				// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
				'meta_query'     => array(
					array(
						'key'   => '_aialtg_processed',
						'value' => 'failed',
					),
				),
			);
			$query_failed   = new WP_Query( $args_failed );
			$failed_images  = $query_failed->found_posts;

			$stats = array(
				'total'     => $total_images,
				'processed' => $processed_images,
				'failed'    => $failed_images,
			);

			set_transient( 'aialtg_stats', $stats, HOUR_IN_SECONDS );
		} else {
			$total_images     = $stats['total'];
			$processed_images = $stats['processed'];
			$failed_images    = isset( $stats['failed'] ) ? $stats['failed'] : 0;
		}

		// Pending calculation: Total - (Processed + Failed).
		$pending    = max( 0, $total_images - $processed_images - $failed_images );
		// Percentage is based on completed attempts (success or fail).
		$completed  = $processed_images + $failed_images;
		$percentage = $total_images > 0 ? round( ( $completed / $total_images ) * 100 ) : 0;

		?>
		<div class="aialtg-card aialtg-stats-card">
			<div class="aialtg-card-header">
				<h3><?php esc_html_e( 'Statistics', AIALTG_TEXT_DOMAIN ); ?></h3>
			</div>

			<div class="aialtg-stats-grid">
				<div class="aialtg-stat-item">
					<span class="aialtg-stat-label"><?php esc_html_e( 'Total Images', AIALTG_TEXT_DOMAIN ); ?></span>
					<span class="aialtg-stat-value"><?php echo absint( $total_images ); ?></span>
				</div>
				<div class="aialtg-stat-item">
					<span class="aialtg-stat-label"><?php esc_html_e( 'Processed', AIALTG_TEXT_DOMAIN ); ?></span>
					<span class="aialtg-stat-value success"><?php echo absint( $processed_images ); ?></span>
				</div>
				<div class="aialtg-stat-item">
					<span class="aialtg-stat-label"><?php esc_html_e( 'Failed', AIALTG_TEXT_DOMAIN ); ?></span>
					<span class="aialtg-stat-value error"><?php echo absint( $failed_images ); ?></span>
				</div>
				<div class="aialtg-stat-item">
					<span class="aialtg-stat-label"><?php esc_html_e( 'Pending', AIALTG_TEXT_DOMAIN ); ?></span>
					<span class="aialtg-stat-value neutral"><?php echo absint( $pending ); ?></span>
				</div>
			</div>

			<div class="aialtg-progress-bar-wrap">
				<div class="aialtg-progress-bar">
					<div class="aialtg-progress-fill" style="width: <?php echo esc_attr( $percentage ); ?>%;"></div>
				</div>
				<span class="aialtg-progress-text"><?php echo esc_html( $percentage ); ?>% <?php esc_html_e( 'Complete', AIALTG_TEXT_DOMAIN ); ?></span>
			</div>

			<div class="aialtg-controls-wrapper">
				<div class="aialtg-buttons-row">
					<button type="button" class="button button-secondary aialtg-reset-btn" data-nonce="<?php echo esc_attr( wp_create_nonce( 'aialtg_reset_nonce' ) ); ?>">
						<span class="dashicons dashicons-update"></span>
						<?php esc_html_e( 'Reset Progress', AIALTG_TEXT_DOMAIN ); ?>
					</button>

					<button type="button" class="button button-secondary aialtg-retry-failed-btn" data-nonce="<?php echo esc_attr( wp_create_nonce( 'aialtg_retry_failed_nonce' ) ); ?>">
						<span class="dashicons dashicons-redo"></span>
						<?php esc_html_e( 'Retry Failed', AIALTG_TEXT_DOMAIN ); ?>
					</button>

					<button type="button" class="button button-secondary aialtg-fix-json-btn" data-nonce="<?php echo esc_attr( wp_create_nonce( 'aialtg_fix_json_nonce' ) ); ?>">
						<span class="dashicons dashicons-hammer"></span>
						<?php esc_html_e( 'Fix JSON Errors', AIALTG_TEXT_DOMAIN ); ?>
					</button>
				</div>

				<div class="aialtg-status-area" style="display: none;">
					<span class="spinner aialtg-status-spinner"></span>
					<span class="aialtg-status-message"></span>
				</div>
			</div>

			<div class="aialtg-card-footer">
				<p class="description">
					<?php esc_html_e( 'Resetting will re-analyze all images. Retry Failed moves error images back to pending. Fix JSON repairs accidental raw code in metadata.', AIALTG_TEXT_DOMAIN ); ?>
				</p>
			</div>
		</div>
		<?php
	}

	public function render_section_info() {
		echo '<p class="aialtg-section-desc">' . esc_html__( 'Choose an AI provider and enter your API credentials. All providers use the same chat completions format for maximum compatibility.', AIALTG_TEXT_DOMAIN ) . '</p>';
	}

	/**
	 * Available providers and their configuration.
	 */
	public static function get_providers() {
		return array(
			'openrouter' => array(
				'label' => __( 'OpenRouter', AIALTG_TEXT_DOMAIN ),
				'api_key_placeholder' => 'sk-or-...',
				'models_url'      => 'https://openrouter.ai/api/v1/models',
				'base_url'        => 'https://openrouter.ai/api/v1/chat/completions',
				'vision_context'  => true, // include image_url in body
				'default_model'   => 'google/gemini-2.5-flash-lite',
			),
			'openai' => array(
				'label' => __( 'OpenAI', AIALTG_TEXT_DOMAIN ),
				'api_key_placeholder' => 'sk-...',
				'models_url'      => 'https://api.openai.com/v1/models',
				'base_url'        => 'https://api.openai.com/v1/chat/completions',
				'vision_context'  => true,
				'default_model'   => 'gpt-4o',
			),
			'nvidia' => array(
				'label' => __( 'NVIDIA NIM', AIALTG_TEXT_DOMAIN ),
				'api_key_placeholder' => 'nvapi-...',
				'models_url'      => 'https://integrate.api.nvidia.com/v1/models',
				'base_url'        => 'https://integrate.api.nvidia.com/v1/chat/completions',
				'vision_context'  => true,
				'default_model'   => 'meta/llama-3.2-11b-vision-instruct',
			),
			'minimax' => array(
				'label' => __( 'MiniMax', AIALTG_TEXT_DOMAIN ),
				'api_key_placeholder' => 'your-api-key',
				'models_url'      => 'https://api.minimax.io/v1/models',
				'base_url'        => 'https://api.minimax.io/v1/chat/completions',
				'vision_context'  => true,
				'default_model'   => 'MiniMax-M3',
				'needs_auth_for_models' => true,
			),
		);
	}

	/**
	 * API key placeholders keyed by provider slug (for admin UI).
	 *
	 * @return array<string, string>
	 */
	public static function get_provider_placeholders() {
		$placeholders = array();
		foreach ( self::get_providers() as $id => $data ) {
			$placeholders[ $id ] = $data['api_key_placeholder'];
		}
		return $placeholders;
	}

	public function render_provider_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$current  = isset( $options['provider'] ) ? $options['provider'] : 'openrouter';
		$providers = self::get_providers();
		?>
			<div class="aialtg-input-wrap">
			<select id="aialtg-provider-select" class="regular-text" style="width: 100%; max-width: 400px;" data-provider="<?php echo esc_attr( $current ); ?>">
				<?php foreach ( $providers as $id => $data ) : ?>
					<option value="<?php echo esc_attr( $id ); ?>" <?php selected( $current, $id ); ?>>
						<?php echo esc_html( $data['label'] ); ?>
					</option>
				<?php endforeach; ?>
			</select>
			<p class="description"><?php esc_html_e( 'Select your AI provider. Each supports different models. The model dropdown and API key placeholder will update automatically.', AIALTG_TEXT_DOMAIN ); ?></p>
		</div>
		<?php
	}

	public function render_options_section_info() {
		echo '<p class="aialtg-section-desc">' . esc_html__( 'Configure how the AI generates text for your images.', AIALTG_TEXT_DOMAIN ) . '</p>';
	}

	public function render_api_key_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$has_key = ! empty( $options['api_key'] );
		$provider = isset( $options['provider'] ) ? $options['provider'] : 'openrouter';
		$providers = self::get_providers();
		$placeholder = isset( $providers[ $provider ] ) ? $providers[ $provider ]['api_key_placeholder'] : 'sk-...';
		if ( $has_key ) {
			$placeholder = __( 'Leave blank to keep existing key', AIALTG_TEXT_DOMAIN );
		}
		?>
		<div class="aialtg-input-wrap">
			<input type="password" name="<?php echo esc_attr( self::$option_name . '[api_key]' ); ?>" value="" class="regular-text" id="aialtg-api-key-input" placeholder="<?php echo esc_attr( $placeholder ); ?>" autocomplete="off" />
			<?php if ( $has_key ) : ?>
				<p class="description"><?php esc_html_e( 'A key is saved. Enter a new value only to replace it.', AIALTG_TEXT_DOMAIN ); ?></p>
			<?php endif; ?>
		</div>
		<?php
	}

	public function render_nvidia_api_keys_field() {
		$options     = get_option( self::$option_name );
		$options     = ( is_array( $options ) ) ? $options : array();
		$nvidia_keys = isset( $options['nvidia_api_keys'] ) ? $options['nvidia_api_keys'] : array();
		?>
		<div class="aialtg-nvidia-keys-wrap" id="aialtg-nvidia-keys-section" style="<?php echo ( isset( $options['provider'] ) && 'nvidia' === $options['provider'] ) ? '' : 'display:none;'; ?>">
			<p class="description" style="margin-bottom:8px;"><?php esc_html_e( 'Enter up to 3 NVIDIA API keys for round-robin parallel processing. Each key processes a different image simultaneously.', AIALTG_TEXT_DOMAIN ); ?></p>
			<?php for ( $i = 1; $i <= 3; $i++ ) :
				$has_key = isset( $nvidia_keys[ $i - 1 ] ) && '' !== $nvidia_keys[ $i - 1 ];
			?>
			<div class="aialtg-input-wrap" style="margin-bottom:6px;">
				<label style="display:inline-block;width:60px;font-weight:600;"><?php printf( esc_html__( 'Key %d:', AIALTG_TEXT_DOMAIN ), $i ); ?></label>
				<input type="password" name="<?php echo esc_attr( self::$option_name . '[nvidia_key_' . $i . ']' ); ?>" value="" class="regular-text aialtg-nvidia-key-input" placeholder="<?php echo esc_attr( $has_key ? __( 'Leave blank to keep existing key', AIALTG_TEXT_DOMAIN ) : 'nvapi-...' ); ?>" autocomplete="off" />
			</div>
			<?php endfor; ?>
			<p class="description"><?php esc_html_e( 'Leave empty to use the single API Key field above. Fill all 3 for maximum throughput.', AIALTG_TEXT_DOMAIN ); ?></p>
		</div>
		<?php
	}

	public function render_model_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$provider = isset( $options['provider'] ) ? $options['provider'] : 'openrouter';
		$providers = self::get_providers();
		$default   = isset( $providers[ $provider ] ) ? $providers[ $provider ]['default_model'] : 'google/gemini-2.5-flash-lite';
		$value     = isset( $options['model'] ) && ! empty( $options['model'] ) ? $options['model'] : $default;
		?>
		<div class="aialtg-model-field-container" data-current-value="<?php echo esc_attr( $value ); ?>" data-nonce="<?php echo esc_attr( wp_create_nonce( 'aialtg_models_nonce' ) ); ?>" data-provider="<?php echo esc_attr( $provider ); ?>">
			<!-- Skeleton Loader -->
			<div class="aialtg-skeleton-loader">
				<div class="aialtg-skeleton-input"></div>
			</div>
			<!-- Select Wrap -->
			<div class="aialtg-model-select-wrap" style="display: none;">
				<select id="aialtg-model-select" class="regular-text">
					<option value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $value ); ?></option>
				</select>
				<!-- Custom Input Wrap -->
				<div class="aialtg-custom-model-input-wrap" style="display: none;">
					<input type="text" id="aialtg-custom-model-input" class="regular-text" placeholder="e.g. google/gemini-2.5-flash-lite" />
				</div>
				<!-- Hidden real input that holds the actual submitted value -->
				<input type="hidden" name="<?php echo esc_attr( self::$option_name . '[model]' ); ?>" id="aialtg-model-real-input" value="<?php echo esc_attr( $value ); ?>" />
				<input type="hidden" name="<?php echo esc_attr( self::$option_name . '[provider]' ); ?>" id="aialtg-provider-real-input" value="<?php echo esc_attr( $provider ); ?>" />
				<p class="description"><?php esc_html_e( 'Select the language model to use. Models with 📷 support image analysis.', AIALTG_TEXT_DOMAIN ); ?></p>
			</div>
		</div>
		<?php
	}

	public function render_global_context_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$val     = isset( $options['global_context'] ) ? $options['global_context'] : '';
		?>
		<div class="aialtg-input-wrap">
			<textarea name="<?php echo esc_attr( self::$option_name . '[global_context]' ); ?>" rows="3" cols="50" class="large-text code"><?php echo esc_textarea( $val ); ?></textarea>
			<p class="description"><?php esc_html_e( 'Global instructions included in all requests. Use {post_title} and {post_content} variables here.', AIALTG_TEXT_DOMAIN ); ?></p>
		</div>
		<?php
	}

	public function render_allowed_formats_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$val     = isset( $options['allowed_formats'] ) ? $options['allowed_formats'] : 'jpg,jpeg,png,webp';
		?>
		<div class="aialtg-input-wrap">
			<input type="text" name="<?php echo esc_attr( self::$option_name . '[allowed_formats]' ); ?>" value="<?php echo esc_attr( $val ); ?>" class="large-text" />
			<p class="description"><?php esc_html_e( 'Comma-separated list (e.g., jpg, png, webp).', AIALTG_TEXT_DOMAIN ); ?></p>
		</div>
		<?php
	}

	public function render_enable_alt_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		?>
		<label class="aialtg-toggle">
			<input type="checkbox" name="<?php echo esc_attr( self::$option_name . '[enable_alt]' ); ?>" value="1" <?php checked( isset( $options['enable_alt'] ) ? $options['enable_alt'] : '1', '1' ); ?> />
			<span class="aialtg-toggle-slider"></span>
			<span class="aialtg-toggle-label"><?php esc_html_e( 'Enable Alt Text', AIALTG_TEXT_DOMAIN ); ?></span>
		</label>
		<?php
	}

	public function render_alt_prompt_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$val     = isset( $options['prompt'] ) ? $options['prompt'] : 'Generate a concise, descriptive alt text...';
		?>
		<div class="aialtg-input-wrap">
			<textarea name="<?php echo esc_attr( self::$option_name . '[prompt]' ); ?>" rows="3" cols="50" class="large-text code"><?php echo esc_textarea( $val ); ?></textarea>
		</div>
		<?php
	}

	public function render_enable_title_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		?>
		<label class="aialtg-toggle">
			<input type="checkbox" name="<?php echo esc_attr( self::$option_name . '[enable_title]' ); ?>" value="1" <?php checked( isset( $options['enable_title'] ) ? $options['enable_title'] : '1', '1' ); ?> />
			<span class="aialtg-toggle-slider"></span>
			<span class="aialtg-toggle-label"><?php esc_html_e( 'Enable Title', AIALTG_TEXT_DOMAIN ); ?></span>
		</label>
		<?php
	}

	public function render_title_prompt_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$val     = isset( $options['title_prompt'] ) ? $options['title_prompt'] : 'Generate a short title...';
		?>
		<div class="aialtg-input-wrap">
			<textarea name="<?php echo esc_attr( self::$option_name . '[title_prompt]' ); ?>" rows="2" cols="50" class="large-text code"><?php echo esc_textarea( $val ); ?></textarea>
		</div>
		<?php
	}

	public function render_enable_caption_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		?>
		<label class="aialtg-toggle">
			<input type="checkbox" name="<?php echo esc_attr( self::$option_name . '[enable_caption]' ); ?>" value="1" <?php checked( isset( $options['enable_caption'] ) ? $options['enable_caption'] : '1', '1' ); ?> />
			<span class="aialtg-toggle-slider"></span>
			<span class="aialtg-toggle-label"><?php esc_html_e( 'Enable Caption', AIALTG_TEXT_DOMAIN ); ?></span>
		</label>
		<?php
	}

	public function render_caption_prompt_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$val     = isset( $options['caption_prompt'] ) ? $options['caption_prompt'] : 'Generate a 1-2 sentence caption providing supplementary context about this image...';
		?>
		<div class="aialtg-input-wrap">
			<textarea name="<?php echo esc_attr( self::$option_name . '[caption_prompt]' ); ?>" rows="2" cols="50" class="large-text code"><?php echo esc_textarea( $val ); ?></textarea>
		</div>
		<?php
	}

	public function render_enable_description_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		?>
		<label class="aialtg-toggle">
			<input type="checkbox" name="<?php echo esc_attr( self::$option_name . '[enable_description]' ); ?>" value="1" <?php checked( isset( $options['enable_description'] ) ? $options['enable_description'] : '1', '1' ); ?> />
			<span class="aialtg-toggle-slider"></span>
			<span class="aialtg-toggle-label"><?php esc_html_e( 'Enable Description', AIALTG_TEXT_DOMAIN ); ?></span>
		</label>
		<?php
	}

	public function render_description_prompt_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$val     = isset( $options['description_prompt'] ) ? $options['description_prompt'] : 'Generate a detailed 2-4 sentence description of this image, including context, setting, and relevant details...';
		?>
		<div class="aialtg-input-wrap">
			<textarea name="<?php echo esc_attr( self::$option_name . '[description_prompt]' ); ?>" rows="3" cols="50" class="large-text code"><?php echo esc_textarea( $val ); ?></textarea>
		</div>
		<?php
	}

	public function render_save_gen_meta_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		?>
		<label class="aialtg-toggle">
			<input type="checkbox" name="<?php echo esc_attr( self::$option_name . '[save_gen_meta]' ); ?>" value="1" <?php checked( isset( $options['save_gen_meta'] ) ? $options['save_gen_meta'] : '0', '1' ); ?> />
			<span class="aialtg-toggle-slider"></span>
			<span class="aialtg-toggle-label"><?php esc_html_e( 'Save generation metadata (timestamp/source)', AIALTG_TEXT_DOMAIN ); ?></span>
		</label>
		<?php
	}

	public function render_cron_enabled_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();

		$val = isset( $options['cron_enabled'] ) ? $options['cron_enabled'] : '0';
		?>
		<label class="aialtg-toggle">
			<input type="checkbox" name="<?php echo esc_attr( self::$option_name . '[cron_enabled]' ); ?>" value="1" <?php checked( $val, '1' ); ?> />
			<span class="aialtg-toggle-slider"></span>
			<span class="aialtg-toggle-label"><?php esc_html_e( 'Enable Background Processing', AIALTG_TEXT_DOMAIN ); ?></span>
		</label>
		<?php
	}

	public function render_cron_batch_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$val     = isset( $options['cron_batch_size'] ) ? $options['cron_batch_size'] : 1;
		$nvidia_count = 0;
		if ( isset( $options['provider'] ) && 'nvidia' === $options['provider'] ) {
			$nvidia_count = count( Aialtg_Helpers::get_nvidia_keys( $options ) );
		}
		?>
		<div class="aialtg-input-group">
			<input type="number" name="<?php echo esc_attr( self::$option_name . '[cron_batch_size]' ); ?>" value="<?php echo esc_attr( $val ); ?>" class="small-text" min="1" max="10" />
			<span class="aialtg-suffix"><?php esc_html_e( 'images per run', AIALTG_TEXT_DOMAIN ); ?></span>
		</div>
		<p class="description"><?php esc_html_e( 'Keep this low (1-3) to avoid server timeouts.', AIALTG_TEXT_DOMAIN ); ?>
		<?php if ( $nvidia_count > 1 ) : ?>
			<?php
			printf(
				/* translators: %d: number of NVIDIA API keys */
				esc_html__( ' With %d NVIDIA keys configured, set batch size to at least %d to use each key per run.', AIALTG_TEXT_DOMAIN ),
				(int) $nvidia_count,
				(int) $nvidia_count
			);
			?>
		<?php endif; ?>
		</p>
		<?php
	}

	public function render_cron_interval_field() {
		$options = get_option( self::$option_name );
		$options = ( is_array( $options ) ) ? $options : array();
		$val     = isset( $options['cron_interval'] ) ? $options['cron_interval'] : 5;
		?>
		<div class="aialtg-input-group">
			<input type="number" name="<?php echo esc_attr( self::$option_name . '[cron_interval]' ); ?>" value="<?php echo esc_attr( $val ); ?>" class="small-text" min="1" />
			<span class="aialtg-suffix"><?php esc_html_e( 'minutes', AIALTG_TEXT_DOMAIN ); ?></span>
		</div>
		<?php
	}

	public function render_settings_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$logo_url = AIALTG_PLUGIN_URL . 'assets/images/icon-256x256.png';
		?>
		<div class="wrap aialtg-wrapper">
			<div class="aialtg-header">
				<div class="aialtg-header-brand">
					<img src="<?php echo esc_url( $logo_url ); ?>" alt="" class="aialtg-header-logo" width="56" height="56" />
					<div class="aialtg-header-text">
						<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
						<p class="aialtg-subtitle"><?php esc_html_e( 'WPStack-powered image metadata for SEO and accessibility', AIALTG_TEXT_DOMAIN ); ?></p>
					</div>
				</div>
			</div>

			<div class="aialtg-content-wrap">
				<form action="options.php" method="post" class="aialtg-main-form">
					<?php
					settings_fields( 'aialtg_plugin_options' );
					do_settings_sections( AIALTG_SLUG );

					echo '<div class="aialtg-submit-wrap">';
					submit_button( __( 'Save Settings', AIALTG_TEXT_DOMAIN ), 'primary large' );
					echo '</div>';
					?>
				</form>
			</div>

			<?php $this->render_brand_footer(); ?>
		</div>
		<?php
	}

	/**
	 * Brand footer with partner linkbacks.
	 */
	public function render_brand_footer() {
		?>
		<div class="aialtg-brand-footer">
			<p class="aialtg-brand-tagline"><?php esc_html_e( 'Built for WordPress image SEO and accessibility.', AIALTG_TEXT_DOMAIN ); ?></p>
			<p class="aialtg-brand-links">
				<?php esc_html_e( 'A product by', AIALTG_TEXT_DOMAIN ); ?>
				<a href="<?php echo esc_url( AIALTG_BRAND_WPSTACK ); ?>" target="_blank" rel="noopener noreferrer">WPStack</a>
				<span class="aialtg-brand-sep" aria-hidden="true">&middot;</span>
				<a href="<?php echo esc_url( AIALTG_BRAND_MIRACUVES ); ?>" target="_blank" rel="noopener noreferrer">Miracuves</a>
			</p>
		</div>
		<?php
	}
}