<?php
/**
 * Render handler module for SiteStaffr widget.
 *
 * @package SiteStaffr
 */

class SiteStaffr_Widget_Render_Handler {

	/**
	 * Render the fixed position widget.
	 *
	 * Shortcode: [sitestaffr_widget]
	 *
	 * Attributes:
	 *  - position: bottom-right (default), bottom-left
	 *  - background_color: hex color (default: #10b981)
	 *  - icon_color: hex color (default: #ffffff)
	 *  - size: button diameter in px (default: 60px)
	 *
	 * @since 0.11.75
	 * @param SiteStaffr_Widget $widget Widget instance.
	 * @param array            $atts Shortcode attributes.
	 * @param callable         $mark_rendered Callback to mark widget as rendered.
	 * @param callable         $enqueue_assets Callback to enqueue widget assets.
	 * @param callable         $get_fixed_icon_svg Callback to fetch icon SVG.
	 * @return string Widget HTML.
	 */
	public static function render_widget( SiteStaffr_Widget $widget, $atts, callable $mark_rendered, callable $enqueue_assets, callable $get_fixed_icon_svg ) {
		// Mark as rendered to prevent double-rendering via wp_footer
		$mark_rendered();

		// Get saved widget settings
		$widget_settings = SiteStaffr_Widget_Settings_Provider::get_widget_settings();
		$default_border_radius = self::build_border_radius_from_settings(
			$widget_settings,
			'fixed',
			array(
				'top'    => '20px',
				'right'  => '20px',
				'bottom' => '20px',
				'left'   => '0px',
			),
			'fixed_border_radius'
		);

		// Parse attributes with defaults (use saved settings if available)
		$atts = shortcode_atts(
			array(
				'position'               => isset( $widget_settings['fixed_position'] ) ? $widget_settings['fixed_position'] : 'bottom-right',
				'background_color'       => isset( $widget_settings['fixed_background_color'] ) ? $widget_settings['fixed_background_color'] : '#10b981',
				'icon_color'             => isset( $widget_settings['fixed_icon_color'] ) ? $widget_settings['fixed_icon_color'] : '#ffffff',
				'size'                   => isset( $widget_settings['fixed_size'] ) ? $widget_settings['fixed_size'] : '60px',
				'hover_background_color' => isset( $widget_settings['fixed_hover_background_color'] ) ? $widget_settings['fixed_hover_background_color'] : '',
				'hover_icon_color'       => isset( $widget_settings['fixed_hover_icon_color'] ) ? $widget_settings['fixed_hover_icon_color'] : '',
				'border_radius'          => $default_border_radius,
				'border_style'           => isset( $widget_settings['fixed_border_style'] ) ? $widget_settings['fixed_border_style'] : 'none',
				'border_width'           => isset( $widget_settings['fixed_border_width'] ) ? $widget_settings['fixed_border_width'] : '0',
				'border_color'           => isset( $widget_settings['fixed_border_color'] ) ? $widget_settings['fixed_border_color'] : '#cccccc',
				'persona'                => '',
				'mode'                   => '',
				'sounds'                 => 'on',
			),
			$atts,
			'sitestaffr_widget'
		);

		// Sanitize attributes
		$position               = sanitize_text_field( $atts['position'] );
		$background_color       = sanitize_hex_color( $atts['background_color'] );
		$hover_background_color = ! empty( $atts['hover_background_color'] ) ? sanitize_hex_color( $atts['hover_background_color'] ) : $background_color;
		$icon_color             = sanitize_hex_color( $atts['icon_color'] );
		$hover_icon_color       = ! empty( $atts['hover_icon_color'] ) ? sanitize_hex_color( $atts['hover_icon_color'] ) : '';
		$size                   = sanitize_text_field( $atts['size'] );
		$border_radius          = self::normalize_border_radius_shorthand( sanitize_text_field( $atts['border_radius'] ), $default_border_radius );
		$border_style = sanitize_key( $atts['border_style'] );
		$border_width = sanitize_text_field( $atts['border_width'] );
		$border_color = ! empty( $atts['border_color'] ) ? sanitize_hex_color( $atts['border_color'] ) : '#cccccc';
		$valid_border_styles = array( 'none', 'solid', 'dashed', 'dotted', 'double' );
		if ( ! in_array( $border_style, $valid_border_styles, true ) ) {
			$border_style = 'none';
		}
		$persona               = sanitize_text_field( $atts['persona'] );

		// Resolve widget mode (voice, text, or both)
		$mode_default = isset( $widget_settings['mode'] ) ? sanitize_key( $widget_settings['mode'] ) : 'both';
		$mode = ! empty( $atts['mode'] ) ? sanitize_key( $atts['mode'] ) : $mode_default;
		if ( ! in_array( $mode, array( 'voice', 'text', 'both' ), true ) ) {
			$mode = 'voice';
		}

		// Override to text-only when voice minutes are exhausted.
		if ( 'text' !== $mode && class_exists( 'SiteStaffr_Billing_State' ) ) {
			$balance = SiteStaffr_Billing_State::get_minutes_balance();
			if ( is_array( $balance ) && 0 === (int) $balance['total'] ) {
				$mode = 'text';
			}
		}

		$sounds_enabled = ( 'off' !== sanitize_key( $atts['sounds'] ) );

		// Validate position
		$valid_positions = array( 'bottom-right', 'bottom-left' );
		if ( ! in_array( $position, $valid_positions, true ) ) {
			$position = 'bottom-right';
		}

		// Validate size (must be numeric value with px)
		if ( ! preg_match( '/^\d+px$/', $size ) ) {
			$size = '60px';
		}

		// Enqueue widget assets
		$enqueue_assets( $mode, $sounds_enabled );

		// Get site ID (WordPress site URL)
		$site_id = get_site_url();

		// NOTE: Auth token is NOT embedded in HTML to prevent caching issues
		// Token will be fetched dynamically via AJAX when widget is clicked
		// This ensures guests on cached pages get fresh, valid tokens

		// Get fixed icon settings
		$fixed_icon      = isset( $widget_settings['fixed_icon'] ) ? sanitize_key( $widget_settings['fixed_icon'] ) : 'sitestaffr';
		$fixed_icon_size = isset( $widget_settings['fixed_icon_size'] ) ? sanitize_text_field( $widget_settings['fixed_icon_size'] ) : '24px';

		// Tooltip settings
		$tooltip_text       = ! empty( $widget_settings['fixed_tooltip_text'] ) ? sanitize_text_field( $widget_settings['fixed_tooltip_text'] ) : __( 'Talk to AI Assistant', 'sitestaffr' );
		$tooltip_persistent = ! empty( $widget_settings['fixed_tooltip_always_show'] );
		$tooltip_position   = isset( $widget_settings['fixed_tooltip_position'] ) && 'bottom' === $widget_settings['fixed_tooltip_position'] ? 'bottom' : 'top';

		// Build widget HTML
		ob_start();
		?>
		<div id="sitestaffr-widget"
		     class="sitestaffr-widget <?php echo esc_attr( 'position-' . $position ); ?><?php echo $tooltip_persistent ? ' sitestaffr-tooltip--persistent' : ''; ?><?php echo 'bottom' === $tooltip_position ? ' sitestaffr-tooltip--bottom' : ''; ?>"
		     data-position="<?php echo esc_attr( $position ); ?>"
		     data-background-color="<?php echo esc_attr( $background_color ); ?>"
		     data-icon-color="<?php echo esc_attr( $icon_color ); ?>"
		     data-size="<?php echo esc_attr( $size ); ?>"
		     data-site-id="<?php echo esc_attr( $site_id ); ?>"
		     data-idle-text="<?php echo esc_attr( $tooltip_text ); ?>"
		     data-persona="<?php echo esc_attr( $persona ); ?>"
		     data-mode="<?php echo esc_attr( $mode ); ?>"
		     style="--widget-bg-color: <?php echo esc_attr( $background_color ); ?>; --widget-hover-bg-color: <?php echo esc_attr( $hover_background_color ); ?>; --widget-icon-color: <?php echo esc_attr( $icon_color ); ?>;<?php if ( ! empty( $hover_icon_color ) ) : ?> --widget-hover-icon-color: <?php echo esc_attr( $hover_icon_color ); ?>;<?php endif; ?> --widget-size: <?php echo esc_attr( $size ); ?>; --widget-icon-size: <?php echo esc_attr( $fixed_icon_size ); ?>; --widget-border-radius: <?php echo esc_attr( $border_radius ); ?>;<?php if ( 'none' !== $border_style ) : ?> --widget-border-width: <?php echo esc_attr( $border_width ); ?>; --widget-border-style: <?php echo esc_attr( $border_style ); ?>; --widget-border-color: <?php echo esc_attr( $border_color ); ?>;<?php endif; ?>">

			<!-- Widget Button -->
			<button type="button" class="sitestaffr-widget-button" aria-label="<?php esc_attr_e( 'Talk to AI Assistant', 'sitestaffr' ); ?>">
				<!-- Pulse Animation (listening state) - INSIDE button for proper centering -->
				<div class="sitestaffr-pulse-ring"></div>

				<!-- Idle State Icon (selected by widget settings) -->
				<?php echo wp_kses( $get_fixed_icon_svg( $fixed_icon ), SiteStaffr_Button_Widget::get_svg_allowed_html() ); ?>

				<!-- Microphone Icon (listening state only) -->
				<svg class="sitestaffr-icon sitestaffr-icon-microphone" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
					<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
					<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
					<line x1="12" y1="19" x2="12" y2="23"></line>
					<line x1="8" y1="23" x2="16" y2="23"></line>
				</svg>

				<!-- Loading Spinner (thinking state) -->
				<svg class="sitestaffr-icon sitestaffr-icon-spinner" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
					<line x1="12" y1="2" x2="12" y2="6"></line>
					<line x1="12" y1="18" x2="12" y2="22"></line>
					<line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line>
					<line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line>
					<line x1="2" y1="12" x2="6" y2="12"></line>
					<line x1="18" y1="12" x2="22" y2="12"></line>
					<line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line>
					<line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line>
				</svg>

				<!-- Sound Wave (speaking state) -->
				<div class="sitestaffr-icon sitestaffr-icon-soundwave">
					<span></span>
					<span></span>
					<span></span>
				</div>
			</button>

			<!-- Status Tooltip -->
			<div class="sitestaffr-widget-tooltip">
				<span class="sitestaffr-tooltip-text"><?php echo esc_html( $tooltip_text ); ?></span>
			</div>

			<!-- Audio Element (hidden) -->
			<audio id="sitestaffr-audio-player" style="display: none;"></audio>
		</div>
		<?php
		return ob_get_clean();
	}

	/**
	 * Build border-radius shorthand from per-side settings with legacy fallback.
	 *
	 * @param array  $settings      Widget settings.
	 * @param string $prefix        Setting prefix (e.g., fixed or button).
	 * @param array  $defaults      Default px values by side.
	 * @param string $legacy_option Legacy single-value option key.
	 * @return string
	 */
	private static function build_border_radius_from_settings( $settings, $prefix, $defaults, $legacy_option ) {
		$legacy_value = isset( $settings[ $legacy_option ] ) ? sanitize_text_field( $settings[ $legacy_option ] ) : '';

		$top = isset( $settings[ $prefix . '_border_radius_top' ] )
			? sanitize_text_field( $settings[ $prefix . '_border_radius_top' ] )
			: ( '' !== $legacy_value ? $legacy_value : $defaults['top'] );
		$right = isset( $settings[ $prefix . '_border_radius_right' ] )
			? sanitize_text_field( $settings[ $prefix . '_border_radius_right' ] )
			: ( '' !== $legacy_value ? $legacy_value : $defaults['right'] );
		$bottom = isset( $settings[ $prefix . '_border_radius_bottom' ] )
			? sanitize_text_field( $settings[ $prefix . '_border_radius_bottom' ] )
			: ( '' !== $legacy_value ? $legacy_value : $defaults['bottom'] );
		$left = isset( $settings[ $prefix . '_border_radius_left' ] )
			? sanitize_text_field( $settings[ $prefix . '_border_radius_left' ] )
			: ( '' !== $legacy_value ? $legacy_value : $defaults['left'] );

		return self::normalize_border_radius_shorthand(
			trim( $top . ' ' . $right . ' ' . $bottom . ' ' . $left ),
			trim( $defaults['top'] . ' ' . $defaults['right'] . ' ' . $defaults['bottom'] . ' ' . $defaults['left'] )
		);
	}

	/**
	 * Normalize border-radius shorthand to a safe four-value px string.
	 *
	 * @param string $value    Raw border-radius input.
	 * @param string $fallback Fallback shorthand.
	 * @return string
	 */
	private static function normalize_border_radius_shorthand( $value, $fallback ) {
		$parts = preg_split( '/\s+/', trim( $value ) );
		$parts = array_values( array_filter( $parts ) );

		if ( empty( $parts ) ) {
			return $fallback;
		}

		if ( 1 === count( $parts ) ) {
			$normalized = self::normalize_radius_part( $parts[0], '0px' );
			return trim( $normalized . ' ' . $normalized . ' ' . $normalized . ' ' . $normalized );
		}

		if ( 4 === count( $parts ) ) {
			$normalized_parts = array();
			foreach ( $parts as $part ) {
				$normalized_parts[] = self::normalize_radius_part( $part, '0px' );
			}
			return implode( ' ', $normalized_parts );
		}

		return $fallback;
	}

	/**
	 * Normalize a single radius part to px.
	 *
	 * @param string $value      Raw value.
	 * @param string $default_px Default px value.
	 * @return string
	 */
	private static function normalize_radius_part( $value, $default_px ) {
		if ( preg_match( '/^(\d{1,3})px$/', $value, $matches ) ) {
			return intval( $matches[1] ) . 'px';
		}
		if ( preg_match( '/^\d{1,3}$/', $value ) ) {
			return intval( $value ) . 'px';
		}
		return $default_px;
	}
}
