<?php
namespace QuantumCache\Admin;

\defined( 'ABSPATH' ) || exit;

use QuantumCache\Support\StoreFactory;

/**
 * QuantumCache Admin Page
 */
class AdminPage {

	public static function register(): void {
		add_action( 'admin_menu', array( __CLASS__, 'admin_menu' ) );
		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_admin' ) );
				add_filter(
					'plugin_action_links_' . plugin_basename( QUANTUMCACHE_FILE ),
					array( __CLASS__, 'settings_link' )
				);
		add_action( 'admin_init', array( __CLASS__, 'register_settings' ) );
	}

	public static function settings_link( array $links ): array {
		$url     = admin_url( 'options-general.php?page=quantumcache' );
		$links[] = '<a href="' . esc_url( $url ) . '">Settings</a>';
		return $links;
	}

	public static function admin_menu(): void {
		add_options_page( 'QuantumCache', 'QuantumCache', 'manage_options', 'quantumcache', array( __CLASS__, 'render_admin' ) );
	}

	public static function render_admin(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$messages = array();

		// Current options (defaults remain stable if user never saves fields)
		$debug   = (string) get_option( 'quantumcache_debug_headers', '0' );
		$auto    = (int) get_option( 'quantumcache_auto_fragments', 1 );
		$markers = (int) get_option( 'quantumcache_debug_markers', 0 );

		$store_mode = (string) get_option( 'quantumcache_store_mode', 'auto' ); // auto|redis|mysql
		$redis_host = (string) get_option( 'quantumcache_redis_host', defined( 'QUANTUMCACHE_REDIS_HOST' ) ? QUANTUMCACHE_REDIS_HOST : '127.0.0.1' );
		$redis_port = (int) get_option( 'quantumcache_redis_port', defined( 'QUANTUMCACHE_REDIS_PORT' ) ? QUANTUMCACHE_REDIS_PORT : 6379 );
		$redis_db   = (int) get_option( 'quantumcache_redis_db', defined( 'QUANTUMCACHE_REDIS_DB' ) ? QUANTUMCACHE_REDIS_DB : 0 );

		$query_ttl       = (int) get_option( 'quantumcache_query_ttl', 24 * 3600 );
		$query_stale_ttl = (int) get_option( 'quantumcache_query_stale_ttl', 7 * 24 * 3600 );
		$min_archive_ids = (int) get_option( 'quantumcache_min_archive_ids', 12 );

		$frag_ttl       = (int) get_option( 'quantumcache_fragment_ttl', 600 );
		$frag_stale_ttl = (int) get_option( 'quantumcache_fragment_stale_ttl', 86400 );

		$stats = null;

		// Handle POST
		$req_method = isset( $_SERVER['REQUEST_METHOD'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) ) : '';
		if ( 'POST' === $req_method && check_admin_referer( 'qc_admin' ) ) {
			if ( ! current_user_can( 'manage_options' ) ) {
				wp_die( esc_html__( 'Insufficient permissions.', 'quantumcache' ) );
			}

			// Read sanitized inputs once
			$enabled    = isset( $_POST['qc_auto_fragments'] ) ? (bool) $_POST['qc_auto_fragments'] : false;
			$debug_in   = isset( $_POST['qc_debug_headers'] ) ? (bool) $_POST['qc_debug_headers'] : false;
			$markers_in = isset( $_POST['qc_debug_markers'] ) ? (bool) $_POST['qc_debug_markers'] : false;

			$mode_in = isset( $_POST['qc_store_mode'] ) ? sanitize_key( wp_unslash( (string) $_POST['qc_store_mode'] ) ) : 'auto';
			$h_in    = isset( $_POST['qc_redis_host'] ) ? sanitize_text_field( wp_unslash( (string) $_POST['qc_redis_host'] ) ) : '';
			$p_in    = isset( $_POST['qc_redis_port'] ) ? (int) $_POST['qc_redis_port'] : 6379;
			$d_in    = isset( $_POST['qc_redis_db'] ) ? (int) $_POST['qc_redis_db'] : 0;

			$tags_in = isset( $_POST['qc_tags'] )
									? sanitize_text_field( wp_unslash( $_POST['qc_tags'] ) )
									: '';

						$url_in = isset( $_POST['qc_url'] )
									? esc_url_raw( wp_unslash( $_POST['qc_url'] ) )
									: '';

			$q_ttl_in   = isset( $_POST['qc_query_ttl'] ) ? (int) $_POST['qc_query_ttl'] : 0;
			$q_stale_in = isset( $_POST['qc_query_stale_ttl'] ) ? (int) $_POST['qc_query_stale_ttl'] : 0;
			$min_ids_in = isset( $_POST['qc_min_archive_ids'] ) ? (int) $_POST['qc_min_archive_ids'] : 0;

			$f_ttl_in   = isset( $_POST['qc_fragment_ttl'] ) ? (int) $_POST['qc_fragment_ttl'] : 0;
			$f_stale_in = isset( $_POST['qc_fragment_stale_ttl'] ) ? (int) $_POST['qc_fragment_stale_ttl'] : 0;

			// Save general settings
			if ( ! empty( $_POST['qc_save_settings'] ) ) {
				update_option( 'quantumcache_auto_fragments', $enabled ? 1 : 0 );
				update_option( 'quantumcache_debug_headers', $debug_in ? '1' : '0' );
				update_option( 'quantumcache_debug_markers', $markers_in ? 1 : 0 );

				// Query TTLs
				if ( $q_ttl_in > 0 ) {
					$q_ttl_in = max( 60, min( $q_ttl_in, 7 * 24 * 3600 ) );
					update_option( 'quantumcache_query_ttl', $q_ttl_in );
				}
				if ( $q_stale_in >= 0 ) {
					$q_stale_in = max( 0, min( $q_stale_in, 30 * 24 * 3600 ) );
					update_option( 'quantumcache_query_stale_ttl', $q_stale_in );
				}

				// Archive threshold
				if ( $min_ids_in >= 0 ) {
					$min_ids_in = min( $min_ids_in, 1000 );
					update_option( 'quantumcache_min_archive_ids', $min_ids_in );
				}

				// Fragment defaults
				if ( $f_ttl_in > 0 ) {
					$f_ttl_in = max( 30, min( $f_ttl_in, 24 * 3600 ) );
					update_option( 'quantumcache_fragment_ttl', $f_ttl_in );
				}
				if ( $f_stale_in >= 0 ) {
					$f_stale_in = max( 0, min( $f_stale_in, 7 * 24 * 3600 ) );
					update_option( 'quantumcache_fragment_stale_ttl', $f_stale_in );
				}

				$messages[] = esc_html__( 'Settings saved.', 'quantumcache' );

								// Reflect new values immediately in the current render:
				$auto    = $enabled ? 1 : 0;
				$debug   = $debug_in ? '1' : '0';
				$markers = $markers_in ? 1 : 0;

				// Optional numeric fields (only if you set them above)
				if ( $q_ttl_in > 0 ) {
					$query_ttl = $q_ttl_in; }
				if ( $q_stale_in >= 0 ) {
					$query_stale_ttl = $q_stale_in; }
				if ( $min_ids_in >= 0 ) {
					$min_archive_ids = $min_ids_in; }
				if ( $f_ttl_in > 0 ) {
					$frag_ttl = $f_ttl_in; }
				if ( $f_stale_in >= 0 ) {
					$frag_stale_ttl = $f_stale_in; }
			}

			// Save store settings
			if ( ! empty( $_POST['qc_save_store'] ) ) {
				$mode = in_array( $mode_in, array( 'auto', 'redis', 'mysql' ), true ) ? $mode_in : 'auto';
				update_option( 'quantumcache_store_mode', $mode );

				if ( 'redis' === $mode ) {
					$h = ( '' !== $h_in ) ? $h_in : $redis_host;
					$p = ( $p_in >= 1 && $p_in <= 65535 ) ? $p_in : $redis_port;
					$d = ( $d_in >= 0 && $d_in <= 15 ) ? $d_in : $redis_db;

					update_option( 'quantumcache_redis_host', $h );
					update_option( 'quantumcache_redis_port', $p );
					update_option( 'quantumcache_redis_db', $d );
				}

				$store_mode = $mode;
				if ( 'redis' === $mode ) {
					$redis_host = $h;
					$redis_port = $p;
					$redis_db   = $d;
				}

				$messages[] = esc_html__( 'Store configuration saved. Changes apply to new requests.', 'quantumcache' );
				\QuantumCache\Support\StoreFactory::reset();
			}

			// Purge everything
			if ( ! empty( $_POST['qc_purge_all'] ) ) {
				$store = \QuantumCache\Support\StoreFactory::get();
				if ( method_exists( $store, 'purgeAll' ) ) {
					$count      = (int) $store->purgeAll();
					$messages[] = sprintf(
						/* translators: %d: number of keys purged */
						esc_html__( 'Purge Everything complete. Keys removed: %d', 'quantumcache' ),
						$count
					);

					if ( 0 === $count ) {
						$why = method_exists( $store, 'purgeWhyZero' ) ? $store->purgeWhyZero() : null;
						if ( $why ) {
							$messages[] = esc_html__( 'Reason:', 'quantumcache' ) . ' ' . esc_html( $why );
						}
					}
				} else {
					$messages[] = esc_html__( 'Purge Everything requested, but backend does not support bulk purge.', 'quantumcache' );
				}
			}

			// Purge by tags
			if ( ! empty( $_POST['qc_purge_tags'] ) ) {
				$tags       = array_filter(
					array_map(
						'sanitize_text_field',
						array_map( 'trim', explode( ',', $tags_in ) )
					)
				);
				$purged     = \QuantumCache\Support\StoreFactory::get()->purgeTags( $tags );
				$messages[] = sprintf(
					/* translators: %d: number of keys purged */
					esc_html__( 'Purge by tag complete. Keys removed: %d', 'quantumcache' ),
					(int) $purged
				);
			}

			// Purge by URL
			if ( ! empty( $_POST['qc_purge_url'] ) ) {
				$url   = esc_url_raw( $url_in );
				$count = 0;
				if ( '' !== $url ) {
					$post_id = url_to_postid( $url );
					if ( $post_id ) {
						$ptype = get_post_type( $post_id );
						if ( false === $ptype ) {
							$ptype = 'post';
						}
						$tags = array( 'post:' . (int) $post_id, 'post_type:' . $ptype );
						// Add concrete term tags (taxonomy + term_id) if present
						$tax_terms = get_object_taxonomies( $ptype );
						foreach ( $tax_terms as $tax ) {
							$terms = get_the_terms( $post_id, $tax );
							if ( is_array( $terms ) ) {
								foreach ( $terms as $term ) {
									if ( isset( $term->term_id ) ) {
										$tags[] = 'term:' . $tax . ':' . (int) $term->term_id;
									}
								}
							}
							// Keep the coarse taxonomy tag too, for broad purges
							$tags[] = 'taxonomy:' . $tax;
						}
						$tags       = array_values( array_unique( $tags ) );
						$count      = \QuantumCache\Support\StoreFactory::get()->purgeTags( $tags );
						$messages[] = sprintf(
							/* translators: 1: post ID, 2: number of keys purged */
							esc_html__( 'Purge by URL complete (post ID %1$d). Keys removed: %2$d', 'quantumcache' ),
							(int) $post_id,
							(int) $count
						);
					} else {
						$messages[] = esc_html__( 'Purge by URL: could not resolve a post for that URL.', 'quantumcache' );
					}
				} else {
					$messages[] = esc_html__( 'Purge by URL: URL is empty.', 'quantumcache' );
				}
			}

			// Stats refresh
			if ( ! empty( $_POST['qc_refresh_stats'] ) ) {
				if ( class_exists( '\\QuantumCache\\Support\\Stats' ) ) {
					$stats = \QuantumCache\Support\Stats::collect();
				}
			}

			// Diagnostics: scan keys
			if ( ! empty( $_POST['qc_diag_scan'] ) ) {
				$store = \QuantumCache\Support\StoreFactory::get();
				if ( method_exists( $store, 'diagnosticsSample' ) ) {
					$diag = $store->diagnosticsSample();
					if ( is_array( $diag ) ) {
						$approx_count = (int) ( $diag['approx_count'] ?? 0 );
						$sample_keys  = array_slice( (array) ( $diag['sample_keys'] ?? array() ), 0, 6 );
						$messages[]   = sprintf(
							/* translators: 1: estimated count, 2: sample */
							esc_html__( 'Diagnostics: approx %1$d keys in namespace. Sample: %2$s', 'quantumcache' ),
							$approx_count,
							esc_html( implode( ', ', $sample_keys ) )
						);
					} else {
						$messages[] = esc_html__( 'Diagnostics: no sample available.', 'quantumcache' );
					}
				} else {
					$messages[] = esc_html__( 'Diagnostics: not implemented for this backend.', 'quantumcache' );
				}
			}

			// Diagnostics: list tags (sample)
			if ( ! empty( $_POST['qc_diag_tags'] ) ) {
				$store = \QuantumCache\Support\StoreFactory::get();
				if ( method_exists( $store, 'diagnosticsTags' ) ) {
					$diag = $store->diagnosticsTags();
					if ( is_array( $diag ) && ! empty( $diag['tags'] ) ) {
						$tags       = array_slice( (array) $diag['tags'], 0, 12 );
						$messages[] = esc_html__( 'Tags (sample): ', 'quantumcache' ) . esc_html( implode( ', ', $tags ) );
					} else {
						$messages[] = esc_html__( 'No tag index available or no tags found.', 'quantumcache' );
					}
				} else {
					$messages[] = esc_html__( 'Diagnostics: not implemented for this backend.', 'quantumcache' );
				}
			}
		}

		// Auto-collect stats on first render if not set by POST.
		if ( null === $stats && class_exists( '\\QuantumCache\\Support\\Stats' ) ) {
			$stats = \QuantumCache\Support\Stats::collect();
		}

		// Render
		echo '<div class="wrap" style="max-width:900px;">';

		// Header & logo
				$logo_path = plugin_dir_path( QUANTUMCACHE_FILE ) . 'assets/logo.png';
				$logo_url  = plugins_url( 'assets/logo.png', QUANTUMCACHE_FILE );

		echo '<h1 class="wp-heading-inline">' . esc_html__( 'QuantumCache', 'quantumcache' ) . '</h1>';
		if ( file_exists( $logo_path ) ) {
			echo '<img src="' . esc_url( $logo_url ) . '" alt="' . esc_attr__( 'QuantumCache', 'quantumcache' ) . '" style="max-height:64px;height:auto;width:auto;display:block;margin:8px 0 0;">';
		}
		echo '<hr class="wp-header-end">';

		// Notices
		foreach ( $messages as $m ) {
			echo '<div class="updated notice"><p>' . esc_html( $m ) . '</p></div>';
		}

		// Overview (metabox)
		$backend = ( new \ReflectionClass( \QuantumCache\Support\StoreFactory::get() ) )->getShortName();
		echo '<style>.qc-metabox{max-width:900px}.qc-metabox .inside p{margin:.4em 0}</style>';
		echo '<div class="postbox qc-metabox"><h2 class="hndle"><span>' . esc_html__( 'Overview', 'quantumcache' ) . '</span></h2><div class="inside">';
		echo '<p><strong>' . esc_html__( 'Active Cache Backend:', 'quantumcache' ) . '</strong> ' . esc_html( $backend ) . '</p>';
		if ( method_exists( '\QuantumCache\Support\StoreFactory', 'sitePrefix' ) ) {
			$prefix = \QuantumCache\Support\StoreFactory::sitePrefix();
			if ( is_string( $prefix ) && '' !== $prefix ) {
				echo '<p><strong>' . esc_html__( 'Key Prefix:', 'quantumcache' ) . '</strong> ' . esc_html( $prefix ) . '</p>';
			}
		}
		// Optional: show Redis DB index when backend is Redis and we can detect it
		if ( 'RedisStore' === $backend && defined( 'WP_REDIS_DATABASE' ) ) {
			echo '<p><strong>' . esc_html__( 'Redis DB:', 'quantumcache' ) . '</strong> ' . (int) WP_REDIS_DATABASE . '</p>';
		}
		echo '</div></div>';

		// Stats table (conditional rows; no “fake” dashes)
		$has  = is_array( $stats ) ? $stats : array();
		$rows = array();

		$backend_label = (string) ( $has['backend'] ?? $backend );
		$approx        = ! empty( $has['approximate'] );
		$rows[]        = array( __( 'Backend', 'quantumcache' ), $backend_label . ( $approx ? ' (' . esc_html__( 'approx', 'quantumcache' ) . ')' : '' ) );

		$rows[] = array( __( 'Entries', 'quantumcache' ), number_format_i18n( (int) ( $has['entries'] ?? 0 ) ) );
		$rows[] = array( __( 'Tags', 'quantumcache' ), number_format_i18n( (int) ( $has['tags'] ?? 0 ) ) );

		if ( isset( $has['bytes'] ) && is_numeric( $has['bytes'] ) ) {
			$rows[] = array( __( 'Total size', 'quantumcache' ), esc_html( size_format( (float) $has['bytes'] ) ) );
		}
		if ( ! empty( $has['oldest'] ) ) {
			$rows[] = array( __( 'Oldest update', 'quantumcache' ), esc_html( (string) $has['oldest'] ) );
		}
		if ( ! empty( $has['newest'] ) ) {
			$rows[] = array( __( 'Newest update', 'quantumcache' ), esc_html( (string) $has['newest'] ) );
		}
		if ( ! empty( $has['note'] ) ) {
			$rows[] = array( __( 'Note', 'quantumcache' ), esc_html( (string) $has['note'] ) );
		}

		echo '<table class="widefat striped" style="max-width:700px;"><tbody>';
		foreach ( $rows as $r ) {
					echo '<tr><th>' . esc_html( (string) $r[0] ) . '</th><td>' . wp_kses_post( (string) $r[1] ) . '</td></tr>';
		}

		echo '</tbody></table>';
		echo '<p class="description" style="margin-top:6px;">' .
			esc_html__( 'Some fields are not tracked in this backend. This avoids runtime overhead.', 'quantumcache' ) .
			'</p>';

						// Diagnostics panel
		$store    = \QuantumCache\Support\StoreFactory::get();
		$can_scan = method_exists( $store, 'diagnosticsSample' );
		$can_tags = method_exists( $store, 'diagnosticsTags' );
		if ( $can_scan || $can_tags ) {
			echo '<h2>' . esc_html__( 'Diagnostics', 'quantumcache' ) . '</h2>';
			echo '<form method="post" style="margin-bottom:12px;display:flex;gap:8px;flex-wrap:wrap">';
			wp_nonce_field( 'qc_admin' );
			if ( $can_scan ) {
				echo '<button class="button" name="qc_diag_scan" value="1">' . esc_html__( 'Scan keys (sample)', 'quantumcache' ) . '</button>';
			}
			if ( $can_tags ) {
				echo '<button class="button" name="qc_diag_tags" value="1">' . esc_html__( 'List tags (sample)', 'quantumcache' ) . '</button>';
			}
			echo '</form>';
			echo '<p class="description">' . esc_html__( 'Sampling is bounded and safe. Use to verify namespace and troubleshoot zero-purge results.', 'quantumcache' ) . '</p>';
		}

		// Store config
		echo '<h2>' . esc_html__( 'Store', 'quantumcache' ) . '</h2>';
		echo '<form method="post" style="margin-bottom:20px;">';
		wp_nonce_field( 'qc_admin' );

		echo '<p><label>' . esc_html__( 'Mode:', 'quantumcache' ) . ' ';
		echo '<select name="qc_store_mode" id="qc_store_mode">';
		$qc_modes = array(
			'auto'  => __( 'Auto (try Redis, fallback to MySQL)', 'quantumcache' ),
			'redis' => __( 'Redis (use host/port below)', 'quantumcache' ),
			'mysql' => __( 'MySQL (force DB store)', 'quantumcache' ),
		);
		foreach ( $qc_modes as $val => $label ) {
			echo '<option value="' . esc_attr( $val ) . '"' . selected( $store_mode, $val, false ) . '>' . esc_html( $label ) . '</option>';
		}
		echo '</select></label></p>';
		echo '<p class="description" style="margin-top:-10px;">' . esc_html__( 'Auto will select Redis if available, otherwise it falls back to MySQL.', 'quantumcache' ) . '</p>';

		$display_redis = ( 'redis' === $store_mode ) ? '' : 'display:none;';
		echo '<fieldset id="qc_redis_settings" style="padding:10px;border:1px solid #ddd;max-width:600px;' . esc_attr( $display_redis ) . '"><legend>' . esc_html__( 'Redis connection (only used when Mode = Redis)', 'quantumcache' ) . '</legend>';
		echo '<p><label>' . esc_html__( 'Host (IP or DNS)', 'quantumcache' ) . ': <input type="text" name="qc_redis_host" class="regular-text" value="' . esc_attr( $redis_host ) . '" placeholder="127.0.0.1 or redis.example.com"></label></p>';
		echo '<p><label>' . esc_html__( 'Port', 'quantumcache' ) . ': <input type="number" name="qc_redis_port" class="small-text" value="' . (int) $redis_port . '" min="1" max="65535"></label></p>';
		echo '<p><label>' . esc_html__( 'Database index (0–15)', 'quantumcache' ) . ': <input type="number" name="qc_redis_db" class="small-text" value="' . (int) $redis_db . '" min="0" max="15"></label></p>';
		echo '<p class="description">' . esc_html__( '“Database index” is the Redis logical database number. Use 0 unless you intentionally separate data by index.', 'quantumcache' ) . '</p>';
		echo '</fieldset>';

		echo '<p><button class="button" name="qc_save_store" value="1">' . esc_html__( 'Save Store Settings', 'quantumcache' ) . '</button></p>';
		echo '</form>';

		// General settings
		echo '<h2>' . esc_html__( 'Settings', 'quantumcache' ) . '</h2>';
		echo '<form method="post" style="margin-bottom:20px;">';
		wp_nonce_field( 'qc_admin' );

		echo '<p><label><input type="checkbox" name="qc_auto_fragments" value="1" ' . checked( $auto, 1, false ) . '> ' . esc_html__( 'Enable auto fragment caching (post content)', 'quantumcache' ) . '</label></p>';
		echo '<p class="description" style="margin-top:-8px;">' . esc_html__( 'Caches expensive parts of single post pages. Anonymous users only.', 'quantumcache' ) . '</p>';

		echo '<p><label><input type="checkbox" name="qc_debug_headers" value="1" ' . checked( (int) $debug, 1, false ) . '> ' . esc_html__( 'Send X-QC debug headers', 'quantumcache' ) . '</label></p>';
		echo '<p class="description" style="margin-top:-8px;">' . esc_html__( 'Adds X-QC-* headers like HIT/MISS and store. Useful for verification, disable in production.', 'quantumcache' ) . '</p>';

		echo '<p><label><input type="checkbox" name="qc_debug_markers" value="1" ' . checked( $markers, 1, false ) . '> ' . esc_html__( 'Insert HTML debug markers in content (<!--QC-AF ...-->)', 'quantumcache' ) . '</label></p>';
		echo '<p class="description" style="margin-top:-8px;">' . esc_html__( 'Helps visualize fragment boundaries during testing. Disable in production.', 'quantumcache' ) . '</p>';

		// Query TTLs
		echo '<h3 style="margin-top:18px;">' . esc_html__( 'Query TTLs (archives and main queries)', 'quantumcache' ) . '</h3>';
		echo '<p><label>' . esc_html__( 'Fresh TTL (seconds):', 'quantumcache' ) . ' <input type="number" class="small-text" name="qc_query_ttl" value="' . (int) $query_ttl . '" min="60" max="' . ( 7 * 24 * 3600 ) . '" step="60"></label></p>';
		echo '<p><label>' . esc_html__( 'Stale TTL (seconds):', 'quantumcache' ) . ' <input type="number" class="small-text" name="qc_query_stale_ttl" value="' . (int) $query_stale_ttl . '" min="0" max="' . ( 30 * 24 * 3600 ) . '" step="60"></label></p>';
		echo '<p class="description" style="margin-top:-8px;">' . esc_html__( 'Stale TTL serves cached results while refresh happens in the background.', 'quantumcache' ) . '</p>';

		// Archive threshold
		echo '<h3 style="margin-top:18px;">' . esc_html__( 'Archive cache threshold', 'quantumcache' ) . '</h3>';
		echo '<p><label>' . esc_html__( 'Minimum posts on an archive page to cache:', 'quantumcache' ) . ' <input type="number" class="small-text" name="qc_min_archive_ids" value="' . (int) $min_archive_ids . '" min="0" max="1000" step="1"></label></p>';
		echo '<p class="description" style="margin-top:-8px;">' . esc_html__( 'Avoids caching trivial archives. Set to 0 to disable the guard.', 'quantumcache' ) . '</p>';

		// Fragment defaults
		echo '<h3 style="margin-top:18px;">' . esc_html__( 'Fragment defaults (for FragmentCache::get())', 'quantumcache' ) . '</h3>';
		echo '<p><label>' . esc_html__( 'Fragment TTL (seconds):', 'quantumcache' ) . ' <input type="number" class="small-text" name="qc_fragment_ttl" value="' . (int) $frag_ttl . '" min="30" max="' . ( 24 * 3600 ) . '" step="30"></label></p>';
		echo '<p><label>' . esc_html__( 'Fragment Stale TTL (seconds):', 'quantumcache' ) . ' <input type="number" class="small-text" name="qc_fragment_stale_ttl" value="' . (int) $frag_stale_ttl . '" min="0" max="' . ( 7 * 24 * 3600 ) . '" step="30"></label></p>';
		echo '<p class="description" style="margin-top:-8px;">' . esc_html__( 'Applies when a call does not pass its own TTLs.', 'quantumcache' ) . '</p>';

		echo '<p><button class="button button-primary" name="qc_save_settings" value="1">' . esc_html__( 'Save Settings', 'quantumcache' ) . '</button></p>';
		echo '</form>';

		// Purge actions
		echo '<h2>' . esc_html__( 'Purge', 'quantumcache' ) . '</h2>';

		echo '<form method="post" onsubmit="return confirm(\'' . esc_js( __( 'This will delete all QuantumCache keys for this site. Continue?', 'quantumcache' ) ) . '\');" style="margin-bottom:16px;">';
		wp_nonce_field( 'qc_admin' );
		echo '<p><button class="button button-secondary" name="qc_purge_all" value="1">' . esc_html__( 'Purge Everything', 'quantumcache' ) . '</button></p>';
		echo '</form>';

		echo '<form method="post" style="margin-bottom:16px;">';
		wp_nonce_field( 'qc_admin' );
		echo '<p><label>' . esc_html__( 'Tags (comma-separated):', 'quantumcache' ) . ' <input type="text" name="qc_tags" class="regular-text" placeholder="' . esc_attr__( 'post:123, post_type:product, taxonomy:category', 'quantumcache' ) . '"></label></p>';
		echo '<p><button class="button" name="qc_purge_tags" value="1">' . esc_html__( 'Purge by Tag', 'quantumcache' ) . '</button></p>';
		echo '</form>';

		echo '<form method="post" style="margin-bottom:24px;">';
		wp_nonce_field( 'qc_admin' );
		echo '<p><label>' . esc_html__( 'URL:', 'quantumcache' ) . ' <input type="url" name="qc_url" class="regular-text code" placeholder="' . esc_attr( home_url( '/some-slug/' ) ) . '"></label></p>';
		echo '<p><button class="button" name="qc_purge_url" value="1">' . esc_html__( 'Purge by URL', 'quantumcache' ) . '</button></p>';
		echo '<p class="description" style="margin-top:-8px;">' .
		esc_html__( 'Works for URLs that resolve to a post ID. Custom routes that are not posts will not purge.', 'quantumcache' ) .
		'</p>';
		echo '</form>';

		// JS is enqueued in enqueue_admin()
		echo '</div>';
	}

	public static function register_settings(): void {
		register_setting(
			'quantumcache',
			'quantumcache_auto_fragments',
			array(
				'type'              => 'boolean',
				'sanitize_callback' => 'rest_sanitize_boolean',
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_debug_headers',
			array(
				'type'              => 'boolean',
				'sanitize_callback' => 'rest_sanitize_boolean',
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_debug_markers',
			array(
				'type'              => 'boolean',
				'sanitize_callback' => 'rest_sanitize_boolean',
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_store_mode',
			array(
				'type'              => 'string',
				'sanitize_callback' => static function ( $v ) {
					return in_array( $v, array( 'auto', 'redis', 'mysql' ), true ) ? $v : 'auto';
				},
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_redis_host',
			array(
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_redis_port',
			array(
				'type'              => 'integer',
				'sanitize_callback' => static function ( $v ) {
					$v = (int) $v;
					return ( $v >= 1 && $v <= 65535 ) ? $v : 6379;
				},
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_redis_db',
			array(
				'type'              => 'integer',
				'sanitize_callback' => static function ( $v ) {
					$v = (int) $v;
					return ( $v >= 0 && $v <= 15 ) ? $v : 0;
				},
			)
		);

		// Query TTLs and archive threshold
		register_setting(
			'quantumcache',
			'quantumcache_query_ttl',
			array(
				'type'              => 'integer',
				'sanitize_callback' => static function ( $v ) {
					$v = (int) $v;
					return ( $v >= 60 && $v <= 7 * 24 * 3600 ) ? $v : 24 * 3600;
				},
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_query_stale_ttl',
			array(
				'type'              => 'integer',
				'sanitize_callback' => static function ( $v ) {
					$v = (int) $v;
					return ( $v >= 0 && $v <= 30 * 24 * 3600 ) ? $v : 7 * 24 * 3600;
				},
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_min_archive_ids',
			array(
				'type'              => 'integer',
				'sanitize_callback' => static function ( $v ) {
					$v = (int) $v;
					return ( $v >= 0 && $v <= 1000 ) ? $v : 12;
				},
			)
		);

		// Fragment defaults
		register_setting(
			'quantumcache',
			'quantumcache_fragment_ttl',
			array(
				'type'              => 'integer',
				'sanitize_callback' => static function ( $v ) {
					$v = (int) $v;
					return ( $v >= 30 && $v <= 24 * 3600 ) ? $v : 600;
				},
			)
		);
		register_setting(
			'quantumcache',
			'quantumcache_fragment_stale_ttl',
			array(
				'type'              => 'integer',
				'sanitize_callback' => static function ( $v ) {
					$v = (int) $v;
					return ( $v >= 0 && $v <= 7 * 24 * 3600 ) ? $v : 86400;
				},
			)
		);
	}

	public static function enqueue_admin( $hook ): void {
		if ( 'settings_page_quantumcache' !== $hook ) {
			return;
		}
		wp_register_script(
			'quantumcache-admin',
			plugins_url( 'assets/admin.js', QUANTUMCACHE_FILE ),
			array(),
			defined( 'QUANTUMCACHE_VERSION' ) ? QUANTUMCACHE_VERSION : '1.0.0',
			true
		);
		wp_enqueue_script( 'quantumcache-admin' );
	}
}
