<script setup lang="ts">
/**
 * Read-only canvas block for a placed snippet. Renders the resolved snippet
 * definition (via the engine's CardRenderer) inside a yellow dashed border
 * with a "Snippet: <label>" caption. Selection + drag-reorder are delegated to
 * the host via events so the same block works at the root and nested in cards.
 */
import { ChevronsLeftRight, GripHorizontal, Maximize2, Puzzle } from "@lucide/vue"
import CardRenderer from "@/engine/CardRenderer.vue"
import type { DisplayCard } from "@/definitions/cards"
import type { CardElement } from "@/definitions/elements"

export interface SnippetPreviewBundle {
  card: DisplayCard
  cards: Record<string, DisplayCard>
  elements: Record<string, CardElement>
}

export interface SnippetCanvasBlockProps {
  /** Placement token (`snippet#<key>:<instanceId>`). */
  token: string
  /** Display label for the snippet. */
  label: string
  /** Index within the parent container (for drag-reorder + drop targeting). */
  index: number
  /** Whether this placement is the current selection. */
  selected?: boolean
  /** Column span (1–4) — the placement's resized width. */
  colSpan?: number
  /** Resolved read-only render bundle, or null when the definition is missing. */
  preview?: SnippetPreviewBundle | null
  /** Form-data item passed through to the renderer. */
  item?: Record<string, unknown>
}

const props = withDefaults(defineProps<SnippetCanvasBlockProps>(), {
  selected: false,
  colSpan: 4,
  preview: null,
  item: () => ({}),
})

const emit = defineEmits<{
  (e: "select"): void
  (e: "reorder", ev: PointerEvent): void
  (e: "resize", ev: PointerEvent): void
  (e: "expand"): void
}>()
</script>

<template>
  <div
    :data-element-block-index="index"
    :data-testid="`form-builder-row-${token}`"
    class="group relative cursor-pointer rounded border border-dashed transition-colors"
    :class="selected
      ? 'border-amber-500 bg-amber-500/10 ring-1 ring-amber-500/30'
      : 'border-amber-400/60 bg-amber-500/[0.04] hover:border-amber-500'"
    :style="{ gridColumn: `span ${props.colSpan}` }"
    @click="emit('select')"
  >
    <span
      class="absolute left-1/2 top-1 z-20 -translate-x-1/2 cursor-grab touch-none rounded-sm bg-muted/80 px-1 py-0.5 opacity-0 transition-opacity group-hover:opacity-100 active:cursor-grabbing"
      title="Drag to reorder"
      @click.stop
      @pointerdown.stop="(e: PointerEvent) => emit('reorder', e)"
    >
      <GripHorizontal class="h-3 w-3 text-muted-foreground" />
    </span>
    <span
      class="absolute right-1 top-1 z-20 cursor-ew-resize touch-none rounded-sm bg-muted/80 px-1 py-0.5 opacity-0 transition-opacity group-hover:opacity-100"
      :title="`Width: ${props.colSpan}/4 — drag to resize`"
      @click.stop
      @pointerdown.stop="(e: PointerEvent) => emit('resize', e)"
    >
      <ChevronsLeftRight class="h-3 w-3 text-muted-foreground" />
    </span>
    <button
      type="button"
      class="absolute left-1 top-1 z-20 flex h-5 w-5 items-center justify-center rounded bg-muted/80 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100 hover:bg-muted hover:text-foreground"
      :class="{ '!opacity-100': selected }"
      title="Expand to edit this snippet"
      :data-testid="`form-builder-snippet-expand-${token}`"
      @click.stop="emit('expand')"
    >
      <Maximize2 class="h-3.5 w-3.5" />
    </button>
    <div class="flex items-center gap-2 border-b border-amber-400/40 px-2.5 py-1 text-xs">
      <Puzzle class="h-3.5 w-3.5 shrink-0 text-amber-600" />
      <span class="text-muted-foreground">Snippet:</span>
      <span class="font-medium">{{ label }}</span>
    </div>
    <div
      v-if="preview"
      class="pointer-events-none select-none p-2.5"
      :data-testid="`form-builder-snippet-preview-${token}`"
    >
      <CardRenderer
        :card="preview.card"
        :cards="preview.cards"
        :elements="preview.elements"
        :item="item"
      />
    </div>
    <p v-else class="px-2.5 py-2 text-xs italic text-muted-foreground">
      Snippet definition not found.
    </p>
  </div>
</template>
