<script setup>
import { computed, ref, watch } from "vue";
import { Icon } from "@iconify/vue";
import { Effect } from "effect";
import { useI18n } from "vue-i18n";
import { useHead } from "#app";
import { getLocalizedText } from "../../share/locale";
import { cel } from "../../utils/cel";
import { celBindings, injectCELContext } from "../../utils/cel-context";
import SlotRenderer from "../../share/slot-renderer.vue";
import ShwfedModal from "../modal.vue";
import EditorBody from "./config.vue";
import EditorBreadcrumb from "./breadcrumb.vue";
import EditorFooter from "./footer.vue";
import { provideEventTarget } from "../../share/event-bus";
import { operationHandlers } from "../operations/utils/resolve";
import * as alertOperation from "../operations/2026-06-09/com.shwfed.operation.alert/schema";
import * as httpRequestOperation from "../operations/2026-06-11/com.shwfed.operation.http.request.json/schema";
import { PAGE_TARGET_ID, createPageConfig } from "./schema";
import { useConfigEditor } from "./use-editor";
import { findBlock } from "./utils/resolve";
defineOptions({ name: "ShwfedConfig" });
const configModel = defineModel("config", { type: null });
const config = computed({
  get: () => configModel.value ?? createPageConfig(),
  set: (next) => {
    configModel.value = next;
  }
});
const props = defineProps({
  configure: { type: Function, required: false },
  editable: { type: Boolean, required: false }
});
const inheritedCEL = injectCELContext();
const hostConfigure = props.configure ?? (() => {
});
const mergedConfigure = (env) => {
  hostConfigure(env);
  const existing = new Set(env.getDefinitions().variables.map((v) => v.name));
  for (const [name, v] of Object.entries(inheritedCEL)) {
    if (existing.has(name)) continue;
    env.registerVariable(name, v.type, { description: v.description, label: v.label });
  }
};
class PageClosed {
  _tag = "PageClosed";
}
const { locale } = useI18n({ useScope: "global", inheritLocale: true });
const $cel = (expression, context) => cel(expression, { ...celBindings(inheritedCEL), ...context });
provideEventTarget(PAGE_TARGET_ID, {
  close: () => Effect.gen(function* () {
    window.close();
    return yield* Effect.die(new PageClosed());
  }),
  ...operationHandlers(
    [
      { type: alertOperation.type, compatibilityDate: alertOperation.compatibilityDate },
      { type: httpRequestOperation.type, compatibilityDate: httpRequestOperation.compatibilityDate }
    ],
    { cel: $cel, locale: () => locale.value }
  )
});
const editorOpen = ref(false);
const editorState = useConfigEditor(config, {
  configure: mergedConfigure,
  onClose: () => {
    editorOpen.value = false;
  }
});
watch(editorOpen, (open, prev) => {
  if (open && !prev) editorState.reset();
});
function onGridClick(event) {
  if (!props.editable) return;
  if (!event.metaKey && !event.ctrlKey) return;
  event.preventDefault();
  event.stopPropagation();
  editorOpen.value = true;
}
function updateSlot(next) {
  config.value = { ...config.value, slot: next };
}
const pageStyle = computed(() => {
  const expression = config.value.style;
  if (!expression) return void 0;
  try {
    const r = Effect.runSync(cel(expression, celBindings(inheritedCEL)));
    if (r === null || r === void 0) return void 0;
    if (typeof r === "string") return r;
    if (typeof r === "object") return r;
    return String(r);
  } catch {
    return void 0;
  }
});
useHead(() => {
  const title = getLocalizedText(config.value.title, locale.value);
  return title ? { title } : {};
});
const isMac = computed(
  () => typeof navigator !== "undefined" && /Mac/i.test(navigator.platform)
);
</script>

<template>
  <ClientOnly>
    <div
      :class="pageStyle ? '' : 'contents'"
      :style="pageStyle"
      @click.capture="onGridClick"
    >
      <SlotRenderer
        :slot-value="config.slot"
        :configure="mergedConfigure"
        :find-entry="findBlock"
        @update:slot-value="updateSlot"
      >
        <template
          v-if="editable"
          #empty
        >
          <div class="flex flex-col items-center gap-2 py-8 text-xs text-muted-foreground">
            <p class="mb-2 text-sm font-medium text-foreground">
              当前区域为空，按以下步骤进入编辑：
            </p>
            <ol class="flex flex-col gap-1.5 text-left">
              <li class="flex items-center gap-2">
                <span class="font-mono text-xs text-muted-foreground">1.</span>
                <span>将鼠标移动到需要编辑的区域上</span>
              </li>
              <li class="flex items-center gap-2">
                <span class="font-mono text-xs text-muted-foreground">2.</span>
                <span class="flex items-center gap-1.5">
                  <template v-if="isMac">
                    <span>按住</span>
                    <kbd class="inline-flex items-center gap-1 rounded border bg-muted px-1.5 py-0.5 font-medium text-foreground">
                      <Icon icon="fluent:key-command-20-regular" />
                      Command
                    </kbd>
                    <span>键</span>
                  </template>
                  <template v-else>
                    <span>按住</span>
                    <kbd class="inline-flex items-center rounded border bg-muted px-1.5 py-0.5 font-medium text-foreground">
                      Ctrl
                    </kbd>
                    <span>键</span>
                  </template>
                </span>
              </li>
              <li class="flex items-center gap-2">
                <span class="font-mono text-xs text-muted-foreground">3.</span>
                <span>保持按住的同时点击该区域，即可进入编辑</span>
              </li>
            </ol>
          </div>
        </template>
      </SlotRenderer>
    </div>
    <ShwfedModal
      v-if="editable"
      v-model:open="editorOpen"
      content-width="90vw"
      :dismissible="true"
    >
      <template #title>
        <EditorBreadcrumb :state="editorState" />
      </template>
      <template #description>
        <span class="sr-only">编辑页面布局与块配置</span>
      </template>
      <EditorBody :state="editorState" />
      <template #footer>
        <EditorFooter
          :state="editorState"
          @close="editorOpen = false"
        />
      </template>
    </ShwfedModal>
  </ClientOnly>
</template>
