<?php
/**
 * Theme settings page and option helpers.
 *
 * @package wuppi
 */

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

/**
 * Allowed palette slot slugs used by color selects in the settings UI.
 *
 * @return array<string, string>
 */
function wuppi_settings_palette_slots() {
	return array(
		'primary'    => __( 'Primary', 'wuppi' ),
		'accent'     => __( 'Accent', 'wuppi' ),
		'foreground' => __( 'Foreground', 'wuppi' ),
		'background' => __( 'Background', 'wuppi' ),
		'muted'             => __( 'Muted', 'wuppi' ),
		'muted-foreground'  => __( 'Muted Foreground', 'wuppi' ),
		'secondary'         => __( 'Secondary', 'wuppi' ),
		'card'              => __( 'Card', 'wuppi' ),
	);
}

/**
 * Return a slug → hex map for the theme palette, for use in the settings UI color pickers.
 *
 * @return array<string, string>
 */
function wuppi_settings_palette_color_values() {
	$global  = wp_get_global_settings();
	$palette = $global['color']['palette']['theme'] ?? array();
	$map     = array();
	foreach ( $palette as $item ) {
		if ( isset( $item['slug'], $item['color'] ) ) {
			$map[ $item['slug'] ] = $item['color'];
		}
	}
	return $map;
}

/**
 * Allowed radius presets and their pixel values.
 *
 * @return array<string, int>
 */
function wuppi_settings_radius_presets() {
	return array(
		'none' => 0,
		'sm'   => 6,
		'md'   => 8,
		'lg'   => 16,
		'pill' => 999,
	);
}

/**
 * Allowed transition speed presets and their CSS values.
 *
 * @return array<string, string>
 */
function wuppi_settings_transition_presets() {
	return array(
		'none'   => '0s',
		'fast'   => '0.1s',
		'normal' => '0.2s',
		'slow'   => '0.35s',
	);
}

/**
 * Return theme settings defaults.
 *
 * @return array<string, mixed>
 */
function wuppi_get_settings_defaults() {
	return array(
		// General.
		'back_to_top'              => 1,
		'back_to_top_shape'        => 'circle',
		'mobile_content_padding'   => 16,

		// Header (existing).
		'header_height'            => 72,
		'header_nav_density'       => 'compact',
		'header_nav_gap'           => 14,
		'header_desktop_behavior'  => 'scroll',
		'header_mobile_behavior'   => 'sticky-glass',
		'header_auto_hide_delay'   => 900,

		// Header (new — navigation styling).
		'nav_font_weight'          => '400',
		'nav_hover_underline'      => 0,
		'nav_active_indicator'     => 'none',

		// Buttons.
		'btn_radius_use_global'    => 1,
		'btn_radius_preset'        => 'md',
		'btn_padding_preset'       => 'normal',
		'btn_font_weight'          => '500',
		'btn_hover_bg'             => 'accent',
		'btn_hover_color'          => 'background',
		'btn_outline_hover_bg'     => 'muted',
		'btn_outline_hover_color'  => 'foreground',
		'btn_outline_hover_border' => 'foreground',

		// Design — global radius.
		'radius_preset'            => 'md',
		'radius_image_override'    => 0,
		'radius_image'             => 8,
		'radius_card_override'     => 0,
		'radius_card'              => 8,
		'radius_input_override'    => 0,
		'radius_input'             => 6,

		// Design — shadows.
		'shadow_enabled'                => 0,
		'shadow_intensity'              => 8,
		'shadow_on_cards'               => 0,
		'shadow_on_images'              => 0,

		// Buttons — shadow.
		'shadow_on_buttons'             => 0,
		'shadow_on_buttons_hover_only'  => 0,

		// Design — transitions.
		'transition_speed'         => 'normal',
		'respect_reduced_motion'   => 1,

		// Typography.
		'heading_line_height'      => 1.2,
		'heading_letter_spacing'   => -0.01,
		'body_line_height'         => 1.6,

		// Advanced.
		'input_focus_color'        => 'primary',
		'input_focus_style'        => 'outline',
		'custom_css'               => '',
	);
}

/**
 * Get merged theme settings.
 *
 * @return array<string, mixed>
 */
function wuppi_get_settings() {
	$defaults = wuppi_get_settings_defaults();
	$stored   = get_option( 'wuppi_settings', array() );

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

	return wp_parse_args( $stored, $defaults );
}

/**
 * Return the capability required to manage Wuppi settings.
 *
 * @return string
 */
function wuppi_get_settings_page_capability() {
	return 'edit_theme_options';
}

/**
 * Register theme settings page.
 */
function wuppi_add_settings_page() {
	$hook_suffix = add_theme_page(
		esc_html__( 'Wuppi Design', 'wuppi' ),
		esc_html__( 'Wuppi Design', 'wuppi' ),
		wuppi_get_settings_page_capability(),
		'wuppi-settings',
		'wuppi_render_settings_page'
	);

	if ( $hook_suffix ) {
		add_action( 'load-' . $hook_suffix, 'wuppi_add_settings_screen_help' );
	}
}
add_action( 'admin_menu', 'wuppi_add_settings_page' );

/**
 * Ensure the settings form uses the theme capability instead of manage_options.
 *
 * @return string
 */
function wuppi_filter_settings_page_capability() {
	return wuppi_get_settings_page_capability();
}
add_filter( 'option_page_capability_wuppi_settings_group', 'wuppi_filter_settings_page_capability' );

/**
 * Register contextual help for the Wuppi settings screen.
 */
function wuppi_add_settings_screen_help() {
	if ( ! function_exists( 'get_current_screen' ) ) {
		return;
	}

	$screen = get_current_screen();
	if ( ! $screen ) {
		return;
	}

	$help_url = admin_url( 'themes.php?page=wuppi-help' );
	$content  = '<p>' . esc_html__( 'Use this screen to fine-tune Wuppi visual tokens — buttons, radius, shadows, typography — alongside the Site Editor.', 'wuppi' ) . '</p>';
	$content .= '<p><a href="' . esc_url( $help_url ) . '">' . esc_html__( 'Open Wuppi Help', 'wuppi' ) . '</a></p>';

	$screen->add_help_tab(
		array(
			'id'      => 'wuppi-settings-help',
			'title'   => esc_html__( 'Wuppi Help', 'wuppi' ),
			'content' => $content,
		)
	);
}

/**
 * Register the option (no UI sections — that lives in the React app).
 */
function wuppi_register_settings() {
	register_setting(
		'wuppi_settings_group',
		'wuppi_settings',
		array(
			'type'              => 'array',
			'sanitize_callback' => 'wuppi_sanitize_settings',
			'default'           => wuppi_get_settings_defaults(),
			'show_in_rest'      => false,
		)
	);
}
add_action( 'admin_init', 'wuppi_register_settings' );

/**
 * Sanitize theme settings values.
 *
 * @param mixed $input Settings input.
 * @return array<string, mixed>
 */
function wuppi_sanitize_settings( $input ) {
	$defaults = wuppi_get_settings_defaults();
	$output   = $defaults;

	if ( ! is_array( $input ) ) {
		return $output;
	}

	$palette_slots     = array_keys( wuppi_settings_palette_slots() );
	$radius_presets    = array_keys( wuppi_settings_radius_presets() );
	$transition_speeds = array_keys( wuppi_settings_transition_presets() );

	$bool = static function ( $value ) {
		return ! empty( $value ) && '0' !== (string) $value ? 1 : 0;
	};

	$enum = static function ( $value, array $allowed, $fallback ) {
		$value = is_string( $value ) ? sanitize_key( $value ) : '';
		return in_array( $value, $allowed, true ) ? $value : $fallback;
	};

	$int_in_range = static function ( $value, $min, $max, $default ) {
		$int = is_numeric( $value ) ? (int) $value : (int) $default;
		return max( $min, min( $max, $int ) );
	};

	$float_in_range = static function ( $value, $min, $max, $default ) {
		$float = is_numeric( $value ) ? (float) $value : (float) $default;
		if ( $float < $min ) {
			$float = $min;
		}
		if ( $float > $max ) {
			$float = $max;
		}
		return round( $float, 4 );
	};

	$palette_or_default = static function ( $value, array $slots, $default ) use ( $enum ) {
		return $enum( $value, $slots, $default );
	};

	// General.
	$output['back_to_top']            = $bool( $input['back_to_top'] ?? 0 );
	$output['back_to_top_shape']      = $enum( $input['back_to_top_shape'] ?? '', array( 'circle', 'button' ), $defaults['back_to_top_shape'] );
	$output['mobile_content_padding'] = $int_in_range( $input['mobile_content_padding'] ?? null, 8, 40, $defaults['mobile_content_padding'] );

	// Header.
	$output['header_height']           = $int_in_range( $input['header_height'] ?? null, 56, 120, $defaults['header_height'] );
	$output['header_nav_density']      = $enum( $input['header_nav_density'] ?? '', array( 'compact', 'comfortable' ), $defaults['header_nav_density'] );
	$output['header_nav_gap']          = $int_in_range( $input['header_nav_gap'] ?? null, 0, 48, $defaults['header_nav_gap'] );
	$output['header_desktop_behavior'] = $enum( $input['header_desktop_behavior'] ?? '', array( 'scroll', 'fixed-glass', 'fixed-auto-hide' ), $defaults['header_desktop_behavior'] );
	$output['header_mobile_behavior']  = $enum( $input['header_mobile_behavior'] ?? '', array( 'sticky-glass', 'static' ), $defaults['header_mobile_behavior'] );

	$auto_hide = isset( $input['header_auto_hide_delay'] ) ? (int) $input['header_auto_hide_delay'] : (int) $defaults['header_auto_hide_delay'];
	$output['header_auto_hide_delay'] = in_array( $auto_hide, array( 600, 900, 1400 ), true ) ? $auto_hide : (int) $defaults['header_auto_hide_delay'];

	// Header — nav styling.
	$output['nav_font_weight']      = $enum( $input['nav_font_weight'] ?? '', array( '400', '500', '600' ), $defaults['nav_font_weight'] );
	$output['nav_hover_underline']  = $bool( $input['nav_hover_underline'] ?? 0 );
	$output['nav_active_indicator'] = $enum( $input['nav_active_indicator'] ?? '', array( 'none', 'underline', 'dot', 'background' ), $defaults['nav_active_indicator'] );

	// Buttons.
	$output['btn_radius_use_global'] = $bool( $input['btn_radius_use_global'] ?? 1 );
	$output['btn_radius_preset']     = $enum( $input['btn_radius_preset'] ?? '', $radius_presets, $defaults['btn_radius_preset'] );
	$output['btn_padding_preset']    = $enum( $input['btn_padding_preset'] ?? '', array( 'compact', 'normal', 'large' ), $defaults['btn_padding_preset'] );
	$output['btn_font_weight']          = $enum( $input['btn_font_weight'] ?? '', array( '400', '500', '600', '700' ), $defaults['btn_font_weight'] );
	$output['btn_hover_bg']             = $palette_or_default( $input['btn_hover_bg'] ?? '', $palette_slots, $defaults['btn_hover_bg'] );
	$output['btn_hover_color']          = $palette_or_default( $input['btn_hover_color'] ?? '', $palette_slots, $defaults['btn_hover_color'] );
	$output['btn_outline_hover_bg']     = $palette_or_default( $input['btn_outline_hover_bg'] ?? '', $palette_slots, $defaults['btn_outline_hover_bg'] );
	$output['btn_outline_hover_color']  = $palette_or_default( $input['btn_outline_hover_color'] ?? '', $palette_slots, $defaults['btn_outline_hover_color'] );
	$output['btn_outline_hover_border'] = $palette_or_default( $input['btn_outline_hover_border'] ?? '', $palette_slots, $defaults['btn_outline_hover_border'] );

	// Design — radius.
	$output['radius_preset']         = $enum( $input['radius_preset'] ?? '', $radius_presets, $defaults['radius_preset'] );
	$output['radius_image_override'] = $bool( $input['radius_image_override'] ?? 0 );
	$output['radius_image']          = $int_in_range( $input['radius_image'] ?? null, 0, 999, $defaults['radius_image'] );
	$output['radius_card_override']  = $bool( $input['radius_card_override'] ?? 0 );
	$output['radius_card']           = $int_in_range( $input['radius_card'] ?? null, 0, 999, $defaults['radius_card'] );
	$output['radius_input_override'] = $bool( $input['radius_input_override'] ?? 0 );
	$output['radius_input']          = $int_in_range( $input['radius_input'] ?? null, 0, 999, $defaults['radius_input'] );

	// Design — shadows.
	$output['shadow_enabled']               = $bool( $input['shadow_enabled'] ?? 0 );
	$output['shadow_intensity']             = $int_in_range( $input['shadow_intensity'] ?? null, 0, 100, $defaults['shadow_intensity'] );
	$output['shadow_on_cards']              = $bool( $input['shadow_on_cards'] ?? 0 );
	$output['shadow_on_images']             = $bool( $input['shadow_on_images'] ?? 0 );

	// Buttons — shadow.
	$output['shadow_on_buttons']            = $bool( $input['shadow_on_buttons'] ?? 0 );
	$output['shadow_on_buttons_hover_only'] = $bool( $input['shadow_on_buttons_hover_only'] ?? 0 );

	// Design — transitions.
	$output['transition_speed']       = $enum( $input['transition_speed'] ?? '', $transition_speeds, $defaults['transition_speed'] );
	$output['respect_reduced_motion'] = $bool( $input['respect_reduced_motion'] ?? 0 );

	// Typography.
	$output['heading_line_height']    = $float_in_range( $input['heading_line_height'] ?? null, 1.0, 1.8, $defaults['heading_line_height'] );
	$output['heading_letter_spacing'] = $float_in_range( $input['heading_letter_spacing'] ?? null, -0.05, 0.05, $defaults['heading_letter_spacing'] );
	$output['body_line_height']       = $float_in_range( $input['body_line_height'] ?? null, 1.3, 2.0, $defaults['body_line_height'] );

	// Advanced.
	$output['input_focus_color'] = $palette_or_default( $input['input_focus_color'] ?? '', $palette_slots, $defaults['input_focus_color'] );
	$output['input_focus_style'] = $enum( $input['input_focus_style'] ?? '', array( 'outline', 'shadow', 'glow' ), $defaults['input_focus_style'] );

	$css_raw = isset( $input['custom_css'] ) ? (string) $input['custom_css'] : '';
	if ( strlen( $css_raw ) > 50000 ) {
		$css_raw = substr( $css_raw, 0, 50000 );
	}
	$output['custom_css'] = wp_strip_all_tags( $css_raw );

	return $output;
}

/**
 * Convert a settings array into a flat map of CSS custom properties consumed by theme.css.
 *
 * @param array<string, mixed> $settings Sanitized settings.
 * @return array<string, string>
 */
function wuppi_settings_to_css_vars( array $settings ) {
	$presets     = wuppi_settings_radius_presets();
	$transitions = wuppi_settings_transition_presets();

	$global_radius_px = isset( $presets[ $settings['radius_preset'] ] ) ? (int) $presets[ $settings['radius_preset'] ] : 8;
	$image_radius_px  = ! empty( $settings['radius_image_override'] ) ? (int) $settings['radius_image'] : $global_radius_px;
	$card_radius_px   = ! empty( $settings['radius_card_override'] ) ? (int) $settings['radius_card'] : $global_radius_px;
	$input_radius_px  = ! empty( $settings['radius_input_override'] ) ? (int) $settings['radius_input'] : max( 0, $global_radius_px - 2 );

	$transition_speed = isset( $transitions[ $settings['transition_speed'] ] ) ? $transitions[ $settings['transition_speed'] ] : '0.2s';

	$shadow_alpha = max( 0, min( 100, (int) $settings['shadow_intensity'] ) ) / 100;
	$shadow_value = ! empty( $settings['shadow_enabled'] )
		? sprintf( '0 10px 15px -3px rgba(0,0,0,%s), 0 4px 6px -4px rgba(0,0,0,%s)', round( $shadow_alpha, 3 ), round( $shadow_alpha * 0.6, 3 ) )
		: 'none';

	$nav_font_size = ( 'comfortable' === $settings['header_nav_density'] ) ? '1.1875rem' : '1.125rem';

	$padding_presets = array(
		'compact' => array( '0.5rem', '1rem' ),
		'normal'  => array( '0.75rem', '1.5rem' ),
		'large'   => array( '1rem', '2rem' ),
	);
	$btn_padding = $padding_presets[ $settings['btn_padding_preset'] ] ?? $padding_presets['normal'];

	$palette = static function ( $slot ) {
		return 'var(--wp--preset--color--' . sanitize_html_class( $slot ) . ')';
	};

	return array(
		// Header.
		'--calm-header-height'            => (int) $settings['header_height'] . 'px',
		'--calm-nav-gap'                  => (int) $settings['header_nav_gap'] . 'px',
		'--calm-nav-font-size'            => $nav_font_size,
		'--wuppi-nav-font-weight'         => (string) $settings['nav_font_weight'],
		'--wuppi-nav-hover-mark-w'      => ! empty( $settings['nav_hover_underline'] ) ? '100%' : '0px',
		'--wuppi-nav-hover-mark-h'      => ! empty( $settings['nav_hover_underline'] ) ? '2px' : '0px',
		'--wuppi-nav-active-bg'         => 'background' === ( $settings['nav_active_indicator'] ?? 'none' ) ? $palette( 'muted' ) : 'transparent',
		'--wuppi-nav-active-bg-radius'  => 'background' === ( $settings['nav_active_indicator'] ?? 'none' ) ? 'var(--wuppi-radius)' : '0',
		'--wuppi-nav-active-padding'    => 'background' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '0.5em' : '0px',
		'--wuppi-nav-mark-w'            => 'underline' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '100%' : ( 'dot' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '6px' : '0px' ),
		'--wuppi-nav-mark-h'            => 'underline' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '2px' : ( 'dot' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '6px' : '0px' ),
		'--wuppi-nav-mark-bottom'       => 'dot' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '-4px' : '0px',
		'--wuppi-nav-mark-left'         => 'dot' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '50%' : '0px',
		'--wuppi-nav-mark-r'            => 'dot' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '999px' : '1px',
		'--wuppi-nav-mark-x'            => 'dot' === ( $settings['nav_active_indicator'] ?? 'none' ) ? '-50%' : '0%',

		// Buttons.
		'--wuppi-btn-radius'              => ( ! empty( $settings['btn_radius_use_global'] )
			? $global_radius_px
			: ( isset( $presets[ $settings['btn_radius_preset'] ] ) ? (int) $presets[ $settings['btn_radius_preset'] ] : $global_radius_px )
		) . 'px',
		'--wuppi-btn-padding-y'           => $btn_padding[0],
		'--wuppi-btn-padding-x'           => $btn_padding[1],
		'--wuppi-btn-font-weight'         => (string) $settings['btn_font_weight'],
		'--wuppi-btn-hover-bg'            => $palette( $settings['btn_hover_bg'] ),
		'--wuppi-btn-hover-color'         => $palette( $settings['btn_hover_color'] ),
		'--wuppi-btn-outline-hover-bg'    => $palette( $settings['btn_outline_hover_bg'] ),
		'--wuppi-btn-outline-hover-color' => $palette( $settings['btn_outline_hover_color'] ),
		'--wuppi-btn-outline-hover-border' => $palette( $settings['btn_outline_hover_border'] ),

		// Radius.
		'--wuppi-radius'                  => $global_radius_px . 'px',
		'--wuppi-image-radius'            => $image_radius_px . 'px',
		'--wuppi-card-radius'             => $card_radius_px . 'px',
		'--wuppi-input-radius'            => $input_radius_px . 'px',
		'--calm-radius'                   => $global_radius_px . 'px',

		// Shadows.
		'--wuppi-shadow-soft'             => $shadow_value,
		'--wuppi-shadow-cards'            => ! empty( $settings['shadow_on_cards'] ) && ! empty( $settings['shadow_enabled'] ) ? 'var(--wuppi-shadow-soft)' : 'none',
		'--wuppi-shadow-images'           => ! empty( $settings['shadow_on_images'] ) && ! empty( $settings['shadow_enabled'] ) ? 'var(--wuppi-shadow-soft)' : 'none',
		'--wuppi-shadow-buttons'          => ! empty( $settings['shadow_on_buttons'] ) && ! empty( $settings['shadow_enabled'] ) && empty( $settings['shadow_on_buttons_hover_only'] ) ? 'var(--wuppi-shadow-soft)' : 'none',
		'--wuppi-shadow-buttons-hover'    => ! empty( $settings['shadow_on_buttons'] ) && ! empty( $settings['shadow_enabled'] ) ? 'var(--wuppi-shadow-soft)' : 'none',

		// Transitions.
		'--wuppi-transition-speed'        => $transition_speed,

		// Typography.
		'--wuppi-heading-line-height'     => (string) $settings['heading_line_height'],
		'--wuppi-heading-letter-spacing'  => $settings['heading_letter_spacing'] . 'em',
		'--wuppi-body-line-height'        => (string) $settings['body_line_height'],

		// Inputs / focus.
		'--wuppi-input-focus-color'   => $palette( $settings['input_focus_color'] ),
		'--wuppi-input-focus-outline' => 'none',
		'--wuppi-input-focus-shadow'  => 'shadow' === ( $settings['input_focus_style'] ?? 'outline' )
			? '0 8px 20px -4px rgba(0,0,0,.18),0 3px 8px -2px rgba(0,0,0,.1)'
			: ( 'glow' === ( $settings['input_focus_style'] ?? 'outline' )
				? '0 0 12px 4px color-mix(in srgb,var(--wuppi-input-focus-color) 25%,transparent)'
				: '0 0 0 2px color-mix(in srgb,var(--wuppi-input-focus-color) 30%,transparent)' ),
	);
}

/**
 * Render a `:root { --foo: bar; }` block for the given settings.
 *
 * @param array<string, mixed> $settings Sanitized settings.
 * @return string CSS string.
 */
function wuppi_render_settings_inline_css( array $settings ) {
	$vars = wuppi_settings_to_css_vars( $settings );
	$body = '';

	foreach ( $vars as $name => $value ) {
		$body .= sprintf( '%s:%s;', $name, $value );
	}

	$css  = ':root{' . $body . '}';
	$css .= sprintf(
		'@media(max-width:781px){:root{--wuppi-content-padding-inline:%dpx;}}',
		max( 8, min( 40, (int) $settings['mobile_content_padding'] ) )
	);

	if ( 'button' === ( $settings['back_to_top_shape'] ?? 'circle' ) ) {
		$css .= ':root{--wuppi-btt-radius:var(--wuppi-btn-radius);}';
	}

	if ( ! empty( $settings['respect_reduced_motion'] ) ) {
		$css .= '@media(prefers-reduced-motion:reduce){:root{--wuppi-transition-speed:0s;}}';
	}

	$custom = trim( (string) ( $settings['custom_css'] ?? '' ) );
	if ( '' !== $custom ) {
		$css .= "\n" . $custom;
	}

	return $css;
}

/**
 * Render theme settings page (mount point for the React SPA).
 */
function wuppi_render_settings_page() {
	if ( ! current_user_can( wuppi_get_settings_page_capability() ) ) {
		return;
	}

	$help_url = admin_url( 'themes.php?page=wuppi-help' );
	?>
	<div class="wrap wuppi-settings-wrap">
		<h1 class="wp-heading-inline"><?php echo esc_html__( 'Wuppi Design', 'wuppi' ); ?></h1>
		<a class="page-title-action" href="<?php echo esc_url( $help_url ); ?>"><?php echo esc_html__( 'Help', 'wuppi' ); ?></a>
		<hr class="wp-header-end">
		<div id="wuppi-settings-app" data-loading="true">
			<noscript>
				<div class="notice notice-warning">
					<p><?php echo esc_html__( 'The Wuppi Design page requires JavaScript. Please enable JavaScript in your browser.', 'wuppi' ); ?></p>
				</div>
			</noscript>
			<p class="wuppi-settings-loading"><?php echo esc_html__( 'Loading…', 'wuppi' ); ?></p>
		</div>
	</div>
	<?php
}
