<?php
/**
 * Scope Divi Visual Builder preview ScriptData selectors (scroll effects, motion) to arbitrary roots.
 *
 * Used by standalone library previews (Content Toggle, Popup Magnific VB fetch, …).
 *
 * @package DiviSupreme
 */

declare(strict_types=1);

namespace DiviSupreme\Includes;

if ( ! defined( 'ABSPATH' ) ) {
	die( 'Direct access forbidden.' );
}

/**
 * Build scoped selector lists for {@see \ET\Builder\FrontEnd\Module\ScriptData} payloads.
 */
final class DsmPreviewScriptScope {

	/**
	 * Root used by {@see LibraryLayoutRenderer} embed / REST previews.
	 */
	public static function library_layout_renderer_root_selector( int $layout_id ): string {
		return '.dsm-library-layout-renderer[data-dsm-library-preview="' . absint( $layout_id ) . '"]';
	}

	/**
	 * Root for popup library HTML injected as `#dsm-popup-{id}` (modules live under `.dsm-popup-wrapper`).
	 */
	public static function popup_visual_preview_root_selector( int $popup_id ): string {
		return '#dsm-popup-' . absint( $popup_id ) . ' .dsm-popup-wrapper';
	}

	/**
	 * Prefix a frontend selector under a preview root (`$prefix` matches {@see library_layout_renderer_root_selector} or {@see popup_visual_preview_root_selector}).
	 */
	public static function scope_selector_under_root( string $prefix, string $selector ): string {
		$selector = trim( $selector );
		if ( '' === $selector ) {
			return '';
		}
		if ( preg_match( '/^\.\.+/', $selector ) ) {
			$selector = (string) preg_replace( '/^\.\.+/', '.', $selector, 1 );
		}
		if ( 0 === strpos( $selector, $prefix ) ) {
			return $selector;
		}
		return $prefix . ' ' . $selector;
	}

	/**
	 * Scope `id` / `hoverSelector` on each scroll effect object under desktop/tablet/phone.
	 *
	 * @param string $prefix  Preview root selector prefix.
	 * @param array  $effects List of effect arrays.
	 */
	private static function scope_scroll_effect_list( string $prefix, array $effects ): array {
		$out = array();
		foreach ( $effects as $effect ) {
			if ( ! is_array( $effect ) ) {
				$out[] = $effect;
				continue;
			}
			$copy = $effect;
			if ( isset( $copy['id'] ) && is_string( $copy['id'] ) ) {
				$copy['id'] = self::scope_selector_under_root( $prefix, $copy['id'] );
			}
			if ( isset( $copy['hoverSelector'] ) && is_string( $copy['hoverSelector'] ) ) {
				$copy['hoverSelector'] = self::scope_selector_under_root( $prefix, $copy['hoverSelector'] );
			}
			$out[] = $copy;
		}
		return $out;
	}

	/**
	 * Scope breakpoint map for one scroll data item.
	 *
	 * @param array $value Scroll setting (desktop/tablet/phone => arrays of effects).
	 */
	private static function scope_scroll_breakpoints_value( string $prefix, array $value ): array {
		$scoped = array();
		foreach ( $value as $breakpoint => $effects ) {
			if ( ! is_string( $breakpoint ) || ! is_array( $effects ) ) {
				$scoped[ $breakpoint ] = $effects;
				continue;
			}
			$scoped[ $breakpoint ] = self::scope_scroll_effect_list( $prefix, $effects );
		}
		return $scoped;
	}

	/**
	 * Clone {@see ScriptData::get_data( 'scroll' )} with selectors scoped to `$prefix`.
	 *
	 * @param array<string, mixed> $scroll_data Raw scroll script data.
	 */
	public static function scope_scroll_data( array $scroll_data, string $prefix, int $root_key_reference_id ): array {
		if ( $root_key_reference_id <= 0 || '' === trim( $prefix ) || empty( $scroll_data ) ) {
			return array();
		}
		$scoped = array();
		foreach ( $scroll_data as $key => $value ) {
			if ( ! is_string( $key ) || ! is_array( $value ) ) {
				continue;
			}
			$scoped_key               = self::scope_selector_under_root( $prefix, $key );
			$scoped[ $scoped_key ] = self::scope_scroll_breakpoints_value( $prefix, $value );
		}
		return $scoped;
	}

	/**
	 * Scope Design → Animation script entries (`class` selectors) under `$prefix`.
	 *
	 * @param array<int, mixed> $animation_data {@see ScriptData::get_data( 'animation' )}.
	 */
	public static function scope_animation_data( array $animation_data, string $prefix ): array {
		if ( '' === trim( $prefix ) || empty( $animation_data ) ) {
			return array();
		}
		$scoped = array();
		foreach ( $animation_data as $item ) {
			if ( ! is_array( $item ) ) {
				$scoped[] = $item;
				continue;
			}
			$row = $item;
			if ( isset( $row['class'] ) && is_string( $row['class'] ) && '' !== trim( $row['class'] ) ) {
				$cls           = trim( $row['class'] );
				$sel           = ( 0 === strpos( $cls, '.' ) || 0 === strpos( $cls, '#' ) ) ? $cls : '.' . $cls;
				$row['class'] = self::scope_selector_under_root( $prefix, $sel );
			}
			$scoped[] = $row;
		}
		return $scoped;
	}
}
