<template>
  <UForm
    :name="name"
    :schema="schema"
    :class="ui.root({ class: [props.ui?.root, props.class] })"
    :validate-on="['input']"
    :nested="nested"
  >
    <UFormField name="image" :label="label">
      <div :class="ui.base({ class: [props.ui?.base] })">
        <template v-if="state.image">
          <UPopover
            :content="{ align: 'center', side: 'top', sideOffset: 8 }"
            :ui="{ content: 'p-1' }"
            mode="click"
          >
            <CUploraImage
              :image="state.image"
              :alt="state.alt"
              :color="state.color"
              :lqip="state.lqip"
              :aspect="state.aspect"
              :width="state.width"
              :height="state.height"
            />

            <template #content>
              <div class="flex items-center gap-0.5">
                <USelect
                  variant="ghost"
                  color="neutral"
                  size="sm"
                  :items="aspectItems"
                  :model-value="state.aspect"
                  default-value="horizontal"
                  @update:model-value="state = { ...state, aspect: $event === 'horizontal' ? void 0 : $event }"
                />

                <UButton
                  color="neutral"
                  size="sm"
                  variant="ghost"
                  :icon="appConfig.ui.icons.refresh"
                  @click="resetState()"
                />

                <CButtonDeleteConfirm
                  color="error"
                  size="sm"
                  variant="ghost"
                  label=""
                  :icon="appConfig.ui.icons.trash"
                  @confirm="deleteExecute(state.image)"
                />
              </div>
            </template>
          </UPopover>
        </template>
        <div v-else :class="ui.uploader({ class: [props.ui?.uploader] })">
          <template v-if="uploadStatus === 'pending'">
            <UIcon :name="appConfig.ui.icons.loading" :class="ui.uploaderPendingIcon({ class: [props.ui?.uploaderPendingIcon] })" />
          </template>
          <template v-else-if="uploadStatus === 'idle'">
            <button
              type="button"
              :class="ui.uploaderIdleButton({ class: [props.ui?.uploaderIdleButton] })"
              :disabled="disabled"
              @click="open"
            >
              <UAvatar :icon="appConfig.ui.icons.image" size="lg" />

              <p :class="ui.uploaderIdleText({ class: [props.ui?.uploaderIdleText] })">
                Загрузить изображение
              </p>
              <p :class="ui.uploaderIdleExtensions({ class: [props.ui?.uploaderIdleExtensions] })">
                {{ extensions }}
              </p>
            </button>
          </template>
          <template v-else-if="uploadStatus === 'error'">
            <p :class="ui.uploaderErrorText({ class: [props.ui?.uploaderErrorText] })">
              Произошла ошибка при загрузке изображения
            </p>
            <div :class="ui.uploaderErrorActions({ class: [props.ui?.uploaderErrorActions] })">
              <UButton
                label="Отменить"
                variant="ghost"
                color="neutral"
                @click="resetUpload"
              />
              <UButton
                label="Повторить"
                variant="soft"
                color="neutral"
                @click="uploadExecute"
              />
            </div>
          </template>
        </div>
      </div>
    </UFormField>
    <UFormField name="alt">
      <UInput
        placeholder="Введите описание..."
        variant="none"
        size="xs"
        :model-value="state.alt"
        :ui="{ base: 'text-center text-toned' }"
        @update:model-value="state = { ...state, alt: $event || void 0 }"
      />
    </UFormField>
  </UForm>
</template>

<script>
import theme from "#build/cms/form-uplora-image";
import { useAppConfig, useUploraDelete, useUploraUpload } from "#imports";
import { imagesExtensions } from "@uplora/formats";
import { computed } from "vue";
import { z } from "zod";
import { tv } from "../tv";
import CButtonDeleteConfirm from "./ButtonDeleteConfirm.vue";
</script>

<script setup>
const props = defineProps({
  showExtensions: { type: Boolean, required: false, default: true },
  name: { type: String, required: false, default: "image" },
  label: { type: String, required: false },
  disabled: { type: Boolean, required: false },
  as: { type: null, required: false },
  class: { type: null, required: false },
  nested: { type: Boolean, required: false, default: true },
  ui: { type: null, required: false }
});
const emit = defineEmits(["upload", "delete"]);
const model = defineModel({ type: [Object, null] });
const state = computed({
  get: () => {
    return model.value ?? {
      image: void 0,
      width: void 0,
      height: void 0,
      alt: void 0,
      lqip: void 0,
      color: void 0,
      aspect: void 0
    };
  },
  set: (value) => {
    const isEmpty = Object.values(value).every((value2) => !value2);
    model.value = isEmpty ? null : value;
  }
});
const appConfig = useAppConfig();
const schema = z.object({
  image: z.string().min(1),
  alt: z.string().min(1),
  width: z.number(),
  height: z.number(),
  lqip: z.string().min(1).optional(),
  color: z.string().min(1).optional(),
  aspect: z.union([z.literal("horizontal"), z.literal("vertical"), z.literal("dynamic")]).optional()
}).nullable();
const extensions = computed(() => imagesExtensions.filter((extension) => extension !== "jpeg").join(", "));
const aspectItems = [
  { value: "horizontal", label: "\u0413\u043E\u0440\u0438\u0437\u043E\u043D\u0442\u0430\u043B\u044C\u043D\u044B\u0439" },
  { value: "vertical", label: "\u0412\u0435\u0440\u0442\u0438\u043A\u0430\u043B\u044C\u043D\u044B\u0439" },
  { value: "dynamic", label: "\u0414\u0438\u043D\u0430\u043C\u0438\u0447\u0435\u0441\u043A\u0438\u0439" }
];
const { open, execute: uploadExecute, status: uploadStatus, reset: resetUpload, onUploaded } = useUploraUpload({
  accept: "image/*"
});
const { execute: deleteExecute, onDeleted } = useUploraDelete();
function resetState() {
  resetUpload();
  state.value = {
    image: void 0,
    width: void 0,
    height: void 0,
    alt: void 0,
    lqip: void 0,
    color: void 0,
    aspect: void 0
  };
}
onUploaded((file) => {
  state.value = {
    image: file.id,
    width: file.width,
    height: file.height,
    alt: void 0,
    lqip: file.lqip,
    color: file.color,
    aspect: void 0
  };
  emit("upload", state.value);
});
onDeleted(() => {
  resetState();
  emit("delete");
});
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.formUploraImage || {} })({
  disabled: props.disabled
}));
</script>
