<script lang="ts" setup>
import { number, object, string, type InferType } from 'yup'
import type { FormSubmitEvent, TableColumn } from '#ui/types'

const toast = useToast()
const loginState = useLoginState()

const data_layout = ref<'grid' | 'list'>('grid')
const pagination = reactive({
  page: 1,
  pageSize: 14,
})
const showSystemAvatar = ref(false)
watchEffect(() => {
  if (showSystemAvatar.value) {
    data_layout.value = 'list'
  }
})

const {
  data: userAvatarList,
  status: userAvatarStatus,
  refresh: refreshUserAvatarList,
} = useAsyncData(
  'user-digital-human',
  () =>
    useFetchWrapped<
      req.gen.DigitalHumanList & AuthedRequest,
      BaseResponse<PagedData<DigitalHumanItem>>
    >('App.User_UserDigital.GetList', {
      token: loginState.token!,
      user_id: loginState.user.id,
      to_user_id: loginState.user.id,
      page: pagination.page,
      perpage: pagination.pageSize,
    }),
  {
    watch: [pagination, showSystemAvatar],
  }
)

const {
  data: systemAvatarList,
  status: systemAvatarStatus,
  refresh: refreshSystemAvatarList,
} = useAsyncData(
  'sys-digital-human',
  () =>
    useFetchWrapped<
      req.gen.DigitalHumanList & AuthedRequest,
      BaseResponse<PagedData<DigitalHumanItem>>
    >('App.Digital_Human.GetList', {
      token: loginState.token!,
      user_id: loginState.user.id,
      to_user_id: loginState.user.id,
      page: pagination.page,
      perpage: pagination.pageSize,
    }),
  {
    watch: [pagination, showSystemAvatar],
  }
)

const {
  data: avatarTrainList,
  status: avatarTrainStatus,
  refresh: refreshAvatarTrainList,
} = useAsyncData(
  () =>
    useFetchWrapped<
      PagedDataRequest & AuthedRequest,
      BaseResponse<PagedData<DigitalHumanTrainItem>>
    >('App.Digital_Train.GetList', {
      token: loginState.token!,
      user_id: loginState.user.id,
      to_user_id: loginState.user.id,
      page: 1,
      perpage: 20,
    }),
  {}
)

const onSystemAvatarDelete = (row: DigitalHumanItem) => {
  useFetchWrapped<
    { digital_human_id: number } & AuthedRequest,
    BaseResponse<{ code: 0 | 1 }>
  >('App.Digital_Human.Delete', {
    token: loginState.token!,
    user_id: loginState.user.id,
    digital_human_id: row.id!,
  })
    .then((res) => {
      if (res.ret === 200 && res.data.code === 1) {
        toast.add({
          title: '删除成功',
          description: '数字人已删除',
          color: 'success',
          icon: 'i-tabler-check',
        })
        refreshSystemAvatarList()
      } else {
        toast.add({
          title: '删除失败',
          description: res.msg || '未知错误',
          color: 'error',
          icon: 'i-tabler-alert-triangle',
        })
      }
    })
    .catch(() => {
      toast.add({
        title: '删除失败',
        description: '未知错误',
        color: 'error',
        icon: 'i-tabler-alert-triangle',
      })
    })
}

const columns: TableColumn<DigitalHumanItem>[] = [
  {
    accessorKey: 'avatar',
    header: '图片',
  },
  {
    accessorKey: 'name',
    header: '名称',
  },
  {
    accessorKey: 'model_id',
    header: 'ID',
  },
  {
    accessorKey: 'type',
    header: '来源',
  },
  {
    accessorKey: 'description',
    header: '备注',
  },
  {
    accessorKey: 'actions',
  },
]

const sourceTypeList = [
  { label: 'xsh_wm', value: 1, color: 'info' as const }, // 万木（腾讯）
  { label: 'xsh_zy', value: 2, color: 'success' as const }, // XSH 自有
  { label: 'xsh_fh', value: 3, color: 'warning' as const }, // 硅基（泛化数字人）
  { label: 'xsh_bb', value: 4, color: 'primary' as const }, // 百度小冰
]

const isCreateSlideOpen = ref(false)
const isTrainCreatorOpen = ref(false)

const createAvatarState = reactive({
  name: '',
  description: '',
  model_id: undefined,
  avatar: '',
  type: 2,
})

const createAvatarSchema = object({
  name: string().required('请输入名称'),
  description: string().required('请输入备注'),
  model_id: number().required('请输入ID'),
  avatar: string().required('请上传图片'),
  type: number().required('请选择类型'),
})

type CreateAvatarSchema = InferType<typeof createAvatarSchema>

const onCreateAvatarSubmit = (event: FormSubmitEvent<CreateAvatarSchema>) => {
  useFetchWrapped<
    CreateAvatarSchema & AuthedRequest,
    BaseResponse<{ digital_human_id: number }>
  >('App.Digital_Human.Create', {
    token: loginState.token!,
    user_id: loginState.user.id,
    name: event.data.name,
    description: event.data.description,
    model_id: event.data.model_id,
    avatar: createAvatarState.avatar,
    type: event.data.type,
  })
    .then((res) => {
      if (res.ret === 200 && res.data.digital_human_id) {
        toast.add({
          title: '创建成功',
          description: '数字人已创建',
          color: 'success',
          icon: 'i-tabler-check',
        })
        refreshSystemAvatarList()
        showSystemAvatar.value = true
        isCreateSlideOpen.value = false
      } else {
        toast.add({
          title: '创建失败',
          description: res.msg || '未知错误',
          color: 'error',
          icon: 'i-tabler-alert-triangle',
        })
      }
    })
    .catch(() => {
      toast.add({
        title: '创建失败',
        description: '未知错误',
        color: 'error',
        icon: 'i-tabler-alert-triangle',
      })
    })
}

const onAvatarUpload = async (files: FileList) => {
  const file = files[0]
  if (!file) return

  try {
    const url = await useFileGo(file, 'material')
    createAvatarState.avatar = url
    toast.add({
      title: '上传文件成功',
      description: '文件已上传',
      color: 'success',
      icon: 'i-tabler-check',
    })
  } catch {
    toast.add({
      title: '上传文件失败',
      description: '请重试',
      color: 'error',
      icon: 'i-tabler-alert-triangle',
    })
  }
}
</script>

<template>
  <div class="h-full">
    <div class="p-4 pb-0">
      <BubbleTitle
        title="数字讲师管理"
        subtitle="Avatars"
      >
        <template #action>
          <UButton
            color="neutral"
            variant="soft"
            :label="showSystemAvatar ? '显示用户数字人' : '显示系统数字人'"
            @click="showSystemAvatar = !showSystemAvatar"
          />
          <UButton
            :icon="
              data_layout === 'grid'
                ? 'tabler:layout-list'
                : 'tabler:layout-grid'
            "
            variant="soft"
            color="neutral"
            @click="data_layout = data_layout === 'grid' ? 'list' : 'grid'"
            :label="data_layout === 'grid' ? '列表视图' : '宫格视图'"
          />
          <UButton
            v-if="loginState.user.auth_code === 2"
            color="warning"
            variant="soft"
            icon="tabler:user-cog"
            label="定制管理"
            :to="'/generation/admin/digital-human-train'"
          />
          <UButton
            color="info"
            variant="soft"
            icon="tabler:user-plus"
            label="定制数字人"
            @click="isTrainCreatorOpen = true"
          />
          <UButton
            v-if="loginState.user.auth_code === 2"
            color="warning"
            variant="soft"
            icon="tabler:plus"
            label="创建数字人"
            @click="isCreateSlideOpen = true"
          />
        </template>
      </BubbleTitle>
      <GradientDivider />
    </div>
    <div class="p-4">
      <UAlert
        v-if="showSystemAvatar && loginState.user.auth_code === 2"
        icon="tabler:user-shield"
        title="正在显示系统数字人"
        description="当前正在显示和管理系统数字人，仅管理员可见"
        class="mb-4"
      />
      <div
        v-if="data_layout === 'grid'"
        class="grid grid-cols-7 gap-4"
      >
        <div
          v-for="(avatar, k) in showSystemAvatar
            ? systemAvatarList?.data.items
            : userAvatarList?.data.items"
          :key="avatar.model_id || k"
          class="shadow-xs aspect-9/16 group relative w-full overflow-hidden rounded-lg"
        >
          <NuxtImg
            :src="avatar.avatar"
            class="h-full w-full object-cover"
          />
          <div
            class="bg-linear-to-t absolute inset-x-0 bottom-0 flex gap-2 from-black/50 to-transparent p-2"
          >
            <UBadge
              color="neutral"
              variant="subtle"
              icon="tabler:user-screen"
            >
              {{ avatar.name }}
            </UBadge>
            <template
              v-for="(t, i) in sourceTypeList"
              :key="i"
            >
              <UBadge
                v-if="t.value === avatar.type"
                variant="subtle"
                :color="t.color"
                :label="t.label"
              />
            </template>
          </div>
          <div
            class="absolute inset-0 flex flex-col items-center justify-center bg-white/50 opacity-0 backdrop-blur-sm transition-opacity group-hover:opacity-100 dark:bg-neutral-800/50"
          >
            <UButtonGroup>
              <UButton
                color="neutral"
                icon="tabler:download"
                label="下载图片"
                @click="
                  () => {
                    const { download } = useDownload(
                      avatar.avatar,
                      `数字人_${avatar.name}.png`
                    )
                    download()
                  }
                "
              />
            </UButtonGroup>
            <span
              class="pt-4 text-xs font-medium text-neutral-400 dark:text-neutral-300"
            >
              ID: {{ avatar.model_id }}
            </span>
          </div>
        </div>
      </div>
      <div v-else>
        <div class="flex flex-col gap-4">
          <UTable
            :data="
              showSystemAvatar
                ? systemAvatarList?.data.items
                : userAvatarList?.data.items
            "
            :columns="columns"
            :loading="userAvatarStatus === 'pending'"
            loading-color="warning"
            loading-animation="carousel"
            class="rounded-md border dark:border-neutral-800"
          >
            <template #avatar-cell="{ row }">
              <NuxtImg
                :src="row.original.avatar"
                class="h-16 w-auto rounded-lg object-contain"
              />
            </template>
            <template #type-cell="{ row }">
              <template
                v-for="(t, i) in sourceTypeList"
                :key="i"
              >
                <UBadge
                  v-if="t.value === row.original.type"
                  variant="subtle"
                  :color="t.color"
                  :label="t.label"
                />
              </template>
            </template>
            <template #actions-cell="{ row }">
              <div class="flex gap-2">
                <UButton
                  color="neutral"
                  icon="tabler:download"
                  label="下载图片"
                  variant="soft"
                  size="xs"
                  @click="
                    () => {
                      const { download } = useDownload(
                        row.original.avatar,
                        `数字人_${row.original.name}.png`
                      )
                      download()
                    }
                  "
                />
                <UButton
                  color="error"
                  icon="tabler:trash"
                  label="删除"
                  variant="soft"
                  size="xs"
                  @click="onSystemAvatarDelete(row.original)"
                />
              </div>
            </template>
          </UTable>
        </div>
      </div>
      <div class="mt-4 flex justify-end">
        <UPagination
          v-model:page="pagination.page"
          :max="9"
          :page-count="pagination.pageSize"
          :total="userAvatarList?.data.total || 0"
        />
      </div>
    </div>

    <USlideover v-model:open="isCreateSlideOpen">
      <template #content>
        <UCard
          :ui="{
            body: 'flex-1',
          }"
          class="flex flex-1 flex-col"
        >
          <template #header>
            <UButton
              class="absolute end-5 top-5 z-10 flex"
              color="neutral"
              icon="tabler:x"
              padded
              size="sm"
              square
              variant="ghost"
              @click="isCreateSlideOpen = false"
            />
            创建系统数字人
          </template>

          <UForm
            class="space-y-3"
            :schema="createAvatarSchema"
            :state="createAvatarState"
            @submit="onCreateAvatarSubmit"
          >
            <UFormField
              label="名称"
              name="name"
            >
              <UInput v-model="createAvatarState.name" />
            </UFormField>
            <UFormField
              label="备注"
              name="description"
            >
              <UInput v-model="createAvatarState.description" />
            </UFormField>
            <UFormField
              label="ID"
              name="model_id"
            >
              <UInput v-model="createAvatarState.model_id" />
            </UFormField>
            <UFormField
              label="图片"
              name="avatar"
            >
              <UniFileDnD
                accept="image/png,image/jpeg"
                @change="onAvatarUpload"
              />
            </UFormField>
            <UFormField
              label="类型"
              name="type"
            >
              <USelectMenu
                v-model="createAvatarState.type"
                :items="sourceTypeList"
                value-key="value"
              />
            </UFormField>
            <UFormField class="flex justify-end pt-4">
              <UButton
                type="submit"
                color="primary"
                label="创建"
              />
            </UFormField>
          </UForm>
        </UCard>
      </template>
    </USlideover>

    <!-- 数字人定制对话框 -->
    <DigitalHumanTrainCreator v-model="isTrainCreatorOpen" />
  </div>
</template>

<style scoped></style>
