<?php

/**
 * Handles custom block attributes for the Cryzel theme.
 *
 * This file manages custom block attributes and their application to blocks.
 * It includes support for hover effects and other custom attributes.
 *
 * @package Cryzel
 * @since 1.0.0
 */

if (! defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

// Include hover effects functionality
require_once get_template_directory() . '/includes/features/hover-effects.php';

if (! class_exists('Cryzel_Block_Attributes')) {
    /**
     * Cryzel_Block_Attributes Class
     * 
     * Manages custom block attributes and their application to blocks.
     * Handles the processing of custom attributes during block rendering.
     */
    class Cryzel_Block_Attributes {

        /**
         * Constructor
         * 
         * Sets up the filter for applying custom block attributes.
         */
        public function __construct() {
            add_filter('render_block', [$this, 'apply_custom_block_attributes'], 10, 2);
        }

        /**
         * Apply custom block attributes to block content
         * 
         * Processes block attributes and applies them to the block's HTML.
         * Currently handles hover effects and other custom attributes.
         *
         * @param string $block_content The block content about to be rendered.
         * @param array  $block         The full block, including name and attributes.
         * @return string Modified block content with applied attributes.
         */
        public function apply_custom_block_attributes($block_content, $block) {
            // Skip if no attributes or invalid content
            if (empty($block['attrs']) || !is_string($block_content) || empty($block_content)) {
                return $block_content;
            }

            // Process HTML with tag processor
            $tags = new WP_HTML_Tag_Processor($block_content);

            if (! $tags->next_tag()) {
                return $block_content;
            }

            $attrs   = $block['attrs'];
            $classes = [];
            $styles  = [];

            // Collect classes and styles from hover effect strategy
            $classes = array_merge($classes, HoverEffectsAttributes::get_classes($attrs));
            $styles  = array_merge($styles, HoverEffectsAttributes::get_styles($attrs));

            // Apply collected classes to the block
            foreach ($classes as $class) {
                $tags->add_class($class);
            }

            // Merge and apply styles
            if (! empty($styles)) {
                $existing_style = $tags->get_attribute('style');
                $merged_style   = $this->merge_styles($existing_style, $styles);
                $tags->set_attribute('style', $merged_style);
            }

            return $tags->get_updated_html();
        }

        /**
         * Merge existing styles with new inline styles.
         *
         * Combines existing inline styles with new styles, ensuring no duplicates.
         *
         * @param string $existing    Existing inline style string.
         * @param array  $new_styles  New styles to be applied.
         * @return string             Merged style string.
         */
        private function merge_styles($existing, $new_styles) {
            $style_array = [];

            // Parse existing styles into array
            if (! empty($existing)) {
                $rules = explode(';', $existing);
                foreach ($rules as $rule) {
                    if (strpos($rule, ':') !== false) {
                        list($prop, $val) = explode(':', $rule, 2);
                        $style_array[trim($prop)] = trim($val);
                    }
                }
            }

            // Add or update with new styles
            foreach ($new_styles as $prop => $val) {
                $style_array[$prop] = $val;
            }

            // Convert back to string
            $final = '';
            foreach ($style_array as $prop => $val) {
                $final .= $prop . ': ' . $val . '; ';
            }

            return trim($final);
        }
    }

    // Initialize the class
    new Cryzel_Block_Attributes();
}
