<?php
/**
 * Custom Variable Processor
 *
 * @package Brandy\DynamicCss\Processors
 */

namespace Brandy\DynamicCss\Processors;

use Brandy\Utils\Helpers;
use Brandy\Utils\StylesDataHelpers;

/**
 * Processor for custom CSS variables with conditional mapping
 */
class CustomVariableProcessor extends AbstractVariableProcessor {

	/**
	 * Check if this processor supports the given type
	 *
	 * @param string $type Variable type.
	 * @return bool
	 */
	public function supports( string $type ): bool {
		return 'custom_variables' === $type;
	}

	/**
	 * Process custom variable data
	 *
	 * @param array $variable_data Variable configuration.
	 * @return array Device-keyed CSS variables
	 */
	public function process( array $variable_data ): array {
		$result   = $this->responsive_helper->get_empty_device_result();
		$selector = $variable_data['selector'] ?? '';

		if ( ! empty( $variable_data['mapping_variables'] ) ) {
			return $this->process_mapping_variables( $variable_data, $selector );
		}

		return $this->process_responsive( $variable_data, function( $data, $value ) {
			return StylesDataHelpers::get_css_variable( $data['name'], $value );
		});

	}

	/**
	 * Process mapping variables with conditional logic
	 *
	 * @param array  $variable_data Variable configuration.
	 * @param string $selector      CSS selector.
	 * @return array Device-keyed CSS variables
	 */
	private function process_mapping_variables( array $variable_data, string $selector ): array {
		$result = $this->responsive_helper->get_empty_device_result();

		foreach ( $variable_data['mapping_variables'] as $mapping_variable ) {
			$check_value = $this->get_check_value( $variable_data, $mapping_variable['path'] );

			if ( ! isset( $check_value ) || is_null( $check_value ) ) {
				continue;
			}

			if ( ! $this->evaluate_condition( $mapping_variable['condition'], $check_value ) ) {
				continue;
			}

			$this->apply_mapping( $result, $mapping_variable['mapping'], $selector );
		}

		return $result;
	}

	/**
	 * Get value to check from variable data
	 *
	 * @param array $variable_data Variable configuration.
	 * @param array $path          Path to value.
	 * @return mixed Value to check
	 */
	private function get_check_value( array $variable_data, array $path ) {
		if ( empty( $path ) ) {
			return $variable_data['value'];
		}

		$check_value = Helpers::get_nested_value( $variable_data['value'], $path );

		// Fallback to tablet if mobile not found.
		if ( is_null( $check_value ) ) {
			$device_position = array_search( 'mobile', $path, true );
			if ( false !== $device_position ) {
				$path[ $device_position ] = 'tablet';
				$check_value              = Helpers::get_nested_value( $variable_data['value'], $path );
			}
		}

		// Fallback to desktop if tablet not found.
		if ( is_null( $check_value ) ) {
			$device_position = array_search( 'tablet', $path, true );
			if ( false !== $device_position ) {
				$path[ $device_position ] = 'desktop';
				$check_value              = Helpers::get_nested_value( $variable_data['value'], $path );
			}
		}

		return $check_value;
	}

	/**
	 * Evaluate condition against check value
	 *
	 * @param array $condition   Condition configuration.
	 * @param mixed $check_value Value to check.
	 * @return bool True if condition passes
	 */
	private function evaluate_condition( array $condition, $check_value ): bool {
		$operator        = $condition['operator'];
		$condition_value = $condition['value'];

		switch ( $operator ) {
			case 'equal':
				return $check_value == $condition_value;
			case 'not_equal':
				return $check_value != $condition_value;
			case 'contains':
				return false !== strpos( $check_value, $condition_value );
			case 'not_contains':
				return false === strpos( $check_value, $condition_value );
			case 'in_array':
				return in_array( $check_value, $condition_value, true );
			case 'not_in_array':
				return ! in_array( $check_value, $condition_value, true );
			default:
				return false;
		}
	}

	/**
	 * Apply mapping to result
	 *
	 * @param array  $result   Result array (passed by reference).
	 * @param array  $mapping  Device-keyed variable mapping.
	 * @param string $selector CSS selector.
	 * @return void
	 */
	private function apply_mapping( array &$result, array $mapping, string $selector ): void {
		foreach ( $mapping as $device => $variables ) {
			foreach ( $variables as $var_name => $var_value ) {
				$css_var = StylesDataHelpers::get_css_variable( $var_name, $var_value );
				$this->responsive_helper->add_to_result( $result, $device, $selector, $css_var );
			}
		}
	}
}
