<script setup>
import { computed, ref } from "vue";
import { Icon } from "@iconify/vue";
import { Button } from "../../../../ui/button";
import { Field, FieldLabel } from "../../../../ui/field";
import { InputGroup, InputGroupInput, InputGroupNumberField } from "../../../../ui/input-group";
import { ExpressionEditor } from "../../../../ui/expression-editor";
import { Locale as LocaleField } from "../../../../ui/locale";
import { Markdown } from "../../../../ui/markdown";
import { ScrollArea } from "../../../../ui/scroll-area";
import { Separator } from "../../../../ui/separator";
import {
  useTreeDnd
} from "../../../../../composables/useTreeDnd";
import {
  dataSourceSchema,
  getStructFieldDescription,
  getStructFieldTitle,
  itemSchema,
  schema
} from "./schema";
defineOptions({ name: "ShwfedBlockAnimatedNumberConfig" });
const block = defineModel({ type: null, ...{ required: true } });
const blockSchema = schema(() => {
});
const itemSchemaObj = itemSchema(() => {
});
const dsSchema = dataSourceSchema(() => {
});
const fieldTitle = (f) => getStructFieldTitle(blockSchema, f) ?? f;
const fieldDescription = (f) => getStructFieldDescription(blockSchema, f);
const itemTitle = (f) => getStructFieldTitle(itemSchemaObj, f) ?? f;
const itemDescription = (f) => getStructFieldDescription(itemSchemaObj, f);
const dsTitle = (f) => getStructFieldTitle(dsSchema, f) ?? f;
const dsDescription = (f) => getStructFieldDescription(dsSchema, f);
const JSON_VAR = {
  json: { type: "optional<dyn>", label: "HTTP \u54CD\u5E94\u4F53\uFF08\u914D\u7F6E\u4E86\u8BF7\u6C42\u65F6\u53EF\u7528\uFF09" }
};
const viewMode = ref("item");
const selectedId = ref(block.value.items[0]?.id ?? "");
const selectedItem = computed(
  () => block.value.items.find((i) => i.id === selectedId.value) ?? null
);
function selectGeneral() {
  viewMode.value = "general";
}
function selectItem(id) {
  viewMode.value = "item";
  selectedId.value = id;
}
function itemLabel(it, i) {
  const name = it.name?.trim();
  return name && name.length > 0 ? name : `\u6570\u5B57 ${i + 1}`;
}
function setDisplayName(v) {
  const s = String(v ?? "");
  block.value = { ...block.value, displayName: s.length > 0 ? s : void 0 };
}
function setLocale(v) {
  block.value = { ...block.value, locale: v };
}
function writeItems(next) {
  block.value = { ...block.value, items: next };
}
function addItem() {
  const it = { id: crypto.randomUUID(), dataSource: { value: "0" } };
  writeItems([...block.value.items, it]);
  selectItem(it.id);
}
function removeItem(id) {
  if (block.value.items.length <= 1) return;
  const i = block.value.items.findIndex((x) => x.id === id);
  if (i < 0) return;
  const next = block.value.items.filter((x) => x.id !== id);
  writeItems(next);
  if (selectedId.value === id) {
    selectedId.value = next[Math.max(0, i - 1)]?.id ?? "";
  }
}
function patchItem(id, patch) {
  writeItems(block.value.items.map((i) => i.id === id ? { ...i, ...patch } : i));
}
function setName(id, v) {
  const s = String(v ?? "");
  patchItem(id, { name: s.length > 0 ? s : void 0 });
}
function patchDataSource(id, patch) {
  const it = block.value.items.find((x) => x.id === id);
  if (!it) return;
  patchItem(id, { dataSource: { ...it.dataSource, ...patch } });
}
function setRequest(id, v) {
  const it = block.value.items.find((x) => x.id === id);
  if (!it) return;
  if (v.trim() === "") {
    patchItem(id, { dataSource: { value: it.dataSource.value } });
    return;
  }
  patchDataSource(id, { request: v });
}
function setValue(id, v) {
  patchDataSource(id, { value: v });
}
function setInterval(id, v) {
  patchItem(id, { pollingInterval: typeof v === "number" && v > 0 ? Math.round(v) : void 0 });
}
function setPrefix(id, v) {
  patchItem(id, { prefix: v.length > 0 ? v : void 0 });
}
function setSuffix(id, v) {
  patchItem(id, { suffix: v.length > 0 ? v : void 0 });
}
function setStyle(id, v) {
  patchItem(id, { style: v.trim().length > 0 ? v : void 0 });
}
const ROW_KIND = "animated-number-item-row";
function rowId(i) {
  return `item-${i}`;
}
function moveItem(from, to) {
  if (from === to || from < 0 || to < 0) return;
  if (from >= block.value.items.length || to >= block.value.items.length) return;
  const next = [...block.value.items];
  const [moved] = next.splice(from, 1);
  if (!moved) return;
  next.splice(to, 0, moved);
  writeItems(next);
}
function onRowDrop(e) {
  if (e.source.kind !== ROW_KIND || e.target.kind !== ROW_KIND) return;
  const from = block.value.items.findIndex((_, i) => rowId(i) === e.source.id);
  const to = block.value.items.findIndex((_, i) => rowId(i) === e.target.id);
  if (from < 0 || to < 0) return;
  if (e.instruction === "reorder-above") moveItem(from, from < to ? to - 1 : to);
  else if (e.instruction === "reorder-below") moveItem(from, from <= to ? to : to + 1);
}
const dnd = useTreeDnd({ onRowDrop });
const pickDragHandle = (el) => el.querySelector(".drag-handle");
function rowConfig(i) {
  return {
    kind: ROW_KIND,
    canDrop: (src) => src.kind === ROW_KIND,
    blockInstructions: (src) => {
      const blocked = ["make-child", "reparent"];
      if (src.id === rowId(i)) blocked.push("reorder-above", "reorder-below");
      return blocked;
    },
    dragHandle: pickDragHandle
  };
}
</script>

<template>
  <div class="flex min-w-0 gap-3 min-h-96">
    <!-- Left rail: general config + reorderable items -->
    <div class="flex w-52 shrink-0 flex-col">
      <div
        class="row pl-2"
        :class="viewMode === 'general' ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
        @click="selectGeneral()"
      >
        <Icon
          icon="fluent:settings-20-regular"
          class="size-4 shrink-0"
        />
        <span class="flex-1 truncate">通用配置</span>
      </div>

      <Separator class="my-2" />

      <ScrollArea class="flex-1">
        <div class="flex flex-col gap-0.5">
          <div
            v-for="(it, i) in block.items"
            :key="it.id"
            :ref="dnd.rowRef(rowId(i), rowConfig(i))"
            class="row group"
            :class="viewMode === 'item' && selectedId === it.id ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
            :data-instruction="dnd.instructionFor(rowId(i)) ?? void 0"
            @click="selectItem(it.id)"
          >
            <Icon
              icon="fluent:re-order-dots-vertical-20-regular"
              class="drag-handle size-4 shrink-0 cursor-grab text-zinc-400"
            />
            <span class="flex-1 truncate">{{ itemLabel(it, i) }}</span>
            <button
              type="button"
              class="ml-auto inline-flex size-5 shrink-0 items-center justify-center rounded text-zinc-300 opacity-0 transition-opacity group-hover:opacity-100 hover:bg-red-50 hover:text-red-500 disabled:opacity-0"
              :disabled="block.items.length <= 1"
              aria-label="删除数字项"
              @click.stop="removeItem(it.id)"
            >
              <Icon
                icon="fluent:delete-20-regular"
                class="size-3.5"
              />
            </button>
          </div>
        </div>
      </ScrollArea>

      <Button
        variant="ghost"
        size="sm"
        class="mt-1 w-full justify-center"
        @click="addItem()"
      >
        <Icon
          icon="fluent:add-20-regular"
          class="size-4"
        />
        <span>新增数字</span>
      </Button>
    </div>

    <Separator orientation="vertical" />

    <!-- Right pane -->
    <div class="min-w-0 flex-1">
      <!-- General -->
      <div
        v-if="viewMode === 'general'"
        class="flex flex-col gap-4"
      >
        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="fieldDescription('displayName')"
              #tooltip
            >
              <Markdown
                :source="fieldDescription('displayName')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ fieldTitle("displayName") }}
          </FieldLabel>
          <InputGroup>
            <InputGroupInput
              :model-value="block.displayName ?? ''"
              placeholder="例：核心指标"
              @update:model-value="setDisplayName"
            />
          </InputGroup>
        </Field>

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="fieldDescription('locale')"
              #tooltip
            >
              <Markdown
                :source="fieldDescription('locale')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ fieldTitle("locale") }}
          </FieldLabel>
          <LocaleField
            markdown
            translate-hint="animated number caption"
            :model-value="block.locale"
            @update:model-value="setLocale"
          />
        </Field>
      </div>

      <!-- Item editor -->
      <div
        v-else-if="selectedItem"
        class="flex flex-col gap-4"
      >
        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="itemDescription('name')"
              #tooltip
            >
              <Markdown
                :source="itemDescription('name')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ itemTitle("name") }}
          </FieldLabel>
          <InputGroup>
            <InputGroupInput
              :model-value="selectedItem.name ?? ''"
              placeholder="例：在线人数"
              @update:model-value="(v) => setName(selectedItem.id, v)"
            />
          </InputGroup>
        </Field>

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="dsDescription('request')"
              #tooltip
            >
              <Markdown
                :source="dsDescription('request')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ dsTitle("request") }}
          </FieldLabel>
          <ExpressionEditor
            :model-value="selectedItem.dataSource.request ?? ''"
            placeholder="可选；如 http.get('/api/online')"
            result-type="HttpRequest"
            multiline
            class="min-h-20"
            @update:model-value="(v) => setRequest(selectedItem.id, v)"
          />
        </Field>

        <div class="grid grid-cols-2 gap-3">
          <Field orientation="vertical">
            <FieldLabel class="text-xs text-zinc-500">
              <template
                v-if="dsDescription('value')"
                #tooltip
              >
                <Markdown
                  :source="dsDescription('value')"
                  block
                  class="prose prose-sm prose-zinc"
                />
              </template>
              {{ dsTitle("value") }}
            </FieldLabel>
            <ExpressionEditor
              :model-value="selectedItem.dataSource.value"
              placeholder="返回数字的表达式，如 json.count"
              result-type="number"
              :extra-vars="JSON_VAR"
              @update:model-value="(v) => setValue(selectedItem.id, v)"
            />
          </Field>

          <Field orientation="vertical">
            <FieldLabel class="text-xs text-zinc-500">
              <template
                v-if="itemDescription('pollingInterval')"
                #tooltip
              >
                <Markdown
                  :source="itemDescription('pollingInterval')"
                  block
                  class="prose prose-sm prose-zinc"
                />
              </template>
              {{ itemTitle("pollingInterval") }}
            </FieldLabel>
            <InputGroup>
              <InputGroupNumberField
                :model-value="selectedItem.pollingInterval"
                :min="1"
                @update:model-value="(v) => setInterval(selectedItem.id, v)"
              />
            </InputGroup>
          </Field>
        </div>

        <Separator />

        <div class="grid grid-cols-2 gap-3">
          <Field orientation="vertical">
            <FieldLabel class="text-xs text-zinc-500">
              <template
                v-if="itemDescription('prefix')"
                #tooltip
              >
                <Markdown
                  :source="itemDescription('prefix')"
                  block
                  class="prose prose-sm prose-zinc"
                />
              </template>
              {{ itemTitle("prefix") }}
            </FieldLabel>
            <ExpressionEditor
              :model-value="selectedItem.prefix ?? ''"
              placeholder="如 '¥'"
              result-type="string"
              :extra-vars="JSON_VAR"
              @update:model-value="(v) => setPrefix(selectedItem.id, v)"
            />
          </Field>

          <Field orientation="vertical">
            <FieldLabel class="text-xs text-zinc-500">
              <template
                v-if="itemDescription('suffix')"
                #tooltip
              >
                <Markdown
                  :source="itemDescription('suffix')"
                  block
                  class="prose prose-sm prose-zinc"
                />
              </template>
              {{ itemTitle("suffix") }}
            </FieldLabel>
            <ExpressionEditor
              :model-value="selectedItem.suffix ?? ''"
              placeholder="如 ' 人'"
              result-type="string"
              :extra-vars="JSON_VAR"
              @update:model-value="(v) => setSuffix(selectedItem.id, v)"
            />
          </Field>
        </div>

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="itemDescription('style')"
              #tooltip
            >
              <Markdown
                :source="itemDescription('style')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ itemTitle("style") }}
          </FieldLabel>
          <ExpressionEditor
            :model-value="selectedItem.style ?? ''"
            placeholder="返回 CSS 字符串或样式对象的表达式，如 'font-size: 3rem'"
            :extra-vars="JSON_VAR"
            multiline
            class="min-h-16"
            @update:model-value="(v) => setStyle(selectedItem.id, v)"
          />
        </Field>
      </div>
    </div>
  </div>
</template>

<style scoped>
.row{align-items:center;border-radius:.25rem;cursor:pointer;display:flex;font-size:.875rem;gap:.375rem;padding-block:.375rem;padding-left:.5rem;padding-right:.5rem;position:relative;transition:background-color .1s ease;-webkit-user-select:none;-moz-user-select:none;user-select:none}[data-instruction=reorder-above]:before,[data-instruction=reorder-below]:after{background:var(--primary,#2563eb);content:"";height:2px;left:.5rem;pointer-events:none;position:absolute;right:.5rem;z-index:1}[data-instruction=reorder-above]:before{top:-1px}[data-instruction=reorder-below]:after{bottom:-1px}
</style>
