<?php
/**
 * Content settings class for AgenticWP plugin.
 *
 * @package AgenticWP
 */

namespace Agentic_WP;

use Agentic_WP\Error_Handler;

defined( 'ABSPATH' ) || exit;

	/**
	 * Handles content generation settings.
	 */
class Settings_Content extends Settings_Base {

	/**
	 * Maximum number of sample prompts allowed.
	 *
	 * @since 1.0.0
	 * @var int
	 */
	protected const MAX_SAMPLE_PROMPTS = 12;

	/**
	 * Registers content settings hooks.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		add_action( 'wp_ajax_agenticwp_save_message_history_limit', array( $this, 'handle_ajax_save_message_history_limit' ) );
		add_action( 'wp_ajax_agenticwp_save_writing_directions', array( $this, 'handle_ajax_save_writing_directions' ) );
		add_action( 'wp_ajax_agenticwp_save_sample_prompts', array( $this, 'handle_ajax_save_sample_prompts' ) );
	}

	/**
	 * Registers content settings fields.
	 *
	 * @since 1.0.0
	 */
	public function register_settings(): void {
		register_setting(
			'agentic_wp',
			'agentic_wp_message_history_limit',
			array(
				'type'              => 'integer',
				'sanitize_callback' => array( $this, 'sanitize_message_history_limit' ),
				'default'           => 50,
			)
		);

		register_setting(
			'agentic_wp',
			'agentic_wp_create_post_directions',
			array(
				'sanitize_callback' => array( $this, 'sanitize_writing_directions' ),
			)
		);

		register_setting(
			'agentic_wp',
			'agentic_wp_sample_prompts',
			array(
				'type'              => 'array',
				'sanitize_callback' => array( $this, 'sanitize_sample_prompts' ),
				'default'           => array(),
			)
		);

		register_setting(
			'agentic_wp',
			'agentic_wp_default_image_id',
			array(
				'type'              => 'integer',
				'sanitize_callback' => 'absint',
				'default'           => 0,
			)
		);
	}

	/**
	 * Add content-related settings fields.
	 *
	 * @param string $chat_section_id    The chat settings section ID.
	 * @param string $content_section_id The content settings section ID.
	 */
	public function add_settings_fields( string $chat_section_id, string $content_section_id ): void {
		add_settings_field(
			'message_history_limit',
			'Message History Limit',
			array( $this, 'message_history_limit_field' ),
			'agentic_wp',
			$chat_section_id
		);

		add_settings_field(
			'create_post_directions',
			'Style Guidance',
			array( $this, 'writing_directions_field' ),
			'agentic_wp',
			$content_section_id
		);

		add_settings_field(
			'default_placeholder_image',
			__( 'Default Placeholder Image', 'agenticwp' ),
			array( $this, 'default_image_field' ),
			'agentic_wp',
			$content_section_id
		);
	}

	/**
	 * Renders message history limit field.
	 *
	 * @since 1.0.0
	 */
	public function message_history_limit_field() {
		$value = get_option( 'agentic_wp_message_history_limit', 50 );
		?>
		<input type="number" id="agentic_wp_message_history_limit" name="agentic_wp_message_history_limit" value="<?php echo esc_attr( $value ); ?>" class="regular-text" min="10" max="50" step="10" />
		<p class="description"><?php esc_html_e( 'How many previous chat messages the assistant can remember (10-50). Fewer messages save money, but the assistant might forget earlier conversation details.', 'agenticwp' ); ?></p>
		<?php
	}

	/**
	 * Renders message history limit tooltip.
	 *
	 * @since 1.0.0
	 */
	public function message_history_limit_tooltip() {
		$tooltip_content  = '<p><strong>' . esc_html__( 'How Message History Works:', 'agenticwp' ) . '</strong></p>';
		$tooltip_content .= '<p>' . esc_html__( 'The AI assistant reviews your recent chat messages to understand context and provide better responses. More messages mean better context, but also higher costs.', 'agenticwp' ) . '</p>';
		$tooltip_content .= '<ul>';
		$tooltip_content .= '<li><strong>' . esc_html__( '10-20 messages', 'agenticwp' ) . '</strong> - ' . esc_html__( 'Best for simple tasks and quick questions. Keeps costs low.', 'agenticwp' ) . '</li>';
		$tooltip_content .= '<li><strong>' . esc_html__( '30-40 messages', 'agenticwp' ) . '</strong> - ' . esc_html__( 'Good balance for most conversations and ongoing projects.', 'agenticwp' ) . '</li>';
		$tooltip_content .= '<li><strong>' . esc_html__( '50 messages', 'agenticwp' ) . '</strong> - ' . esc_html__( 'Maximum context for complex discussions spanning multiple topics.', 'agenticwp' ) . '</li>';
		$tooltip_content .= '</ul>';

		printf(
			'<div id="message-history-limit-tooltip" class="agenticwp-tooltip" role="tooltip" hidden>%s</div>',
			wp_kses_post( $tooltip_content )
		);
	}

	/**
	 * Renders writing directions textarea field.
	 *
	 * @since 1.0.0
	 */
	public function writing_directions_field() {
		$value = get_option( 'agentic_wp_create_post_directions', '' );

		$sample_prompts = $this->get_effective_sample_prompts();
		$next_index     = count( $sample_prompts );

		echo '<div class="agenticwp-writing-directions-wrapper">';
		echo '<div class="agenticwp-writing-directions-toolbar">';
		echo '<label for="agenticwp-sample-prompts" class="screen-reader-text">' . esc_html__( 'Choose a style', 'agenticwp' ) . '</label>';
		echo '<select id="agenticwp-sample-prompts" class="agenticwp-sample-prompts">';
		echo '<option value="">' . esc_html__( 'Choose a style…', 'agenticwp' ) . '</option>';
		foreach ( $sample_prompts as $prompt ) {
			if ( empty( $prompt['content'] ) ) {
				continue;
			}
			$label = '' !== $prompt['label'] ? $prompt['label'] : __( 'Sample example', 'agenticwp' );
			echo '<option value="' . esc_attr( $prompt['content'] ) . '">' . esc_html( $label ) . '</option>';
		}
		echo '</select>';
		echo '<button type="button" class="button button-secondary agenticwp-manage-prompts-toggle">';
		echo '<span class="dashicons dashicons-admin-settings"></span>';
		echo esc_html__( 'Manage styles', 'agenticwp' );
		echo '</button>';
		echo '</div>';
		echo '<textarea id="agentic_wp_create_post_directions" name="agentic_wp_create_post_directions" rows="8" class="large-text code" maxlength="' . esc_attr( self::MAX_CREATE_POST_DIRECTIONS ) . '">' . esc_textarea( (string) $value ) . '</textarea>';
		echo '<div class="agenticwp-character-counter">';
		echo '<p class="description">' . esc_html__( 'Optional: Define your writing style, tone, target audience, or content approach.', 'agenticwp' ) . '</p>';
		echo '<span id="agenticwp-char-count">0</span>/' . esc_html( self::MAX_CREATE_POST_DIRECTIONS ) . ' characters';
		echo '</div>';
		echo '<div class="agenticwp-modal-backdrop agenticwp-prompts-modal" style="display: none;">';
		echo '<div class="agenticwp-modal-container">';
		echo '<div class="agenticwp-modal-header">';
		echo '<h3>' . esc_html__( 'Manage Styles', 'agenticwp' ) . '</h3>';
		echo '<button type="button" class="agenticwp-modal-close" aria-label="' . esc_attr__( 'Close modal', 'agenticwp' ) . '">&times;</button>';
		echo '</div>';
		echo '<div class="agenticwp-modal-body">';
		echo '<p class="description">' . esc_html__( 'Create and organize reusable writing style presets. Each style defines the tone, voice, and approach the AI should use when creating content. Select a style from the dropdown to instantly apply it to your writing instructions.', 'agenticwp' ) . '</p>';
		echo '<div class="agenticwp-sample-prompts-manager" data-next-index="' . esc_attr( (string) $next_index ) . '" data-max-prompts="' . esc_attr( (string) self::MAX_SAMPLE_PROMPTS ) . '">';
		echo '<div class="agenticwp-prompts-grid">';
		foreach ( $sample_prompts as $index => $prompt ) {
			$this->render_sample_prompt_card( $index, $prompt['label'], $prompt['content'] );
		}
		echo '</div>';
		echo '</div>';
		echo '</div>';
		echo '<div class="agenticwp-modal-footer">';
		echo '<button type="button" class="button button-secondary agenticwp-add-sample-prompt">';
		echo '<span class="dashicons dashicons-plus-alt2"></span>';
		echo esc_html__( 'Add New Style', 'agenticwp' );
		echo '</button>';
		echo '<button type="button" class="button button-primary agenticwp-save-prompts">';
		echo '<span class="dashicons dashicons-saved"></span>';
		echo esc_html__( 'Save Changes', 'agenticwp' );
		echo '</button>';
		echo '</div>';
		echo '</div>';
		echo '</div>';

		$template_markup = $this->get_sample_prompt_template_markup();
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Template markup is escaped within get_sample_prompt_template_markup().
		echo '<script type="text/template" id="agenticwp-sample-prompt-template">' . $template_markup . '</script>';
		echo '</div>';
	}

	/**
	 * Renders sample prompt card HTML.
	 *
	 * @since 1.0.0
	 * @param int    $index   The prompt index.
	 * @param string $label   The prompt label.
	 * @param string $content The prompt content.
	 */
	protected function render_sample_prompt_card( int $index, string $label, string $content ): void {
		$index_attr      = (string) $index;
		$content_preview = '' !== $content ? ( mb_strlen( $content ) > 100 ? mb_substr( $content, 0, 100 ) . '…' : $content ) : '';

		echo '<div class="agenticwp-prompt-card" data-index="' . esc_attr( $index_attr ) . '">';
		echo '<div class="agenticwp-prompt-card-header">';
		echo '<h4 class="agenticwp-prompt-card-title">' . ( '' !== $label ? esc_html( $label ) : esc_html__( 'Untitled Example', 'agenticwp' ) ) . '</h4>';
		echo '<button type="button" class="agenticwp-prompt-card-expand" aria-label="' . esc_attr__( 'Edit example', 'agenticwp' ) . '">';
		echo '<span class="dashicons dashicons-edit"></span>';
		echo '</button>';
		echo '</div>';
		if ( '' !== $content_preview ) {
			echo '<div class="agenticwp-prompt-card-preview">' . esc_html( $content_preview ) . '</div>';
		}
		echo '<div class="agenticwp-prompt-card-expanded" style="display: none;">';
		echo '<div class="agenticwp-sample-prompt-field">';
		echo '<label for="agenticwp-sample-prompt-label-' . esc_attr( $index_attr ) . '">' . esc_html__( 'Example label', 'agenticwp' ) . '</label>';
		echo '<input type="text" id="agenticwp-sample-prompt-label-' . esc_attr( $index_attr ) . '" name="agentic_wp_sample_prompts[' . esc_attr( $index_attr ) . '][label]" value="' . esc_attr( $label ) . '" class="regular-text agenticwp-sample-prompt-label" />';
		echo '</div>';
		echo '<div class="agenticwp-sample-prompt-field">';
		echo '<label for="agenticwp-sample-prompt-content-' . esc_attr( $index_attr ) . '">' . esc_html__( 'Example content', 'agenticwp' ) . '</label>';
		echo '<textarea id="agenticwp-sample-prompt-content-' . esc_attr( $index_attr ) . '" name="agentic_wp_sample_prompts[' . esc_attr( $index_attr ) . '][content]" rows="4" class="large-text agenticwp-sample-prompt-content" maxlength="' . esc_attr( self::MAX_CREATE_POST_DIRECTIONS ) . '">' . esc_textarea( $content ) . '</textarea>';
		echo '</div>';
		echo '<div class="agenticwp-prompt-card-actions">';
		echo '<button type="button" class="button-link-delete agenticwp-remove-sample-prompt">';
		echo '<span class="dashicons dashicons-trash"></span>';
		echo esc_html__( 'Remove', 'agenticwp' );
		echo '</button>';
		echo '</div>';
		echo '</div>';
		echo '</div>';
	}

	/**
	 * Returns sample prompt template markup.
	 *
	 * @since 1.0.0
	 * @return string The template HTML markup.
	 */
	protected function get_sample_prompt_template_markup(): string {
		ob_start();
		?>
<div class="agenticwp-prompt-card" data-index="<?php echo esc_attr( '__index__' ); ?>">
	<div class="agenticwp-prompt-card-header">
		<h4 class="agenticwp-prompt-card-title"><?php echo esc_html__( 'New Style', 'agenticwp' ); ?></h4>
		<button type="button" class="agenticwp-prompt-card-expand" aria-label="<?php echo esc_attr__( 'Edit example', 'agenticwp' ); ?>">
			<span class="dashicons dashicons-edit"></span>
		</button>
	</div>
	<div class="agenticwp-prompt-card-expanded">
		<div class="agenticwp-sample-prompt-field">
			<label for="agenticwp-sample-prompt-label-<?php echo esc_attr( '__index__' ); ?>"><?php echo esc_html__( 'Style label', 'agenticwp' ); ?></label>
			<input type="text" id="agenticwp-sample-prompt-label-<?php echo esc_attr( '__index__' ); ?>" name="agentic_wp_sample_prompts[__index__][label]" value="" class="regular-text agenticwp-sample-prompt-label" />
		</div>
		<div class="agenticwp-sample-prompt-field">
			<label for="agenticwp-sample-prompt-content-<?php echo esc_attr( '__index__' ); ?>"><?php echo esc_html__( 'Style content', 'agenticwp' ); ?></label>
			<textarea id="agenticwp-sample-prompt-content-<?php echo esc_attr( '__index__' ); ?>" name="agentic_wp_sample_prompts[__index__][content]" rows="4" class="large-text agenticwp-sample-prompt-content" maxlength="<?php echo esc_attr( self::MAX_CREATE_POST_DIRECTIONS ); ?>"></textarea>
		</div>
		<div class="agenticwp-prompt-card-actions">
			<button type="button" class="button-link-delete agenticwp-remove-sample-prompt">
				<span class="dashicons dashicons-trash"></span>
				<?php echo esc_html__( 'Remove', 'agenticwp' ); ?>
			</button>
		</div>
	</div>
</div>
		<?php
		return (string) ob_get_clean();
	}

	/**
	 * Sanitize the managed sample prompts array.
	 *
	 * @param mixed $input Raw input from the settings form.
	 * @return array
	 */
	public function sanitize_sample_prompts( $input ): array {
		if ( ! is_array( $input ) ) {
			return array();
		}

		$sanitized = array();
		foreach ( $input as $prompt ) {
			if ( ! is_array( $prompt ) ) {
				continue;
			}

			$label   = isset( $prompt['label'] ) ? sanitize_text_field( (string) $prompt['label'] ) : '';
			$content = isset( $prompt['content'] ) ? sanitize_textarea_field( (string) $prompt['content'] ) : '';

			if ( '' === $label && '' === $content ) {
				continue;
			}

			if ( '' === $content ) {
				continue;
			}

			if ( function_exists( 'mb_strlen' ) && mb_strlen( $label ) > 160 ) {
				$label = mb_substr( $label, 0, 160 );
			} elseif ( strlen( $label ) > 160 ) {
				$label = substr( $label, 0, 160 );
			}

			if ( function_exists( 'mb_strlen' ) && mb_strlen( $content ) > self::MAX_CREATE_POST_DIRECTIONS ) {
				$content = mb_substr( $content, 0, self::MAX_CREATE_POST_DIRECTIONS );
			} elseif ( strlen( $content ) > self::MAX_CREATE_POST_DIRECTIONS ) {
				$content = substr( $content, 0, self::MAX_CREATE_POST_DIRECTIONS );
			}

			if ( '' === $label && '' !== $content ) {
				$label = sanitize_text_field( wp_trim_words( $content, 6, '…' ) );
			}

			if ( '' === $label ) {
				$label = sanitize_text_field( __( 'Untitled style', 'agenticwp' ) );
			}

			$sanitized[] = array(
				'label'   => $label,
				'content' => $content,
			);

			if ( count( $sanitized ) >= self::MAX_SAMPLE_PROMPTS ) {
				break;
			}
		}

		return $sanitized;
	}

	/**
	 * Retrieves effective sample prompts list.
	 *
	 * @since 1.0.0
	 * @return array The sample prompts array.
	 */
	protected function get_effective_sample_prompts(): array {
		$raw_prompts = get_option( 'agentic_wp_sample_prompts', false );
		if ( false === $raw_prompts ) {
			return $this->get_default_sample_prompts();
		}

		$prompts = $this->sanitize_sample_prompts( $raw_prompts );
		if ( empty( $prompts ) ) {
			return array(
				array(
					'label'   => '',
					'content' => '',
				),
			);
		}

		return $prompts;
	}

	/**
	 * Returns default sample prompts array.
	 *
	 * @since 1.0.0
	 * @return array The default prompts array.
	 */
	protected function get_default_sample_prompts(): array {
		return array(
			array(
				'label'   => __( 'Professional & Approachable', 'agenticwp' ),
				'content' => __( 'Write in a professional yet friendly tone. Use clear, jargon-free language. Include practical examples and actionable advice. Structure content with clear headings and bullet points for easy scanning.', 'agenticwp' ),
			),
			array(
				'label'   => __( 'Authoritative Expert', 'agenticwp' ),
				'content' => __( 'Write with confidence and expertise. Use industry terminology appropriately. Support claims with data or examples. Maintain a formal tone while remaining accessible to your target audience.', 'agenticwp' ),
			),
			array(
				'label'   => __( 'Casual & Conversational', 'agenticwp' ),
				'content' => __( 'Write as if talking to a friend. Use contractions, ask rhetorical questions, and include personal anecdotes when appropriate. Keep sentences short and paragraphs brief for easy reading.', 'agenticwp' ),
			),
			array(
				'label'   => __( 'Educational & Instructional', 'agenticwp' ),
				'content' => __( 'Focus on teaching and explaining concepts clearly. Use step-by-step instructions, include helpful tips and warnings. Anticipate common questions and address them proactively. End with a summary or next steps.', 'agenticwp' ),
			),
		);
	}

	/**
	 * Returns maximum sample prompts limit.
	 *
	 * @since 1.0.0
	 * @return int The maximum number of prompts.
	 */
	public static function get_max_sample_prompts(): int {
		return self::MAX_SAMPLE_PROMPTS;
	}

	/**
	 * Renders default image selection field.
	 *
	 * @since 1.0.0
	 */
	public function default_image_field() {
		$attachment_id = (int) get_option( 'agentic_wp_default_image_id', 0 );

		$preview_url = '';
		if ( $attachment_id > 0 ) {
			$src = wp_get_attachment_image_src( $attachment_id, 'medium' );
			if ( is_array( $src ) && ! empty( $src[0] ) ) {
				$preview_url = (string) $src[0];
			}
		}
		if ( '' === $preview_url ) {
			$preview_url = self::get_bundled_default_image_url();
		}

		$has_attachment = $attachment_id > 0;

		echo '<div class="agenticwp-default-image-field" data-default-url="' . esc_url( self::get_bundled_default_image_url() ) . '">';
		echo '<input type="hidden" id="agenticwp-default-image-id" name="agentic_wp_default_image_id" value="' . esc_attr( (string) $attachment_id ) . '" />';

		echo '<div class="agenticwp-image-selector-card">';
		echo '<div class="agenticwp-image-selector-preview">';
		echo '<img src="' . esc_url( $preview_url ) . '" alt="' . esc_attr__( 'Default placeholder image preview', 'agenticwp' ) . '" class="agenticwp-preview-img" />';
		echo '</div>';

		echo '<div class="agenticwp-image-selector-content">';
		echo '<div class="agenticwp-image-selector-info">';
		echo '<h4 class="agenticwp-image-selector-title">' . esc_html__( 'Temporary Image for New Content', 'agenticwp' ) . '</h4>';
		echo '<p class="agenticwp-image-selector-desc">' . esc_html__( 'Choose an image that will appear in your content while it\'s being created. You can always replace it with the perfect image later when editing your post.', 'agenticwp' ) . '</p>';
		echo '</div>';

		echo '<div class="agenticwp-image-selector-actions">';
		echo '<button type="button" class="button button-primary agenticwp-select-default-image">';
		echo '<span class="dashicons dashicons-format-image"></span>';
		echo esc_html__( 'Select Image', 'agenticwp' );
		echo '</button>';
		echo '<button type="button" class="button agenticwp-remove-default-image"' . ( $has_attachment ? '' : ' style="display:none;"' ) . '>';
		echo '<span class="dashicons dashicons-trash"></span>';
		echo esc_html__( 'Remove', 'agenticwp' );
		echo '</button>';
		echo '</div>';
		echo '</div>';
		echo '</div>';

		echo '<p class="description">' . esc_html__( 'If you don\'t select one, we\'ll use a simple AgenticWP logo as the temporary image.', 'agenticwp' ) . '</p>';
		echo '</div>';
	}

	/**
	 * Sanitize message history limit setting with range validation.
	 *
	 * @param mixed $input The message history limit input value.
	 * @return int The sanitized value within the allowed range (10-50).
	 */
	public function sanitize_message_history_limit( $input ) {
		$value = intval( $input );

		if ( $value < 10 ) {
			$value = 10;
		} elseif ( $value > 50 ) {
			$value = 50;
		}

		return $value;
	}

	/**
	 * Sanitize writing directions textarea with length validation.
	 *
	 * @param string $input Raw textarea input.
	 * @return string Sanitized and length-limited value.
	 */
	public function sanitize_writing_directions( $input ): string {
		$sanitized = sanitize_textarea_field( (string) $input );
		$max       = self::MAX_CREATE_POST_DIRECTIONS;
		if ( function_exists( 'mb_strlen' ) && function_exists( 'mb_substr' ) ) {
			if ( mb_strlen( $sanitized ) > $max ) {
				$sanitized = mb_substr( $sanitized, 0, $max );
			}
		} elseif ( strlen( $sanitized ) > $max ) {
				$sanitized = substr( $sanitized, 0, $max );
		}
		return $sanitized;
	}

	/**
	 * Retrieves message history limit setting.
	 *
	 * @since 1.0.0
	 * @return int The message history limit.
	 */
	public static function get_message_history_limit(): int {
		return (int) get_option( 'agentic_wp_message_history_limit', 50 );
	}

	/**
	 * Handle AJAX request to save message history limit.
	 */
	public function handle_ajax_save_message_history_limit() {
		try {
			$this->verify_ajax_request( 'agenticwp_save_message_history_limit' );

			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified via verify_ajax_request() above.
			$limit = intval( $_POST['value'] ?? 0 );
			if ( $limit <= 0 ) {
				Error_Handler::log_error(
					'ajax_settings',
					'Invalid message history limit',
					array( 'limit' => $limit )
				);
				wp_send_json_error(
					array( 'message' => __( 'Message history limit is required.', 'agenticwp' ) ),
					400
				);
			}

			if ( $limit < 10 ) {
				$limit = 10;
			} elseif ( $limit > 50 ) {
				$limit = 50;
			}

			update_option( 'agentic_wp_message_history_limit', $limit );

			Error_Handler::debug_log(
				'Message history limit updated',
				array( 'limit' => $limit )
			);

			wp_send_json_success(
				array(
					'message' => __( 'Message history limit updated successfully.', 'agenticwp' ),
					'value'   => $limit,
				)
			);
		} catch ( \Throwable $e ) {
			Error_Handler::log_error(
				'ajax_settings',
				'Failed to save message history limit: ' . $e->getMessage(),
				array( 'trace' => $e->getTraceAsString() )
			);
			wp_send_json_error(
				array( 'message' => __( 'Failed to update message history limit.', 'agenticwp' ) ),
				500
			);
		}
	}

	/**
	 * Handle AJAX request to save writing directions.
	 */
	public function handle_ajax_save_writing_directions() {
		try {
			$this->verify_ajax_request( 'agenticwp_save_writing_directions' );

			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified via verify_ajax_request() above.
			$value = sanitize_textarea_field( wp_unslash( $_POST['value'] ?? '' ) );
			$value = $this->sanitize_writing_directions( $value );

			update_option( 'agentic_wp_create_post_directions', $value );

			Error_Handler::debug_log(
				'Writing directions updated',
				array( 'length' => strlen( $value ) )
			);

			wp_send_json_success(
				array(
					'message' => __( 'Writing directions updated successfully.', 'agenticwp' ),
					'value'   => $value,
				)
			);
		} catch ( \Throwable $e ) {
			Error_Handler::log_error(
				'ajax_settings',
				'Failed to save writing directions: ' . $e->getMessage(),
				array( 'trace' => $e->getTraceAsString() )
			);
			wp_send_json_error(
				array( 'message' => __( 'Failed to update writing directions.', 'agenticwp' ) ),
				500
			);
		}
	}

	/**
	 * Handle AJAX request to save sample prompts.
	 */
	public function handle_ajax_save_sample_prompts() {
		try {
			$this->verify_ajax_request( 'agenticwp_save_sample_prompts' );

			// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified via verify_ajax_request() above.
			// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized in sanitize_sample_prompts() below.
			$prompts = isset( $_POST['prompts'] ) ? wp_unslash( $_POST['prompts'] ) : array();
			// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			// phpcs:enable WordPress.Security.NonceVerification.Missing

			if ( ! is_array( $prompts ) ) {
				Error_Handler::log_error(
					'ajax_settings',
					'Invalid prompts data type',
					array( 'type' => gettype( $prompts ) )
				);
				wp_send_json_error(
					array( 'message' => __( 'Invalid prompts data.', 'agenticwp' ) ),
					400
				);
			}

			$sanitized_prompts = $this->sanitize_sample_prompts( $prompts );

			update_option( 'agentic_wp_sample_prompts', $sanitized_prompts );

			Error_Handler::debug_log(
				'Sample prompts updated',
				array( 'count' => count( $sanitized_prompts ) )
			);

			wp_send_json_success(
				array(
					'message' => __( 'Style examples updated successfully.', 'agenticwp' ),
					'prompts' => $sanitized_prompts,
				)
			);
		} catch ( \Throwable $e ) {
			Error_Handler::log_error(
				'ajax_settings',
				'Failed to save sample prompts: ' . $e->getMessage(),
				array( 'trace' => $e->getTraceAsString() )
			);
			wp_send_json_error(
				array( 'message' => __( 'Failed to update style examples.', 'agenticwp' ) ),
				500
			);
		}
	}

	/**
	 * Retrieves post creation directions text.
	 *
	 * @since 1.0.0
	 * @return string The post creation directions.
	 */
	public static function get_create_post_directions(): string {
		return (string) get_option( 'agentic_wp_create_post_directions', '' );
	}

	/**
	 * Retrieves session timeout in minutes.
	 *
	 * @since 1.0.0
	 * @return int The timeout value in minutes.
	 */
	public static function get_session_timeout_min(): int {
		return (int) self::BUILD_SESSION_TIMEOUT_MIN;
	}

	/**
	 * Get the post schema used by content generation.
	 *
	 * Returns the built-in default schema, allowing overrides via the
	 * `agentic_wp_post_schema` filter. This removes DB persistence so there is
	 * a single source of truth for the schema.
	 *
	 * @return array
	 */
	public static function get_post_schema(): array {
		$schema = self::DEFAULT_POST_SCHEMA;
		/**
		 * Filters the post schema used by the create_post tool.
		 *
		 * The post schema defines available post types, taxonomies, and custom fields
		 * that the AI agent can use when creating content. This filter allows developers
		 * to customize which post types and fields are exposed to the agent.
		 *
		 * @hook agentic_wp_post_schema
		 * @since 1.0.0
		 *
		 * @param array $schema {
		 *     Default schema array containing post types and taxonomies configuration.
		 *
		 *     @type array $post_types Available post types with their settings.
		 *     @type array $taxonomies Available taxonomies with their settings.
		 * }
		 * @return array The filtered post schema configuration.
		 */
		return apply_filters( 'agentic_wp_post_schema', $schema );
	}


	/**
	 * Retrieves default image attachment ID.
	 *
	 * @since 1.0.0
	 * @return int The attachment ID.
	 */
	public static function get_default_image_id(): int {
		return (int) get_option( 'agentic_wp_default_image_id', 0 );
	}

	/**
	 * Retrieves default image URL.
	 *
	 * @since 1.0.0
	 * @return string The image URL.
	 */
	public static function get_default_image_url(): string {
		$id = self::get_default_image_id();
		if ( $id > 0 ) {
			$url = wp_get_attachment_url( $id );
			if ( is_string( $url ) && '' !== $url ) {
				return $url;
			}
		}
		return self::get_bundled_default_image_url();
	}
}
