<?php
/**
 * Performance Settings — admin UI renderer.
 *
 * Surfaces every Niwa polling/cron interval as a select with sensible
 * preset buckets, so site owners can throttle Niwa background work down
 * (or up) without editing code or asking support.
 *
 * Save flow: `Niwa_AI_Performance_Settings::sanitize()` snaps values to
 * allowed buckets AND calls `reschedule_all_jobs()`, so a single click
 * on the Save button is enough to fully re-register every cron event.
 *
 * @package Niwa_AI
 * @since   0.12.78
 */

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

class Niwa_AI_Performance_Settings_UI {

	const OPTION_KEY  = Niwa_AI_Constants::OPT_PERFORMANCE_SETTINGS;
	const OPTION_GROUP = 'niwa_ai_performance_group';

	/**
	 * Register the setting only; UI renders inside Personal Assistant.
	 */
	public function register_hooks() {
		add_action( 'admin_init', array( $this, 'register_settings' ) );
	}

	/**
	 * Register the option with the WordPress Settings API. Sanitize is
	 * static on the value class so unit tests can hit it without booting
	 * the UI class.
	 */
	public function register_settings() {
		register_setting(
			self::OPTION_GROUP,
			self::OPTION_KEY,
			array(
				'type'              => 'array',
				'sanitize_callback' => array( Niwa_AI_Performance_Settings::class, 'sanitize' ),
				'default'           => Niwa_AI_Performance_Settings::defaults(),
				'show_in_rest'      => false,
			)
		);
	}

	/**
	 * Render the settings page.
	 */
	public function render_page( $embedded = false ) {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$opts = Niwa_AI_Performance_Settings::get();
		$n    = self::OPTION_KEY;

		$seconds_label = function ( $value ) {
			$seconds = intval( $value );
			if ( $seconds < 60 ) {
				/* translators: %d seconds */
				return sprintf( _n( '%d second', '%d seconds', $seconds, 'niwa-ai' ), $seconds );
			}
			if ( $seconds < 3600 ) {
				$mins = intval( round( $seconds / 60 ) );
				/* translators: %d minutes */
				return sprintf( _n( '%d minute', '%d minutes', $mins, 'niwa-ai' ), $mins );
			}
			$hours = intval( round( $seconds / 3600 ) );
			/* translators: %d hours */
			return sprintf( _n( '%d hour', '%d hours', $hours, 'niwa-ai' ), $hours );
		};

		$ms_label = function ( $value ) {
			$seconds = intval( $value ) / 1000;
			if ( $seconds < 1 ) {
				/* translators: %d milliseconds */
				return sprintf( __( '%d ms', 'niwa-ai' ), intval( $value ) );
			}
			if ( $seconds < 60 ) {
				/* translators: %s seconds (may be fractional) */
				return sprintf( __( '%s seconds', 'niwa-ai' ), rtrim( rtrim( number_format( $seconds, 1 ), '0' ), '.' ) );
			}
			$mins = intval( round( $seconds / 60 ) );
			/* translators: %d minutes */
			return sprintf( _n( '%d minute', '%d minutes', $mins, 'niwa-ai' ), $mins );
		};

		$sections = array(
			array(
				'title'       => __( 'Background cron intervals', 'niwa-ai' ),
				'description' => __( 'How often Niwa\'s WP-Cron jobs fire. Larger intervals reduce server load but make fallback recovery and scheduled tasks slower to react.', 'niwa-ai' ),
				'fields'      => array(
					array(
						'key'     => 'telegram_poll_seconds',
						'label'   => __( 'Telegram webhook fallback poll', 'niwa-ai' ),
						'hint'    => __( 'Fallback getUpdates interval used only when the Telegram webhook is unhealthy or unavailable. Normal Telegram messages are webhook-driven and stay instant.', 'niwa-ai' ),
						'label_fn' => $seconds_label,
					),
					array(
						'key'     => 'scheduled_tasks_seconds',
						'label'   => __( 'Scheduled task runner', 'niwa-ai' ),
						'hint'    => __( 'How often Niwa picks up delayed/one-time tasks scheduled by the agent.', 'niwa-ai' ),
						'label_fn' => $seconds_label,
					),
					array(
						'key'     => 'background_tick_seconds',
						'label'   => __( 'Background scheduler check', 'niwa-ai' ),
						'hint'    => __( 'Checks whether daily report, heartbeat, scheduled jobs, queues, and runtime maintenance are due. This check does not call the LLM unless a due job requires it.', 'niwa-ai' ),
						'label_fn' => $seconds_label,
					),
					array(
						'key'     => 'frontend_chat_queue_seconds',
						'label'   => __( 'Frontend chat queue', 'niwa-ai' ),
						'hint'    => __( 'How often queued frontend visitor messages get processed. Raise only if visitor chat traffic is low.', 'niwa-ai' ),
						'label_fn' => $seconds_label,
					),
					array(
						'key'     => 'memory_embeddings_seconds',
						'label'   => __( 'Memory embeddings worker', 'niwa-ai' ),
						'hint'    => __( 'Builds vector embeddings for the knowledge index. Safe to run hourly on most sites.', 'niwa-ai' ),
						'label_fn' => $seconds_label,
					),
				),
			),
			array(
				'title'       => __( 'Browser-side admin polls', 'niwa-ai' ),
				'description' => __( 'How often the wp-admin Niwa chat tab pings the server. On WooCommerce sites short intervals can cause noticeable wp-admin slowdown because each poll competes for the same WooCommerce session row.', 'niwa-ai' ),
				'fields'      => array(
					array(
						'key'     => 'admin_history_poll_ms',
						'label'   => __( 'Admin chat history poll', 'niwa-ai' ),
						'hint'    => __( 'Interval between automatic history syncs in wp-admin Niwa tab while the chat is open. Default 60s.', 'niwa-ai' ),
						'label_fn' => $ms_label,
					),
					array(
						'key'     => 'embeddings_status_poll_ms',
						'label'   => __( 'Embeddings status poll', 'niwa-ai' ),
						'hint'    => __( 'How often the embeddings progress widget refreshes. Default 5s.', 'niwa-ai' ),
						'label_fn' => $ms_label,
					),
				),
			),
		);

		if ( ! $embedded ) {
			echo '<div class="wrap niwa-wrap">';

			echo '<div class="niwa-page-header">';
			echo '<div class="niwa-page-header__icon">';
			echo '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>';
			echo '</div>';
			echo '<div class="niwa-page-header__text">';
			echo '<h1 class="niwa-page-header__title">' . esc_html__( 'Performance', 'niwa-ai' ) . '</h1>';
			echo '<p class="niwa-page-header__subtitle">' . esc_html__( 'Tune Niwa background work and admin polling intervals to match your hosting plan.', 'niwa-ai' ) . '</p>';
			echo '</div>';
			echo '</div>';
		}

		echo '<form method="post" action="options.php">';
		settings_fields( self::OPTION_GROUP );

		foreach ( $sections as $section ) {
			echo '<div class="niwa-card">';
			echo '<details class="niwa-collapsible" open>';
			echo '<summary>';
			echo '<div class="niwa-card__header">';
			echo '<h2 class="niwa-card__title">' . esc_html( $section['title'] ) . '</h2>';
			echo '</div>';
			echo '</summary>';
			echo '<div class="niwa-card__body">';
			echo '<p style="margin:0 0 16px;color:var(--niwa-ink-3,#6b7280);font-size:13px;">' . esc_html( $section['description'] ) . '</p>';

			foreach ( $section['fields'] as $field ) {
				$key      = $field['key'];
				$current  = isset( $opts[ $key ] ) ? intval( $opts[ $key ] ) : 0;
				$choices  = Niwa_AI_Performance_Settings::ALLOWED_BUCKETS[ $key ] ?? array();
				$label_fn = $field['label_fn'];

				echo '<div class="niwa-field">';
				echo '<label class="niwa-field__label" for="' . esc_attr( $n . '_' . $key ) . '">' . esc_html( $field['label'] ) . '</label>';
				echo '<span class="niwa-field__hint">' . esc_html( $field['hint'] ) . '</span>';
				echo '<select id="' . esc_attr( $n . '_' . $key ) . '" name="' . esc_attr( $n . '[' . $key . ']' ) . '">';
				foreach ( $choices as $bucket ) {
					echo '<option value="' . esc_attr( $bucket ) . '"' . selected( $current, $bucket, false ) . '>'
						. esc_html( call_user_func( $label_fn, $bucket ) )
						. '</option>';
				}
				echo '</select>';
				echo '</div>';
			}

			echo '</div>';
			echo '</details>';
			echo '</div>';
		}

		echo '<div style="margin-top:16px;display:flex;gap:8px;align-items:center;">';
		submit_button( __( 'Save Performance Settings', 'niwa-ai' ), 'primary niwa-btn niwa-btn--primary', 'submit', false );
		echo '</div>';

		echo '<p style="margin-top:24px;color:var(--niwa-ink-3,#6b7280);font-size:12px;">';
		echo esc_html__( 'Saving the form automatically reschedules all WP-Cron events. No manual cron reset is required.', 'niwa-ai' );
		echo '</p>';

		echo '</form>';

		if ( ! $embedded ) {
			echo '</div>';
		}
	}

	public function render_embedded_form() {
		$this->render_page( true );
	}
}
