<?php
/**
 * Maintenance Center settings controller.
 *
 * @package Polanger_Maintenance_Center
 */

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

class Polanger_Maintenance_Settings {

	const OPTION_NAME   = 'pdt_maintenance_center_settings';
	const NONCE_ACTION  = 'pdt_maintenance_center_save';
	const SCHEMA_VERSION = 2;

	/**
	 * Singleton instance.
	 *
	 * @var Polanger_Maintenance_Settings|null
	 */
	private static $instance = null;

	/**
	 * Get singleton instance.
	 *
	 * @return Polanger_Maintenance_Settings
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Reset plugin settings to the new schema defaults.
	 *
	 * @return void
	 */
	public static function activate() {
		update_option( self::OPTION_NAME, self::get_defaults(), false );
	}

	/**
	 * Ensure the new schema exists.
	 *
	 * @return void
	 */
	public static function ensure_defaults() {
		$existing = get_option( self::OPTION_NAME, null );

		if ( ! is_array( $existing ) || absint( $existing['schema_version'] ?? 0 ) !== self::SCHEMA_VERSION ) {
			update_option( self::OPTION_NAME, self::get_defaults(), false );
			return;
		}

		$defaults = self::get_defaults();
		$merged   = wp_parse_args( $existing, $defaults );

		if ( $merged !== $existing ) {
			update_option( self::OPTION_NAME, $merged, false );
		}
	}

	/**
	 * Register admin hooks.
	 *
	 * @return void
	 */
	public function register_hooks() {
		add_filter( 'pdt_settings_tabs', array( $this, 'register_tab' ) );
		add_filter( 'pdt_settings_tab_icons', array( $this, 'register_tab_icon' ) );
		add_action( 'pdt_settings_render_tab_maintenance', array( $this, 'render_tab' ) );
		add_action( 'admin_init', array( $this, 'maybe_handle_save' ), 25 );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
	}

	/**
	 * Register maintenance tab.
	 *
	 * @param array $tabs Existing tabs.
	 * @return array
	 */
	public function register_tab( $tabs ) {
		if ( ! is_array( $tabs ) ) {
			$tabs = array();
		}

		if ( isset( $tabs['maintenance'] ) ) {
			return $tabs;
		}

		$new_tabs = array();

		foreach ( $tabs as $tab_id => $label ) {
			$new_tabs[ $tab_id ] = $label;

			if ( 'woocommerce' === $tab_id ) {
				$new_tabs['maintenance'] = __( 'Maintenance', 'polanger-admin-menu-manager' );
			}
		}

		if ( ! isset( $new_tabs['maintenance'] ) ) {
			$new_tabs['maintenance'] = __( 'Maintenance', 'polanger-admin-menu-manager' );
		}

		return $new_tabs;
	}

	/**
	 * Register maintenance tab icon.
	 *
	 * @param array $icons Existing icons.
	 * @return array
	 */
	public function register_tab_icon( $icons ) {
		if ( ! is_array( $icons ) ) {
			$icons = array();
		}

		$icons['maintenance'] = 'dashicons-admin-tools';

		return $icons;
	}

	/**
	 * Retrieve normalized settings.
	 *
	 * @return array
	 */
	public function get_settings() {
		self::ensure_defaults();

		$settings   = get_option( self::OPTION_NAME, array() );
		$settings   = is_array( $settings ) ? $settings : array();
		$normalized = $this->normalize_settings( $settings );

		if ( $normalized !== $settings ) {
			update_option( self::OPTION_NAME, $normalized, false );
		}

		return $normalized;
	}

	/**
	 * Maybe save settings.
	 *
	 * @return void
	 */
	public function maybe_handle_save() {
		if ( ! $this->is_maintenance_tab() ) {
			return;
		}

		if ( empty( $_POST['pdt_maintenance_center_action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
			return;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$nonce = isset( $_POST['pdt_maintenance_center_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['pdt_maintenance_center_nonce'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
		if ( ! wp_verify_nonce( $nonce, self::NONCE_ACTION ) ) {
			return;
		}

		$raw_settings = isset( $_POST['pdt_maintenance_center'] ) && is_array( $_POST['pdt_maintenance_center'] )
			? wp_unslash( $_POST['pdt_maintenance_center'] ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			: array();

		$section            = isset( $_POST['pdt_maintenance_center_section'] ) ? sanitize_key( wp_unslash( $_POST['pdt_maintenance_center_section'] ) ) : 'general'; // phpcs:ignore WordPress.Security.NonceVerification.Missing
		$regenerate_preview = ! empty( $_POST['pdt_maintenance_regenerate_preview_token'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
		$existing_settings  = $this->get_settings();
		$settings           = $this->sanitize_settings(
			$this->merge_section_settings( $existing_settings, $raw_settings, $section ),
			$regenerate_preview
		);

		update_option( self::OPTION_NAME, $settings, false );

		wp_safe_redirect(
			add_query_arg(
				array(
					'page'                => 'polanger-settings',
					'tab'                 => 'maintenance',
					'maintenance_section' => $this->get_active_section( $settings, $section ),
					'pmc_state'           => 'saved',
				),
				admin_url( 'admin.php' )
			)
		);
		exit;
	}

	/**
	 * Enqueue assets for the maintenance tab.
	 *
	 * @return void
	 */
	public function enqueue_assets() {
		if ( ! $this->is_maintenance_tab() ) {
			return;
		}

		wp_enqueue_media();
		wp_enqueue_editor();
		wp_enqueue_style( 'wp-color-picker' );
		wp_enqueue_script( 'wp-color-picker' );

		$css_editor = function_exists( 'wp_enqueue_code_editor' ) ? wp_enqueue_code_editor( array( 'type' => 'text/css' ) ) : false;
		$js_editor  = function_exists( 'wp_enqueue_code_editor' ) ? wp_enqueue_code_editor( array( 'type' => 'application/javascript' ) ) : false;

		wp_enqueue_style(
			'polanger-maintenance-center-admin',
			POLANGER_MAINTENANCE_CENTER_URL . 'assets/css/maintenance-center-admin.css',
			array( 'wp-color-picker' ),
			POLANGER_MAINTENANCE_CENTER_VERSION
		);

		wp_enqueue_script(
			'polanger-maintenance-center-admin',
			POLANGER_MAINTENANCE_CENTER_URL . 'assets/js/maintenance-center-admin.js',
			array( 'jquery', 'wp-color-picker' ),
			POLANGER_MAINTENANCE_CENTER_VERSION,
			true
		);

		wp_localize_script(
			'polanger-maintenance-center-admin',
			'polangerMaintenanceCenterAdmin',
			array(
				'mediaTitle'      => __( 'Choose an image', 'polanger-admin-menu-manager' ),
				'mediaButton'     => __( 'Use this image', 'polanger-admin-menu-manager' ),
				'chooseImage'     => __( 'Choose image', 'polanger-admin-menu-manager' ),
				'changeImage'     => __( 'Change image', 'polanger-admin-menu-manager' ),
				'removeImage'     => __( 'Remove image', 'polanger-admin-menu-manager' ),
				'noImageSelected' => __( 'No image selected yet.', 'polanger-admin-menu-manager' ),
				'cssEditor'       => $css_editor ? $css_editor : null,
				'jsEditor'        => $js_editor ? $js_editor : null,
			)
		);
	}

	/**
	 * Render maintenance settings tab.
	 *
	 * @param bool $is_readonly Whether the current user should see a read-only screen.
	 * @return void
	 */
	public function render_tab( $is_readonly = false ) {
		if ( ! current_user_can( 'manage_options' ) && ! $is_readonly ) {
			echo '<div class="notice notice-warning"><p>' . esc_html__( 'You are not allowed to configure Maintenance Center.', 'polanger-admin-menu-manager' ) . '</p></div>';
			return;
		}

		$settings      = $this->get_settings();
		$section       = $this->get_active_section( $settings );
		$sections      = $this->get_sections( $settings );
		$state         = Polanger_Maintenance_Runtime::get_runtime_state( $settings );
		$preview_url   = Polanger_Maintenance_Runtime::build_preview_url( $settings );
		$response_code = Polanger_Maintenance_Runtime::get_effective_response_code( $settings );
		$is_saved      = isset( $_GET['pmc_state'] ) && 'saved' === sanitize_key( wp_unslash( $_GET['pmc_state'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$readonly      = ! empty( $is_readonly ) || ! current_user_can( 'manage_options' );
		?>
		<div class="pmc-admin">
			<div class="pmc-admin__hero">
				<div class="pmc-admin__hero-copy">
					<span class="pmc-admin__eyebrow"><?php esc_html_e( 'Operations Addon', 'polanger-admin-menu-manager' ); ?></span>
					<h2><?php esc_html_e( 'Maintenance Center', 'polanger-admin-menu-manager' ); ?></h2>
					<p><?php esc_html_e( 'Choose a maintenance mode, decide who can still enter the site, shape the public message, and keep advanced controls tucked away until you need them. The goal is a clean workflow, not a wall of settings.', 'polanger-admin-menu-manager' ); ?></p>
				</div>

				<div class="pmc-admin__hero-state pmc-admin__hero-state--<?php echo esc_attr( $state['badge_class'] ); ?>">
					<span class="pmc-admin__hero-label"><?php esc_html_e( 'Current State', 'polanger-admin-menu-manager' ); ?></span>
					<strong><?php echo esc_html( $state['label'] ); ?></strong>
					<p><?php echo esc_html( $state['description'] ); ?></p>
					<a class="button button-secondary" href="<?php echo esc_url( $preview_url ); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Open preview link', 'polanger-admin-menu-manager' ); ?></a>
				</div>
			</div>

			<?php if ( $readonly ) : ?>
				<div class="notice notice-info">
					<p><?php esc_html_e( 'This screen is currently read-only for your account.', 'polanger-admin-menu-manager' ); ?></p>
				</div>
			<?php endif; ?>

			<?php if ( $is_saved ) : ?>
				<div class="notice notice-success is-dismissible">
					<p><?php esc_html_e( 'Maintenance Center settings saved.', 'polanger-admin-menu-manager' ); ?></p>
				</div>
			<?php endif; ?>

			<div class="pmc-admin__layout">
				<nav class="pmc-admin__nav" aria-label="<?php esc_attr_e( 'Maintenance sections', 'polanger-admin-menu-manager' ); ?>">
					<?php foreach ( $sections as $section_id => $section_label ) : ?>
						<a class="pmc-admin__nav-item<?php echo $section === $section_id ? ' is-active' : ''; ?>" href="<?php echo esc_url( add_query_arg( array( 'page' => 'polanger-settings', 'tab' => 'maintenance', 'maintenance_section' => $section_id ), admin_url( 'admin.php' ) ) ); ?>">
							<span><?php echo esc_html( $section_label ); ?></span>
						</a>
					<?php endforeach; ?>
				</nav>

				<div class="pmc-admin__content">
					<form method="post" class="pmc-form">
						<?php wp_nonce_field( self::NONCE_ACTION, 'pdt_maintenance_center_nonce' ); ?>
						<input type="hidden" name="pdt_maintenance_center_action" value="save" />
						<input type="hidden" name="pdt_maintenance_center_section" value="<?php echo esc_attr( $section ); ?>" />

						<?php $this->render_section( $section, $settings, $preview_url, $readonly ); ?>

						<p class="submit">
							<button type="submit" class="button button-primary" <?php disabled( $readonly ); ?>><?php esc_html_e( 'Save Maintenance Settings', 'polanger-admin-menu-manager' ); ?></button>
						</p>
					</form>
				</div>

				<aside class="pmc-admin__summary">
					<div class="pmc-summary-card">
						<h3><?php esc_html_e( 'Quick Summary', 'polanger-admin-menu-manager' ); ?></h3>

						<div class="pmc-summary-row">
							<span><?php esc_html_e( 'Mode', 'polanger-admin-menu-manager' ); ?></span>
							<strong><?php echo esc_html( $this->get_mode_choices()[ $settings['mode'] ]['label'] ); ?></strong>
						</div>

						<div class="pmc-summary-row">
							<span><?php esc_html_e( 'HTTP response', 'polanger-admin-menu-manager' ); ?></span>
							<strong><?php echo esc_html( (string) $response_code ); ?></strong>
						</div>

						<div class="pmc-summary-row">
							<span><?php esc_html_e( 'Bypass roles', 'polanger-admin-menu-manager' ); ?></span>
							<strong><?php echo esc_html( (string) count( $settings['bypass_roles'] ) ); ?></strong>
						</div>

						<div class="pmc-summary-row">
							<span><?php esc_html_e( 'Logged-in bypass', 'polanger-admin-menu-manager' ); ?></span>
							<strong><?php echo esc_html( $settings['allow_logged_in'] ? __( 'Enabled', 'polanger-admin-menu-manager' ) : __( 'Disabled', 'polanger-admin-menu-manager' ) ); ?></strong>
						</div>

						<div class="pmc-summary-row">
							<span><?php esc_html_e( 'Schedule', 'polanger-admin-menu-manager' ); ?></span>
							<strong><?php echo esc_html( ! empty( $settings['schedule_end'] ) ? __( 'Automatic End', 'polanger-admin-menu-manager' ) : __( 'Manual', 'polanger-admin-menu-manager' ) ); ?></strong>
						</div>

						<label class="pmc-summary-label" for="pmc-summary-preview"><strong><?php esc_html_e( 'Preview URL', 'polanger-admin-menu-manager' ); ?></strong></label>
						<input id="pmc-summary-preview" type="text" readonly value="<?php echo esc_attr( $preview_url ); ?>" />
						<a class="button button-secondary pmc-summary-button" href="<?php echo esc_url( $preview_url ); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Open preview', 'polanger-admin-menu-manager' ); ?></a>
					</div>
				</aside>
			</div>
		</div>
		<?php
	}

	/**
	 * Render the active section.
	 *
	 * @param string $section     Section slug.
	 * @param array  $settings    Settings payload.
	 * @param string $preview_url Signed preview URL.
	 * @param bool   $readonly    Whether the screen is read-only.
	 * @return void
	 */
	private function render_section( $section, $settings, $preview_url, $readonly ) {
		switch ( $section ) {
			case 'access':
				$this->render_access_section( $settings, $preview_url, $readonly );
				break;
			case 'appearance':
				$this->render_appearance_section( $settings, $readonly );
				break;
			case 'deployment':
				$this->render_deployment_section( $settings, $readonly );
				break;
			case 'advanced':
				$this->render_advanced_section( $settings, $readonly );
				break;
			case 'general':
			default:
				$this->render_general_section( $settings, $readonly );
				break;
		}
	}

	/**
	 * Render General section.
	 *
	 * @param array $settings Settings payload.
	 * @param bool  $readonly Read-only state.
	 * @return void
	 */
	private function render_general_section( $settings, $readonly ) {
		$modes = $this->get_mode_choices();
		?>
		<section class="pmc-panel">
			<div class="pmc-panel__head">
				<h3><?php esc_html_e( 'General', 'polanger-admin-menu-manager' ); ?></h3>
				<p><?php esc_html_e( 'Start here. Turn the module on, choose the public mode, and shape the public content visitors will see while the site is temporarily unavailable.', 'polanger-admin-menu-manager' ); ?></p>
			</div>

			<div class="pmc-stack">
				<?php
				$this->render_toggle_row(
					'enabled',
					'pmc-enabled',
					$settings['enabled'],
					__( 'Enable Maintenance Center', 'polanger-admin-menu-manager' ),
					__( 'When disabled, the frontend behaves normally and none of the runtime restrictions load.', 'polanger-admin-menu-manager' ),
					$readonly
				);
				?>

				<div class="pmc-field">
					<label><strong><?php esc_html_e( 'Mode', 'polanger-admin-menu-manager' ); ?></strong></label>
					<p class="description"><?php esc_html_e( 'Choose the public experience you want visitors to see while the site is not fully open.', 'polanger-admin-menu-manager' ); ?></p>
					<div class="pmc-mode-grid">
						<?php foreach ( $modes as $mode_key => $mode_data ) : ?>
							<label class="pmc-mode-card<?php echo $settings['mode'] === $mode_key ? ' is-selected' : ''; ?>">
								<input type="radio" name="pdt_maintenance_center[mode]" value="<?php echo esc_attr( $mode_key ); ?>" <?php checked( $settings['mode'], $mode_key ); ?> <?php disabled( $readonly ); ?> />
								<span class="pmc-mode-card__title"><?php echo esc_html( $mode_data['label'] ); ?></span>
								<span class="pmc-mode-card__description"><?php echo esc_html( $mode_data['description'] ); ?></span>
							</label>
						<?php endforeach; ?>
					</div>
					<p class="description"><?php esc_html_e( 'If you select Deployment mode and save, a dedicated Deployment section will appear in the sidebar.', 'polanger-admin-menu-manager' ); ?></p>
				</div>

				<div class="pmc-subsection">
					<div class="pmc-subsection__head">
						<h4><?php esc_html_e( 'Public Content', 'polanger-admin-menu-manager' ); ?></h4>
						<p><?php esc_html_e( 'Set the logo, message, button, countdown and footer content that visitors should see while maintenance mode is active.', 'polanger-admin-menu-manager' ); ?></p>
					</div>

					<?php $this->render_content_fields( $settings, $readonly, true ); ?>
				</div>
			</div>
		</section>
		<?php
	}

	/**
	 * Render maintenance content fields.
	 *
	 * @param array $settings      Settings payload.
	 * @param bool  $readonly      Read-only state.
	 * @param bool  $single_column Whether fields should be stacked vertically.
	 * @return void
	 */
	private function render_content_fields( $settings, $readonly, $single_column = false ) {
		$units = $this->get_countdown_unit_choices();
		?>
		<div class="pmc-stack">
			<?php if ( $single_column ) : ?>
				<div class="pmc-content-card">
					<div class="pmc-content-card__head">
						<h5><?php esc_html_e( 'Logo', 'polanger-admin-menu-manager' ); ?></h5>
						<p><?php esc_html_e( 'Choose the brand mark that should appear at the top of the maintenance card, then set its position beside it.', 'polanger-admin-menu-manager' ); ?></p>
					</div>
					<div class="pmc-content-card__grid pmc-content-card__grid--media">
						<?php
						$this->render_media_field(
							array(
								'field_base'  => 'logo',
								'label'       => __( 'Logo image', 'polanger-admin-menu-manager' ),
								'description' => __( 'Use a compact logo that stays clear on desktop and mobile.', 'polanger-admin-menu-manager' ),
								'image_id'    => $settings['logo_id'],
								'image_url'   => $settings['logo_url'],
								'readonly'    => $readonly,
							)
						);

						$this->render_alignment_control(
							array(
								'label'       => __( 'Logo alignment', 'polanger-admin-menu-manager' ),
								'name'        => 'pdt_maintenance_center[logo_alignment]',
								'value'       => $settings['logo_alignment'],
								'readonly'    => $readonly,
								'show_labels' => false,
							)
						);
						?>
					</div>
				</div>

				<div class="pmc-content-card">
					<div class="pmc-content-card__head">
						<h5><?php esc_html_e( 'Headline', 'polanger-admin-menu-manager' ); ?></h5>
						<p><?php esc_html_e( 'Set the main title visitors should notice first, then choose how that heading should sit on the page.', 'polanger-admin-menu-manager' ); ?></p>
					</div>
					<div class="pmc-content-card__grid pmc-content-card__grid--text">
						<div class="pmc-field">
							<label for="pmc-headline"><strong><?php esc_html_e( 'Headline text', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-headline" type="text" name="pdt_maintenance_center[headline]" value="<?php echo esc_attr( $settings['headline'] ); ?>" <?php disabled( $readonly ); ?> />
						</div>

						<?php
						$this->render_alignment_control(
							array(
								'label'       => __( 'Headline alignment', 'polanger-admin-menu-manager' ),
								'name'        => 'pdt_maintenance_center[headline_alignment]',
								'value'       => $settings['headline_alignment'],
								'readonly'    => $readonly,
								'show_labels' => false,
							)
						);
						?>
					</div>
				</div>

				<div class="pmc-content-card">
					<div class="pmc-content-card__head">
						<h5><?php esc_html_e( 'Description', 'polanger-admin-menu-manager' ); ?></h5>
						<p><?php esc_html_e( 'Use the WordPress editor for paragraphs, links, shortcodes and allowed HTML. The editor already lets you align the content itself.', 'polanger-admin-menu-manager' ); ?></p>
					</div>
					<div class="pmc-field">
						<?php $this->render_rich_editor( 'pmc-message-editor', 'pdt_maintenance_center[message]', $settings['message'], $readonly ); ?>
					</div>
					<input type="hidden" name="pdt_maintenance_center[message_alignment]" value="<?php echo esc_attr( $settings['message_alignment'] ); ?>" />
				</div>
			<?php else : ?>
				<div class="pmc-grid pmc-grid--content">
					<div class="pmc-stack">
						<?php
						$this->render_media_field(
							array(
								'field_base'  => 'logo',
								'label'       => __( 'Logo', 'polanger-admin-menu-manager' ),
								'description' => __( 'Choose the brand mark that should appear at the top of the maintenance card.', 'polanger-admin-menu-manager' ),
								'image_id'    => $settings['logo_id'],
								'image_url'   => $settings['logo_url'],
								'readonly'    => $readonly,
							)
						);

						$this->render_alignment_control(
							array(
								'label'       => __( 'Logo alignment', 'polanger-admin-menu-manager' ),
								'name'        => 'pdt_maintenance_center[logo_alignment]',
								'value'       => $settings['logo_alignment'],
								'readonly'    => $readonly,
								'show_labels' => false,
							)
						);
						?>
					</div>

					<div class="pmc-stack">
						<div class="pmc-field">
							<label for="pmc-headline"><strong><?php esc_html_e( 'Headline', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-headline" type="text" name="pdt_maintenance_center[headline]" value="<?php echo esc_attr( $settings['headline'] ); ?>" <?php disabled( $readonly ); ?> />
						</div>

						<?php
						$this->render_alignment_control(
							array(
								'label'       => __( 'Headline alignment', 'polanger-admin-menu-manager' ),
								'name'        => 'pdt_maintenance_center[headline_alignment]',
								'value'       => $settings['headline_alignment'],
								'readonly'    => $readonly,
								'show_labels' => false,
							)
						);
						?>

						<div class="pmc-field">
							<label><strong><?php esc_html_e( 'Description', 'polanger-admin-menu-manager' ); ?></strong></label>
							<p class="description"><?php esc_html_e( 'Use the WordPress editor for paragraphs, links, shortcodes and allowed HTML. This is the main message visitors will read.', 'polanger-admin-menu-manager' ); ?></p>
							<?php $this->render_rich_editor( 'pmc-message-editor', 'pdt_maintenance_center[message]', $settings['message'], $readonly ); ?>
						</div>

						<?php
						$this->render_alignment_control(
							array(
								'label'    => __( 'Description alignment', 'polanger-admin-menu-manager' ),
								'name'     => 'pdt_maintenance_center[message_alignment]',
								'value'    => $settings['message_alignment'],
								'readonly' => $readonly,
							)
						);
						?>
					</div>
				</div>
			<?php endif; ?>

			<?php if ( $single_column ) : ?>
				<div class="pmc-content-card">
					<div class="pmc-content-card__head">
						<h5><?php esc_html_e( 'Primary Button', 'polanger-admin-menu-manager' ); ?></h5>
						<p><?php esc_html_e( 'Choose the main action text and where visitors should go when they click it.', 'polanger-admin-menu-manager' ); ?></p>
					</div>
					<div class="pmc-content-card__grid pmc-content-card__grid--two">
						<div class="pmc-field">
							<label for="pmc-button-label"><strong><?php esc_html_e( 'Primary button label', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-button-label" type="text" name="pdt_maintenance_center[button_label]" value="<?php echo esc_attr( $settings['button_label'] ); ?>" <?php disabled( $readonly ); ?> />
						</div>

						<div class="pmc-field">
							<label for="pmc-button-url"><strong><?php esc_html_e( 'Primary button URL', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-button-url" type="url" name="pdt_maintenance_center[button_url]" value="<?php echo esc_attr( $settings['button_url'] ); ?>" <?php disabled( $readonly ); ?> />
						</div>
					</div>
				</div>
			<?php else : ?>
				<div class="pmc-grid pmc-grid--two">
					<div class="pmc-field">
						<label for="pmc-button-label"><strong><?php esc_html_e( 'Primary button label', 'polanger-admin-menu-manager' ); ?></strong></label>
						<input id="pmc-button-label" type="text" name="pdt_maintenance_center[button_label]" value="<?php echo esc_attr( $settings['button_label'] ); ?>" <?php disabled( $readonly ); ?> />
					</div>

					<div class="pmc-field">
						<label for="pmc-button-url"><strong><?php esc_html_e( 'Primary button URL', 'polanger-admin-menu-manager' ); ?></strong></label>
						<input id="pmc-button-url" type="url" name="pdt_maintenance_center[button_url]" value="<?php echo esc_attr( $settings['button_url'] ); ?>" <?php disabled( $readonly ); ?> />
					</div>
				</div>
			<?php endif; ?>

			<?php if ( $single_column ) : ?>
				<div class="pmc-content-card">
					<div class="pmc-content-card__head">
						<h5><?php esc_html_e( 'Status and Countdown', 'polanger-admin-menu-manager' ); ?></h5>
						<p><?php esc_html_e( 'Show a live countdown if visitors should know when to expect the site back.', 'polanger-admin-menu-manager' ); ?></p>
					</div>

					<input type="hidden" name="pdt_maintenance_center[status_note]" value="" />
					<input type="hidden" name="pdt_maintenance_center[schedule_start]" value="" />

					<?php
					$this->render_toggle_row(
						'countdown_enabled',
						'pmc-countdown-enabled',
						$settings['countdown_enabled'],
						__( 'Show countdown', 'polanger-admin-menu-manager' ),
						__( 'Turn this on when visitors should see the maintenance end time as a live countdown.', 'polanger-admin-menu-manager' ),
						$readonly
					);
					?>

					<div class="pmc-conditional<?php echo $settings['countdown_enabled'] ? ' is-visible' : ''; ?>" data-pmc-conditional="countdown">
						<div class="pmc-stack">
							<input type="hidden" name="pdt_maintenance_center[countdown_target]" value="" />
							<div class="pmc-field">
								<label for="pmc-countdown-label"><strong><?php esc_html_e( 'Countdown label', 'polanger-admin-menu-manager' ); ?></strong></label>
								<input id="pmc-countdown-label" type="text" name="pdt_maintenance_center[countdown_label]" value="<?php echo esc_attr( $settings['countdown_label'] ); ?>" <?php disabled( $readonly ); ?> />
								<p class="description"><?php esc_html_e( 'Leave this empty if you do not want a countdown heading on the frontend.', 'polanger-admin-menu-manager' ); ?></p>
							</div>

							<div class="pmc-field">
								<label for="pmc-schedule-end"><strong><?php esc_html_e( 'End date and time', 'polanger-admin-menu-manager' ); ?></strong></label>
								<input id="pmc-schedule-end" type="datetime-local" name="pdt_maintenance_center[schedule_end]" value="<?php echo esc_attr( $settings['schedule_end'] ); ?>" <?php disabled( $readonly ); ?> />
								<p class="description"><?php esc_html_e( 'Choose the exact date and time the countdown should count toward on the frontend.', 'polanger-admin-menu-manager' ); ?></p>
								<p class="description"><?php printf( esc_html__( 'The countdown uses the WordPress timezone from Settings > General: %s.', 'polanger-admin-menu-manager' ), esc_html( wp_timezone_string() ? wp_timezone_string() : 'UTC' ) ); ?></p>
							</div>

							<div class="pmc-field">
								<label><strong><?php esc_html_e( 'Visible countdown units', 'polanger-admin-menu-manager' ); ?></strong></label>
								<div class="pmc-check-grid">
									<?php foreach ( $units as $unit_key => $unit_label ) : ?>
										<?php $field_key = 'countdown_show_' . $unit_key; ?>
										<label class="pmc-check-card<?php echo $settings[ $field_key ] ? ' is-selected' : ''; ?>">
											<input type="checkbox" name="pdt_maintenance_center[<?php echo esc_attr( $field_key ); ?>]" value="1" <?php checked( $settings[ $field_key ] ); ?> <?php disabled( $readonly ); ?> />
											<span class="pmc-check-card__title"><?php echo esc_html( $unit_label ); ?></span>
											<span class="pmc-check-card__description"><?php esc_html_e( 'Show this time unit in the live countdown.', 'polanger-admin-menu-manager' ); ?></span>
										</label>
									<?php endforeach; ?>
								</div>
							</div>
						</div>
					</div>
				</div>

				<div class="pmc-content-card">
					<div class="pmc-content-card__head">
						<h5><?php esc_html_e( 'Footer Content', 'polanger-admin-menu-manager' ); ?></h5>
						<p><?php esc_html_e( 'Use this area for support details, business hours, contact notes or any extra reassurance for visitors.', 'polanger-admin-menu-manager' ); ?></p>
					</div>
					<div class="pmc-field">
						<?php $this->render_rich_editor( 'pmc-footer-editor', 'pdt_maintenance_center[footer_content]', $settings['footer_content'], $readonly ); ?>
					</div>
				</div>
			<?php else : ?>
				<input type="hidden" name="pdt_maintenance_center[status_note]" value="" />
				<input type="hidden" name="pdt_maintenance_center[schedule_start]" value="" />

				<?php
				$this->render_toggle_row(
					'countdown_enabled',
					'pmc-countdown-enabled',
					$settings['countdown_enabled'],
					__( 'Show countdown', 'polanger-admin-menu-manager' ),
					__( 'Turn this on when visitors should see the maintenance end time as a live countdown.', 'polanger-admin-menu-manager' ),
					$readonly
				);
				?>

				<div class="pmc-conditional<?php echo $settings['countdown_enabled'] ? ' is-visible' : ''; ?>" data-pmc-conditional="countdown">
					<div class="pmc-stack">
						<input type="hidden" name="pdt_maintenance_center[countdown_target]" value="" />
						<div class="pmc-field">
							<label for="pmc-countdown-label"><strong><?php esc_html_e( 'Countdown label', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-countdown-label" type="text" name="pdt_maintenance_center[countdown_label]" value="<?php echo esc_attr( $settings['countdown_label'] ); ?>" <?php disabled( $readonly ); ?> />
							<p class="description"><?php esc_html_e( 'Leave this empty if you do not want a countdown heading on the frontend.', 'polanger-admin-menu-manager' ); ?></p>
						</div>

						<div class="pmc-field">
							<label for="pmc-schedule-end-secondary"><strong><?php esc_html_e( 'End date and time', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-schedule-end-secondary" type="datetime-local" name="pdt_maintenance_center[schedule_end]" value="<?php echo esc_attr( $settings['schedule_end'] ); ?>" <?php disabled( $readonly ); ?> />
							<p class="description"><?php esc_html_e( 'Choose the exact date and time the countdown should count toward on the frontend.', 'polanger-admin-menu-manager' ); ?></p>
							<p class="description"><?php printf( esc_html__( 'The countdown uses the WordPress timezone from Settings > General: %s.', 'polanger-admin-menu-manager' ), esc_html( wp_timezone_string() ? wp_timezone_string() : 'UTC' ) ); ?></p>
						</div>

						<div class="pmc-field">
							<label><strong><?php esc_html_e( 'Visible countdown units', 'polanger-admin-menu-manager' ); ?></strong></label>
							<div class="pmc-check-grid">
								<?php foreach ( $units as $unit_key => $unit_label ) : ?>
									<?php $field_key = 'countdown_show_' . $unit_key; ?>
									<label class="pmc-check-card<?php echo $settings[ $field_key ] ? ' is-selected' : ''; ?>">
										<input type="checkbox" name="pdt_maintenance_center[<?php echo esc_attr( $field_key ); ?>]" value="1" <?php checked( $settings[ $field_key ] ); ?> <?php disabled( $readonly ); ?> />
										<span class="pmc-check-card__title"><?php echo esc_html( $unit_label ); ?></span>
										<span class="pmc-check-card__description"><?php esc_html_e( 'Show this time unit in the live countdown.', 'polanger-admin-menu-manager' ); ?></span>
									</label>
								<?php endforeach; ?>
							</div>
						</div>
					</div>
				</div>

				<div class="pmc-field">
					<label><strong><?php esc_html_e( 'Footer content', 'polanger-admin-menu-manager' ); ?></strong></label>
					<p class="description"><?php esc_html_e( 'Use this area for support details, business hours, contact notes or any extra reassurance for visitors.', 'polanger-admin-menu-manager' ); ?></p>
					<?php $this->render_rich_editor( 'pmc-footer-editor', 'pdt_maintenance_center[footer_content]', $settings['footer_content'], $readonly ); ?>
				</div>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Render Access section.
	 *
	 * @param array  $settings    Settings payload.
	 * @param string $preview_url Signed preview URL.
	 * @param bool   $readonly    Read-only state.
	 * @return void
	 */
	private function render_access_section( $settings, $preview_url, $readonly ) {
		$roles = $this->get_role_choices();
		?>
		<section class="pmc-panel">
			<div class="pmc-panel__head">
				<h3><?php esc_html_e( 'Access', 'polanger-admin-menu-manager' ); ?></h3>
				<p><?php esc_html_e( 'Choose who can bypass the maintenance screen, which IP addresses are always allowed in, and how temporary preview links should behave.', 'polanger-admin-menu-manager' ); ?></p>
			</div>

			<div class="pmc-stack">
				<?php
				$this->render_toggle_row(
					'allow_logged_in',
					'pmc-allow-logged-in',
					$settings['allow_logged_in'],
					__( 'Allow all logged-in users to bypass', 'polanger-admin-menu-manager' ),
					__( 'Turn this on when any authenticated account should still reach the live frontend during maintenance.', 'polanger-admin-menu-manager' ),
					$readonly
				);
				?>

				<div class="pmc-field">
					<label><strong><?php esc_html_e( 'Bypass roles', 'polanger-admin-menu-manager' ); ?></strong></label>
					<p class="description"><?php esc_html_e( 'Choose the roles that should continue seeing the real website even while visitors get the maintenance page.', 'polanger-admin-menu-manager' ); ?></p>
					<div class="pmc-role-grid">
						<?php foreach ( $roles as $role_key => $role_label ) : ?>
							<label class="pmc-role-card<?php echo in_array( $role_key, $settings['bypass_roles'], true ) ? ' is-selected' : ''; ?>">
								<input type="checkbox" name="pdt_maintenance_center[bypass_roles][]" value="<?php echo esc_attr( $role_key ); ?>" <?php checked( in_array( $role_key, $settings['bypass_roles'], true ) ); ?> <?php disabled( $readonly ); ?> />
								<span class="pmc-role-card__label"><?php echo esc_html( $role_label ); ?></span>
								<span class="pmc-role-card__hint"><?php esc_html_e( 'Users with this role can bypass the maintenance screen.', 'polanger-admin-menu-manager' ); ?></span>
							</label>
						<?php endforeach; ?>
					</div>
				</div>

				<div class="pmc-field">
					<label for="pmc-bypass-ips"><strong><?php esc_html_e( 'Always allowed IP addresses', 'polanger-admin-menu-manager' ); ?></strong></label>
					<textarea id="pmc-bypass-ips" name="pdt_maintenance_center[bypass_ips]" rows="6" <?php disabled( $readonly ); ?>><?php echo esc_textarea( $settings['bypass_ips'] ); ?></textarea>
					<p class="description"><?php esc_html_e( 'Add one IP per line if you need a fixed safe list for your team, QA devices or client review machines.', 'polanger-admin-menu-manager' ); ?></p>
				</div>

				<div class="pmc-preview-card">
					<div class="pmc-preview-card__head">
						<div>
							<h4><?php esc_html_e( 'Preview link', 'polanger-admin-menu-manager' ); ?></h4>
							<p><?php esc_html_e( 'Open or share this signed URL when someone needs to preview the maintenance screen exactly as visitors will see it.', 'polanger-admin-menu-manager' ); ?></p>
						</div>
						<button type="submit" class="button button-secondary" name="pdt_maintenance_regenerate_preview_token" value="1" <?php disabled( $readonly ); ?>><?php esc_html_e( 'Regenerate link token', 'polanger-admin-menu-manager' ); ?></button>
					</div>

					<div class="pmc-grid pmc-grid--two">
						<div class="pmc-field">
							<label for="pmc-preview-url"><strong><?php esc_html_e( 'Current preview URL', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-preview-url" type="text" readonly value="<?php echo esc_attr( $preview_url ); ?>" />
						</div>

						<div class="pmc-field">
							<label for="pmc-preview-ttl"><strong><?php esc_html_e( 'Preview lifetime (hours)', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-preview-ttl" type="number" min="1" max="168" name="pdt_maintenance_center[preview_token_ttl]" value="<?php echo esc_attr( (string) $settings['preview_token_ttl'] ); ?>" <?php disabled( $readonly ); ?> />
						</div>
					</div>
				</div>
			</div>
		</section>
		<?php
	}

	/**
	 * Render Content section.
	 *
	 * @param array $settings Settings payload.
	 * @param bool  $readonly Read-only state.
	 * @return void
	 */
	private function render_content_section( $settings, $readonly ) {
		$units = $this->get_countdown_unit_choices();
		?>
		<section class="pmc-panel">
			<div class="pmc-panel__head">
				<h3><?php esc_html_e( 'Content', 'polanger-admin-menu-manager' ); ?></h3>
				<p><?php esc_html_e( 'Build the public-facing message visitors will see, from the logo and headline to the editor content, countdown and footer area.', 'polanger-admin-menu-manager' ); ?></p>
			</div>

			<div class="pmc-stack">
				<div class="pmc-grid pmc-grid--content">
					<div class="pmc-stack">
						<?php
						$this->render_media_field(
							array(
								'field_base'  => 'logo',
								'label'       => __( 'Logo', 'polanger-admin-menu-manager' ),
								'description' => __( 'Choose the brand mark that should appear at the top of the maintenance card.', 'polanger-admin-menu-manager' ),
								'image_id'    => $settings['logo_id'],
								'image_url'   => $settings['logo_url'],
								'readonly'    => $readonly,
							)
						);

						$this->render_alignment_control(
							array(
								'label'    => __( 'Logo alignment', 'polanger-admin-menu-manager' ),
								'name'     => 'pdt_maintenance_center[logo_alignment]',
								'value'    => $settings['logo_alignment'],
								'readonly' => $readonly,
							)
						);
						?>
					</div>

					<div class="pmc-stack">
						<div class="pmc-field">
							<label for="pmc-headline"><strong><?php esc_html_e( 'Headline', 'polanger-admin-menu-manager' ); ?></strong></label>
							<input id="pmc-headline" type="text" name="pdt_maintenance_center[headline]" value="<?php echo esc_attr( $settings['headline'] ); ?>" <?php disabled( $readonly ); ?> />
						</div>

						<?php
						$this->render_alignment_control(
							array(
								'label'       => __( 'Headline alignment', 'polanger-admin-menu-manager' ),
								'name'        => 'pdt_maintenance_center[headline_alignment]',
								'value'       => $settings['headline_alignment'],
								'readonly'    => $readonly,
								'show_labels' => false,
							)
						);
						?>

						<div class="pmc-field">
							<label><strong><?php esc_html_e( 'Description', 'polanger-admin-menu-manager' ); ?></strong></label>
							<p class="description"><?php esc_html_e( 'Use the WordPress editor for paragraphs, links, shortcodes and allowed HTML. This is the main message visitors will read.', 'polanger-admin-menu-manager' ); ?></p>
							<?php $this->render_rich_editor( 'pmc-message-editor', 'pdt_maintenance_center[message]', $settings['message'], $readonly ); ?>
						</div>

						<?php
						$this->render_alignment_control(
							array(
								'label'    => __( 'Description alignment', 'polanger-admin-menu-manager' ),
								'name'     => 'pdt_maintenance_center[message_alignment]',
								'value'    => $settings['message_alignment'],
								'readonly' => $readonly,
							)
						);
						?>
					</div>
				</div>

				<div class="pmc-grid pmc-grid--two">
					<div class="pmc-field">
						<label for="pmc-button-label"><strong><?php esc_html_e( 'Primary button label', 'polanger-admin-menu-manager' ); ?></strong></label>
						<input id="pmc-button-label" type="text" name="pdt_maintenance_center[button_label]" value="<?php echo esc_attr( $settings['button_label'] ); ?>" <?php disabled( $readonly ); ?> />
					</div>

					<div class="pmc-field">
						<label for="pmc-button-url"><strong><?php esc_html_e( 'Primary button URL', 'polanger-admin-menu-manager' ); ?></strong></label>
						<input id="pmc-button-url" type="url" name="pdt_maintenance_center[button_url]" value="<?php echo esc_attr( $settings['button_url'] ); ?>" <?php disabled( $readonly ); ?> />
					</div>
				</div>

				<div class="pmc-field">
					<label for="pmc-status-note"><strong><?php esc_html_e( 'Status note', 'polanger-admin-menu-manager' ); ?></strong></label>
					<input id="pmc-status-note" type="text" name="pdt_maintenance_center[status_note]" value="<?php echo esc_attr( $settings['status_note'] ); ?>" <?php disabled( $readonly ); ?> />
					<p class="description"><?php esc_html_e( 'A short secondary note such as “Scheduled maintenance in progress” or “Deployment currently underway”.', 'polanger-admin-menu-manager' ); ?></p>
				</div>

				<?php
				$this->render_toggle_row(
					'countdown_enabled',
					'pmc-countdown-enabled',
					$settings['countdown_enabled'],
					__( 'Show countdown', 'polanger-admin-menu-manager' ),
					__( 'Turn this on when visitors should see the maintenance end time as a live countdown.', 'polanger-admin-menu-manager' ),
					$readonly
				);
				?>

				<div class="pmc-conditional<?php echo $settings['countdown_enabled'] ? ' is-visible' : ''; ?>" data-pmc-conditional="countdown">
					<input type="hidden" name="pdt_maintenance_center[countdown_target]" value="" />
					<div class="pmc-field">
						<label for="pmc-countdown-label"><strong><?php esc_html_e( 'Countdown label', 'polanger-admin-menu-manager' ); ?></strong></label>
						<input id="pmc-countdown-label" type="text" name="pdt_maintenance_center[countdown_label]" value="<?php echo esc_attr( $settings['countdown_label'] ); ?>" <?php disabled( $readonly ); ?> />
					</div>

					<div class="pmc-field pmc-conditional<?php echo ! empty( $settings['schedule_end'] ) ? ' is-visible' : ''; ?>" data-pmc-conditional="countdown-schedule-on">
						<p class="description"><?php esc_html_e( 'The countdown automatically uses the end date and time set above.', 'polanger-admin-menu-manager' ); ?></p>
					</div>

					<div class="pmc-field pmc-conditional<?php echo empty( $settings['schedule_end'] ) ? ' is-visible' : ''; ?>" data-pmc-conditional="countdown-schedule-off">
						<p class="description"><?php esc_html_e( 'Set an end date and time above so the countdown has a target to count toward on the frontend.', 'polanger-admin-menu-manager' ); ?></p>
					</div>

					<div class="pmc-field">
						<label><strong><?php esc_html_e( 'Visible countdown units', 'polanger-admin-menu-manager' ); ?></strong></label>
						<div class="pmc-check-grid">
							<?php foreach ( $units as $unit_key => $unit_label ) : ?>
								<?php $field_key = 'countdown_show_' . $unit_key; ?>
								<label class="pmc-check-card<?php echo $settings[ $field_key ] ? ' is-selected' : ''; ?>">
									<input type="checkbox" name="pdt_maintenance_center[<?php echo esc_attr( $field_key ); ?>]" value="1" <?php checked( $settings[ $field_key ] ); ?> <?php disabled( $readonly ); ?> />
									<span class="pmc-check-card__title"><?php echo esc_html( $unit_label ); ?></span>
									<span class="pmc-check-card__description"><?php esc_html_e( 'Show this time unit in the live countdown.', 'polanger-admin-menu-manager' ); ?></span>
								</label>
							<?php endforeach; ?>
						</div>
					</div>
				</div>

				<div class="pmc-field">
					<label><strong><?php esc_html_e( 'Footer content', 'polanger-admin-menu-manager' ); ?></strong></label>
					<p class="description"><?php esc_html_e( 'Use this area for support details, business hours, contact notes or any extra reassurance for visitors.', 'polanger-admin-menu-manager' ); ?></p>
					<?php $this->render_rich_editor( 'pmc-footer-editor', 'pdt_maintenance_center[footer_content]', $settings['footer_content'], $readonly ); ?>
				</div>
			</div>
		</section>
		<?php
	}

	/**
	 * Render Appearance section.
	 *
	 * @param array $settings Settings payload.
	 * @param bool  $readonly Read-only state.
	 * @return void
	 */
	private function render_appearance_section( $settings, $readonly ) {
		$background_types = $this->get_background_type_choices();
		?>
		<section class="pmc-panel">
			<div class="pmc-panel__head">
				<h3><?php esc_html_e( 'Appearance', 'polanger-admin-menu-manager' ); ?></h3>
				<p><?php esc_html_e( 'Control the background treatment behind the maintenance screen. Keep it simple with one color, add depth with a gradient, or upload an image.', 'polanger-admin-menu-manager' ); ?></p>
			</div>

			<div class="pmc-stack">
				<div class="pmc-field">
					<label><strong><?php esc_html_e( 'Background type', 'polanger-admin-menu-manager' ); ?></strong></label>
					<div class="pmc-mode-grid">
						<?php foreach ( $background_types as $type_key => $type_data ) : ?>
							<label class="pmc-mode-card<?php echo $settings['background_type'] === $type_key ? ' is-selected' : ''; ?>">
								<input type="radio" name="pdt_maintenance_center[background_type]" value="<?php echo esc_attr( $type_key ); ?>" <?php checked( $settings['background_type'], $type_key ); ?> <?php disabled( $readonly ); ?> />
								<span class="pmc-mode-card__title"><?php echo esc_html( $type_data['label'] ); ?></span>
								<span class="pmc-mode-card__description"><?php echo esc_html( $type_data['description'] ); ?></span>
							</label>
						<?php endforeach; ?>
					</div>
				</div>

				<div class="pmc-grid pmc-grid--two">
					<div class="pmc-field">
						<label for="pmc-background-primary"><strong><?php esc_html_e( 'Primary color', 'polanger-admin-menu-manager' ); ?></strong></label>
						<input id="pmc-background-primary" class="pmc-color-field" type="text" name="pdt_maintenance_center[background_primary]" value="<?php echo esc_attr( $settings['background_primary'] ); ?>" <?php disabled( $readonly ); ?> />
					</div>

					<div class="pmc-field pmc-conditional<?php echo in_array( $settings['background_type'], array( 'gradient', 'image' ), true ) ? ' is-visible' : ''; ?>" data-pmc-conditional="background-secondary">
						<label for="pmc-background-secondary"><strong><?php esc_html_e( 'Secondary color', 'polanger-admin-menu-manager' ); ?></strong></label>
						<input id="pmc-background-secondary" class="pmc-color-field" type="text" name="pdt_maintenance_center[background_secondary]" value="<?php echo esc_attr( $settings['background_secondary'] ); ?>" <?php disabled( $readonly ); ?> />
					</div>
				</div>

				<div class="pmc-conditional<?php echo 'image' === $settings['background_type'] ? ' is-visible' : ''; ?>" data-pmc-conditional="background-image">
					<?php
					$this->render_media_field(
						array(
							'field_base'  => 'background_image',
							'label'       => __( 'Background image', 'polanger-admin-menu-manager' ),
							'description' => __( 'This image sits behind the card. The selected colors are still used as an overlay to keep text readable.', 'polanger-admin-menu-manager' ),
							'image_id'    => $settings['background_image_id'],
							'image_url'   => $settings['background_image_url'],
							'readonly'    => $readonly,
						)
					);
					?>
				</div>
			</div>
		</section>
		<?php
	}

	/**
	 * Render Deployment section.
	 *
	 * @param array $settings Settings payload.
	 * @param bool  $readonly Read-only state.
	 * @return void
	 */
	private function render_deployment_section( $settings, $readonly ) {
		?>
		<section class="pmc-panel">
			<div class="pmc-panel__head">
				<h3><?php esc_html_e( 'Deployment', 'polanger-admin-menu-manager' ); ?></h3>
				<p><?php esc_html_e( 'These locks apply only when Deployment mode is selected and active. They help you temporarily reduce public write activity during a release window.', 'polanger-admin-menu-manager' ); ?></p>
			</div>

			<?php if ( 'deployment' !== $settings['mode'] ) : ?>
				<div class="notice notice-info inline">
					<p><?php esc_html_e( 'Save the General section with Deployment mode selected to unlock these controls.', 'polanger-admin-menu-manager' ); ?></p>
				</div>
			<?php else : ?>
				<div class="pmc-stack">
					<?php
					$this->render_toggle_row(
						'deployment_disable_comments',
						'pmc-deployment-disable-comments',
						$settings['deployment_disable_comments'],
						__( 'Disable comments', 'polanger-admin-menu-manager' ),
						__( 'Useful when you want to avoid new public interaction while deploying updates.', 'polanger-admin-menu-manager' ),
						$readonly
					);

					$this->render_toggle_row(
						'deployment_disable_registration',
						'pmc-deployment-disable-registration',
						$settings['deployment_disable_registration'],
						__( 'Disable account registration', 'polanger-admin-menu-manager' ),
						__( 'Temporarily prevents public account sign-ups while the deployment window is active.', 'polanger-admin-menu-manager' ),
						$readonly
					);

					$this->render_toggle_row(
						'deployment_disable_checkout',
						'pmc-deployment-disable-checkout',
						$settings['deployment_disable_checkout'],
						__( 'Lock checkout access', 'polanger-admin-menu-manager' ),
						__( 'Prevents public visitors from entering the checkout flow during deployment mode.', 'polanger-admin-menu-manager' ),
						$readonly
					);

					$this->render_toggle_row(
						'deployment_disable_purchases',
						'pmc-deployment-disable-purchases',
						$settings['deployment_disable_purchases'],
						__( 'Disable product purchasing', 'polanger-admin-menu-manager' ),
						__( 'Marks WooCommerce products as not purchasable for visitors while deployment mode is active.', 'polanger-admin-menu-manager' ),
						$readonly
					);
					?>
				</div>
			<?php endif; ?>
		</section>
		<?php
	}

	/**
	 * Render Advanced section.
	 *
	 * @param array $settings Settings payload.
	 * @param bool  $readonly Read-only state.
	 * @return void
	 */
	private function render_advanced_section( $settings, $readonly ) {
		?>
		<section class="pmc-panel">
			<div class="pmc-panel__head">
				<h3><?php esc_html_e( 'Advanced', 'polanger-admin-menu-manager' ); ?></h3>
				<p><?php esc_html_e( 'These controls are for SEO behavior, HTTP handling and small custom front-end tweaks. Most sites can leave them as-is.', 'polanger-admin-menu-manager' ); ?></p>
			</div>

			<div class="pmc-stack">
				<div class="pmc-field">
					<label for="pmc-response-code"><strong><?php esc_html_e( 'HTTP response code', 'polanger-admin-menu-manager' ); ?></strong></label>
					<select id="pmc-response-code" name="pdt_maintenance_center[response_code]" <?php disabled( $readonly ); ?>>
						<?php foreach ( $this->get_response_code_choices() as $value => $label ) : ?>
							<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $settings['response_code'], $value ); ?>><?php echo esc_html( $label ); ?></option>
						<?php endforeach; ?>
					</select>
				</div>

				<?php
				$this->render_toggle_row(
					'block_index',
					'pmc-block-index',
					$settings['block_index'],
					__( 'Discourage indexing', 'polanger-admin-menu-manager' ),
					__( 'Adds noindex signals to the maintenance screen so search engines do not treat it like real content.', 'polanger-admin-menu-manager' ),
					$readonly
				);

				$this->render_toggle_row(
					'allow_sitemap',
					'pmc-allow-sitemap',
					$settings['allow_sitemap'],
					__( 'Keep XML sitemaps reachable', 'polanger-admin-menu-manager' ),
					__( 'Allow sitemap endpoints to stay available while the public site is temporarily closed.', 'polanger-admin-menu-manager' ),
					$readonly
				);
				?>

				<div class="pmc-field">
					<label for="pmc-custom-css"><strong><?php esc_html_e( 'Custom CSS', 'polanger-admin-menu-manager' ); ?></strong></label>
					<textarea id="pmc-custom-css" class="large-text code" rows="10" name="pdt_maintenance_center[custom_css]" <?php disabled( $readonly ); ?>><?php echo esc_textarea( $settings['custom_css'] ); ?></textarea>
				</div>

				<div class="pmc-field">
					<label for="pmc-custom-js"><strong><?php esc_html_e( 'Custom JavaScript', 'polanger-admin-menu-manager' ); ?></strong></label>
					<textarea id="pmc-custom-js" class="large-text code" rows="10" name="pdt_maintenance_center[custom_js]" <?php disabled( $readonly ); ?>><?php echo esc_textarea( $settings['custom_js'] ); ?></textarea>
				</div>
			</div>
		</section>
		<?php
	}

	/**
	 * Sanitize raw settings payload.
	 *
	 * @param array $raw_settings       Raw posted settings.
	 * @param bool  $regenerate_preview Whether preview token should be regenerated.
	 * @return array
	 */
	private function sanitize_settings( $raw_settings, $regenerate_preview = false ) {
		$raw_settings = is_array( $raw_settings ) ? $raw_settings : array();
		$settings     = $this->normalize_settings( $raw_settings );

		if ( $regenerate_preview || '' === $settings['preview_token'] ) {
			$settings['preview_token'] = self::generate_preview_token();
		}

		return $settings;
	}

	/**
	 * Merge a single section payload into the existing settings array.
	 *
	 * Each settings screen only submits the fields rendered in that section, so we
	 * preserve stored values from the other sections and only reset missing
	 * checkbox-style controls that belong to the current section.
	 *
	 * @param array  $existing_settings Persisted settings.
	 * @param array  $raw_settings      Raw posted settings for the active section.
	 * @param string $section           Active section slug.
	 * @return array
	 */
	private function merge_section_settings( $existing_settings, $raw_settings, $section ) {
		$existing_settings = is_array( $existing_settings ) ? $existing_settings : array();
		$raw_settings      = is_array( $raw_settings ) ? $raw_settings : array();
		$defaults          = self::get_defaults();
		$section_fields    = $this->get_section_field_keys( $section );
		$empty_values      = $this->get_section_implicit_empty_values( $section );
		$settings          = $existing_settings;

		foreach ( $section_fields as $field_key ) {
			if ( array_key_exists( $field_key, $raw_settings ) ) {
				$settings[ $field_key ] = $raw_settings[ $field_key ];
				continue;
			}

			if ( array_key_exists( $field_key, $empty_values ) ) {
				$settings[ $field_key ] = $empty_values[ $field_key ];
				continue;
			}

			$settings[ $field_key ] = $defaults[ $field_key ] ?? '';
		}

		return $settings;
	}

	/**
	 * Return the field keys owned by a settings section.
	 *
	 * @param string $section Active section slug.
	 * @return array
	 */
	private function get_section_field_keys( $section ) {
		switch ( $section ) {
			case 'access':
				return array(
					'allow_logged_in',
					'bypass_roles',
					'bypass_ips',
					'preview_token_ttl',
				);

			case 'appearance':
				return array(
					'background_type',
					'background_primary',
					'background_secondary',
					'background_image_id',
					'background_image_url',
				);

			case 'deployment':
				return array(
					'deployment_disable_comments',
					'deployment_disable_registration',
					'deployment_disable_checkout',
					'deployment_disable_purchases',
				);

			case 'advanced':
				return array(
					'response_code',
					'block_index',
					'allow_sitemap',
					'custom_css',
					'custom_js',
				);

			case 'general':
			default:
				return array(
					'enabled',
					'mode',
					'schedule_enabled',
					'schedule_start',
					'schedule_end',
					'timezone',
					'logo_id',
					'logo_url',
					'logo_alignment',
					'headline',
					'headline_alignment',
					'message',
					'message_alignment',
					'button_label',
					'button_url',
					'status_note',
					'countdown_enabled',
					'countdown_label',
					'countdown_target',
					'countdown_show_years',
					'countdown_show_days',
					'countdown_show_hours',
					'countdown_show_minutes',
					'countdown_show_seconds',
					'footer_content',
				);
		}
	}

	/**
	 * Return section field values that should be treated as empty when omitted from POST.
	 *
	 * Checkbox inputs and checkbox groups do not submit anything when unchecked, so
	 * they must be reset explicitly instead of falling back to schema defaults.
	 *
	 * @param string $section Active section slug.
	 * @return array
	 */
	private function get_section_implicit_empty_values( $section ) {
		switch ( $section ) {
			case 'access':
				return array(
					'allow_logged_in' => false,
					'bypass_roles'    => array(),
				);

			case 'deployment':
				return array(
					'deployment_disable_comments'     => false,
					'deployment_disable_registration' => false,
					'deployment_disable_checkout'     => false,
					'deployment_disable_purchases'    => false,
				);

			case 'advanced':
				return array(
					'block_index'   => false,
					'allow_sitemap' => false,
				);

			case 'general':
			default:
				return array(
					'enabled'                => false,
					'countdown_enabled'      => false,
					'countdown_show_years'   => false,
					'countdown_show_days'    => false,
					'countdown_show_hours'   => false,
					'countdown_show_minutes' => false,
					'countdown_show_seconds' => false,
				);
		}
	}

	/**
	 * Normalize settings structure.
	 *
	 * @param array $settings Raw settings.
	 * @return array
	 */
	private function normalize_settings( $settings ) {
		$defaults = self::get_defaults();
		$settings = wp_parse_args( is_array( $settings ) ? $settings : array(), $defaults );

		$settings['schema_version'] = self::SCHEMA_VERSION;
		$settings['enabled']        = ! empty( $settings['enabled'] );
		$settings['mode']           = $this->sanitize_mode( $settings['mode'] );

		$site_timezone = function_exists( 'wp_timezone_string' ) ? wp_timezone_string() : (string) get_option( 'timezone_string', 'UTC' );
		$site_timezone = '' !== $site_timezone ? $site_timezone : 'UTC';

		$settings['schedule_start'] = '';
		$settings['schedule_end']   = $this->sanitize_datetime_local( $settings['schedule_end'] );
		$settings['timezone']       = $site_timezone;

		$settings['allow_logged_in'] = ! empty( $settings['allow_logged_in'] );
		$settings['bypass_roles']    = array_values(
			array_intersect(
				array_keys( $this->get_role_choices() ),
				array_map( 'sanitize_key', (array) $settings['bypass_roles'] )
			)
		);
		$settings['bypass_ips']      = $this->sanitize_ip_list( $settings['bypass_ips'] );
		$settings['preview_token']   = $this->sanitize_preview_token( $settings['preview_token'] );
		$settings['preview_token_ttl'] = max( 1, min( 168, absint( $settings['preview_token_ttl'] ) ) );

		$settings['logo_id']          = absint( $settings['logo_id'] );
		$settings['logo_url']         = esc_url_raw( $settings['logo_url'] );
		$settings['logo_alignment']   = $this->sanitize_alignment( $settings['logo_alignment'] );
		$settings['headline']         = sanitize_text_field( $settings['headline'] );
		$settings['headline_alignment'] = $this->sanitize_alignment( $settings['headline_alignment'] );
		$settings['message']          = wp_kses_post( (string) $settings['message'] );
		$settings['message_alignment'] = $this->sanitize_alignment( $settings['message_alignment'] );
		$settings['button_label']     = sanitize_text_field( $settings['button_label'] );
		$settings['button_url']       = esc_url_raw( $settings['button_url'] );
		$settings['status_note']      = sanitize_text_field( $settings['status_note'] );
		$settings['countdown_enabled'] = ! empty( $settings['countdown_enabled'] );
		$settings['countdown_label']  = sanitize_text_field( $settings['countdown_label'] );
		$settings['countdown_target'] = '';
		if ( ! $settings['countdown_enabled'] ) {
			$settings['schedule_end'] = '';
		}
		$settings['schedule_enabled'] = $settings['countdown_enabled'] && '' !== $settings['schedule_end'];
		$settings['countdown_show_years']   = ! empty( $settings['countdown_show_years'] );
		$settings['countdown_show_days']    = ! empty( $settings['countdown_show_days'] );
		$settings['countdown_show_hours']   = ! empty( $settings['countdown_show_hours'] );
		$settings['countdown_show_minutes'] = ! empty( $settings['countdown_show_minutes'] );
		$settings['countdown_show_seconds'] = ! empty( $settings['countdown_show_seconds'] );
		$settings['footer_content']   = wp_kses_post( (string) $settings['footer_content'] );

		$settings['background_type']      = $this->sanitize_background_type( $settings['background_type'] );
		$settings['background_primary']   = sanitize_hex_color( $settings['background_primary'] );
		$settings['background_secondary'] = sanitize_hex_color( $settings['background_secondary'] );
		$settings['background_image_id']  = absint( $settings['background_image_id'] );
		$settings['background_image_url'] = esc_url_raw( $settings['background_image_url'] );

		$settings['response_code'] = $this->sanitize_response_code( $settings['response_code'] );
		$settings['block_index']   = ! empty( $settings['block_index'] );
		$settings['allow_sitemap'] = ! empty( $settings['allow_sitemap'] );
		$settings['custom_css']    = $this->sanitize_code_block( $settings['custom_css'] );
		$settings['custom_js']     = $this->sanitize_code_block( $settings['custom_js'] );

		$settings['deployment_disable_comments']     = ! empty( $settings['deployment_disable_comments'] );
		$settings['deployment_disable_registration'] = ! empty( $settings['deployment_disable_registration'] );
		$settings['deployment_disable_checkout']     = ! empty( $settings['deployment_disable_checkout'] );
		$settings['deployment_disable_purchases']    = ! empty( $settings['deployment_disable_purchases'] );

		if ( '' === $settings['background_primary'] ) {
			$settings['background_primary'] = $defaults['background_primary'];
		}

		if ( '' === $settings['background_secondary'] ) {
			$settings['background_secondary'] = $defaults['background_secondary'];
		}

		if ( '' === $settings['button_url'] ) {
			$settings['button_url'] = home_url( '/' );
		}

		if ( '' === $settings['preview_token'] ) {
			$settings['preview_token'] = self::generate_preview_token();
		}

		if ( $settings['logo_id'] ) {
			$resolved_logo = $this->resolve_media_url( $settings['logo_id'] );
			if ( '' !== $resolved_logo ) {
				$settings['logo_url'] = $resolved_logo;
			}
		}

		if ( $settings['background_image_id'] ) {
			$resolved_background = $this->resolve_media_url( $settings['background_image_id'] );
			if ( '' !== $resolved_background ) {
				$settings['background_image_url'] = $resolved_background;
			}
		}

		return $settings;
	}

	/**
	 * Get default settings.
	 *
	 * @return array
	 */
	public static function get_defaults() {
		$timezone = function_exists( 'wp_timezone_string' ) ? wp_timezone_string() : (string) get_option( 'timezone_string', 'UTC' );
		$timezone = '' !== $timezone ? $timezone : 'UTC';

		return array(
			'schema_version'                  => self::SCHEMA_VERSION,
			'enabled'                         => false,
			'mode'                            => 'maintenance',
			'schedule_enabled'                => false,
			'schedule_start'                  => '',
			'schedule_end'                    => '',
			'timezone'                        => $timezone,
			'allow_logged_in'                 => false,
			'bypass_roles'                    => array( 'administrator' ),
			'bypass_ips'                      => '',
			'preview_token'                   => self::generate_preview_token(),
			'preview_token_ttl'               => 24,
			'logo_id'                         => 0,
			'logo_url'                        => '',
			'logo_alignment'                  => 'center',
			'headline'                        => __( 'We will be back shortly.', 'polanger-admin-menu-manager' ),
			'headline_alignment'              => 'center',
			'message'                         => __( 'The website is temporarily unavailable while planned maintenance or deployment work is completed.', 'polanger-admin-menu-manager' ),
			'message_alignment'               => 'center',
			'button_label'                    => __( 'Return to homepage', 'polanger-admin-menu-manager' ),
			'button_url'                      => home_url( '/' ),
			'status_note'                     => __( 'Scheduled maintenance in progress', 'polanger-admin-menu-manager' ),
			'countdown_enabled'               => false,
			'countdown_label'                 => __( 'Estimated return', 'polanger-admin-menu-manager' ),
			'countdown_target'                => '',
			'countdown_show_years'            => false,
			'countdown_show_days'             => true,
			'countdown_show_hours'            => true,
			'countdown_show_minutes'          => true,
			'countdown_show_seconds'          => true,
			'footer_content'                  => '',
			'background_type'                 => 'gradient',
			'background_primary'              => '#0f172a',
			'background_secondary'            => '#312e81',
			'background_image_id'             => 0,
			'background_image_url'            => '',
			'response_code'                   => 'auto',
			'block_index'                     => true,
			'allow_sitemap'                   => false,
			'custom_css'                      => '',
			'custom_js'                       => '',
			'deployment_disable_comments'     => true,
			'deployment_disable_registration' => true,
			'deployment_disable_checkout'     => true,
			'deployment_disable_purchases'    => true,
		);
	}

	/**
	 * Generate a preview token.
	 *
	 * @return string
	 */
	public static function generate_preview_token() {
		if ( function_exists( 'wp_generate_password' ) ) {
			return wp_generate_password( 20, false, false );
		}

		$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
		$length     = strlen( $characters );
		$token      = '';

		for ( $index = 0; $index < 20; $index++ ) {
			try {
				$position = random_int( 0, $length - 1 );
			} catch ( Exception $exception ) {
				$position = mt_rand( 0, $length - 1 );
			}

			$token .= $characters[ $position ];
		}

		return $token;
	}

	/**
	 * Get visible sidebar sections.
	 *
	 * @param array $settings Settings payload.
	 * @return array
	 */
	private function get_sections( $settings ) {
		$sections = array(
			'general'    => __( 'General', 'polanger-admin-menu-manager' ),
			'access'     => __( 'Access', 'polanger-admin-menu-manager' ),
			'appearance' => __( 'Appearance', 'polanger-admin-menu-manager' ),
		);

		if ( 'deployment' === $settings['mode'] ) {
			$sections['deployment'] = __( 'Deployment', 'polanger-admin-menu-manager' );
		}

		$sections['advanced'] = __( 'Advanced', 'polanger-admin-menu-manager' );

		return $sections;
	}

	/**
	 * Get active section.
	 *
	 * @param array|null $settings        Settings payload.
	 * @param string     $requested_value Optional requested section.
	 * @return string
	 */
	private function get_active_section( $settings = null, $requested_value = '' ) {
		$settings = is_array( $settings ) ? $settings : $this->get_settings();

		if ( '' === $requested_value ) {
			$requested_value = isset( $_GET['maintenance_section'] ) ? sanitize_key( wp_unslash( $_GET['maintenance_section'] ) ) : 'general'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		}

		$sections = $this->get_sections( $settings );

		return isset( $sections[ $requested_value ] ) ? $requested_value : 'general';
	}

	/**
	 * Get mode choices.
	 *
	 * @return array
	 */
	private function get_mode_choices() {
		return array(
			'coming-soon' => array(
				'label'       => __( 'Coming Soon', 'polanger-admin-menu-manager' ),
				'description' => __( 'Best for sites that are not public yet but still need a polished holding page.', 'polanger-admin-menu-manager' ),
			),
			'maintenance' => array(
				'label'       => __( 'Maintenance', 'polanger-admin-menu-manager' ),
				'description' => __( 'Use this for normal planned maintenance when the site is temporarily unavailable.', 'polanger-admin-menu-manager' ),
			),
			'deployment'  => array(
				'label'       => __( 'Deployment', 'polanger-admin-menu-manager' ),
				'description' => __( 'Adds extra public locks that are useful while you ship updates or releases.', 'polanger-admin-menu-manager' ),
			),
		);
	}

	/**
	 * Get background type choices.
	 *
	 * @return array
	 */
	private function get_background_type_choices() {
		return array(
			'color' => array(
				'label'       => __( 'Solid color', 'polanger-admin-menu-manager' ),
				'description' => __( 'Use a single background color for the cleanest possible look.', 'polanger-admin-menu-manager' ),
			),
			'gradient' => array(
				'label'       => __( 'Gradient', 'polanger-admin-menu-manager' ),
				'description' => __( 'Blend two colors for a more branded and modern presentation.', 'polanger-admin-menu-manager' ),
			),
			'image' => array(
				'label'       => __( 'Image', 'polanger-admin-menu-manager' ),
				'description' => __( 'Place a background image behind the maintenance card with a color overlay.', 'polanger-admin-menu-manager' ),
			),
		);
	}

	/**
	 * Get response code choices.
	 *
	 * @return array
	 */
	private function get_response_code_choices() {
		return array(
			'auto' => __( 'Automatic', 'polanger-admin-menu-manager' ),
			'503'  => __( '503 Service Unavailable', 'polanger-admin-menu-manager' ),
			'200'  => __( '200 OK', 'polanger-admin-menu-manager' ),
		);
	}

	/**
	 * Get countdown unit choices.
	 *
	 * @return array
	 */
	private function get_countdown_unit_choices() {
		return array(
			'years'   => __( 'Years', 'polanger-admin-menu-manager' ),
			'days'    => __( 'Days', 'polanger-admin-menu-manager' ),
			'hours'   => __( 'Hours', 'polanger-admin-menu-manager' ),
			'minutes' => __( 'Minutes', 'polanger-admin-menu-manager' ),
			'seconds' => __( 'Seconds', 'polanger-admin-menu-manager' ),
		);
	}

	/**
	 * Get alignment choices.
	 *
	 * @return array
	 */
	private function get_alignment_choices() {
		return array(
			'left'   => array(
				'label' => __( 'Left', 'polanger-admin-menu-manager' ),
				'icon'  => 'editor-alignleft',
			),
			'center' => array(
				'label' => __( 'Center', 'polanger-admin-menu-manager' ),
				'icon'  => 'editor-aligncenter',
			),
			'right'  => array(
				'label' => __( 'Right', 'polanger-admin-menu-manager' ),
				'icon'  => 'editor-alignright',
			),
		);
	}

	/**
	 * Get role choices.
	 *
	 * @return array
	 */
	private function get_role_choices() {
		$roles = function_exists( 'wp_roles' ) ? wp_roles() : null;

		if ( ! $roles || empty( $roles->roles ) || ! is_array( $roles->roles ) ) {
			return array(
				'administrator' => __( 'Administrator', 'polanger-admin-menu-manager' ),
			);
		}

		$choices = array();

		foreach ( $roles->roles as $role_key => $role_data ) {
			$choices[ $role_key ] = isset( $role_data['name'] ) ? translate_user_role( $role_data['name'] ) : ucfirst( $role_key );
		}

		return $choices;
	}

	/**
	 * Get timezone choices.
	 *
	 * @return array
	 */
	private function get_timezone_choices() {
		$choices = array( 'UTC' => 'UTC' );

		foreach ( timezone_identifiers_list() as $timezone ) {
			$choices[ $timezone ] = $timezone;
		}

		return $choices;
	}

	/**
	 * Check if the current admin page is the maintenance tab.
	 *
	 * @return bool
	 */
	private function is_maintenance_tab() {
		$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$tab  = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		return 'polanger-settings' === $page && 'maintenance' === $tab;
	}

	/**
	 * Sanitize mode key.
	 *
	 * @param string $mode Raw mode.
	 * @return string
	 */
	private function sanitize_mode( $mode ) {
		$mode = sanitize_key( (string) $mode );

		return isset( $this->get_mode_choices()[ $mode ] ) ? $mode : 'maintenance';
	}

	/**
	 * Sanitize response code key.
	 *
	 * @param string $response_code Raw response code.
	 * @return string
	 */
	private function sanitize_response_code( $response_code ) {
		$response_code = sanitize_key( (string) $response_code );

		return isset( $this->get_response_code_choices()[ $response_code ] ) ? $response_code : 'auto';
	}

	/**
	 * Sanitize text alignment.
	 *
	 * @param string $alignment Raw alignment.
	 * @return string
	 */
	private function sanitize_alignment( $alignment ) {
		$alignment = sanitize_key( (string) $alignment );

		return isset( $this->get_alignment_choices()[ $alignment ] ) ? $alignment : 'center';
	}

	/**
	 * Sanitize background type.
	 *
	 * @param string $background_type Raw background type.
	 * @return string
	 */
	private function sanitize_background_type( $background_type ) {
		$background_type = sanitize_key( (string) $background_type );

		return isset( $this->get_background_type_choices()[ $background_type ] ) ? $background_type : 'gradient';
	}

	/**
	 * Sanitize preview token.
	 *
	 * @param string $token Raw token.
	 * @return string
	 */
	private function sanitize_preview_token( $token ) {
		$token = preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $token );

		return is_string( $token ) ? $token : '';
	}

	/**
	 * Sanitize timezone identifier.
	 *
	 * @param string $timezone Raw timezone.
	 * @return string
	 */
	private function sanitize_timezone( $timezone ) {
		$timezone = trim( (string) $timezone );

		if ( '' === $timezone ) {
			return 'UTC';
		}

		if ( in_array( $timezone, timezone_identifiers_list(), true ) ) {
			return $timezone;
		}

		try {
			new DateTimeZone( $timezone );
			return $timezone;
		} catch ( Exception $exception ) {
			unset( $exception );
		}

		return 'UTC';
	}

	/**
	 * Sanitize datetime-local string.
	 *
	 * @param string $value Raw value.
	 * @return string
	 */
	private function sanitize_datetime_local( $value ) {
		$value = trim( (string) $value );

		if ( preg_match( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/', $value ) ) {
			return $value;
		}

		return '';
	}

	/**
	 * Sanitize IP list textarea content.
	 *
	 * @param string $raw Raw content.
	 * @return string
	 */
	private function sanitize_ip_list( $raw ) {
		$items = preg_split( '/[\r\n,]+/', (string) $raw );
		$valid = array();

		foreach ( (array) $items as $item ) {
			$item = trim( $item );

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

			if ( false !== filter_var( $item, FILTER_VALIDATE_IP ) ) {
				$valid[] = $item;
			}
		}

		return implode( "\n", array_values( array_unique( $valid ) ) );
	}

	/**
	 * Sanitize code block content.
	 *
	 * @param string $content Raw content.
	 * @return string
	 */
	private function sanitize_code_block( $content ) {
		$content = (string) $content;
		$content = str_replace( "\0", '', $content );
		$content = str_replace( array( "\r\n", "\r" ), "\n", $content );

		return trim( $content );
	}

	/**
	 * Resolve attachment URL.
	 *
	 * @param int $attachment_id Attachment ID.
	 * @return string
	 */
	private function resolve_media_url( $attachment_id ) {
		$attachment_id = absint( $attachment_id );

		if ( ! $attachment_id ) {
			return '';
		}

		$url = wp_get_attachment_image_url( $attachment_id, 'full' );

		return is_string( $url ) ? esc_url_raw( $url ) : '';
	}

	/**
	 * Render media picker field.
	 *
	 * @param array $args Arguments.
	 * @return void
	 */
	private function render_media_field( $args ) {
		$field_base  = isset( $args['field_base'] ) ? sanitize_key( $args['field_base'] ) : '';
		$label       = isset( $args['label'] ) ? (string) $args['label'] : '';
		$description = isset( $args['description'] ) ? (string) $args['description'] : '';
		$image_id    = isset( $args['image_id'] ) ? absint( $args['image_id'] ) : 0;
		$image_url   = isset( $args['image_url'] ) ? esc_url_raw( (string) $args['image_url'] ) : '';
		$readonly    = ! empty( $args['readonly'] );

		if ( '' === $field_base ) {
			return;
		}
		?>
		<div class="pmc-field">
			<label><strong><?php echo esc_html( $label ); ?></strong></label>
			<?php if ( '' !== $description ) : ?>
				<p class="description"><?php echo esc_html( $description ); ?></p>
			<?php endif; ?>
			<div class="pmc-media" data-pmc-media-field="<?php echo esc_attr( $field_base ); ?>">
				<input type="hidden" name="pdt_maintenance_center[<?php echo esc_attr( $field_base ); ?>_id]" value="<?php echo esc_attr( $image_id ); ?>" data-pmc-media-id="<?php echo esc_attr( $field_base ); ?>" />
				<input type="hidden" name="pdt_maintenance_center[<?php echo esc_attr( $field_base ); ?>_url]" value="<?php echo esc_attr( $image_url ); ?>" data-pmc-media-url="<?php echo esc_attr( $field_base ); ?>" />

				<div class="pmc-media__preview<?php echo '' !== $image_url ? ' has-image' : ''; ?>" data-pmc-media-preview="<?php echo esc_attr( $field_base ); ?>">
					<?php if ( '' !== $image_url ) : ?>
						<img src="<?php echo esc_url( $image_url ); ?>" alt="" />
					<?php else : ?>
						<span><?php esc_html_e( 'No image selected yet.', 'polanger-admin-menu-manager' ); ?></span>
					<?php endif; ?>
				</div>

				<div class="pmc-media__actions">
					<button type="button" class="button button-secondary" data-pmc-media-open="<?php echo esc_attr( $field_base ); ?>" <?php disabled( $readonly ); ?>><?php echo esc_html( '' !== $image_url ? __( 'Change image', 'polanger-admin-menu-manager' ) : __( 'Choose image', 'polanger-admin-menu-manager' ) ); ?></button>
					<button type="button" class="button button-link-delete" data-pmc-media-clear="<?php echo esc_attr( $field_base ); ?>" <?php disabled( $readonly || '' === $image_url ); ?>><?php esc_html_e( 'Remove image', 'polanger-admin-menu-manager' ); ?></button>
				</div>
			</div>
		</div>
		<?php
	}

	/**
	 * Render alignment control.
	 *
	 * @param array $args Arguments.
	 * @return void
	 */
	private function render_alignment_control( $args ) {
		$label       = isset( $args['label'] ) ? (string) $args['label'] : '';
		$name        = isset( $args['name'] ) ? (string) $args['name'] : '';
		$value       = isset( $args['value'] ) ? $this->sanitize_alignment( $args['value'] ) : 'center';
		$readonly    = ! empty( $args['readonly'] );
		$show_labels = ! isset( $args['show_labels'] ) || ! empty( $args['show_labels'] );

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

		$choices = $this->get_alignment_choices();
		$options_class = 'pmc-alignment-options';

		if ( ! $show_labels ) {
			$options_class .= ' pmc-alignment-options--icons-only';
		}
		?>
		<div class="pmc-field">
			<label><strong><?php echo esc_html( $label ); ?></strong></label>
			<div class="<?php echo esc_attr( $options_class ); ?>" role="radiogroup" aria-label="<?php echo esc_attr( $label ); ?>">
				<?php foreach ( $choices as $choice_value => $choice_data ) : ?>
					<label class="pmc-alignment-option<?php echo $value === $choice_value ? ' is-selected' : ''; ?>">
						<input type="radio" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $choice_value ); ?>" aria-label="<?php echo esc_attr( $choice_data['label'] ); ?>" <?php checked( $value, $choice_value ); ?> <?php disabled( $readonly ); ?> />
						<span class="pmc-alignment-option__icon dashicons dashicons-<?php echo esc_attr( $choice_data['icon'] ); ?>" aria-hidden="true"></span>
						<?php if ( $show_labels ) : ?>
							<span class="pmc-alignment-option__label"><?php echo esc_html( $choice_data['label'] ); ?></span>
						<?php else : ?>
							<span class="screen-reader-text"><?php echo esc_html( $choice_data['label'] ); ?></span>
						<?php endif; ?>
					</label>
				<?php endforeach; ?>
			</div>
		</div>
		<?php
	}

	/**
	 * Render rich editor or read-only preview.
	 *
	 * @param string $editor_id     Editor ID.
	 * @param string $textarea_name Textarea name.
	 * @param string $content       Editor content.
	 * @param bool   $readonly      Read-only state.
	 * @return void
	 */
	private function render_rich_editor( $editor_id, $textarea_name, $content, $readonly ) {
		if ( $readonly ) {
			$preview = trim( (string) $content );

			if ( '' !== $preview ) {
				$preview = do_shortcode( $preview );
				$preview = wp_kses_post( $preview );

				if ( $preview === wp_strip_all_tags( $preview ) ) {
					$preview = wpautop( $preview );
				}
			}
			?>
			<div class="pmc-editor-preview">
				<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				<?php echo '' !== $preview ? $preview : '<p>' . esc_html__( 'No content added yet.', 'polanger-admin-menu-manager' ) . '</p>'; ?>
			</div>
			<?php
			return;
		}

		wp_editor(
			$content,
			$editor_id,
			array(
				'textarea_name' => $textarea_name,
				'textarea_rows' => 8,
				'media_buttons' => false,
				'teeny'         => false,
				'quicktags'     => true,
				'tinymce'       => array(
					'wpautop'   => true,
					'toolbar1'  => 'formatselect,bold,italic,underline,strikethrough,bullist,numlist,blockquote,alignleft,aligncenter,alignright,forecolor,backcolor,link,unlink,wp_adv',
					'toolbar2'  => 'fontselect,fontsizeselect,pastetext,removeformat,charmap,outdent,indent,undo,redo,code',
					'branding'  => false,
					'statusbar' => false,
				),
			)
		);
	}

	/**
	 * Render toggle field row.
	 *
	 * @param string $field_key   Field key.
	 * @param string $field_id    Input ID.
	 * @param bool   $checked     Checked state.
	 * @param string $label       Label.
	 * @param string $description Description.
	 * @param bool   $readonly    Read-only state.
	 * @return void
	 */
	private function render_toggle_row( $field_key, $field_id, $checked, $label, $description, $readonly ) {
		?>
		<div class="pmc-toggle-row">
			<label class="pdt-toggle-switch">
				<input id="<?php echo esc_attr( $field_id ); ?>" type="checkbox" name="pdt_maintenance_center[<?php echo esc_attr( $field_key ); ?>]" value="1" <?php checked( $checked ); ?> <?php disabled( $readonly ); ?> />
				<span class="pdt-toggle-slider"></span>
				<span class="pdt-toggle-label"><?php echo esc_html( $label ); ?></span>
			</label>
			<?php if ( '' !== $description ) : ?>
				<p class="description"><?php echo esc_html( $description ); ?></p>
			<?php endif; ?>
		</div>
		<?php
	}
}
