<template>
    <div
        :data-bm-instance="instance.instance_id"
        class="bm-pv-row"
        :class="{
            'is-selected': instance.instance_id === selectedId,
            'bm-pv-row--container': isContainer,
        }"
        @click.stop="$emit('select', instance.instance_id)"
    >
        <!-- Container element: header label + recursive nested drop zone -->
        <template v-if="isContainer">
            <div class="bm-pv-container__header">
                <span class="bm-pv-container__label">{{ instance.element_type }}</span>
                <span class="bm-pv-container__variant">{{ instance.variant }}</span>
            </div>
            <VueDraggable
                :model-value="instance.children"
                :group="{ name: 'bm-elements' }"
                item-key="instance_id"
                ghost-class="bm-pv-ghost"
                chosen-class="bm-pv-chosen"
                drag-class="bm-pv-drag"
                :force-fallback="true"
                :fallback-on-body="true"
                draggable=".bm-pv-row"
                :empty-insert-threshold="60"
                :animation="150"
                :class="['bm-pv-container__drop-zone', styleClass]"
                @update:modelValue="(next) => $emit('children-input', instance.instance_id, next)"
                @add="(evt) => $emit('child-add', instance.instance_id, evt)"
            >
                <BlockPreviewNode
                    v-for="child in instance.children"
                    :key="child.instance_id"
                    :instance="child"
                    :selected-id="selectedId"
                    :html-by-instance="htmlByInstance"
                    @select="(id) => $emit('select', id)"
                    @delete="(id) => $emit('delete', id)"
                    @children-input="(cid, next) => $emit('children-input', cid, next)"
                    @child-add="(cid, evt) => $emit('child-add', cid, evt)"
                />
                <div v-if="instance.children.length === 0" class="bm-pv-container__empty">
                    Drop elements here
                </div>
            </VueDraggable>
        </template>

        <!-- Regular (non-container) element -->
        <template v-else>
            <div
                v-if="html"
                class="bm-pv-row__body"
                v-html="html"
            ></div>
            <div v-else class="bm-pv-row__pending">
                {{ instance.element_type }} — rendering…
            </div>
        </template>

        <button
            type="button"
            class="bm-pv-row__delete"
            aria-label="Delete element"
            @click.stop="$emit('delete', instance.instance_id)"
        >×</button>
    </div>
</template>

<script>
import { VueDraggable } from 'vue-draggable-plus';

export default {
    // `name` enables the recursive <BlockPreviewNode> self-reference below.
    name: 'BlockPreviewNode',
    components: { VueDraggable },
    props: {
        instance: { type: Object, required: true },
        selectedId: { type: String, default: null },
        // The full instance_id → outerHTML map from the preview API. Passed
        // whole (not per-node) so children re-render reactively when it changes.
        htmlByInstance: { type: Object, required: true },
    },
    computed: {
        isContainer() {
            return this.instance.children !== undefined;
        },
        // Only leaf nodes render server HTML. A container's stored innerHTML
        // already contains its descendants' markup; v-html'ing it here would
        // double-render against the live recursive drop zone below.
        html() {
            if (this.isContainer) return '';
            return this.htmlByInstance[this.instance.instance_id] || '';
        },
        /**
         * Per-instance scope class for a container's generated CSS. MUST match
         * InstanceClass::for() in PHP byte-for-byte: the backend emits rules
         * against `.bm-ci-<sanitized id>` for every container at any depth, and
         * we apply that same class to this container's drop-zone so the rules
         * have a target in the composer.
         */
        styleClass() {
            if (!this.isContainer) return '';
            const id = String(this.instance.instance_id || '');
            return 'bm-ci-' + id.replace(/[^a-zA-Z0-9_-]/g, '-');
        },
    },
};
</script>
