<?php
/**
 * Dynamic CSS Orchestrator
 *
 * @package Brandy\DynamicCss
 */

namespace Brandy\DynamicCss;

use Brandy\DynamicCss\Processors\BackgroundVariableProcessor;
use Brandy\DynamicCss\Processors\BoxShadowVariableProcessor;
use Brandy\DynamicCss\Processors\ColorVariableProcessor;
use Brandy\DynamicCss\Processors\CustomVariableProcessor;
use Brandy\DynamicCss\Processors\DimensionVariableProcessor;
use Brandy\DynamicCss\Processors\NormalVariableProcessor;
use Brandy\DynamicCss\Processors\SpacingVariableProcessor;
use Brandy\DynamicCss\Processors\SwitcherVariableProcessor;
use Brandy\DynamicCss\Processors\TypographyVariableProcessor;
use Brandy\Utils\Helpers;

/**
 * Orchestrates dynamic CSS generation for builders
 */
class DynamicCssOrchestrator {

	/**
	 * Responsive helper instance
	 *
	 * @var ResponsiveHelper
	 */
	private ResponsiveHelper $responsive_helper;

	/**
	 * CSS output builder instance
	 *
	 * @var CssOutputBuilder
	 */
	private CssOutputBuilder $output_builder;

	/**
	 * Builder CSS renderer instance
	 *
	 * @var BuilderCssRenderer
	 */
	private BuilderCssRenderer $builder_renderer;

	/**
	 * Variable processors
	 *
	 * @var VariableProcessorInterface[]
	 */
	private array $processors = [];

	/**
	 * Constructor
	 */
	public function __construct() {
		$this->responsive_helper = new ResponsiveHelper();
		$this->output_builder    = new CssOutputBuilder( $this->responsive_helper );
		$this->builder_renderer  = new BuilderCssRenderer( [ $this, 'render_element_variables' ] );
		$this->register_processors();
	}

	/**
	 * Register all variable processors
	 *
	 * @return void
	 */
	private function register_processors(): void {
		$this->processors = [
			new ColorVariableProcessor( $this->responsive_helper ),
			new TypographyVariableProcessor( $this->responsive_helper ),
			new DimensionVariableProcessor( $this->responsive_helper ),
			new SpacingVariableProcessor( $this->responsive_helper ),
			new SwitcherVariableProcessor( $this->responsive_helper ),
			new BoxShadowVariableProcessor( $this->responsive_helper ),
			new BackgroundVariableProcessor( $this->responsive_helper ),
			new CustomVariableProcessor( $this->responsive_helper ),
			new NormalVariableProcessor( $this->responsive_helper ),
		];
	}

	/**
	 * Reset rendered elements state
	 *
	 * @return void
	 */
	public function reset_state(): void {
		$this->output_builder->reset_state();
	}

	/**
	 * Print dynamic styles and scripts
	 *
	 * @return void
	 */
	public function wp_print_scripts(): void {
		if ( is_admin() && ! is_block_editor_screen() ) {
			return;
		}

		do_action( 'brandy_print_global_css' );
		?>
		<style id="brandy-dynamic-css">
			html {
				-ms-overflow-style: none;
				scrollbar-width: none;
			}
			html::-webkit-scrollbar {
				display: none;
			}
			<?php $this->print_dynamic_css(); ?>
		</style>
		<style id="brandy-editor-content-css">
			<?php do_action( 'brandy_print_editor_content_css' ); ?>
		</style>
		<?php
	}

	/**
	 * Process printing builder dynamic styles
	 *
	 * @return void
	 */
	public function print_dynamic_css(): void {
		$this->builder_renderer->print_builder_css( 'header' );
		$this->builder_renderer->print_builder_css( 'footer' );
	}

	/**
	 * Render element variables CSS
	 *
	 * @param array $input_data        Element configuration.
	 * @param array $components        Component definitions.
	 * @param array $available_devices Devices to generate CSS for.
	 * @return void
	 */
	public function render_element_variables( array $input_data, array $components, array $available_devices = [ 'desktop', 'tablet', 'mobile' ] ): void {
		$variables = $this->responsive_helper->get_empty_device_result();

		foreach ( $components as $component_data ) {
			if ( isset( $component_data['render_options']['type'] ) && 'variable' === $component_data['render_options']['type'] ) {
				foreach ( $component_data['render_options']['data'] as $variable_data ) {
					$value     = Helpers::get_nested_value( $input_data['settings'], $variable_data['value_path'], $component_data['default_value'] );
					$variables = array_merge_recursive( $variables, $this->get_variables( array_merge( $variable_data, [ 'value' => $value ] ), $component_data['type'] ) );
				}
			}
		}

		$selector   = ! empty( $input_data['selector'] )
			? $input_data['selector']
			: "[data-section-id='" . $input_data['id'] . "'][data-builder='" . $input_data['builder'] . "']";

		$device_css = $this->output_builder->build_device_css( $variables, $selector );
		$result     = $this->output_builder->output_device_css( $device_css, $input_data, $available_devices );

		echo wp_kses_post( $result );
	}

	/**
	 * Get CSS variables using appropriate processor
	 *
	 * @param array  $variable_data Variable configuration.
	 * @param string $type          Variable type.
	 * @return array Device-keyed CSS variables
	 */
	public function get_variables( array $variable_data, string $type = '' ): array {
		$variable_data['type'] = $variable_data['type'] ?? '';

		foreach ( $this->processors as $processor ) {
			if ( $processor->supports( $variable_data['type'] ?? '' ) ) {
				return $processor->process( $variable_data );
			}
		}

		return $this->responsive_helper->get_empty_device_result();
	}

	/**
	 * Get responsive helper instance
	 *
	 * @return ResponsiveHelper
	 */
	public function get_responsive_helper(): ResponsiveHelper {
		return $this->responsive_helper;
	}
}
