<script setup>
import { format as formatDate } from "date-fns";
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 { getLocalizedText } from "../../../../../share/locale";
import { DATE_RANGE_PICKER_DEFAULT_FORMATS, DateRangePicker } from "../../../../ui/date-range-picker";
import { Field, FieldLabel, FieldMessages } from "../../../../ui/field";
import { Markdown } from "../../../../ui/markdown";
import { DEFAULT_FIELD_ORIENTATION } from "../../../utils/common";
import { useFieldValidation } from "../../../utils/validation";
import { useFormReadonly } from "../../../utils/readonly";
import { useFormState } from "../../../utils/state";
defineOptions({ name: "ShwfedMonthRangeFieldRuntime" });
const props = defineProps({
  fieldId: { type: String, required: true },
  config: { type: null, required: true }
});
const { locale } = useI18n();
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 startPlaceholderText = computed(
  () => props.config.startPlaceholder ? getLocalizedText(props.config.startPlaceholder, locale.value) : void 0
);
const endPlaceholderText = computed(
  () => props.config.endPlaceholder ? getLocalizedText(props.config.endPlaceholder, locale.value) : void 0
);
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 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");
const { isRequired, errors, warnings, visible } = useFieldValidation({
  fieldId: () => props.fieldId,
  config: () => props.config,
  $cel,
  locale: () => locale.value
});
const resolvedValueFormat = computed(
  () => props.config.valueFormat ?? DATE_RANGE_PICKER_DEFAULT_FORMATS.monthrange.value
);
const shortcuts = computed(() => {
  const list = props.config.presets;
  if (!list || list.length === 0) return void 0;
  return list.map((preset) => ({
    name: preset.label,
    value: () => {
      try {
        const start = Effect.runSync($cel(preset.start, { form: state.value ?? {} }));
        const end = Effect.runSync($cel(preset.end, { form: state.value ?? {} }));
        return [
          formatDate(start, resolvedValueFormat.value),
          formatDate(end, resolvedValueFormat.value)
        ];
      } catch (err) {
        console.error(`[shwfed-form] failed to evaluate preset "${preset.start}" .. "${preset.end}" for ${props.fieldId}:`, err);
        return ["", ""];
      }
    }
  }));
});
function asRange(raw) {
  if (!Array.isArray(raw) || raw.length !== 2) return void 0;
  const [a, b] = raw;
  if (typeof a !== "string" || typeof b !== "string") return void 0;
  if (a.length === 0 || b.length === 0) return void 0;
  return [a, b];
}
function asString(raw) {
  return typeof raw === "string" && raw.length > 0 ? raw : void 0;
}
const uncontrolled = ref(void 0);
const model = computed({
  get: () => {
    const binding = props.config.binding;
    if (binding == null) return uncontrolled.value;
    if (typeof binding === "string") return asRange(getAt(binding));
    const a = asString(getAt(binding[0]));
    const b = asString(getAt(binding[1]));
    if (a == null || b == null) return void 0;
    return [a, b];
  },
  set: (next) => {
    const binding = props.config.binding;
    if (binding == null) {
      uncontrolled.value = next;
      return;
    }
    if (typeof binding === "string") {
      setAt(binding, next);
      return;
    }
    setAt(binding[0], next?.[0]);
    setAt(binding[1], next?.[1]);
  }
});
const readonlyText = computed(() => {
  const v = model.value;
  if (!v) return "\u2014";
  return `${v[0]} ~ ${v[1]}`;
});
</script>

<template>
  <Field
    :orientation="config.orientation ?? DEFAULT_FIELD_ORIENTATION"
    :data-disabled="isDisabled || void 0"
  >
    <FieldLabel
      v-if="labelText"
      :for="fieldId"
      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>
    <DateRangePicker
      v-else
      :id="fieldId"
      v-model="model"
      type="monthrange"
      :format="config.format"
      :value-format="config.valueFormat"
      :start-placeholder="startPlaceholderText"
      :end-placeholder="endPlaceholderText"
      :range-separator-icon="config.rangeSeparatorIcon"
      :disabled="isDisabled"
      :shortcuts="shortcuts"
    />
    <FieldMessages
      v-if="visible"
      :errors="errors"
      :warnings="warnings"
    />
  </Field>
</template>
