<template>
  <div class="flex flex-col bg-base-100 justify-center items-center">
    <!-- Title -->
    <h1 class="font-bold text-2xl">上传比特流文件</h1>

    <!-- Input File -->
    <fieldset class="fieldset w-full">
      <legend class="fieldset-legend text-sm">选择或拖拽上传文件</legend>
      <input type="file" ref="fileInput" class="file-input w-full" @change="handleFileChange" />
      <label class="fieldset-label">文件最大容量: {{ maxMemory }}MB</label>
    </fieldset>

    <!-- Upload Button -->
    <div class="card-actions w-full">
      <button @click="handleClick" class="btn btn-primary grow" :disabled="isUploading">
        <div v-if="isUploading">
          <span class="loading loading-spinner"></span>
          下载中...
        </div>
        <div v-else>
          {{ buttonText }}
        </div>
      </button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref, useTemplateRef, onMounted } from "vue";
import { useDialogStore } from "@/stores/dialog";
import { isNull, isUndefined } from "lodash";

interface Props {
  uploadEvent?: (file: File) => Promise<boolean>;
  downloadEvent?: () => Promise<boolean>;
  maxMemory?: number;
}

const props = withDefaults(defineProps<Props>(), {
  maxMemory: 4,
});

const emits = defineEmits<{
  finishedUpload: [file: File];
}>();

const dialog = useDialogStore();

const isUploading = ref(false);
const buttonText = computed(() => {
  return isUndefined(props.downloadEvent) ? "上传" : "上传并下载";
});

const fileInput = useTemplateRef("fileInput");
const bitstream = defineModel("bitstreamFile", {
  type: File,
  default: undefined,
});
onMounted(() => {
  if (!isUndefined(bitstream.value) && !isNull(fileInput.value)) {
    let fileList = new DataTransfer();
    fileList.items.add(bitstream.value);
    fileInput.value.files = fileList.files;
  }
});

function handleFileChange(event: Event): void {
  const target = event.target as HTMLInputElement;
  const file = target.files?.[0]; // 获取选中的第一个文件

  if (!file) {
    return;
  }

  bitstream.value = file;
}

function checkFile(file: File): boolean {
  const maxBytes = props.maxMemory! * 1024 * 1024; // 将最大容量从 MB 转换为字节
  if (file.size > maxBytes) {
    dialog.error(`文件大小超过最大限制: ${props.maxMemory}MB`);
    return false;
  }
  return true;
}

async function handleClick(event: Event): Promise<void> {
  if (isNull(bitstream.value) || isUndefined(bitstream.value)) {
    dialog.error(`未选择文件`);
    return;
  }

  if (!checkFile(bitstream.value)) return;
  if (isUndefined(props.uploadEvent)) {
    dialog.error("无法上传");
    return;
  }

  isUploading.value = true;
  try {
    const ret = await props.uploadEvent(bitstream.value);
    if (isUndefined(props.downloadEvent)) {
      if (ret) {
        dialog.info("上传成功");
        emits("finishedUpload", bitstream.value);
      } else dialog.error("上传失败");
      return;
    }
    if (!ret) {
      isUploading.value = false;
      return;
    }
  } catch (e) {
    dialog.error("上传失败");
    console.error(e);
    return;
  }

  // Download
  try {
    const ret = await props.downloadEvent();
    if (ret) dialog.info("下载成功");
    else dialog.error("下载失败");
  } catch (e) {
    dialog.error("下载失败");
    console.error(e);
  }

  isUploading.value = false;
}
</script>

<style scoped lang="postcss">
@import "../assets/main.css";
</style>
