<?php
/**
 * RSM Headline widget design tokens.
 *
 * @package Rsmspark_Content_Widgets
 */

defined( 'ABSPATH' ) || exit;

/**
 * CSS variables and helpers for the Headline widget.
 */
final class Rsmspark_Content_Widgets_Headline_Styles {

	/**
	 * Text alignment options.
	 *
	 * @return array<string, string>
	 */
	public static function get_align_options() {
		return array(
			'left'   => __( 'Left', 'rsm-content-widgets' ),
			'center' => __( 'Center', 'rsm-content-widgets' ),
			'right'  => __( 'Right', 'rsm-content-widgets' ),
		);
	}

	/**
	 * Headline HTML tag options.
	 *
	 * @return array<string, string>
	 */
	public static function get_headline_tag_options() {
		return array(
			'h1' => __( 'H1', 'rsm-content-widgets' ),
			'h2' => __( 'H2', 'rsm-content-widgets' ),
			'h3' => __( 'H3', 'rsm-content-widgets' ),
			'h4' => __( 'H4', 'rsm-content-widgets' ),
			'h5' => __( 'H5', 'rsm-content-widgets' ),
			'h6' => __( 'H6', 'rsm-content-widgets' ),
		);
	}

	/**
	 * @return array<string, string>
	 */
	public static function get_corner_options() {
		return array(
			'square'  => __( 'Square corners', 'rsm-content-widgets' ),
			'rounded' => __( 'Rounded corners', 'rsm-content-widgets' ),
		);
	}

	/**
	 * Default fluid font-size when slider is 0 (inherit theme).
	 *
	 * @param string $line overline|headline|subheadline.
	 * @return string
	 */
	public static function default_size_clamp( $line ) {
		switch ( sanitize_key( (string) $line ) ) {
			case 'overline':
				return 'clamp(0.6875rem, 0.625rem + 0.25vw, 0.8125rem)';
			case 'subheadline':
				return 'clamp(1rem, 0.9rem + 0.5vw, 1.375rem)';
			case 'headline':
			default:
				return 'clamp(1.75rem, 1.25rem + 2.5vw, 2.75rem)';
		}
	}

	/**
	 * Responsive font size from admin slider (0 = theme fluid default).
	 *
	 * @param int    $size Slider px value.
	 * @param string $line Line key.
	 * @return string
	 */
	public static function responsive_font_size_to_css( $size, $line ) {
		$size = (int) $size;
		if ( $size <= 0 ) {
			return self::default_size_clamp( $line );
		}

		$max = max( 10, min( 72, $size ) );
		$min = max( 10, (int) round( $max * 0.72 ) );
		$vw  = round( $max * 0.035, 2 );
		$mid = max( 10, (int) round( $max * 0.55 ) );

		return 'clamp(' . $min . 'px, ' . $vw . 'vw + ' . $mid . 'px, ' . $max . 'px)';
	}

	/**
	 * CSS font-family for a line.
	 *
	 * @param string $font_key Stored font key.
	 * @param string $line     overline|headline|subheadline.
	 * @return string
	 */
	public static function font_stack_css( $font_key, $line ) {
		$key = Rsmspark_Content_Widgets_Features_Fonts::sanitize_key( $font_key );
		if ( 'inherit' === $key ) {
			if ( 'headline' === sanitize_key( (string) $line ) ) {
				return 'var(--openrsm-heading-font-family, inherit)';
			}
			return 'var(--openrsm-body-font-family, inherit)';
		}

		return Rsmspark_Content_Widgets_Features_Fonts::get_stack( $key );
	}

	/**
	 * Sanitize alignment.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	public static function sanitize_align( $value ) {
		$key = sanitize_key( (string) $value );
		return array_key_exists( $key, self::get_align_options() ) ? $key : 'center';
	}

	/**
	 * Sanitize headline tag.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	public static function sanitize_headline_tag( $value ) {
		$key = sanitize_key( (string) $value );
		return array_key_exists( $key, self::get_headline_tag_options() ) ? $key : 'h2';
	}

	/**
	 * Allowed HTML for headline text lines (manual line breaks only).
	 *
	 * @return array<string, array<string, bool>>
	 */
	public static function allowed_line_html() {
		if ( class_exists( 'Rsmspark_Rich_Text_Registry', false ) ) {
			return Rsmspark_Rich_Text_Registry::allowed_tags( Rsmspark_Rich_Text_Registry::PROFILE_HEADLINE );
		}

		return array(
			'br' => array(),
		);
	}

	/**
	 * Strip pasted front-end wrappers (inspector copy) before sanitizing line HTML.
	 *
	 * @param string $html Raw attribute HTML.
	 * @return string
	 */
	public static function normalize_line_markup( $html ) {
		$html = trim( (string) $html );
		if ( '' === $html ) {
			return '';
		}

		$patterns = array(
			'/^<h[1-6][^>]*\brsmspark-cw-headline__title\b[^>]*>([\s\S]*)<\/h[1-6]>$/i',
			'/^<p[^>]*\brsmspark-cw-headline__overline\b[^>]*>([\s\S]*)<\/p>$/i',
			'/^<p[^>]*\brsmspark-cw-headline__subheadline\b[^>]*>([\s\S]*)<\/p>$/i',
		);

		foreach ( $patterns as $pattern ) {
			if ( preg_match( $pattern, $html, $matches ) ) {
				$html = (string) ( $matches[1] ?? '' );
				break;
			}
		}

		return trim( $html );
	}

	/**
	 * Sanitize line text: plain text plus optional <br> and newline → <br>.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	public static function sanitize_line_html( $value ) {
		$value = self::normalize_line_markup( (string) $value );

		if ( class_exists( 'Rsmspark_Rich_Text', false ) ) {
			return Rsmspark_Rich_Text::sanitize( $value, Rsmspark_Rich_Text_Registry::PROFILE_HEADLINE );
		}

		$text = (string) $value;
		$text = str_replace( array( "\r\n", "\r" ), "\n", $text );
		$text = str_replace( "\n", '<br />', $text );

		return wp_kses( $text, self::allowed_line_html() );
	}

	/**
	 * Whether sanitized line HTML has visible text.
	 *
	 * @param string $html Sanitized line HTML.
	 * @return bool
	 */
	public static function line_has_text( $html ) {
		if ( class_exists( 'Rsmspark_Rich_Text', false ) ) {
			return Rsmspark_Rich_Text::has_text( $html );
		}

		return '' !== trim( wp_strip_all_tags( (string) $html ) );
	}

	/**
	 * Sanitize optional hex color (empty = inherit).
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	public static function sanitize_color( $value ) {
		$value = trim( (string) $value );
		if ( '' === $value || 'inherit' === strtolower( $value ) ) {
			return '';
		}
		$hex = sanitize_hex_color( $value );
		return $hex ? $hex : '';
	}

	/**
	 * @param mixed $value Raw checkbox.
	 * @return bool
	 */
	public static function is_enabled( $value ) {
		if ( is_bool( $value ) ) {
			return $value;
		}
		if ( is_string( $value ) ) {
			return in_array( strtolower( $value ), array( '1', 'true', 'yes', 'on' ), true );
		}
		return ! empty( $value );
	}

	/**
	 * @param string $hex     Hex color.
	 * @param int    $opacity Opacity 0–100.
	 * @return string
	 */
	public static function hex_to_rgba( $hex, $opacity ) {
		$hex = sanitize_hex_color( (string) $hex );
		if ( ! $hex ) {
			$hex = '#e2e8f0';
		}
		$opacity = max( 0, min( 100, (int) $opacity ) ) / 100;
		$hex     = ltrim( $hex, '#' );
		if ( 3 === strlen( $hex ) ) {
			$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
		}
		$r = hexdec( substr( $hex, 0, 2 ) );
		$g = hexdec( substr( $hex, 2, 2 ) );
		$b = hexdec( substr( $hex, 4, 2 ) );
		return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . round( $opacity, 2 ) . ')';
	}

	/**
	 * Normalize typography line settings.
	 *
	 * @param array<string, mixed> $line Raw line values.
	 * @param string               $key  Line prefix key.
	 * @return array<string, mixed>
	 */
	public static function normalize_line( array $line, $key ) {
		return array(
			'font'      => Rsmspark_Content_Widgets_Features_Fonts::sanitize_key( $line[ $key . '_font' ] ?? 'inherit' ),
			'font_size' => max( 0, min( 72, (int) ( $line[ $key . '_font_size' ] ?? 0 ) ) ),
			'color'     => self::sanitize_color( $line[ $key . '_color' ] ?? '' ),
			'align'     => self::sanitize_align( $line[ $key . '_align' ] ?? 'center' ),
		);
	}

	/**
	 * SiteOrigin typography section fields.
	 *
	 * @param string $prefix Line prefix (overline|headline|subheadline).
	 * @param string $label  Section label.
	 * @return array<string, mixed>
	 */
	public static function siteorigin_typography_section( $prefix, $label ) {
		return array(
			'type'   => 'section',
			'label'  => $label,
			'fields' => array(
				$prefix . '_font' => array(
					'type'    => 'select',
					'label'   => __( 'Font', 'rsm-content-widgets' ),
					'default' => 'inherit',
					'options' => Rsmspark_Content_Widgets_Features_Fonts::get_select_options(),
				),
				$prefix . '_font_size' => array(
					'type'        => 'slider',
					'label'       => __( 'Font size (px)', 'rsm-content-widgets' ),
					'description' => __( '0 = responsive theme default.', 'rsm-content-widgets' ),
					'min'         => 0,
					'max'         => 72,
					'integer'     => true,
					'default'     => 0,
				),
				$prefix . '_color' => array(
					'type'        => 'color',
					'label'       => __( 'Text color', 'rsm-content-widgets' ),
					'description' => __( 'Leave default for inherited page text color.', 'rsm-content-widgets' ),
					'default'     => '',
				),
				$prefix . '_align' => array(
					'type'    => 'select',
					'label'   => __( 'Alignment', 'rsm-content-widgets' ),
					'default' => 'center',
					'options' => self::get_align_options(),
				),
			),
		);
	}

	/**
	 * Build CSS variables for the widget root.
	 *
	 * @param array<string, mixed> $overline    Normalized overline line.
	 * @param array<string, mixed> $headline    Normalized headline line.
	 * @param array<string, mixed> $subheadline Normalized subheadline line.
	 * @param array<string, mixed> $container   Container section.
	 * @return array<string, string>
	 */
	public static function build_css_variables( array $overline, array $headline, array $subheadline, array $container ) {
		$width_pct = max( 10, min( 100, (int) ( $container['width_pct'] ?? 100 ) ) );
		$max_width = max( 0, min( 1600, (int) ( $container['max_width'] ?? 0 ) ) );

		$corners = sanitize_key( (string) ( $container['corners'] ?? 'square' ) );
		if ( ! in_array( $corners, array( 'square', 'rounded' ), true ) ) {
			$corners = 'square';
		}

		$radius = 0;
		if ( 'rounded' === $corners ) {
			$radius = max( 0, min( 64, (int) ( $container['corner_radius'] ?? 12 ) ) );
		}

		$vars = array(
			'--rh-width'     => $width_pct . '%',
			'--rh-max-width' => $max_width > 0 ? $max_width . 'px' : 'none',
			'--rh-radius'    => $radius . 'px',
		);

		$bg = self::sanitize_color( $container['background_color'] ?? '' );
		if ( '' !== $bg ) {
			$vars['--rh-bg'] = $bg;
		}

		foreach ( array(
			'overline'    => $overline,
			'headline'    => $headline,
			'subheadline' => $subheadline,
		) as $line_key => $line ) {
			$vars[ '--rh-' . $line_key . '-font' ]  = self::font_stack_css( $line['font'], $line_key );
			$vars[ '--rh-' . $line_key . '-size' ]  = self::responsive_font_size_to_css( $line['font_size'], $line_key );
			$vars[ '--rh-' . $line_key . '-align' ] = $line['align'];
			if ( '' !== $line['color'] ) {
				$vars[ '--rh-' . $line_key . '-color' ] = $line['color'];
			}
		}

		if ( self::is_enabled( $container['border_enable'] ?? false ) ) {
			$vars['--rh-border-width'] = max( 1, min( 12, (int) ( $container['border_width'] ?? 1 ) ) ) . 'px';
			$vars['--rh-border-color'] = self::hex_to_rgba(
				$container['border_color'] ?? '#e2e8f0',
				$container['border_opacity'] ?? 100
			);
			$vars['--rh-padding'] = '1.25rem 1.5rem';
		}

		return $vars;
	}

	/**
	 * @param array<string, string> $vars CSS variables.
	 * @return string
	 */
	public static function vars_to_inline_style( array $vars ) {
		$pairs = array();
		foreach ( $vars as $key => $value ) {
			$pairs[] = $key . ':' . $value;
		}
		return implode( ';', $pairs );
	}
}
