<script setup>
import { computed } from "vue";
import { DEFAULT_GAP } from "./schema";
import { findField } from "./utils/resolve";
defineOptions({ name: "ShwfedFormUnitRenderer" });
const props = defineProps({
  unit: { type: Object, required: true },
  evaluateMedia: { type: Function, required: true },
  isHidden: { type: Function, required: false }
});
function pickLayout(sets) {
  for (const set of sets) {
    if (!set.media) return set;
    try {
      if (props.evaluateMedia(set.media)) return set;
    } catch (err) {
      console.error(`[shwfed-form] failed to evaluate layout media for ${set.name}:`, err);
    }
  }
  return sets[sets.length - 1];
}
const activeLayout = computed(() => pickLayout(props.unit.layouts));
const warnedMissing = /* @__PURE__ */ new Set();
const placedFields = computed(() => {
  const layout = activeLayout.value?.layout;
  if (!layout) return [];
  const out = [];
  for (const field of props.unit.fields) {
    const placement = layout.placements[field.id];
    if (!placement) continue;
    if (props.isHidden?.(field)) continue;
    const entry = findField(field.type, field.compatibilityDate);
    if (!entry) {
      const key = `${field.type}@${field.compatibilityDate}`;
      if (!warnedMissing.has(key)) {
        warnedMissing.add(key);
        console.warn(`[shwfed-form] no registered field type for ${key}`);
      }
      continue;
    }
    out.push({ field, placement, entry });
  }
  return out;
});
function cellStyle(placement) {
  const [[x1, y1], [x2, y2]] = placement.area;
  const parts = [`grid-column: ${x1} / ${x2}`, `grid-row: ${y1} / ${y2}`, "min-width: 0"];
  const h = placement.h && placement.h !== "stretch" ? placement.h : null;
  const v = placement.v && placement.v !== "stretch" ? placement.v : null;
  if (h || v) {
    parts.push("display: flex");
    const toFlex = (a) => a === "start" ? "flex-start" : a === "end" ? "flex-end" : "center";
    if (h) parts.push(`justify-content: ${toFlex(h)}`);
    if (v) parts.push(`align-items: ${toFlex(v)}`);
  }
  return parts.join("; ");
}
const gridStyle = computed(() => {
  const l = activeLayout.value?.layout;
  if (!l) return "";
  const colTemplate = `repeat(${l.columns}, minmax(0, 1fr))`;
  let rowTemplate = "";
  if (l.rows) {
    const grows = Array.from({ length: l.rows }, () => false);
    for (const p of placedFields.value) {
      if (!p.entry.metadata.h.grow) continue;
      const [[, y1], [, y2]] = p.placement.area;
      const lo = Math.max(1, y1);
      const hi = Math.min(l.rows, y2 - 1);
      for (let r = lo; r <= hi; r++) grows[r - 1] = true;
    }
    rowTemplate = grows.map((g) => g ? "auto" : "minmax(auto, 1fr)").join(" ");
  }
  const gap = `calc(${l.gap ?? DEFAULT_GAP} * 0.25rem)`;
  const colGap = l.columns > 1 ? `min(${gap}, calc(100% / ${l.columns - 1}))` : gap;
  const parts = [
    "display: grid",
    `grid-template-columns: ${colTemplate}`,
    rowTemplate ? `grid-template-rows: ${rowTemplate}` : "",
    `column-gap: ${colGap}`,
    `row-gap: ${gap}`,
    l.style ?? ""
  ].filter(Boolean);
  return parts.join("; ");
});
const rendered = computed(
  () => placedFields.value.map((p) => ({
    key: p.field.id,
    style: cellStyle(p.placement),
    component: p.entry.runtime,
    fieldId: p.field.id,
    config: p.field
  }))
);
</script>

<template>
  <div :style="gridStyle">
    <div
      v-for="r in rendered"
      :key="r.key"
      :style="r.style"
    >
      <component
        :is="r.component"
        :field-id="r.fieldId"
        :config="r.config"
      />
    </div>
  </div>
</template>
