<script setup>
import { computed, provide, ref, toRef, useTemplateRef } from "vue";
import { Icon } from "@iconify/vue";
import { toast } from "vue-sonner";
import { readClip, reidFragment, writeClip } from "../../share/clipboard";
import BlockLayoutEditor from "../block-layout-editor/index.vue";
import LayoutsSidebar from "../block-layout-editor/sidebar.vue";
import LayoutMetaStrip from "../block-layout-editor/meta-strip.vue";
import { Button } from "../ui/button";
import { ExpressionEditor } from "../ui/expression-editor";
import { Field, FieldLabel } from "../ui/field";
import { Locale as LocaleField } from "../ui/locale";
import { Markdown } from "../ui/markdown";
import { ScrollArea } from "../ui/scroll-area";
import { Separator } from "../ui/separator";
import { provideEventAncestor } from "../../share/event-bus";
import { BREADCRUMB_EXTENSION_KEY } from "./breadcrumb-extension";
import { PAGE_TARGET_ID, PageConfig, getStructFieldDescription, getStructFieldTitle, metadata as pageMetadata } from "./schema";
defineOptions({ name: "ShwfedConfigConfig" });
const props = defineProps({
  state: { type: Object, required: true }
});
const viewMode = ref("content");
function selectGeneral() {
  viewMode.value = "general";
}
function selectLayout(index) {
  activeLayoutIndex.value = index;
  viewMode.value = "content";
}
const pageSchema = PageConfig(() => {
});
const titleTitle = getStructFieldTitle(pageSchema, "title") ?? "\u6807\u9898";
const titleDescription = getStructFieldDescription(pageSchema, "title");
const styleTitle = getStructFieldTitle(pageSchema, "style") ?? "\u6837\u5F0F";
const styleDescription = getStructFieldDescription(pageSchema, "style");
function isLocaleBlank(v) {
  return !v || v.every((item) => item.message.trim().length === 0);
}
const pageTitle = computed({
  get: () => props.state.draft.value.title,
  set: (v) => {
    props.state.draft.value = {
      ...props.state.draft.value,
      title: isLocaleBlank(v) ? void 0 : v
    };
  }
});
const pageStyle = computed({
  get: () => props.state.draft.value.style ?? "",
  set: (v) => {
    const trimmed = v.trim();
    props.state.draft.value = {
      ...props.state.draft.value,
      style: trimmed.length > 0 ? v : void 0
    };
  }
});
const layouts = computed({
  get: () => props.state.layouts.value,
  set: (next) => {
    props.state.layouts.value = next;
  }
});
const selectedBlockIds = computed({
  get: () => props.state.selectedBlockIds.value,
  set: (next) => {
    props.state.selectedBlockIds.value = next;
  }
});
const activeLayoutIndex = computed({
  get: () => props.state.activeLayoutIndex.value,
  set: (next) => {
    props.state.activeLayoutIndex.value = next;
  }
});
const blocks = toRef(() => props.state.blocks.value);
const top = toRef(() => props.state.top.value);
const activeBlock = toRef(() => props.state.activeBlock.value);
const activeBlockEntry = toRef(() => props.state.activeBlockEntry.value);
const pickerEntries = toRef(() => props.state.pickerEntries.value);
provide(BREADCRUMB_EXTENSION_KEY, {
  add: props.state.addCrumb,
  addParentSuffix: props.state.addParentSuffix
});
const pageEventAncestor = computed(() => ({
  instanceId: PAGE_TARGET_ID,
  typeName: pageMetadata.name,
  typeIcon: pageMetadata.icon,
  operations: pageMetadata.operations
}));
provideEventAncestor(pageEventAncestor);
const sidebarRef = useTemplateRef("sidebarRef");
function addLayout() {
  sidebarRef.value?.addLayout();
}
function addBlock(entry, options) {
  props.state.addBlock(entry, options);
}
function onDrillDown(id) {
  props.state.onDrillDown(id);
}
async function copyBlocks(ids) {
  const want = new Set(ids);
  const items = props.state.blocks.value.filter((b) => want.has(b.id));
  if (items.length === 0) return;
  const ls = layouts.value[activeLayoutIndex.value];
  const placements = {};
  if (ls) {
    for (const id of ids) {
      const p = ls.layout.placements[id];
      if (p) placements[id] = p;
    }
  }
  if (!await writeClip("block", items, placements)) {
    toast.error("\u590D\u5236\u5931\u8D25");
    return;
  }
  toast.success(`\u5DF2\u590D\u5236 ${items.length} \u4E2A\u5757`);
}
async function pasteBlocks(target) {
  const payload = await readClip();
  if (!payload || payload.surface !== "block") return;
  const { items, placements } = reidFragment(payload.items, payload.placements);
  const pasted = items;
  if (pasted.length === 0) return;
  if (placements && Object.keys(placements).length > 0) {
    props.state.addBlocksWithPlacements(pasted, placements, target);
  } else {
    props.state.addBlocks(pasted);
  }
  toast.success(`\u5DF2\u7C98\u8D34 ${pasted.length} \u4E2A\u5757`);
}
function updateActiveBlock(next) {
  props.state.updateActiveBlock(next);
}
function getBlockLabel(b) {
  return props.state.getBlockLabel(b);
}
function findBlockMeta(type, compatibilityDate) {
  return props.state.findBlockMeta(type, compatibilityDate);
}
</script>

<template>
  <div class="relative flex min-w-0 flex-col">
    <div
      v-show="top.kind === 'layout'"
      class="flex gap-2 min-h-128"
    >
      <div class="flex w-64 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">
          <LayoutsSidebar
            ref="sidebarRef"
            v-model="layouts"
            v-model:active-index="activeLayoutIndex"
            :active="viewMode !== 'general'"
            @select="selectLayout"
          />
        </ScrollArea>
        <Button
          variant="ghost"
          size="sm"
          @click="addLayout()"
        >
          <Icon
            icon="fluent:add-20-regular"
            class="size-4"
          />
          <span>新增布局</span>
        </Button>
      </div>

      <div class="flex flex-1 flex-col gap-2">
        <!-- Page-level general settings. -->
        <template v-if="viewMode === 'general'">
          <Field orientation="vertical">
            <FieldLabel class="text-xs text-zinc-500">
              <template
                v-if="titleDescription"
                #tooltip
              >
                <Markdown
                  :source="titleDescription"
                  block
                  class="prose prose-sm prose-zinc"
                />
              </template>
              {{ titleTitle }}
            </FieldLabel>
            <LocaleField
              :model-value="pageTitle"
              translate-hint="page tab title"
              @update:model-value="(v) => {
  pageTitle = v;
}"
            />
          </Field>

          <Field orientation="vertical">
            <FieldLabel class="text-xs text-zinc-500">
              <template
                v-if="styleDescription"
                #tooltip
              >
                <Markdown
                  :source="styleDescription"
                  block
                  class="prose prose-sm prose-zinc"
                />
              </template>
              {{ styleTitle }}
            </FieldLabel>
            <ExpressionEditor
              v-model="pageStyle"
              placeholder="返回 CSS 字符串或样式对象的表达式，如 'padding: 2rem'"
              multiline
              class="min-h-16"
            />
          </Field>
        </template>

        <!-- Per-layout meta + canvas. -->
        <template v-else>
          <LayoutMetaStrip
            v-model="layouts"
            :index="activeLayoutIndex"
          />
          <div class="flex-1">
            <BlockLayoutEditor
              v-model="layouts"
              v-model:active-index="activeLayoutIndex"
              v-model:selected-item-ids="selectedBlockIds"
              :items="blocks"
              :find-entry="findBlockMeta"
              :get-item-label="getBlockLabel"
              :picker-entries="pickerEntries"
              :can-delete="true"
              item-noun="块"
              @add-new="addBlock"
              @drill-down="onDrillDown"
              @delete-item="(id) => props.state.removeBlock(id)"
              @delete-items="(ids) => props.state.removeBlocks(ids)"
              @copy-items="copyBlocks"
              @paste="pasteBlocks"
            />
          </div>
        </template>
      </div>
    </div>

    <div v-if="top.kind === 'block'">
      <div
        v-if="!activeBlock"
        class="flex min-h-96 items-center justify-center p-8 text-sm text-zinc-400"
      >
        块已不存在
      </div>
      <div
        v-else-if="activeBlockEntry"
      >
        <component
          :is="activeBlockEntry.config"
          :model-value="activeBlock"
          :configure="props.state.configure"
          @update:model-value="(next) => updateActiveBlock(next)"
        />
      </div>
      <div
        v-else
        class="p-6 text-sm text-red-500"
      >
        未注册的块类型：{{ activeBlock.type }}@{{ activeBlock.compatibilityDate }}
      </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}
</style>
