<?php
/**
 * NotFound admin settings UI.
 *
 * @package SEOvaultSEO\NotFound
 */

namespace SEOvaultSEO\NotFound;

use SEOvaultSEO\Core\Options;

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

/**
 * Admin fields and save handlers for NotFound settings.
 */
class AdminSettings {

	/**
	 * Initialize admin settings hooks if needed.
	 */
	public static function init() {
	}

	/**
	 * Render Layer A fallback controls inside the existing 404 Monitor tab.
	 *
	 * @return void
	 */
	public static function render_fallback_fields() {
		$mode       = Options::get_notfound_fallback_mode();
		$status     = Options::get_notfound_fallback_status();
		$custom_url = Options::get_notfound_fallback_custom_url();
		$page_id    = Options::get_notfound_fallback_custom_page_id();
		$pages      = get_pages(
			array(
				'post_status' => 'publish',
				'sort_column' => 'post_title',
				'sort_order'  => 'ASC',
			)
		);
		?>
		<h3><?php esc_html_e( 'Fallback Behavior', 'seovault-ai' ); ?></h3>
		<p class="description">
			<?php esc_html_e( 'Choose what happens when no Redirect Manager rule matches a 404 request.', 'seovault-ai' ); ?>
		</p>
		<table class="form-table seovaultseo-notfound-fallback-settings">
			<tr>
				<th scope="row"><?php esc_html_e( 'Unmatched 404s', 'seovault-ai' ); ?></th>
				<td>
					<fieldset>
						<label>
							<input type="radio" name="notfound_fallback_mode" value="theme" <?php checked( $mode, 'theme' ); ?> />
							<strong><?php esc_html_e( 'Theme 404', 'seovault-ai' ); ?></strong>
							<span class="description"><?php esc_html_e( 'Keep the 404 response and use the active theme’s 404 template.', 'seovault-ai' ); ?></span>
						</label>
						<br />
						<label>
							<input type="radio" name="notfound_fallback_mode" value="home" <?php checked( $mode, 'home' ); ?> />
							<strong><?php esc_html_e( 'Redirect to homepage', 'seovault-ai' ); ?></strong>
							<span class="description"><?php esc_html_e( 'Send unmatched 404 requests to the site homepage.', 'seovault-ai' ); ?></span>
						</label>
						<br />
						<label>
							<input type="radio" name="notfound_fallback_mode" value="custom" <?php checked( $mode, 'custom' ); ?> />
							<strong><?php esc_html_e( 'Redirect to custom URL', 'seovault-ai' ); ?></strong>
							<span class="description"><?php esc_html_e( 'Send unmatched 404 requests to the URL below.', 'seovault-ai' ); ?></span>
						</label>
					</fieldset>
				</td>
			</tr>
			<tr>
				<th scope="row"><label for="notfound_fallback_status"><?php esc_html_e( 'Redirect status', 'seovault-ai' ); ?></label></th>
				<td>
					<select name="notfound_fallback_status" id="notfound_fallback_status" class="seovaultseo-select">
						<option value="301" <?php selected( $status, 301 ); ?>><?php esc_html_e( '301 — Moved Permanently', 'seovault-ai' ); ?></option>
						<option value="302" <?php selected( $status, 302 ); ?>><?php esc_html_e( '302 — Found (temporary)', 'seovault-ai' ); ?></option>
						<option value="307" <?php selected( $status, 307 ); ?>><?php esc_html_e( '307 — Temporary Redirect', 'seovault-ai' ); ?></option>
					</select>
					<p class="description">
						<?php esc_html_e( '302 is the safest default for a global 404 fallback. Avoid 301 to the homepage or a generic page unless that destination permanently replaces the missing URL — search engines may treat that pattern as a soft 404.', 'seovault-ai' ); ?>
					</p>
					<div
						class="notice notice-warning inline seovaultseo-notfound-soft404-warning"
						<?php if ( ! Warnings::should_show_soft404_warning( $mode, $status ) ) : ?>
							hidden
						<?php endif; ?>
					>
						<p><?php echo esc_html( Warnings::get_soft404_warning_message() ); ?></p>
					</div>
				</td>
			</tr>
			<tbody
				id="seovaultseo-notfound-custom-target"
				<?php if ( 'custom' !== $mode ) : ?>
					hidden
				<?php endif; ?>
			>
				<tr>
					<th scope="row"><label for="notfound_fallback_custom_page_id"><?php esc_html_e( 'Custom page', 'seovault-ai' ); ?></label></th>
					<td>
						<select name="notfound_fallback_custom_page_id" id="notfound_fallback_custom_page_id" class="seovaultseo-select">
							<option value="0"><?php esc_html_e( 'No page selected — use custom URL', 'seovault-ai' ); ?></option>
							<?php foreach ( $pages as $page ) : ?>
								<option
									value="<?php echo esc_attr( (string) $page->ID ); ?>"
									data-permalink="<?php echo esc_url( get_permalink( $page->ID ) ); ?>"
									<?php selected( $page_id, (int) $page->ID ); ?>
								>
									<?php echo esc_html( $page->post_title ); ?>
								</option>
							<?php endforeach; ?>
						</select>
						<p class="description"><?php esc_html_e( 'A selected published page takes precedence over the custom URL.', 'seovault-ai' ); ?></p>
					</td>
				</tr>
				<tr>
					<th scope="row"><label for="notfound_fallback_custom_url"><?php esc_html_e( 'Custom URL', 'seovault-ai' ); ?></label></th>
					<td>
						<input type="url" name="notfound_fallback_custom_url" id="notfound_fallback_custom_url" value="<?php echo esc_attr( $custom_url ); ?>" class="regular-text code" placeholder="https://example.com/help/" />
						<p class="description"><?php esc_html_e( 'Enter an absolute URL for the custom fallback.', 'seovault-ai' ); ?></p>
					</td>
				</tr>
			</tbody>
		</table>
		<?php
	}

	/**
	 * Sanitize fallback form fields as one save payload.
	 *
	 * @param array $payload Raw fallback form values.
	 * @return array{mode:string,status:int,custom_url:string,custom_page_id:int}
	 */
	public static function sanitize_save_payload( array $payload ) {
		return array(
			'mode'           => Sanitizer::sanitize_fallback_mode( $payload['notfound_fallback_mode'] ?? 'theme' ),
			'status'         => Sanitizer::sanitize_fallback_status( $payload['notfound_fallback_status'] ?? 302 ),
			'custom_url'     => Sanitizer::sanitize_custom_url( $payload['notfound_fallback_custom_url'] ?? '' ),
			'custom_page_id' => Sanitizer::sanitize_custom_page_id( $payload['notfound_fallback_custom_page_id'] ?? 0 ),
		);
	}

	/**
	 * Persist sanitized fallback form fields.
	 *
	 * Authorization and nonce verification are handled by SettingsPage before
	 * this method is called.
	 *
	 * @param array $payload Raw fallback form values.
	 * @return void
	 */
	public static function save_fallback_settings( array $payload ) {
		$settings = self::sanitize_save_payload( $payload );

		Options::set_notfound_fallback_mode( $settings['mode'] );
		Options::set_notfound_fallback_status( $settings['status'] );
		Options::set_notfound_fallback_custom_url( $settings['custom_url'] );
		Options::set_notfound_fallback_custom_page_id( $settings['custom_page_id'] );
	}

	/**
	 * Render Layer B recovery controls inside the existing 404 Monitor tab.
	 *
	 * @return void
	 */
	public static function render_recovery_fields() {
		$mode             = Options::get_notfound_fallback_mode();
		$enabled          = Options::is_notfound_recovery_enabled();
		$headline         = Options::get_notfound_recovery_headline();
		$message          = Options::get_notfound_recovery_message();
		$show_search      = Options::is_notfound_recovery_show_search();
		$show_home_cta    = Options::is_notfound_recovery_show_home_cta();
		$cta_label        = Options::get_notfound_recovery_cta_label();
		$show_recent      = Options::is_notfound_recovery_show_recent();
		$recent_count     = Options::get_notfound_recovery_recent_count();
		$use_theme_colors = Options::is_notfound_recovery_use_theme_colors();
		$accent           = Options::get_notfound_recovery_accent();
		$accent_for_color = self::accent_for_color_input( $accent );
		$content_mode     = Options::get_notfound_recovery_content_mode();
		$recovery_page_id = Options::get_notfound_recovery_page_id();
		$pages            = get_pages(
			array(
				'post_status' => 'publish',
				'sort_column' => 'post_title',
				'sort_order'  => 'ASC',
			)
		);
		?>
		<h3><?php esc_html_e( '404 Recovery Page', 'seovault-ai' ); ?></h3>
		<p class="description">
			<?php esc_html_e( 'Optionally replace the theme 404 body with a simple recovery page. The response stays HTTP 404 and is still logged by the 404 Monitor. No WordPress page is created automatically.', 'seovault-ai' ); ?>
		</p>
		<div
			class="notice notice-info inline seovaultseo-notfound-recovery-theme-notice"
			<?php if ( 'theme' === $mode ) : ?>
				hidden
			<?php endif; ?>
		>
			<p><?php esc_html_e( 'The 404 Recovery Page only applies when Fallback Behavior is set to Theme 404.', 'seovault-ai' ); ?></p>
		</div>
		<table class="form-table seovaultseo-notfound-recovery-settings">
			<tr>
				<th scope="row"><?php esc_html_e( 'Enable recovery page', 'seovault-ai' ); ?></th>
				<td>
					<?php
					\SEOvaultSEO\Admin\Dashboard::render_toggle(
						'notfound_recovery_enabled',
						__( 'Show the built-in recovery page on unmatched 404s', 'seovault-ai' ),
						$enabled
					);
					?>
				</td>
			</tr>
			<tbody
				id="seovaultseo-notfound-recovery-details"
				<?php if ( ! $enabled ) : ?>
					hidden
				<?php endif; ?>
			>
			<tr class="seovaultseo-notfound-recovery-builtin-copy">
				<th scope="row"><label for="notfound_recovery_headline"><?php esc_html_e( 'Headline', 'seovault-ai' ); ?></label></th>
				<td>
					<input
						type="text"
						name="notfound_recovery_headline"
						id="notfound_recovery_headline"
						value="<?php echo esc_attr( $headline ); ?>"
						class="regular-text"
					/>
				</td>
			</tr>
			<tr class="seovaultseo-notfound-recovery-builtin-copy">
				<th scope="row"><label for="notfound_recovery_message"><?php esc_html_e( 'Message', 'seovault-ai' ); ?></label></th>
				<td>
					<textarea
						name="notfound_recovery_message"
						id="notfound_recovery_message"
						rows="3"
						class="large-text"
					><?php echo esc_textarea( $message ); ?></textarea>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php esc_html_e( 'Show search form', 'seovault-ai' ); ?></th>
				<td>
					<?php
					\SEOvaultSEO\Admin\Dashboard::render_toggle(
						'notfound_recovery_show_search',
						__( 'Include the WordPress search form', 'seovault-ai' ),
						$show_search
					);
					?>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php esc_html_e( 'Show home CTA', 'seovault-ai' ); ?></th>
				<td>
					<?php
					\SEOvaultSEO\Admin\Dashboard::render_toggle(
						'notfound_recovery_show_home_cta',
						__( 'Show a button linking back to the homepage', 'seovault-ai' ),
						$show_home_cta
					);
					?>
				</td>
			</tr>
			<tr
				id="seovaultseo-notfound-recovery-cta-label-row"
				<?php if ( ! $show_home_cta ) : ?>
					hidden
				<?php endif; ?>
			>
				<th scope="row"><label for="notfound_recovery_cta_label"><?php esc_html_e( 'CTA label', 'seovault-ai' ); ?></label></th>
				<td>
					<input
						type="text"
						name="notfound_recovery_cta_label"
						id="notfound_recovery_cta_label"
						value="<?php echo esc_attr( $cta_label ); ?>"
						class="regular-text"
					/>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php esc_html_e( 'Show recent posts', 'seovault-ai' ); ?></th>
				<td>
					<?php
					\SEOvaultSEO\Admin\Dashboard::render_toggle(
						'notfound_recovery_show_recent',
						__( 'List recent published posts on the recovery page', 'seovault-ai' ),
						$show_recent
					);
					?>
				</td>
			</tr>
			<tr
				id="seovaultseo-notfound-recovery-recent-count-row"
				<?php if ( ! $show_recent ) : ?>
					hidden
				<?php endif; ?>
			>
				<th scope="row"><label for="notfound_recovery_recent_count"><?php esc_html_e( 'Recent post count', 'seovault-ai' ); ?></label></th>
				<td>
					<input
						type="number"
						name="notfound_recovery_recent_count"
						id="notfound_recovery_recent_count"
						value="<?php echo esc_attr( (string) $recent_count ); ?>"
						min="1"
						max="6"
						step="1"
						class="small-text"
					/>
					<p class="description"><?php esc_html_e( 'Between 1 and 6 posts.', 'seovault-ai' ); ?></p>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php esc_html_e( 'Use theme colors', 'seovault-ai' ); ?></th>
				<td>
					<?php
					\SEOvaultSEO\Admin\Dashboard::render_toggle(
						'notfound_recovery_use_theme_colors',
						__( 'Prefer colors from the active theme when available', 'seovault-ai' ),
						$use_theme_colors
					);
					?>
				</td>
			</tr>
			<tr>
				<th scope="row"><label for="notfound_recovery_accent"><?php esc_html_e( 'Accent color', 'seovault-ai' ); ?></label></th>
				<td>
					<input
						type="color"
						name="notfound_recovery_accent"
						id="notfound_recovery_accent"
						value="<?php echo esc_attr( $accent_for_color ); ?>"
					/>
					<p class="description"><?php esc_html_e( 'Hex color used when theme colors are off, or as a fallback accent.', 'seovault-ai' ); ?></p>
				</td>
			</tr>
			<tr>
				<th scope="row"><?php esc_html_e( 'Content source', 'seovault-ai' ); ?></th>
				<td>
					<fieldset>
						<label>
							<input
								type="radio"
								name="notfound_recovery_content_mode"
								value="builtin"
								<?php checked( $content_mode, 'builtin' ); ?>
							/>
							<strong><?php esc_html_e( 'Built-in copy', 'seovault-ai' ); ?></strong>
							<span class="description"><?php esc_html_e( 'Use the headline and message above.', 'seovault-ai' ); ?></span>
						</label>
						<br />
						<label>
							<input
								type="radio"
								name="notfound_recovery_content_mode"
								value="page"
								<?php checked( $content_mode, 'page' ); ?>
							/>
							<strong><?php esc_html_e( 'Existing WordPress page', 'seovault-ai' ); ?></strong>
							<span class="description"><?php esc_html_e( 'Show that page’s content inside the recovery layout.', 'seovault-ai' ); ?></span>
						</label>
					</fieldset>
				</td>
			</tr>
			<tr
				id="seovaultseo-notfound-recovery-page-row"
				<?php if ( 'page' !== $content_mode ) : ?>
					hidden
				<?php endif; ?>
			>
				<th scope="row"><label for="notfound_recovery_page_id"><?php esc_html_e( 'Recovery page', 'seovault-ai' ); ?></label></th>
				<td>
					<select name="notfound_recovery_page_id" id="notfound_recovery_page_id" class="seovaultseo-select">
						<option value="0"><?php esc_html_e( 'Select a published page…', 'seovault-ai' ); ?></option>
						<?php foreach ( $pages as $page ) : ?>
							<option
								value="<?php echo esc_attr( (string) $page->ID ); ?>"
								<?php selected( $recovery_page_id, (int) $page->ID ); ?>
							>
								<?php echo esc_html( $page->post_title ); ?>
							</option>
						<?php endforeach; ?>
					</select>
					<p class="description">
						<?php esc_html_e( 'Create a normal Page yourself if you want custom copy — SEOvault will not auto-create one.', 'seovault-ai' ); ?>
					</p>
				</td>
			</tr>
			</tbody>
		</table>
		<?php
	}

	/**
	 * Sanitize recovery form fields as one save payload.
	 *
	 * @param array $payload Raw recovery form values.
	 * @return array{
	 *     enabled:bool,
	 *     headline:string,
	 *     message:string,
	 *     show_search:bool,
	 *     show_home_cta:bool,
	 *     cta_label:string,
	 *     show_recent:bool,
	 *     recent_count:int,
	 *     use_theme_colors:bool,
	 *     accent:string,
	 *     content_mode:string,
	 *     page_id:int
	 * }
	 */
	public static function sanitize_recovery_save_payload( array $payload ) {
		return array(
			'enabled'          => Sanitizer::sanitize_boolean( $payload['notfound_recovery_enabled'] ?? false ),
			'headline'         => Sanitizer::sanitize_recovery_text( $payload['notfound_recovery_headline'] ?? '' ),
			'message'          => Sanitizer::sanitize_recovery_text( $payload['notfound_recovery_message'] ?? '' ),
			'show_search'      => Sanitizer::sanitize_boolean( $payload['notfound_recovery_show_search'] ?? false ),
			'show_home_cta'    => Sanitizer::sanitize_boolean( $payload['notfound_recovery_show_home_cta'] ?? false ),
			'cta_label'        => Sanitizer::sanitize_recovery_text( $payload['notfound_recovery_cta_label'] ?? '' ),
			'show_recent'      => Sanitizer::sanitize_boolean( $payload['notfound_recovery_show_recent'] ?? false ),
			'recent_count'     => Sanitizer::sanitize_recovery_recent_count( $payload['notfound_recovery_recent_count'] ?? 3 ),
			'use_theme_colors' => Sanitizer::sanitize_boolean( $payload['notfound_recovery_use_theme_colors'] ?? false ),
			'accent'           => Sanitizer::sanitize_recovery_accent( $payload['notfound_recovery_accent'] ?? '' ),
			'content_mode'     => Sanitizer::sanitize_recovery_content_mode( $payload['notfound_recovery_content_mode'] ?? 'builtin' ),
			'page_id'          => Sanitizer::sanitize_recovery_page_id( $payload['notfound_recovery_page_id'] ?? 0 ),
		);
	}

	/**
	 * Persist sanitized recovery form fields.
	 *
	 * Authorization and nonce verification are handled by SettingsPage before
	 * this method is called.
	 *
	 * @param array $payload Raw recovery form values.
	 * @return void
	 */
	public static function save_recovery_settings( array $payload ) {
		$settings = self::sanitize_recovery_save_payload( $payload );

		Options::set_notfound_recovery_enabled( $settings['enabled'] );
		Options::set_notfound_recovery_headline( $settings['headline'] );
		Options::set_notfound_recovery_message( $settings['message'] );
		Options::set_notfound_recovery_show_search( $settings['show_search'] );
		Options::set_notfound_recovery_show_home_cta( $settings['show_home_cta'] );
		Options::set_notfound_recovery_cta_label( $settings['cta_label'] );
		Options::set_notfound_recovery_show_recent( $settings['show_recent'] );
		Options::set_notfound_recovery_recent_count( $settings['recent_count'] );
		Options::set_notfound_recovery_use_theme_colors( $settings['use_theme_colors'] );
		Options::set_notfound_recovery_accent( $settings['accent'] );
		Options::set_notfound_recovery_content_mode( $settings['content_mode'] );
		Options::set_notfound_recovery_page_id( $settings['page_id'] );
	}

	/**
	 * Expand a 3-digit hex accent so HTML color inputs can use it.
	 *
	 * @param string $accent Sanitized accent hex.
	 * @return string
	 */
	private static function accent_for_color_input( $accent ) {
		if ( preg_match( '/^#([a-f0-9])([a-f0-9])([a-f0-9])$/i', $accent, $matches ) ) {
			return '#' . $matches[1] . $matches[1] . $matches[2] . $matches[2] . $matches[3] . $matches[3];
		}

		return preg_match( '/^#[a-f0-9]{6}$/i', $accent ) ? strtolower( $accent ) : '#1a1a1a';
	}
}
