<?php

namespace Extendify\Agent;

defined('ABSPATH') || die('No direct access.');

/**
 * Tag blocks inside template parts (header/footer/etc.) with deterministic IDs.
 * - Only runs inside core/template-part scopes.
 * - Preorder numbering per template-part.
 */
class TagTemplateParts
{
    private static $frames = [];
    private static $blockStack = [];

    public static function init()
    {
        // Reset per-request state
        add_action('template_redirect', function () {
            self::$frames = [];
            self::$blockStack = [];
        });
        // Assign IDs at the block-data layer (pre-order, stable)
        add_filter('render_block_data', [self::class, 'onRenderBlockData'], 10, 2);
        // Turn those IDs into DOM attributes & manage scope lifecycle
        add_filter('render_block', [self::class, 'onRenderBlock'], 10, 2);
    }

    private static function isTemplatePart(array $b): bool
    {
        return (($b['blockName'] ?? '') === 'core/template-part');
    }

    private static function currentFrame()
    {
        return self::$frames ? self::$frames[count(self::$frames) - 1] : null;
    }

    private static function setCurrentFrame(array $frame)
    {
        self::$frames[count(self::$frames) - 1] = $frame;
    }

    private static function labelForPart(array $b): string
    {
        if (!empty($b['attrs']['area'])) {
            return (string) $b['attrs']['area'];
        }
        if (!empty($b['attrs']['slug'])) {
            return (string) $b['attrs']['slug'];
        }
        return 'template-part';
    }

    /** Assign IDs/labels into attrs before render (pre-order) */
    public static function onRenderBlockData(array $block, array $source): array
    {
        $name = $block['blockName'] ?? '';
        if ($name === '') {
            return $block;
        }

        // OPEN a template-part scope (do not number the wrapper itself)
        if (self::isTemplatePart($block)) {
            $label = self::labelForPart($block);
            $slug = $block['attrs']['slug'] ?? '';
            self::$frames[] = [
                'label' => $label,
                'slug' => $slug,
                'seq' => 0, // per-part counter
            ];
            // mark so we know to pop when this wrapper finishes rendering
            $block['attrs']['__extendify_scope_open'] = 1;
            return $block;
        }

        // Not inside a template-part? Ignore (prevents tagging post content).
        if (empty(self::$frames)) {
            return $block;
        }

        // Inside a template part
        $frame = self::currentFrame();
        // Any other block inside the part → number it
        if ($frame) {
            $frame['seq']++;
            self::$blockStack[] = [
                'id' => $frame['seq'],
                'label' => $frame['label'],
                'slug' => $frame['slug'] ?? '',
            ];
            self::setCurrentFrame($frame);
        }

        return $block;
    }

    /** Inject DOM attributes and close scopes after render */
    public static function onRenderBlock(string $html, array $block): string
    {
        $name = $block['blockName'] ?? '';
        if ($name === '') {
            return $html;
        }

        // When the template-part wrapper finishes rendering, POP the frame
        if (self::isTemplatePart($block) && !empty($block['attrs']['__extendify_scope_open'])) {
            // wrapper itself isn’t tagged; just close the scope
            array_pop(self::$frames);
            return $html;
        }

        // If we’re not inside a template part, do nothing
        if (empty(self::$frames)) {
            return $html;
        }

        // Inject attributes for blocks we numbered
        $info = !empty(self::$blockStack)
            ? array_pop(self::$blockStack)
            : null;

        if ($info && $html) {
            $tp = new \WP_HTML_Tag_Processor($html);
            if ($tp->next_tag()) {
                $tp->set_attribute('data-extendify-part-block-id', (string) (int) $info['id']);
                $tp->set_attribute('data-extendify-part', $info['label']);
                if (!empty($info['slug'])) {
                    $tp->set_attribute('data-extendify-part-slug', $info['slug']);
                }
                $html = $tp->get_updated_html();
            }
        }
        return $html;
    }
}
