<script setup>
import { Effect } from "effect";
import { computed, ref } from "vue";
import { useI18n } from "vue-i18n";
import { cel as _rawCel } from "../../../../../utils/cel";
import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
import { interpolateMarkdown } from "../../../../table/utils/runtime";
import { getLocalizedText } from "../../../../../share/locale";
import { RadioGroup, RadioGroupItem } from "../../../../ui/radio-group";
import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
import { Markdown } from "../../../../ui/markdown";
import { useFieldValidation } from "../../../utils/validation";
import { useFormReadonly } from "../../../utils/readonly";
import { useFormState } from "../../../utils/state";
defineOptions({ name: "ShwfedRadioGroupFieldRuntime" });
const props = defineProps({
  fieldId: { type: String, required: true },
  config: { type: null, required: true }
});
const { locale, t } = useI18n({
  inheritLocale: true,
  messages: {
    zh: { "radio-group-empty": "\u65E0\u53EF\u9009\u9879" },
    en: { "radio-group-empty": "No options" },
    ja: { "radio-group-empty": "\u9078\u629E\u80A2\u306A\u3057" }
  }
});
const { state, getAt, setAt } = useFormState();
const inherited = injectCELContext();
const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
const labelText = computed(() => getLocalizedText(props.config.label, locale.value));
const tooltipText = computed(
  () => props.config.tooltip ? getLocalizedText(props.config.tooltip, locale.value) : void 0
);
function evalBool(expression, label) {
  if (!expression) return false;
  try {
    return Effect.runSync($cel(expression, { form: state.value ?? {} }));
  } catch (err) {
    console.error(`[shwfed-form] failed to evaluate ${label} for ${props.fieldId}:`, err);
    return false;
  }
}
const { isRequired, errors, warnings, visible } = useFieldValidation({
  fieldId: () => props.fieldId,
  config: () => props.config,
  $cel,
  locale: () => locale.value
});
const isDisabled = computed(() => evalBool(props.config.disabled, "disabled"));
const formReadonly = useFormReadonly();
const isReadonly = computed(
  () => props.config.readonly != null ? evalBool(props.config.readonly, "readonly") : formReadonly.value
);
const effectiveReadonly = computed(() => isReadonly.value || props.config.derived?.mode === "formula");
function safeInterpolate(tpl, ctx) {
  try {
    return interpolateMarkdown(tpl, $cel, ctx);
  } catch (err) {
    console.error(`[shwfed-form] failed to interpolate option text for ${props.fieldId}:`, err);
    return tpl;
  }
}
const entries = computed(
  () => (props.config.items ?? []).map((item) => {
    const labelTpl = getLocalizedText(item.label, locale.value) ?? "";
    const tooltipTpl = item.tooltip ? getLocalizedText(item.tooltip, locale.value) : void 0;
    const ctx = { form: state.value ?? {} };
    return {
      key: item.id,
      value: item.value.value,
      label: labelTpl ? safeInterpolate(labelTpl, ctx) : "",
      tooltip: tooltipTpl ? safeInterpolate(tooltipTpl, ctx) : void 0
    };
  })
);
const uncontrolled = ref(void 0);
const model = computed({
  get: () => {
    const path = props.config.binding;
    const raw = path == null ? uncontrolled.value : getAt(path);
    return typeof raw === "string" || typeof raw === "number" ? raw : void 0;
  },
  set: (next) => {
    const path = props.config.binding;
    if (path == null) {
      uncontrolled.value = next;
      return;
    }
    setAt(path, next);
  }
});
function onSelect(next) {
  if (isDisabled.value) return;
  model.value = typeof next === "string" || typeof next === "number" ? next : void 0;
}
const readonlyText = computed(() => {
  const selected = entries.value.find((e) => e.value === model.value);
  return selected?.label || "\u2014";
});
</script>

<template>
  <Field
    orientation="vertical"
    :data-disabled="isDisabled || void 0"
  >
    <FieldLabel
      v-if="labelText"
      class="text-xs text-zinc-500"
    >
      <template
        v-if="tooltipText"
        #tooltip
      >
        <Markdown
          :source="tooltipText"
          class="prose prose-xs prose-zinc"
        />
      </template>
      {{ labelText }}<span
        v-if="isRequired"
        aria-hidden="true"
        class="text-red-600"
      > *</span>
    </FieldLabel>
    <div
      v-if="effectiveReadonly"
      class="min-h-9 py-1.5 text-sm text-zinc-700"
    >
      {{ readonlyText }}
    </div>
    <div
      v-else-if="entries.length === 0"
      class="min-h-9 py-1.5 text-sm text-zinc-400"
    >
      {{ t("radio-group-empty") }}
    </div>
    <RadioGroup
      v-else
      :model-value="model"
      :disabled="isDisabled"
      class="flex flex-wrap items-start gap-x-6 gap-y-2 py-1"
      @update:model-value="onSelect"
    >
      <label
        v-for="entry in entries"
        :key="entry.key"
        data-slot="radio-group-option"
        class="flex items-start gap-2"
        :class="isDisabled ? 'cursor-not-allowed opacity-60' : 'cursor-pointer'"
      >
        <RadioGroupItem
          :value="entry.value"
          :disabled="isDisabled"
          class="mt-0.5"
        />
        <span class="flex flex-col gap-0.5">
          <span class="text-sm text-zinc-700">{{ entry.label }}</span>
          <Markdown
            v-if="entry.tooltip"
            :source="entry.tooltip"
            block
            class="prose prose-xs prose-zinc text-zinc-400"
          />
        </span>
      </label>
    </RadioGroup>
    <FieldMessages
      v-if="visible"
      :errors="errors"
      :warnings="warnings"
    />
  </Field>
</template>
