<script setup>
import { computed, ref } from "vue";
import { provideCELContext } from "../../utils/cel-context";
import { ExpressionEditor } from "../ui/expression-editor";
import { Field, FieldLabel } from "../ui/field";
import { Input } from "../ui/input";
import { Markdown } from "../ui/markdown";
import { Textarea } from "../ui/textarea";
import { provideEventAncestor } from "../../share/event-bus";
import {
  FormConfig,
  getNestedStructFieldDescription,
  getNestedStructFieldTitle,
  getStructFieldDescription,
  getStructFieldTitle,
  metadata as formMetadata
} from "./schema";
import ShwfedFormUnitConfig, {} from "./unit-config.vue";
import { buildFormCelScope } from "./utils/cel-scope";
defineOptions({ name: "ShwfedFormConfig" });
const config = defineModel({ type: Object, ...{ required: true } });
const props = defineProps({
  configure: { type: Function, required: false }
});
const configure = props.configure ?? (() => {
});
const formConfigSchema = FormConfig(configure);
const generalFieldTitle = (f) => getStructFieldTitle(formConfigSchema, f) ?? f;
const generalFieldDescription = (f) => getStructFieldDescription(formConfigSchema, f);
const initialFieldTitle = (f) => getNestedStructFieldTitle(formConfigSchema, "initial", f) ?? f;
const initialFieldDescription = (f) => getNestedStructFieldDescription(formConfigSchema, "initial", f);
provideCELContext(buildFormCelScope(configure));
const formEventAncestor = computed(() => {
  const id = config.value.id;
  if (!id) return null;
  const displayName = config.value.displayName;
  return {
    instanceId: id,
    // Left undefined when the configurer wrote no 内部名称 — the trigger UI
    // then shows just the type name rather than a redundant 「表单」.
    name: displayName && displayName.length > 0 ? displayName : void 0,
    typeName: formMetadata.name,
    typeIcon: formMetadata.icon,
    operations: formMetadata.operations
  };
});
provideEventAncestor(formEventAncestor);
const unitModel = computed({
  get: () => ({ fields: config.value.fields, layouts: config.value.layouts }),
  set: (next) => {
    config.value = { ...config.value, fields: next.fields, layouts: next.layouts };
  }
});
const EXTRAS = [
  { id: "general", label: "\u901A\u7528\u914D\u7F6E", icon: "fluent:settings-20-regular" }
];
const selection = ref({ kind: "extras", id: "general" });
function setInitialField(key, value) {
  const current = config.value.initial ?? {};
  const { [key]: _omit, ...rest } = current;
  const next = value.trim() === "" ? rest : { ...rest, [key]: value };
  if (Object.keys(next).length === 0) {
    const { initial: _drop, ...cfg } = config.value;
    config.value = cfg;
  } else {
    config.value = { ...config.value, initial: next };
  }
}
function updateDisplayName(value) {
  const next = { ...config.value };
  if (value.trim() === "") {
    const { displayName: _omit, ...rest } = next;
    config.value = rest;
  } else {
    config.value = { ...next, displayName: value };
  }
}
function updateReadonly(value) {
  const next = { ...config.value };
  if (value.trim() === "") {
    const { readonly: _omit, ...rest } = next;
    config.value = rest;
  } else {
    config.value = { ...next, readonly: value };
  }
}
function updateStyle(value) {
  const next = { ...config.value };
  if (value.trim() === "") {
    const { style: _omit, ...rest } = next;
    config.value = rest;
  } else {
    config.value = { ...next, style: value };
  }
}
</script>

<template>
  <ShwfedFormUnitConfig
    v-model="unitModel"
    v-model:selection="selection"
    :extras="EXTRAS"
    :configure="configure"
  >
    <template #extras-pane>
      <div class="flex flex-col gap-4">
        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="generalFieldDescription('displayName')"
              #tooltip
            >
              <Markdown
                :source="generalFieldDescription('displayName')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ generalFieldTitle("displayName") }}
          </FieldLabel>
          <Input
            :model-value="config.displayName ?? ''"
            placeholder="如 用户信息表单"
            @update:model-value="(v) => updateDisplayName(String(v))"
          />
        </Field>

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="initialFieldDescription('request')"
              #tooltip
            >
              <Markdown
                :source="initialFieldDescription('request')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ initialFieldTitle("request") }}
          </FieldLabel>
          <ExpressionEditor
            :model-value="config.initial?.request ?? ''"
            placeholder="如 http.get('https://api.example.com/record/1')"
            result-type="HttpRequest"
            multiline
            class="min-h-20"
            @update:model-value="(v) => setInitialField('request', v)"
          />
        </Field>

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="initialFieldDescription('data')"
              #tooltip
            >
              <Markdown
                :source="initialFieldDescription('data')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ initialFieldTitle("data") }}
          </FieldLabel>
          <ExpressionEditor
            :model-value="config.initial?.data ?? ''"
            placeholder="如 { 'name': '', 'age': 0 }"
            result-type="dyn"
            :extra-vars="{ json: { type: 'optional<dyn>', label: 'HTTP \u54CD\u5E94\u4F53', description: '\u300C\u8BF7\u6C42\u300D\u7684\u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF09\uFF1B\u672A\u914D\u7F6E\u8BF7\u6C42\u65F6\u4E3A none' } }"
            multiline
            class="min-h-20"
            @update:model-value="(v) => setInitialField('data', v)"
          />
        </Field>

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="generalFieldDescription('readonly')"
              #tooltip
            >
              <Markdown
                :source="generalFieldDescription('readonly')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ generalFieldTitle("readonly") }}
          </FieldLabel>
          <ExpressionEditor
            :model-value="config.readonly ?? ''"
            placeholder="例：form.status == 'submitted'"
            result-type="bool"
            class="min-h-10"
            @update:model-value="updateReadonly"
          />
        </Field>

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="generalFieldDescription('style')"
              #tooltip
            >
              <Markdown
                :source="generalFieldDescription('style')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ generalFieldTitle("style") }}
          </FieldLabel>
          <Textarea
            :model-value="config.style ?? ''"
            placeholder="如 max-width: 640px; margin: 0 auto;"
            class="min-h-20 font-mono text-xs"
            @update:model-value="(v) => updateStyle(String(v))"
          />
        </Field>
      </div>
    </template>
  </ShwfedFormUnitConfig>
</template>
