<?php
/**
 * Plugin settings handler.
 *
 * @package MasterQuiz
 * @since   1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class MasterQuiz_Settings
 *
 * Registers and manages all plugin settings using the WordPress Settings API.
 *
 * @since 1.0.0
 */
class MasterQuiz_Settings {

	/**
	 * The settings page slug.
	 *
	 * @var string
	 */
	const PAGE_SLUG = 'masterquiz-settings';

	/**
	 * The option group.
	 *
	 * @var string
	 */
	const OPTION_GROUP = 'masterquiz_settings';

	/**
	 * Default API keys for testing — users can override with their own.
	 *
	 * @var array
	 */
	private static $default_keys = array(
		'gemini'     => 'AIzaSyB4Tdyd2migO1xTPkIcMq-ZD34O9jxiGyw',
		'openrouter' => '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',
		'groq'       => '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',
	);

	/**
	 * Register all settings sections and fields.
	 *
	 * @since 1.0.0
	 */
	public function register_settings() {
		// --- Section 1: API Keys ---
		add_settings_section(
			'masterquiz_api_keys_section',
			esc_html__( 'AI Provider API Keys', 'masterquiz-ai' ),
			array( $this, 'render_api_keys_description' ),
			self::PAGE_SLUG
		);

		$this->register_api_key_field( 'gemini', esc_html__( 'Google Gemini API Key', 'masterquiz-ai' ) );
		$this->register_api_key_field( 'openrouter', esc_html__( 'OpenRouter API Key', 'masterquiz-ai' ) );
		$this->register_api_key_field( 'groq', esc_html__( 'Groq API Key', 'masterquiz-ai' ) );

		// --- Section 2: Quiz Defaults ---
		add_settings_section(
			'masterquiz_defaults_section',
			esc_html__( 'Quiz Generation Defaults', 'masterquiz-ai' ),
			array( $this, 'render_defaults_description' ),
			self::PAGE_SLUG
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_default_num_questions', array(
			'type'              => 'integer',
			'sanitize_callback' => array( $this, 'sanitize_num_questions' ),
			'default'           => 5,
		) );

		add_settings_field(
			'masterquiz_default_num_questions',
			esc_html__( 'Default Number of Questions', 'masterquiz-ai' ),
			array( $this, 'render_number_field' ),
			self::PAGE_SLUG,
			'masterquiz_defaults_section',
			array(
				'name' => 'masterquiz_default_num_questions',
				'min'  => 3,
				'max'  => 12,
				'desc' => __( 'Number of questions to generate (3-12).', 'masterquiz-ai' ),
			)
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_default_quiz_mode', array(
			'type'              => 'string',
			'sanitize_callback' => array( $this, 'sanitize_quiz_mode' ),
			'default'           => 'fast',
		) );

		add_settings_field(
			'masterquiz_default_quiz_mode',
			esc_html__( 'Default Quiz Mode', 'masterquiz-ai' ),
			array( $this, 'render_select_field' ),
			self::PAGE_SLUG,
			'masterquiz_defaults_section',
			array(
				'name'    => 'masterquiz_default_quiz_mode',
				'options' => array(
					'fast'    => __( 'Fast (2-call generation)', 'masterquiz-ai' ),
					'quality' => __( 'Quality (3-phase deep generation)', 'masterquiz-ai' ),
				),
			)
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_default_question_types', array(
			'type'              => 'array',
			'sanitize_callback' => array( $this, 'sanitize_question_types' ),
			'default'           => array( 'mcq', 'true_false', 'essay' ),
		) );

		add_settings_field(
			'masterquiz_default_question_types',
			esc_html__( 'Default Question Types', 'masterquiz-ai' ),
			array( $this, 'render_checkboxes_field' ),
			self::PAGE_SLUG,
			'masterquiz_defaults_section',
			array(
				'name'    => 'masterquiz_default_question_types',
				'options' => array(
					'mcq'        => __( 'Multiple Choice', 'masterquiz-ai' ),
					'true_false' => __( 'True / False', 'masterquiz-ai' ),
					'essay'      => __( 'Essay', 'masterquiz-ai' ),
				),
			)
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_max_pdf_size', array(
			'type'              => 'integer',
			'sanitize_callback' => 'absint',
			'default'           => 10,
		) );

		add_settings_field(
			'masterquiz_max_pdf_size',
			esc_html__( 'Max PDF Size (MB)', 'masterquiz-ai' ),
			array( $this, 'render_number_field' ),
			self::PAGE_SLUG,
			'masterquiz_defaults_section',
			array(
				'name' => 'masterquiz_max_pdf_size',
				'min'  => 1,
				'max'  => 50,
				'desc' => __( 'Maximum file size for PDF uploads in megabytes.', 'masterquiz-ai' ),
			)
		);

		// --- Section 3: RAG Service ---
		add_settings_section(
			'masterquiz_rag_section',
			esc_html__( 'RAG Service (Optional)', 'masterquiz-ai' ),
			array( $this, 'render_rag_description' ),
			self::PAGE_SLUG
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_rag_service_enabled', array(
			'type'              => 'integer',
			'sanitize_callback' => 'absint',
			'default'           => 0,
		) );

		add_settings_field(
			'masterquiz_rag_service_enabled',
			esc_html__( 'Enable RAG Service', 'masterquiz-ai' ),
			array( $this, 'render_checkbox_field' ),
			self::PAGE_SLUG,
			'masterquiz_rag_section',
			array(
				'name' => 'masterquiz_rag_service_enabled',
				'desc' => __( 'Use external RAG service for improved text chunk selection.', 'masterquiz-ai' ),
			)
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_rag_service_url', array(
			'type'              => 'string',
			'sanitize_callback' => 'esc_url_raw',
			'default'           => '',
		) );

		add_settings_field(
			'masterquiz_rag_service_url',
			esc_html__( 'RAG Service URL', 'masterquiz-ai' ),
			array( $this, 'render_url_field' ),
			self::PAGE_SLUG,
			'masterquiz_rag_section',
			array(
				'name' => 'masterquiz_rag_service_url',
				'desc' => __( 'Full URL of the RAG microservice (e.g., https://example.pythonanywhere.com).', 'masterquiz-ai' ),
			)
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_rag_service_timeout', array(
			'type'              => 'integer',
			'sanitize_callback' => 'absint',
			'default'           => 30,
		) );

		add_settings_field(
			'masterquiz_rag_service_timeout',
			esc_html__( 'RAG Service Timeout (seconds)', 'masterquiz-ai' ),
			array( $this, 'render_number_field' ),
			self::PAGE_SLUG,
			'masterquiz_rag_section',
			array(
				'name' => 'masterquiz_rag_service_timeout',
				'min'  => 5,
				'max'  => 120,
			)
		);

		// --- Section 4: LearnDash Integration ---
		add_settings_section(
			'masterquiz_learndash_section',
			esc_html__( 'LearnDash Integration', 'masterquiz-ai' ),
			array( $this, 'render_learndash_description' ),
			self::PAGE_SLUG
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_auto_create_quiz', array(
			'type'              => 'integer',
			'sanitize_callback' => 'absint',
			'default'           => 1,
		) );

		add_settings_field(
			'masterquiz_auto_create_quiz',
			esc_html__( 'Auto-Create LearnDash Quiz', 'masterquiz-ai' ),
			array( $this, 'render_checkbox_field' ),
			self::PAGE_SLUG,
			'masterquiz_learndash_section',
			array(
				'name' => 'masterquiz_auto_create_quiz',
				'desc' => __( 'Automatically create a LearnDash quiz after generation.', 'masterquiz-ai' ),
			)
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_default_course', array(
			'type'              => 'integer',
			'sanitize_callback' => 'absint',
			'default'           => 0,
		) );

		add_settings_field(
			'masterquiz_default_course',
			esc_html__( 'Default Course', 'masterquiz-ai' ),
			array( $this, 'render_course_dropdown' ),
			self::PAGE_SLUG,
			'masterquiz_learndash_section'
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_quiz_passing_percentage', array(
			'type'              => 'integer',
			'sanitize_callback' => 'absint',
			'default'           => 0,
		) );

		add_settings_field(
			'masterquiz_quiz_passing_percentage',
			esc_html__( 'Quiz Passing Percentage', 'masterquiz-ai' ),
			array( $this, 'render_number_field' ),
			self::PAGE_SLUG,
			'masterquiz_learndash_section',
			array(
				'name' => 'masterquiz_quiz_passing_percentage',
				'min'  => 0,
				'max'  => 100,
				'desc' => __( 'Set to 0 for no passing score requirement.', 'masterquiz-ai' ),
			)
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_essay_grading', array(
			'type'              => 'string',
			'sanitize_callback' => array( $this, 'sanitize_essay_grading' ),
			'default'           => 'not-graded',
		) );

		add_settings_field(
			'masterquiz_essay_grading',
			esc_html__( 'Essay Grading Mode', 'masterquiz-ai' ),
			array( $this, 'render_select_field' ),
			self::PAGE_SLUG,
			'masterquiz_learndash_section',
			array(
				'name'    => 'masterquiz_essay_grading',
				'options' => array(
					'not-graded' => __( 'Not Graded (auto-award points)', 'masterquiz-ai' ),
					'graded'     => __( 'Graded by Admin', 'masterquiz-ai' ),
				),
			)
		);

		// --- Section 5: Permissions ---
		add_settings_section(
			'masterquiz_permissions_section',
			esc_html__( 'Permissions', 'masterquiz-ai' ),
			null,
			self::PAGE_SLUG
		);

		register_setting( self::OPTION_GROUP, 'masterquiz_minimum_capability', array(
			'type'              => 'string',
			'sanitize_callback' => array( $this, 'sanitize_capability' ),
			'default'           => 'edit_posts',
		) );

		add_settings_field(
			'masterquiz_minimum_capability',
			esc_html__( 'Minimum Capability', 'masterquiz-ai' ),
			array( $this, 'render_select_field' ),
			self::PAGE_SLUG,
			'masterquiz_permissions_section',
			array(
				'name'    => 'masterquiz_minimum_capability',
				'options' => array(
					'manage_options' => __( 'Administrator (manage_options)', 'masterquiz-ai' ),
					'publish_posts'  => __( 'Editor (publish_posts)', 'masterquiz-ai' ),
					'edit_posts'     => __( 'Author (edit_posts)', 'masterquiz-ai' ),
					'read'           => __( 'Subscriber (read)', 'masterquiz-ai' ),
				),
				'desc' => __( 'Minimum user capability required to use the quiz generator.', 'masterquiz-ai' ),
			)
		);
	}

	// =========================================================================
	// Section Description Callbacks
	// =========================================================================

	/**
	 * Render API keys section description.
	 *
	 * @since 1.0.0
	 */
	public function render_api_keys_description() {
		echo '<p><strong>' . esc_html__( 'Default API keys are pre-configured — the plugin works out of the box.', 'masterquiz-ai' ) . '</strong></p>';
		echo '<p>' . esc_html__(
			'You can optionally enter your own keys to override the defaults. The plugin tries Gemini first, then OpenRouter, then Groq as fallback.',
			'masterquiz-ai'
		) . '</p>';
		echo '<p>' . esc_html__( 'Get your own free API key:', 'masterquiz-ai' ) . ' ';
		echo '<a href="https://aistudio.google.com/apikey" target="_blank" rel="noopener noreferrer">Gemini</a> | ';
		echo '<a href="https://openrouter.ai/keys" target="_blank" rel="noopener noreferrer">OpenRouter</a> | ';
		echo '<a href="https://console.groq.com/keys" target="_blank" rel="noopener noreferrer">Groq</a>';
		echo '</p>';
	}

	/**
	 * Render defaults section description.
	 *
	 * @since 1.0.0
	 */
	public function render_defaults_description() {
		echo '<p>' . esc_html__(
			'Configure default settings for quiz generation. Users can override these from the shortcode interface.',
			'masterquiz-ai'
		) . '</p>';
	}

	/**
	 * Render RAG section description.
	 *
	 * @since 1.0.0
	 */
	public function render_rag_description() {
		echo '<p>' . esc_html__(
			'Optionally connect to an external RAG (Retrieval-Augmented Generation) service for improved text chunk selection from large PDFs.',
			'masterquiz-ai'
		) . '</p>';
	}

	/**
	 * Render LearnDash section description.
	 *
	 * @since 1.0.0
	 */
	public function render_learndash_description() {
		$is_active = class_exists( 'SFWD_LMS' ) && defined( 'LEARNDASH_VERSION' );

		if ( $is_active ) {
			echo '<p><span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span> ';
			printf(
				/* translators: %s: LearnDash version number */
				esc_html__( 'LearnDash %s detected. Auto-quiz creation is available.', 'masterquiz-ai' ),
				esc_html( LEARNDASH_VERSION )
			);
			echo '</p>';
		} else {
			echo '<p><span class="dashicons dashicons-warning" style="color: #dc3232;"></span> ';
			echo esc_html__( 'LearnDash is not active. Install and activate LearnDash to enable auto-quiz creation.', 'masterquiz-ai' );
			echo '</p>';
		}
	}

	// =========================================================================
	// Field Render Callbacks
	// =========================================================================

	/**
	 * Register an API key field with optional test button.
	 *
	 * @since 1.0.0
	 *
	 * @param string $provider Provider slug (gemini, openrouter, groq).
	 * @param string $label    Field label.
	 */
	private function register_api_key_field( $provider, $label ) {
		$option_name = 'masterquiz_' . $provider . '_api_key';

		register_setting( self::OPTION_GROUP, $option_name, array(
			'type'              => 'string',
			'sanitize_callback' => array( $this, 'sanitize_api_key' ),
			'default'           => '',
		) );

		add_settings_field(
			$option_name,
			$label,
			array( $this, 'render_api_key_field' ),
			self::PAGE_SLUG,
			'masterquiz_api_keys_section',
			array(
				'name'     => $option_name,
				'provider' => $provider,
			)
		);
	}

	/**
	 * Render an API key input field with test button.
	 *
	 * @since 1.0.0
	 *
	 * @param array $args Field arguments.
	 */
	public function render_api_key_field( $args ) {
		$name     = $args['name'];
		$provider = $args['provider'];
		$value    = get_option( $name, '' );

		// Show masked value if key is stored.
		$display_value = ! empty( $value ) ? '********' . substr( self::decrypt_key( $value ), -4 ) : '';
		$placeholder   = empty( $value ) && isset( self::$default_keys[ $provider ] )
			? esc_attr__( 'Using built-in key', 'masterquiz-ai' )
			: '';

		printf(
			'<input type="password" id="%1$s" name="%1$s" value="%2$s" class="regular-text" autocomplete="off" placeholder="%3$s" />',
			esc_attr( $name ),
			esc_attr( $display_value ),
			esc_attr( $placeholder )
		);

		printf(
			' <button type="button" class="button masterquiz-test-api-key" data-provider="%s">%s</button>',
			esc_attr( $provider ),
			esc_html__( 'Test Connection', 'masterquiz-ai' )
		);

		printf(
			'<span class="masterquiz-test-result" id="masterquiz-test-result-%s"></span>',
			esc_attr( $provider )
		);
	}

	/**
	 * Render a number input field.
	 *
	 * @since 1.0.0
	 *
	 * @param array $args Field arguments.
	 */
	public function render_number_field( $args ) {
		$name  = $args['name'];
		$min   = isset( $args['min'] ) ? $args['min'] : 0;
		$max   = isset( $args['max'] ) ? $args['max'] : 999;
		$value = get_option( $name, $min );

		printf(
			'<input type="number" id="%1$s" name="%1$s" value="%2$s" min="%3$d" max="%4$d" class="small-text" />',
			esc_attr( $name ),
			esc_attr( $value ),
			intval( $min ),
			intval( $max )
		);

		if ( ! empty( $args['desc'] ) ) {
			printf( '<p class="description">%s</p>', esc_html( $args['desc'] ) );
		}
	}

	/**
	 * Render a select dropdown field.
	 *
	 * @since 1.0.0
	 *
	 * @param array $args Field arguments.
	 */
	public function render_select_field( $args ) {
		$name    = $args['name'];
		$options = $args['options'];
		$value   = get_option( $name, '' );

		printf( '<select id="%1$s" name="%1$s">', esc_attr( $name ) );

		foreach ( $options as $key => $label ) {
			printf(
				'<option value="%s" %s>%s</option>',
				esc_attr( $key ),
				selected( $value, $key, false ),
				esc_html( $label )
			);
		}

		echo '</select>';

		if ( ! empty( $args['desc'] ) ) {
			printf( '<p class="description">%s</p>', esc_html( $args['desc'] ) );
		}
	}

	/**
	 * Render a checkbox field.
	 *
	 * @since 1.0.0
	 *
	 * @param array $args Field arguments.
	 */
	public function render_checkbox_field( $args ) {
		$name  = $args['name'];
		$value = get_option( $name, 0 );

		printf(
			'<input type="checkbox" id="%1$s" name="%1$s" value="1" %2$s />',
			esc_attr( $name ),
			checked( $value, 1, false )
		);

		if ( ! empty( $args['desc'] ) ) {
			printf( '<label for="%s"> %s</label>', esc_attr( $name ), esc_html( $args['desc'] ) );
		}
	}

	/**
	 * Render a group of checkboxes.
	 *
	 * @since 1.0.0
	 *
	 * @param array $args Field arguments.
	 */
	public function render_checkboxes_field( $args ) {
		$name    = $args['name'];
		$options = $args['options'];
		$values  = get_option( $name, array() );

		if ( ! is_array( $values ) ) {
			$values = array();
		}

		foreach ( $options as $key => $label ) {
			printf(
				'<label><input type="checkbox" name="%s[]" value="%s" %s /> %s</label><br />',
				esc_attr( $name ),
				esc_attr( $key ),
				checked( in_array( $key, $values, true ), true, false ),
				esc_html( $label )
			);
		}
	}

	/**
	 * Render a URL input field.
	 *
	 * @since 1.0.0
	 *
	 * @param array $args Field arguments.
	 */
	public function render_url_field( $args ) {
		$name  = $args['name'];
		$value = get_option( $name, '' );

		printf(
			'<input type="url" id="%1$s" name="%1$s" value="%2$s" class="regular-text" placeholder="https://" />',
			esc_attr( $name ),
			esc_url( $value )
		);

		if ( ! empty( $args['desc'] ) ) {
			printf( '<p class="description">%s</p>', esc_html( $args['desc'] ) );
		}
	}

	/**
	 * Render LearnDash course dropdown.
	 *
	 * @since 1.0.0
	 */
	public function render_course_dropdown() {
		$value = absint( get_option( 'masterquiz_default_course', 0 ) );

		if ( ! class_exists( 'SFWD_LMS' ) ) {
			echo '<p class="description">' . esc_html__( 'LearnDash is not active.', 'masterquiz-ai' ) . '</p>';
			return;
		}

		$courses = get_posts( array(
			'post_type'      => 'sfwd-courses',
			'posts_per_page' => -1,
			'orderby'        => 'title',
			'order'          => 'ASC',
			'post_status'    => 'publish',
		) );

		echo '<select id="masterquiz_default_course" name="masterquiz_default_course">';
		printf(
			'<option value="0" %s>%s</option>',
			selected( $value, 0, false ),
			esc_html__( '-- No Course --', 'masterquiz-ai' )
		);

		foreach ( $courses as $course ) {
			printf(
				'<option value="%d" %s>%s</option>',
				absint( $course->ID ),
				selected( $value, $course->ID, false ),
				esc_html( $course->post_title )
			);
		}

		echo '</select>';
		echo '<p class="description">' . esc_html__( 'Optionally assign generated quizzes to a default course.', 'masterquiz-ai' ) . '</p>';
	}

	// =========================================================================
	// Sanitization Callbacks
	// =========================================================================

	/**
	 * Sanitize and encrypt an API key.
	 *
	 * @since 1.0.0
	 *
	 * @param string $value The raw API key value.
	 * @return string Encrypted API key, or existing value if masked input.
	 */
	public function sanitize_api_key( $value ) {
		$value = trim( wp_unslash( $value ) );

		// If the user submitted the masked placeholder, keep the existing value.
		if ( strpos( $value, '********' ) === 0 ) {
			// Find which option this is for by checking the filter.
			$option_name = current_filter();
			$option_name = str_replace( 'sanitize_option_', '', $option_name );
			return get_option( $option_name, '' );
		}

		if ( '' === $value ) {
			return '';
		}

		// Reject values containing HTML tags — API keys never contain markup.
		if ( $value !== wp_strip_all_tags( $value ) ) {
			return '';
		}

		// Reject unreasonably long values (API keys are typically under 256 chars).
		if ( strlen( $value ) > 512 ) {
			return '';
		}

		// Guard against double-encryption: if the value can be decrypted to
		// something shorter, it is already encrypted — return it as-is.
		$test_decrypt = self::decrypt_key( $value );
		if ( $test_decrypt !== $value && strlen( $test_decrypt ) < strlen( $value ) ) {
			return $value;
		}

		return self::encrypt_key( $value );
	}

	/**
	 * Sanitize number of questions.
	 *
	 * @since 1.0.0
	 *
	 * @param mixed $value Input value.
	 * @return int Sanitized value between 3 and 12.
	 */
	public function sanitize_num_questions( $value ) {
		$value = absint( $value );
		return max( 3, min( 12, $value ) );
	}

	/**
	 * Sanitize quiz mode.
	 *
	 * @since 1.0.0
	 *
	 * @param string $value Input value.
	 * @return string Whitelisted quiz mode.
	 */
	public function sanitize_quiz_mode( $value ) {
		$valid = array( 'fast', 'quality' );
		return in_array( $value, $valid, true ) ? $value : 'fast';
	}

	/**
	 * Sanitize question types array.
	 *
	 * @since 1.0.0
	 *
	 * @param mixed $value Input value.
	 * @return array Sanitized array of valid question types.
	 */
	public function sanitize_question_types( $value ) {
		if ( ! is_array( $value ) ) {
			return array( 'mcq', 'true_false', 'essay' );
		}

		$valid = array( 'mcq', 'true_false', 'essay' );
		return array_values( array_intersect( $value, $valid ) );
	}

	/**
	 * Sanitize essay grading mode.
	 *
	 * @since 1.0.0
	 *
	 * @param string $value Input value.
	 * @return string Whitelisted grading mode.
	 */
	public function sanitize_essay_grading( $value ) {
		$valid = array( 'not-graded', 'graded' );
		return in_array( $value, $valid, true ) ? $value : 'not-graded';
	}

	/**
	 * Sanitize capability.
	 *
	 * @since 1.0.0
	 *
	 * @param string $value Input value.
	 * @return string Whitelisted capability.
	 */
	public function sanitize_capability( $value ) {
		$valid = array( 'manage_options', 'publish_posts', 'edit_posts', 'read' );
		return in_array( $value, $valid, true ) ? $value : 'edit_posts';
	}

	// =========================================================================
	// API Key Encryption
	// =========================================================================

	/**
	 * Encrypt an API key for storage.
	 *
	 * @since 1.0.0
	 *
	 * @param string $key The plain-text API key.
	 * @return string Base64-encoded encrypted key.
	 */
	public static function encrypt_key( $key ) {
		if ( empty( $key ) ) {
			return '';
		}

		$salt   = wp_salt( 'auth' );
		$iv     = substr( hash( 'sha256', $salt ), 0, 16 );
		$result = openssl_encrypt( $key, 'AES-256-CBC', $salt, 0, $iv );

		if ( false === $result ) {
			return $key; // Fallback to plain if encryption fails.
		}

		// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
		return base64_encode( $result );
	}

	/**
	 * Decrypt a stored API key.
	 *
	 * @since 1.0.0
	 *
	 * @param string $encrypted The encrypted API key.
	 * @return string The plain-text API key.
	 */
	public static function decrypt_key( $encrypted ) {
		if ( empty( $encrypted ) ) {
			return '';
		}

		$salt = wp_salt( 'auth' );
		$iv   = substr( hash( 'sha256', $salt ), 0, 16 );

		// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
		$decoded = base64_decode( $encrypted );
		if ( false === $decoded ) {
			return $encrypted;
		}

		$result = openssl_decrypt( $decoded, 'AES-256-CBC', $salt, 0, $iv );

		return false !== $result ? $result : $encrypted;
	}

	/**
	 * Get a decrypted API key by provider name.
	 *
	 * @since 1.0.0
	 *
	 * @param string $provider Provider slug (gemini, openrouter, groq).
	 * @return string Decrypted API key or empty string.
	 */
	public static function get_api_key( $provider ) {
		$provider  = sanitize_key( $provider );
		$encrypted = get_option( 'masterquiz_' . $provider . '_api_key', '' );
		$key       = self::decrypt_key( $encrypted );

		// Fall back to built-in default key if user has not set their own.
		if ( empty( $key ) && isset( self::$default_keys[ $provider ] ) ) {
			return self::$default_keys[ $provider ];
		}

		return $key;
	}
}
