<template>
  <el-dialog
    v-model="show"
    :title="$t('createComponent')"
    width="600px"
    :modal="false"
    :close-on-click-modal="false"
    align-center
  >
    <el-form label-position="top" ref="form" :model="formData" :rules="rules">
      <el-form-item :label="$t('name')" prop="name">
        <el-input v-model="formData.name" :placeholder="$t('name')" />
      </el-form-item>
      <el-form-item :label="$t('desc')" prop="description">
        <el-input
          v-model="formData.description"
          :rows="3"
          type="textarea"
          :placeholder="$t('desc')"
        />
      </el-form-item>
      <el-form-item :label="$t('icon')" prop="iconFile">
        <el-upload
          drap
          action="#"
          class="avatar-uploader"
          accept=".jpg, .png, .svg"
          :http-request="handleUpload"
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
        >
          <img v-if="imageUrl" :src="imageUrl" class="avatar" />
          <LuPlus v-if="!imageUrl" size="18px" class="avatar-uploader-icon" />
        </el-upload>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button type="primary" @click="onSubmit">{{ $t('confirm') }}</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, onBeforeUnmount } from 'vue'
import { useEventBus } from '@vueuse/core'
import { snapdom } from '@zumer/snapdom'
import { addIDBData } from '@/utils/database'
import { useProjectStore } from '@/store/modules/project'
import { ElMessage } from 'element-plus'
import { v4 } from 'uuid'

import { LuPlus } from 'vue-icons-plus/lu'

import { type UploadProps, type UploadRequestOptions, type FormInstance, dayjs } from 'element-plus'
import { ICustomWidget } from '@/types'
import { klona } from 'klona'

const show = ref(false)
const imageUrl = ref('')
const form = ref<FormInstance>()
const createCustomCompBus = useEventBus('create-custom-comp')
const addedCustomCompBus = useEventBus('created-custom-comp')
const projectStore = useProjectStore()

const formData = ref<{
  id: string
  name: string
  description?: string
  iconFile: File | Blob | null
}>({
  id: '',
  name: '',
  description: '',
  iconFile: null
})

const rules = {
  name: [{ required: true, message: '请输入组件名称', trigger: 'blur' }],
  iconFile: [{ required: true, message: '请选择图标文件', trigger: 'change' }]
}

/**
 * 创建自定义组件
 */
const unsubscribe = createCustomCompBus.on(async (_e, id) => {
  show.value = true
  formData.value.id = id

  // 获取元素图片
  const el = document.querySelector('[widget-id="' + id + '"]')
  if (el) {
    const blob = await snapdom.toBlob(el, {
      exclude: ['.moveable-control-box'],
      outerTransforms: false
    })
    imageUrl.value = URL.createObjectURL(blob)
    formData.value.iconFile = blob
  }
})

const handleAvatarSuccess: UploadProps['onSuccess'] = (_, uploadFile) => {
  imageUrl.value = URL.createObjectURL(uploadFile.raw!)
}

const handleUpload = async (options: UploadRequestOptions) => {
  const { file, onSuccess } = options
  formData.value.iconFile = file
  onSuccess({ code: 200, message: '上传成功' } as any)
}

onBeforeUnmount(() => {
  unsubscribe()
})

const onSubmit = () => {
  form.value?.validate().then(() => {
    const widget = projectStore.getWidgetById(formData.value.id)
    if (widget) {
      // todo：处理widget数据
      const newComponent: ICustomWidget = {
        name: formData.value.name,
        description: formData.value.description,
        iconFile: formData.value.iconFile,
        widget: widget,
        createBy: dayjs().format('YYYY-MM-DD HH:mm:ss'),
        order: 0
      }
      addIDBData(v4(), klona(newComponent))
      form.value?.resetFields()
      ElMessage.success('添加成功')
      show.value = false
      addedCustomCompBus.emit()
    }
  })
}
</script>

<style lang="less" scoped>
.avatar-uploader .el-upload {
  width: 178px;
  height: 178px;
  border: 1px dashed #eee;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}
.avatar {
  width: 178px;
  height: 178px;
}
</style>
