<?php

namespace Wpxero\Marqueex\Integrations\Gutenberg;

use Wpxero\Marqueex\Traits\Singleton;
use WP_Block_Type_Registry;
use Wpxero\Marqueex\Core\CSSBuilder;

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

/**
 * Gutenberg Integration Class
 */
class GutenbergIntegration {
    use Singleton;

    /**
     * Constructor
     */
    private function __construct() {
        add_action('init', [$this, 'init']);
    }

    /**
     * Initialize Shortcode integration
     */
    public function init() {
        // Check if integration is enabled
        $settings = get_option('marqueex_settings', []);
        $gutenberg_enabled = $settings['builder_support']['gutenberg']['enabled'] ?? true;

        if (!$gutenberg_enabled) {
            return;
        }

        // Register blocks
        $this->register_blocks();

        add_action('wp_enqueue_scripts', array($this, 'enqueue_front_scripts'));
        add_action('enqueue_block_editor_assets', array($this, 'enqueue_editor_assets'));
        add_filter('block_categories_all', array($this, 'add_custom_block_category'));
    }

    public function enqueue_editor_assets() {
        $asset_path = MARQUEEX_DIR_PATH . '/dist/marqueex.asset.php';
        if (!file_exists($asset_path)) {
            return;
        }


        $args = require $asset_path;
        wp_enqueue_style('@marqueex/library', MARQUEEX_ADMIN_URL . 'dist/marqueex.css', array(), $args['version']);
        wp_register_script('@marqueex/library', MARQUEEX_ADMIN_URL . 'dist/marqueex.js', $args['dependencies'], $args['version'], true);
        wp_localize_script('@marqueex/library', 'MARQUEEX', array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'home_url' => home_url('/'),
            'nonce' => wp_create_nonce('marqueex-nonce'),
            'rest_url' => rest_url('wpxero/marqueex/v1'),
            'assetsPath' =>  MARQUEEX_ADMIN_URL . 'assets/'
        ));
    }

    public function add_custom_block_category($categories) {
        $category = array(
            'slug' => 'marqueex',
            'title' => 'MarqueeX',
        );
        return array_merge(array($category), $categories);
    }

    public function register_blocks() {
        $dist_dir = MARQUEEX_DIR_PATH . 'dist/';
        if (!is_dir($dist_dir)) {
            return;
        }
        foreach ($this->get_registerable_blocks($dist_dir) as $name) {
            register_block_type($dist_dir . $name);
        }
    }

    /**
     * Return the list of block directories that should be registered, cached
     * per version + settings hash to avoid `scandir` on every request.
     */
    private function get_registerable_blocks($dist_dir) {
        $settings = get_option('marqueex_settings', []);
        $active_blocks = $settings['builder_support']['gutenberg']['elements'] ?? [];

        $cache_key = 'marqueex_registerable_blocks_' . MARQUEEX_VERSION . '_' . md5(wp_json_encode($active_blocks));
        $cached = get_transient($cache_key);
        if (is_array($cached)) {
            return $cached;
        }

        $registerable = [];
        foreach (scandir($dist_dir) as $name) {
            if ($name === '.' || $name === '..' || str_contains($name, '.')) {
                continue;
            }
            $option_name = str_replace('-', '_', $name);
            $should_register = !empty($active_blocks[$option_name]);

            if (!$should_register && str_ends_with($name, '-item')) {
                $parent_option = str_replace('-', '_', substr($name, 0, -strlen('-item')));
                $should_register = !empty($active_blocks[$parent_option]);
            }

            if ($should_register) {
                $registerable[] = $name;
            }
        }

        set_transient($cache_key, $registerable, HOUR_IN_SECONDS);
        return $registerable;
    }


    public function enqueue_front_scripts() {
        $post = get_post();
        if (!$post || empty($post->post_content)) {
            return;
        }
        // Only do work when the post actually contains a MarqueeX block.
        if (
            !has_block('marqueex/infinite-slider', $post) &&
            !has_block('marqueex/infinite-slider-item', $post)
        ) {
            return;
        }

        wp_enqueue_style('marqueex-frontend', MARQUEEX_ADMIN_URL . 'dist/style-marqueex.css', [], MARQUEEX_VERSION);

        foreach (parse_blocks($post->post_content) as $block) {
            $this->style_block($block);
        }
    }

    public function style_block($block, $depth = 0) {
        // Guard against pathological / malformed block trees.
        if ($depth > 16) {
            return;
        }
        $attrs = $block['attrs'] ?? array();
        $block_id = $attrs['blockId'] ?? '';
        if ($block_id) {
            $css = $this->block_css($block);
            if ($css) {
                $escaped_css = wp_strip_all_tags($css); // Escaping as late as possible
                wp_add_inline_style('marqueex-frontend', $escaped_css);
            }
        }

        foreach ($block['innerBlocks'] ?? array() as $inner_block) {
            $this->style_block($inner_block, $depth + 1);
        }
    }

    public function block_css($block) {

        $css = '';
        $registry = WP_Block_Type_Registry::get_instance(); // Get the block type registry instance
        $attrs = $block['attrs'] ?? array();
        $block_id = $attrs['blockId'] ?? '';
        if ($block_id) {
            foreach ($attrs as $attr => $value) {
                if (is_array($value) && !empty($value)) {
                    $selector = $value['__selector__'] ?? null;
                    if (!$selector) {
                        $block_type = $registry->get_registered($block['blockName']);
                        if ($block_type) {
                            $selector = $block_type->attributes[$attr]['selector'] ?? null;
                        }
                    }
                    $css .= $this->build_css("marqueex-$block_id", $value, array('selector' => $selector));
                }
            }
        }
        return $css;
    }

    public function build_css($id, $attributes, $options = array()) {
        $builder = CSSBuilder::get_instance();
        $builder->add_attributes($attributes);
        return $builder->to_css($id, $options);
    }

    /**
     * Get integration status
     */
    public function get_status() {
        return [
            'active' => true,
            'blocks_registered' => true,
            'blocks' => [
                'marqueex_slider' => true,
                'marqueex_ticker' => true,
                'marqueex_infinite' => true,
            ],
        ];
    }
}
