<script setup>
import { computed, defineAsyncComponent } from "vue";
import { Effect } from "effect";
import { cel } from "../../../../../utils/cel";
import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
import SlotRenderer from "../../../../../share/slot-renderer.vue";
import { findBlock } from "../../../utils/resolve";
defineOptions({ name: "ShwfedBlockCardRuntime" });
const CardBadge = defineAsyncComponent(() => import("./badge.vue"));
const block = defineModel("block", { type: null, ...{ required: true } });
const props = defineProps({
  configure: { type: Function, required: false }
});
const configure = computed(() => props.configure ?? (() => {
}));
const inheritedContext = injectCELContext();
function baseContext() {
  return celBindings(inheritedContext);
}
function evalStyle(expression) {
  if (!expression) return void 0;
  try {
    const r = Effect.runSync(cel(expression, baseContext()));
    if (r === null || r === void 0) return void 0;
    if (typeof r === "string") return r;
    if (typeof r === "object") return r;
    return String(r);
  } catch {
    return void 0;
  }
}
const styleValue = computed(() => evalStyle(block.value.style));
const resolvedUrl = computed(() => {
  const expr = block.value.url;
  if (!expr || expr.trim().length === 0) return void 0;
  try {
    const url = Effect.runSync(cel(expr, baseContext()));
    return typeof url === "string" && url ? url : void 0;
  } catch (err) {
    console.warn("[shwfed-card] url evaluation failed", err);
    return void 0;
  }
});
const hasUrl = computed(() => !!block.value.url && block.value.url.trim().length > 0);
function onCardClick(e, navigate) {
  if (!resolvedUrl.value) return;
  const target = e.target;
  if (target?.closest('a, button, input, select, textarea, label, [role="button"]')) return;
  navigate(e);
}
function updateSlot(next) {
  block.value = { ...block.value, slot: next };
}
</script>

<template>
  <!--
    `custom` makes NuxtLink render no anchor of its own — it just hands us a
    baseURL-aware `navigate()`. We keep the card a `<div>` so clicks on
    interactive descendants stay untouched, and only follow the link from the
    guarded handler. `to` is `''` when no URL is configured (navigation is then
    short-circuited in `onCardClick`).
  -->
  <NuxtLink
    :to="resolvedUrl ?? ''"
    custom
  >
    <template #default="{ navigate }">
      <div
        class="relative h-full rounded-sm border border-zinc-200 bg-white p-4"
        :class="hasUrl ? 'cursor-pointer' : ''"
        :style="styleValue"
        @click="(e) => onCardClick(e, navigate)"
      >
        <ClientOnly>
          <CardBadge
            v-if="block.badge"
            :badge="block.badge"
            class="absolute -right-2 -top-2 z-10"
          />
        </ClientOnly>

        <SlotRenderer
          :slot-value="block.slot"
          :configure="configure"
          :find-entry="findBlock"
          @update:slot-value="(s) => updateSlot(s)"
        />
      </div>
    </template>
  </NuxtLink>
</template>
