<script setup>
import { useVModel } from "@vueuse/core";
import { Icon } from "@iconify/vue";
import { computed } from "vue";
import { toast } from "vue-sonner";
import { useTranslateLocale } from "../../../composables/useTranslateLocale";
import { cn } from "../../../utils/cn";
import { Button } from "../button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../dropdown-menu";
import { Field, FieldLabel } from "../field";
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupTextarea } from "../input-group";
const supportedLocales = ["zh", "ja", "en", "ko"];
defineOptions({
  name: "UiLocaleEditor",
  inheritAttrs: false
});
const props = defineProps({
  modelValue: { type: null, required: false },
  class: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
  multiline: { type: Boolean, required: false },
  markdown: { type: Boolean, required: false },
  floating: { type: Boolean, required: false },
  placeholder: { type: String, required: false },
  translateHint: { type: String, required: false }
});
const emits = defineEmits(["update:modelValue"]);
const modelValue = useVModel(props, "modelValue", emits, {
  passive: true,
  defaultValue: createDefaultLocaleValue()
});
const locales = computed(
  () => [...modelValue.value ?? createDefaultLocaleValue()].sort((left, right) => {
    if (left.locale === "zh") {
      return -1;
    }
    if (right.locale === "zh") {
      return 1;
    }
    return 0;
  })
);
const hasRemainingLocales = computed(() => locales.value.length < supportedLocales.length);
const localeLabels = {
  zh: "\u4E2D\u6587",
  ja: "\u65E5\u672C\u8A9E",
  en: "English",
  ko: "\uD55C\uAD6D\uC5B4"
};
function createDefaultLocaleValue() {
  return [{ locale: "zh", message: "" }];
}
function localeIcon(locale) {
  return `circle-flags:lang-${locale}`;
}
function localeLabel(locale) {
  return localeLabels[locale];
}
function availableLocales(index) {
  const currentLocale = locales.value[index]?.locale;
  return supportedLocales.filter((locale) => locale !== currentLocale && !locales.value.some((item) => item.locale === locale));
}
function updateMessage(index, message) {
  modelValue.value = locales.value.map((item, itemIndex) => {
    if (itemIndex !== index) {
      return item;
    }
    return {
      locale: item.locale,
      message: String(message)
    };
  });
}
function updateLocale(index, locale) {
  const currentItem = locales.value[index];
  if (!currentItem || currentItem.locale === "zh" && locale !== "zh") {
    return;
  }
  modelValue.value = locales.value.map((item, itemIndex) => {
    if (itemIndex !== index) {
      return item;
    }
    return {
      locale,
      message: item.message
    };
  });
}
function removeLocale(index) {
  const currentItem = locales.value[index];
  if (!currentItem || currentItem.locale === "zh") {
    return;
  }
  modelValue.value = locales.value.filter((_, itemIndex) => itemIndex !== index);
}
function addLocale() {
  const locale = supportedLocales.find((candidate) => !locales.value.some((item) => item.locale === candidate));
  if (!locale) {
    return;
  }
  const nextValue = [...locales.value];
  nextValue.push({
    locale,
    message: ""
  });
  modelValue.value = nextValue;
}
function handleMessageUpdate(index, value) {
  updateMessage(index, value);
}
const ai = useTranslateLocale({ hint: props.translateHint });
function isAiTarget(locale) {
  return locale !== "zh";
}
function canAiTranslate(locale) {
  if (!isAiTarget(locale)) return false;
  return ai.canTranslate(modelValue.value, locale);
}
function isAiTranslating(locale) {
  if (!isAiTarget(locale)) return false;
  return ai.isTranslating(locale);
}
async function onAiTranslate(locale) {
  if (!isAiTarget(locale)) return;
  const current = modelValue.value;
  if (!current) return;
  try {
    const next = await ai.translate(current, locale);
    modelValue.value = next;
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err);
    toast.error("\u7FFB\u8BD1\u5931\u8D25", { description: message });
  }
}
</script>

<template>
  <div
    v-bind="$attrs"
    data-slot="locale"
    :class="cn('flex flex-col gap-2', props.class)"
  >
    <Field
      v-for="(item, index) in locales"
      :key="item.locale"
      :orientation="props.floating ? 'floating' : 'contents'"
    >
      <FieldLabel v-if="props.floating">
        {{ localeLabel(item.locale) }}
      </FieldLabel>
      <InputGroup
        data-slot="locale-row"
        :data-locale="item.locale"
      >
        <InputGroupAddon
          v-if="props.multiline"
          align="block-start"
          class="border-b border-zinc-200"
        >
          <div class="flex w-full items-center justify-between gap-3">
            <DropdownMenu v-if="item.locale !== 'zh' && availableLocales(index).length > 0">
              <DropdownMenuTrigger as-child>
                <InputGroupButton
                  size="sm"
                  as-child
                >
                  <button
                    type="button"
                    data-slot="locale-trigger"
                    class="text-zinc-500 transition-colors hover:text-zinc-700"
                    :aria-label="`\u9009\u62E9\u8BED\u8A00\uFF1A${localeLabel(item.locale)}`"
                  >
                    <Icon :icon="localeIcon(item.locale)" />
                    <span>{{ localeLabel(item.locale) }}</span>
                  </button>
                </InputGroupButton>
              </DropdownMenuTrigger>
              <DropdownMenuContent align="start">
                <DropdownMenuItem
                  v-for="locale in availableLocales(index)"
                  :key="locale"
                  data-slot="locale-option"
                  :data-locale-option="locale"
                  @select="updateLocale(index, locale)"
                >
                  <Icon :icon="localeIcon(locale)" />
                  <span>{{ localeLabel(locale) }}</span>
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>

            <span
              v-else
              data-slot="locale-icon"
              class="flex items-center gap-2 text-zinc-500"
            >
              <Icon :icon="localeIcon(item.locale)" />
              <span>{{ localeLabel(item.locale) }}</span>
            </span>

            <div class="flex items-center gap-2">
              <Icon
                v-if="props.markdown"
                data-slot="locale-markdown-indicator"
                icon="fluent:markdown-20-regular"
                class="text-purple-600"
                aria-label="支持 Markdown"
              />
              <InputGroupButton
                v-if="canAiTranslate(item.locale) || isAiTranslating(item.locale)"
                size="icon-xs"
                as-child
              >
                <button
                  type="button"
                  data-slot="locale-translate"
                  :disabled="isAiTranslating(item.locale) || !canAiTranslate(item.locale)"
                  :aria-label="`AI \u7FFB\u8BD1\uFF1A${localeLabel(item.locale)}`"
                  @click="onAiTranslate(item.locale)"
                >
                  <Icon
                    :icon="isAiTranslating(item.locale) ? 'fluent:arrow-sync-20-regular' : 'fluent:magic-wand-20-regular'"
                    :class="isAiTranslating(item.locale) ? 'animate-spin' : ''"
                  />
                </button>
              </InputGroupButton>
              <InputGroupButton
                variant="destructive"
                size="icon-xs"
                as-child
              >
                <button
                  type="button"
                  data-slot="locale-delete"
                  :disabled="item.locale === 'zh'"
                  :aria-label="`\u5220\u9664\u8BED\u8A00\uFF1A${localeLabel(item.locale)}`"
                  @click="removeLocale(index)"
                >
                  <Icon icon="fluent:delete-20-regular" />
                </button>
              </InputGroupButton>
            </div>
          </div>
        </InputGroupAddon>

        <InputGroupAddon v-else>
          <DropdownMenu v-if="item.locale !== 'zh' && availableLocales(index).length > 0">
            <DropdownMenuTrigger as-child>
              <InputGroupButton
                size="icon-sm"
                as-child
              >
                <button
                  type="button"
                  data-slot="locale-trigger"
                  class="text-zinc-500 transition-colors hover:text-zinc-700 [&_svg:not([class*='size-'])]:size-3.5"
                  :aria-label="`\u9009\u62E9\u8BED\u8A00\uFF1A${localeLabel(item.locale)}`"
                >
                  <Icon :icon="localeIcon(item.locale)" />
                </button>
              </InputGroupButton>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="start">
              <DropdownMenuItem
                v-for="locale in availableLocales(index)"
                :key="locale"
                data-slot="locale-option"
                :data-locale-option="locale"
                @select="updateLocale(index, locale)"
              >
                <Icon :icon="localeIcon(locale)" />
                <span>{{ localeLabel(locale) }}</span>
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
          <span
            v-else
            data-slot="locale-icon"
            class="-ml-[0.45rem] flex size-8 items-center justify-center text-zinc-500"
          >
            <Icon :icon="localeIcon(item.locale)" />
          </span>
        </InputGroupAddon>

        <InputGroupInput
          v-if="!props.multiline"
          data-slot="locale-input"
          :model-value="item.message"
          :placeholder="props.placeholder ?? (props.floating ? '' : localeLabel(item.locale))"
          @update:model-value="handleMessageUpdate(index, $event)"
        />

        <InputGroupTextarea
          v-else
          data-slot="locale-textarea"
          class="min-h-32"
          :model-value="item.message"
          :placeholder="props.placeholder ?? (props.floating ? '' : localeLabel(item.locale))"
          @update:model-value="handleMessageUpdate(index, $event)"
        />

        <InputGroupAddon
          v-if="!props.multiline"
          align="inline-end"
        >
          <Icon
            v-if="props.markdown"
            data-slot="locale-markdown-indicator"
            icon="fluent:markdown-20-regular"
            class="text-purple-600"
            aria-label="支持 Markdown"
          />
          <InputGroupButton
            v-if="canAiTranslate(item.locale) || isAiTranslating(item.locale)"
            size="icon-xs"
            as-child
          >
            <button
              type="button"
              data-slot="locale-translate"
              :disabled="isAiTranslating(item.locale) || !canAiTranslate(item.locale)"
              :aria-label="`AI \u7FFB\u8BD1\uFF1A${localeLabel(item.locale)}`"
              @click="onAiTranslate(item.locale)"
            >
              <Icon
                :icon="isAiTranslating(item.locale) ? 'fluent:arrow-sync-20-regular' : 'fluent:magic-wand-20-regular'"
                :class="isAiTranslating(item.locale) ? 'animate-spin' : ''"
              />
            </button>
          </InputGroupButton>
          <InputGroupButton
            variant="destructive"
            size="icon-xs"
            as-child
          >
            <button
              type="button"
              data-slot="locale-delete"
              :disabled="item.locale === 'zh'"
              :aria-label="`\u5220\u9664\u8BED\u8A00\uFF1A${localeLabel(item.locale)}`"
              @click="removeLocale(index)"
            >
              <Icon icon="fluent:delete-20-regular" />
            </button>
          </InputGroupButton>
        </InputGroupAddon>
      </InputGroup>
    </Field>

    <Button
      type="button"
      data-slot="locale-add"
      class="justify-center"
      :disabled="!hasRemainingLocales"
      @click="addLocale"
    >
      <Icon icon="fluent:add-20-regular" />
      <span>增加</span>
    </Button>
  </div>
</template>
