<?php
/**
 * Block layout band + vertical spacing for Content Widgets blocks.
 *
 * Fallback when an older RSM Focus build loads Rsmspark_Block_Supports without layout helpers.
 *
 * @package Rsmspark_Content_Widgets
 */

defined( 'ABSPATH' ) || exit;

/**
 * Rsmspark_Content_Widgets_Block_Layout
 */
final class Rsmspark_Content_Widgets_Block_Layout {

	const BLOCK_PREFIXES = array(
		'rsm-content-widgets/',
		'rsmspark-cw-compat/',
	);

	/**
	 * @return void
	 */
	public static function init() {
		if (
			class_exists( 'Rsmspark_Block_Supports', false )
			&& method_exists( 'Rsmspark_Block_Supports', 'layout_from_attributes' )
		) {
			return;
		}

		add_filter( 'register_block_type_args', array( __CLASS__, 'register_block_type_args' ), 10, 2 );
		add_filter( 'render_block', array( __CLASS__, 'render_block' ), 20, 2 );
		add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_front' ), 20 );
		add_action( 'enqueue_block_editor_assets', array( __CLASS__, 'enqueue_editor' ), 20 );
	}

	/**
	 * @return array<string, array<string, mixed>>
	 */
	public static function attribute_schema() {
		return array(
			'rsmBand' => array(
				'type'    => 'string',
				'default' => '',
			),
			'rsmBandBg' => array(
				'type'    => 'string',
				'default' => '',
			),
			'rsmBandPadTop' => array(
				'type'    => 'number',
				'default' => 0,
			),
			'rsmBandPadBottom' => array(
				'type'    => 'number',
				'default' => 0,
			),
			'rsmSpacingTop' => array(
				'type'    => 'number',
				'default' => 0,
			),
			'rsmSpacingBottom' => array(
				'type'    => 'number',
				'default' => 0,
			),
		);
	}

	/**
	 * @param string $name Block name.
	 * @return bool
	 */
	public static function is_supported_block( $name ) {
		$name = (string) $name;
		foreach ( self::BLOCK_PREFIXES as $prefix ) {
			if ( str_starts_with( $name, $prefix ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @param array<string, mixed> $args Block type args.
	 * @param string               $name Block name.
	 * @return array<string, mixed>
	 */
	public static function register_block_type_args( $args, $name ) {
		if ( ! self::is_supported_block( $name ) ) {
			return $args;
		}

		if ( ! isset( $args['attributes'] ) || ! is_array( $args['attributes'] ) ) {
			$args['attributes'] = array();
		}

		$args['attributes'] = array_merge( $args['attributes'], self::attribute_schema() );

		return $args;
	}

	/**
	 * @param array<string, mixed> $attrs Block attributes.
	 * @return array<string, mixed>
	 */
	public static function layout_from_attributes( array $attrs ) {
		$band           = sanitize_key( (string) ( $attrs['rsmBand'] ?? '' ) );
		$spacing_top    = max( 0, (int) ( $attrs['rsmSpacingTop'] ?? 0 ) );
		$spacing_bottom = max( 0, (int) ( $attrs['rsmSpacingBottom'] ?? 0 ) );
		$pad_top        = max( 0, (int) ( $attrs['rsmBandPadTop'] ?? 0 ) );
		$pad_bottom     = max( 0, (int) ( $attrs['rsmBandPadBottom'] ?? 0 ) );
		$bg             = sanitize_hex_color( (string) ( $attrs['rsmBandBg'] ?? '' ) );
		$wrap_band      = 'full' === $band;
		$spacing_parts  = array();

		if ( ! $wrap_band ) {
			if ( $spacing_top > 0 ) {
				$spacing_parts[] = 'margin-top:' . $spacing_top . 'px';
			}
			if ( $spacing_bottom > 0 ) {
				$spacing_parts[] = 'margin-bottom:' . $spacing_bottom . 'px';
			}
		}

		return array(
			'wrap_band'      => $wrap_band,
			'bg'             => $bg ? $bg : '',
			'pad_top'        => $pad_top,
			'pad_bottom'     => $pad_bottom,
			'spacing_top'    => $spacing_top,
			'spacing_bottom' => $spacing_bottom,
			'spacing_style'  => implode( ';', $spacing_parts ),
		);
	}

	/**
	 * Escape inner block HTML before wrapping in a layout shell.
	 *
	 * @param string $html Inner markup.
	 * @return string
	 */
	public static function kses_inner_html( $html ) {
		$html = (string) $html;
		if ( '' === $html ) {
			return $html;
		}

		if ( class_exists( 'Rsmspark_Block_Supports', false )
			&& method_exists( 'Rsmspark_Block_Supports', 'kses_inner_html' )
		) {
			return Rsmspark_Block_Supports::kses_inner_html( $html );
		}

		if ( class_exists( 'Rsmspark_Content_Widgets_Kses', false )
			&& method_exists( 'Rsmspark_Content_Widgets_Kses', 'allowed_html' )
		) {
			return wp_kses( $html, Rsmspark_Content_Widgets_Kses::allowed_html() );
		}

		return wp_kses_post( $html );
	}

	/**
	 * @param string               $content Block HTML.
	 * @param array<string, mixed> $layout  Layout data.
	 * @return string
	 */
	public static function wrap_layout_shell( $content, array $layout ) {
		$content = self::kses_inner_html( $content );
		if ( '' === trim( $content ) ) {
			return $content;
		}

		$styles = array();

		if ( ! empty( $layout['bg'] ) ) {
			$styles[] = 'background-color:' . $layout['bg'];
		}
		if ( ( $layout['pad_top'] ?? 0 ) > 0 ) {
			$styles[] = 'padding-top:' . (int) $layout['pad_top'] . 'px';
		}
		if ( ( $layout['pad_bottom'] ?? 0 ) > 0 ) {
			$styles[] = 'padding-bottom:' . (int) $layout['pad_bottom'] . 'px';
		}
		if ( ( $layout['spacing_top'] ?? 0 ) > 0 ) {
			$styles[] = 'margin-top:' . (int) $layout['spacing_top'] . 'px';
		}
		if ( ( $layout['spacing_bottom'] ?? 0 ) > 0 ) {
			$styles[] = 'margin-bottom:' . (int) $layout['spacing_bottom'] . 'px';
		}

		$style_attr = $styles ? ' style="' . esc_attr( implode( ';', $styles ) ) . '"' : '';

		return '<div class="rsm-rsf-band rsm-rsf-band--full"' . $style_attr . '><div class="rsm-rsf-band__inner">' . $content . '</div></div>';
	}

	/**
	 * @param string               $content Block HTML.
	 * @param array<string, mixed> $layout  Layout data.
	 * @return string
	 */
	public static function apply_spacing_style( $content, array $layout ) {
		$spacing_style = (string) ( $layout['spacing_style'] ?? '' );
		if ( '' === $spacing_style || '' === trim( $content ) ) {
			return $content;
		}

		if ( class_exists( 'WP_HTML_Tag_Processor', false ) ) {
			$processor = new WP_HTML_Tag_Processor( $content );
			if ( $processor->next_tag() ) {
				$existing = (string) ( $processor->get_attribute( 'style' ) ?? '' );
				$processor->set_attribute(
					'style',
					( '' !== $existing ? rtrim( $existing, ';' ) . ';' : '' ) . $spacing_style
				);

				$updated = $processor->get_updated_html();
				if ( '' !== $updated ) {
					return $updated;
				}
			}
		}

		$tag_end = strpos( $content, '>' );
		if ( false === $tag_end ) {
			return $content;
		}

		$open = substr( $content, 0, $tag_end );
		$rest = substr( $content, $tag_end );

		if ( preg_match( '/\bstyle="/', $open ) ) {
			$open = preg_replace(
				'/\bstyle="([^"]*)"/',
				'style="$1' . esc_attr( $spacing_style ) . '"',
				$open,
				1
			);
		} else {
			$open .= ' style="' . esc_attr( $spacing_style ) . '"';
		}

		return $open . $rest;
	}

	/**
	 * @param string $content Block HTML.
	 * @param array  $block   Block data.
	 * @return string
	 */
	public static function render_block( $content, $block ) {
		if ( '' === trim( (string) $content ) || ! is_array( $block ) ) {
			return $content;
		}

		$name = (string) ( $block['blockName'] ?? '' );
		if ( ! self::is_supported_block( $name ) ) {
			return $content;
		}

		$attrs  = is_array( $block['attrs'] ?? null ) ? $block['attrs'] : array();
		$layout = self::layout_from_attributes( $attrs );

		if ( empty( $layout['wrap_band'] ) && '' === ( $layout['spacing_style'] ?? '' ) ) {
			return $content;
		}

		if ( ! empty( $layout['spacing_style'] ) && empty( $layout['wrap_band'] ) ) {
			return self::apply_spacing_style( $content, $layout );
		}

		if ( ! empty( $layout['wrap_band'] ) ) {
			return self::wrap_layout_shell( $content, $layout );
		}

		return $content;
	}

	/**
	 * @return void
	 */
	public static function enqueue_front() {
		if ( is_admin() ) {
			return;
		}

		wp_enqueue_style(
			'rsmspark-cw-block-layout',
			RSMSPARK_CONTENT_WIDGETS_URL . 'assets/css/block-layout.css',
			array(),
			RSMSPARK_CONTENT_WIDGETS_VERSION
		);
	}

	/**
	 * @return void
	 */
	public static function enqueue_editor() {
		if ( ! Rsmspark_Content_Widgets_Settings::block_editor_ui_enabled() ) {
			return;
		}

		wp_enqueue_style(
			'rsmspark-cw-block-layout',
			RSMSPARK_CONTENT_WIDGETS_URL . 'assets/css/block-layout.css',
			array( 'rsmspark-content-widgets-blocks-editor' ),
			RSMSPARK_CONTENT_WIDGETS_VERSION
		);
	}
}
