<template>
  <n-space vertical>
    <n-button @click="showModal = true" size="small">
      <template #icon
        ><n-icon><PlusOutlined /></n-icon> </template
      >选择{{ buttonText }}
    </n-button>
    <div class="w-full">
      <div class="upload">
        <div class="upload-card" v-if="fileList.length > 0">
          <div
            class="upload-card-item"
            :style="getCSSProperties"
            v-for="(item, index) in fileList"
            :key="`img_${index}`"
          >
            <div class="upload-card-item-info">
              <div class="img-box">
                <template v-if="fileType === 'image'">
                  <img :src="item" @error="errorImg($event)" alt="" />
                </template>
                <template v-else>
                  <n-avatar :style="fileAvatarCSS">{{ getFileExt(item) }}</n-avatar>
                </template>
              </div>
              <div class="img-box-actions">
                <template v-if="fileType === 'image'">
                  <n-icon size="18" class="mx-2 action-icon" @click="handlePreview(item)">
                    <EyeOutlined />
                  </n-icon>
                </template>
                <template v-else>
                  <n-icon size="18" class="mx-2 action-icon" @click="handleDownload(item)">
                    <CloudDownloadOutlined />
                  </n-icon>
                </template>
                <n-icon size="18" class="mx-2 action-icon" @click="handleRemove(index)">
                  <DeleteOutlined />
                </n-icon>
              </div>
            </div>
          </div> </div></div
    ></div>
  </n-space>

  <n-modal
    v-model:show="showModal"
    :on-after-leave="handleCancel"
    :style="{
      width: dialogWidth,
    }"
  >
    <n-card title="文件选择">
      <template #header-extra>
        <n-space>
          <n-button @click="handleUpload" ghost>
            <template #icon>
              <n-icon :component="UploadOutlined" />
            </template>
            上传文件
          </n-button>
        </n-space>
      </template>
      <n-card style="overflow: auto" content-style="padding: 0;">
        <Chooser
          ref="chooserRef"
          :file-type="fileType"
          :maxNumber="maxNumber"
          :fileList="fileList"
          @saveChange="saveChange"
        />
      </n-card>
      <template #footer>
        <n-space justify="end">
          <n-button @click="handleCancel"> 取消 </n-button>
          <n-button type="primary" @click="handleSelectFile"> 确定 </n-button>
        </n-space>
      </template>
    </n-card>
  </n-modal>

  <FileUpload
    ref="fileUploadRef"
    :width="dialogWidth"
    :finish-call="handleFinishCall"
    :max-upload="20"
  />

  <Preview ref="previewRef" />
</template>

<script lang="ts" setup>
  import { NButton, NSpace, NCard, NModal, NIcon, useDialog } from 'naive-ui';
  import { cloneDeep } from 'lodash-es';
  import FileUpload from '@/components/FileChooser/src/Upload.vue';
  import Chooser from '@/components/FileChooser/src/Chooser.vue';
  import Preview from '@/components/FileChooser/src/Preview.vue';
  import { computed, onMounted, ref, watch } from 'vue';
  import { adaModalWidth, errorImg } from '@/utils/hotgo';
  import { getFileExt } from '@/utils/urlUtils';
  import {
    UploadOutlined,
    PlusOutlined,
    CloudDownloadOutlined,
    DeleteOutlined,
    EyeOutlined,
  } from '@vicons/antd';
  import { Attachment, FileType, getFileType } from '@/components/FileChooser/src/model';
  import { isArrayString, isString } from '@/utils/is';

  export interface Props {
    value: string | string[] | null;
    maxNumber?: number;
    fileType?: FileType;
    width?: number;
    height?: number;
  }

  const props = withDefaults(defineProps<Props>(), {
    value: '',
    maxNumber: 1,
    fileType: 'default',
    width: 100,
    height: 100,
  });

  const emit = defineEmits(['update:value']);
  const fileUploadRef = ref();
  const dialog = useDialog();
  const showModal = ref(false);
  const chooserRef = ref();
  const previewRef = ref();
  const fileList = ref<string[]>([]);
  const dialogWidth = computed(() => {
    return adaModalWidth(1080);
  });

  const getCSSProperties = computed(() => {
    return {
      width: `${props.width}px`,
      height: `${props.height}px`,
    };
  });

  const fileAvatarCSS = computed(() => {
    return {
      '--n-merged-size': `var(--n-avatar-size-override, ${props.width * 0.8}px)`,
      '--n-font-size': `18px`,
    };
  });

  const buttonText = computed(() => {
    return getFileType(props.fileType);
  });

  // 预览
  function handlePreview(url: string) {
    previewRef.value.openPreview(url);
  }

  // 下载
  function handleDownload(url: string) {
    window.open(url);
  }

  // 删除
  function handleRemove(index: number) {
    dialog.info({
      title: '提示',
      content: '你确定要删除吗？',
      positiveText: '确定',
      negativeText: '取消',
      onPositiveClick: () => {
        fileList.value.splice(index, 1);
        if (props.maxNumber === 1) {
          emit('update:value', '');
        } else {
          emit('update:value', fileList.value);
        }
      },
      onNegativeClick: () => {},
    });
  }

  function handleSelectFile() {
    showModal.value = false;
    if (props.maxNumber === 1) {
      emit('update:value', fileList.value.length > 0 ? fileList.value[0] : '');
    } else {
      emit('update:value', fileList.value);
    }
  }

  function handleCancel() {
    showModal.value = false;
    loadImage();
  }

  function handleUpload() {
    fileUploadRef.value.openModal();
  }

  function handleFinishCall(result: Attachment, success: boolean) {
    if (success) {
      chooserRef.value.reloadTable();
    }
  }

  function saveChange(list: string[]) {
    fileList.value = list;
  }

  function loadImage() {
    const value = cloneDeep(props.value);
    if (props.maxNumber === 1) {
      fileList.value = [];
      if (value !== '') {
        if (!isString(value)) {
          console.warn(
            'When the file picker is currently in single-file mode, but the passed value is not of type string, there may be potential issues.'
          );
        }
        fileList.value.push(value as string);
      }
    } else {
      if (!isArrayString(value)) {
        console.warn(
          'When the file picker is currently in multiple-file mode, but the passed value is not of type string array, there may be potential issues.'
        );
      }
      if (!value) {
        fileList.value = [];
      } else {
        fileList.value = value as string[];
      }
    }
  }

  watch(
    () => props.value,
    () => {
      loadImage();
    },
    {
      immediate: true,
      deep: true,
    }
  );

  onMounted(async () => {
    loadImage();
  });
</script>

<style lang="less">
  .n-upload {
    width: auto; /**  居中 */
  }

  .upload {
    width: 100%;
    overflow: hidden;

    &-card {
      width: auto;
      height: auto;
      display: flex;
      flex-wrap: wrap;
      align-items: center;

      &-item {
        margin: 0 8px 8px 0;
        position: relative;
        padding: 8px;
        border: 1px solid #d9d9d9;
        border-radius: 2px;
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: center;

        &:hover {
          background: 0 0;

          .upload-card-item-info::before {
            opacity: 1;
          }

          &-info::before {
            opacity: 1;
          }
        }

        &-info {
          position: relative;
          height: 100%;
          padding: 0;
          overflow: hidden;

          &:hover {
            .img-box-actions {
              opacity: 1;
            }
          }

          &::before {
            position: absolute;
            z-index: 1;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            opacity: 0;
            transition: all 0.3s;
            content: ' ';
          }

          .img-box {
            position: relative;
            //padding: 8px;
            //border: 1px solid #d9d9d9;
            border-radius: 2px;
          }

          .img-box-actions {
            position: absolute;
            top: 50%;
            left: 50%;
            z-index: 10;
            white-space: nowrap;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            justify-content: space-between;

            &:hover {
              background: 0 0;
            }

            .action-icon {
              color: rgba(255, 255, 255, 0.85);

              &:hover {
                cursor: pointer;
                color: #fff;
              }
            }
          }
        }
      }

      &-item-select-picture {
        border: 1px dashed #d9d9d9;
        border-radius: 2px;
        cursor: pointer;
        background: #fafafa;
        color: #666;

        .upload-title {
          color: #666;
        }
      }
    }
  }
</style>
