<?php
/**
 * Style Collector Class
 *
 * Collects all dynamic styles during page rendering and outputs them
 * as a single <style> block instead of inline styles.
 *
 * @package    Extra_Product_Options_For_WooCommerce
 * @subpackage Extra_Product_Options_For_WooCommerce/includes
 * @since      4.4.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * EPOFW Style Collector Class
 *
 * Collects styles during rendering and outputs them efficiently.
 */
class EPOFW_Style_Collector {

	/**
	 * Static instance of styles array.
	 *
	 * @since 4.4.0
	 * @var array
	 */
	private static $styles = array();

	/**
	 * Counter for generating unique class names.
	 *
	 * @since 4.4.0
	 * @var int
	 */
	private static $counter = 0;

	/**
	 * Add a style to the collector.
	 *
	 * @since 4.4.0
	 *
	 * @param string $selector CSS selector (e.g., '.epofw-style-section-abc123').
	 * @param array  $properties Array of CSS properties (e.g., array('background-color' => '#fff', 'padding' => '10px')).
	 * @return string Unique class name for this style set.
	 */
	public static function add_style( $selector, $properties ) {
		if ( empty( $properties ) || ! is_array( $properties ) ) {
			return '';
		}

		// Generate unique class name if selector is empty.
		if ( empty( $selector ) ) {
			++self::$counter;
			$selector = 'epofw-style-' . wp_rand( 1000, 9999 ) . '-' . self::$counter;
		}

		// Store styles.
		if ( ! isset( self::$styles[ $selector ] ) ) {
			self::$styles[ $selector ] = array();
		}

		// Merge properties (in case same selector is used multiple times).
		self::$styles[ $selector ] = array_merge( self::$styles[ $selector ], $properties );

		// Return class name (remove leading dot if present for return value).
		return str_replace( '.', '', $selector );
	}

	/**
	 * Generate a unique class name.
	 *
	 * @since 4.4.0
	 *
	 * @param string $prefix Class name prefix (e.g., 'epofw-style-section').
	 * @return string Unique class name.
	 */
	public static function generate_class_name( $prefix = 'epofw-style' ) {
		++self::$counter;
		$unique_id = wp_rand( 1000, 9999 ) . '-' . time() . '-' . self::$counter;
		return $prefix . '-' . $unique_id;
	}

	/**
	 * Convert CSS properties array to CSS string.
	 *
	 * @since 4.4.0
	 *
	 * @param array $properties    Array of CSS properties.
	 * @param bool  $add_important Whether to add !important to properties.
	 * @return string CSS properties string.
	 */
	private static function properties_to_css( $properties, $add_important = false ) {
		if ( empty( $properties ) || ! is_array( $properties ) ) {
			return '';
		}

		$css = array();
		foreach ( $properties as $property => $value ) {
			if ( '' !== $value && null !== $value ) {
				$important = $add_important ? ' !important' : '';
				$css[]     = esc_attr( $property ) . ': ' . esc_attr( $value ) . $important;
			}
		}

		return implode( '; ', $css );
	}

	/**
	 * Get all collected styles as CSS.
	 *
	 * @since 4.4.0
	 *
	 * @return string CSS string with all collected styles.
	 */
	public static function get_css() {
		if ( empty( self::$styles ) ) {
			return '';
		}

		$css_rules = array();
		foreach ( self::$styles as $selector => $properties ) {
			// Ensure selector has leading dot.
			$base_selector = ( strpos( $selector, '.' ) === 0 ) ? $selector : '.' . $selector;

			// Check if this is a field container style.
			$is_field_container = strpos( $selector, 'epofw-style-field-container' ) !== false;

			// Use !important for field container styles to override all base CSS rules.
			$css_properties = self::properties_to_css( $properties, $is_field_container );

			if ( ! empty( $css_properties ) ) {
				// Increase specificity for field container styles to override base CSS.
				// Base CSS uses: .epofw_addon_str_div .epofw_field_container (specificity: 20)
				// We use: .epofw_addon_str_div .epofw_field_container.epofw-style-xxx (specificity: 30)
				// Plus !important to override even higher specificity selectors like:
				// .epofw-columns.epofw-columns-multi .epofw-column .epofw_field_container (specificity: 40).
				if ( $is_field_container ) {
					$final_selector = '.epofw_addon_str_div .epofw_field_container' . $base_selector;
				} else {
					$final_selector = $base_selector;
				}

				$css_rules[] = $final_selector . ' { ' . $css_properties . ' }';
			}
		}

		return implode( "\n", $css_rules );
	}

	/**
	 * Output collected styles as a <style> block.
	 *
	 * @since 4.4.0
	 *
	 * @return string HTML style tag with collected CSS.
	 */
	public static function output_styles() {
		$css = self::get_css();
		if ( empty( $css ) ) {
			return '';
		}

		return '<style type="text/css" id="epofw-collected-styles">' . "\n" . $css . "\n" . '</style>' . "\n";
	}

	/**
	 * Clear all collected styles.
	 *
	 * Useful for testing or resetting.
	 *
	 * @since 4.4.0
	 */
	public static function clear() {
		self::$styles  = array();
		self::$counter = 0;
	}

	/**
	 * Get all collected styles (for debugging).
	 *
	 * @since 4.4.0
	 *
	 * @return array Array of styles.
	 */
	public static function get_all_styles() {
		return self::$styles;
	}
}
