<script lang="ts" setup>
  import { Upload, Button } from 'ant-design-vue';
  import { InboxOutlined } from '@ant-design/icons-vue';
  import { computed, ref } from 'vue';
  import StepContainer from './StepContainer.vue';
  import XLSX, { CellObject } from 'xlsx';
  import { basicProps } from './props';
  import { UploadFileParseValue } from './type';

  const props = defineProps({
    ...basicProps,
    value: {
      require: true,
      type: Object as PropType<UploadFileParseValue>,
    },
  });

  const emit = defineEmits(['update:value']);

  const fileList = ref<Record<'uid' | 'name', string>[]>([]);

  interface FileRequestParams {
    file: File & { uid: string };
    onSuccess: Fn;
    onProgress: Fn;
    onError: Fn;
    status: string;
  }

  const readFile = async (file: File): Promise<UploadFileParseValue | boolean> => {
    /**
     * @description 读取表头
     * @param sheet 工作表
     * @param range 区间
     * @param headerRow 表头行
     */
    const getTableHeader = (sheet: XLSX.WorkSheet, range: [number, number], headerRow = 1) => {
      const [startColumn, endColumn] = range;
      const header: string[] = [];
      for (let i = startColumn; i <= endColumn; i++) {
        const columnIndex = XLSX.utils.encode_col(i) + headerRow;
        const value = (sheet[columnIndex] as CellObject).v;
        header.push(value as string);
      }
      return header;
    };

    return new Promise((resolve, reject) => {
      const fileReader = new FileReader();
      fileReader.onload = (event: ProgressEvent) => {
        const data = (event.target as FileReader).result as string;
        const result = XLSX.read(data, { type: 'string' });

        const sheetName = result.SheetNames.at(0);
        const workbook = result.Sheets;
        const sheet = workbook[sheetName as string];
        const sheetRange = sheet['!ref'];

        const {
          s: { c: startColumn },
          e: { c: endColumn },
        } = XLSX.utils.decode_range(sheetRange!);

        const header = getTableHeader(sheet, [startColumn, endColumn]);
        const content = XLSX.utils.sheet_to_json(sheet, { range: sheetRange }) as Recordable[];
        resolve({ header, content });
      };

      fileReader.onerror = () => {
        reject(false);
      };
      fileReader.readAsText(file);
    });
  };

  const handleParseFile = async ({ file, onSuccess, onError }: FileRequestParams) => {
    fileList.value = [];
    const value = await readFile(file);
    if (!value) {
      onError();
      return;
    }
    fileList.value = [file];
    emit('update:value', value);
    onSuccess({}, file);
  };

  const canGoNextStep = computed(() => {
    return !!fileList.value.length;
  });

  const handlePreviousStep = () => {
    props.goPreviousStep?.();
  };

  const handleNextStep = () => {
    props.goNextStep?.();
  };
</script>

<template>
  <StepContainer>
    <div class="">设备文件</div>
    <Upload.Dragger :fileList="fileList" :customRequest="handleParseFile" accept=".csv" name="file">
      <section class="cursor-pointer flex flex-col justify-center items-center">
        <InboxOutlined class="text-[4rem] !text-blue-400" />
        <div class="text-gray-500">点击上传或拖拽上传</div>
      </section>
    </Upload.Dragger>
    <div class="flex justify-end gap-4 mt-4">
      <Button type="primary" @click="handlePreviousStep">上一步</Button>
      <Button type="primary" @click="handleNextStep" :disabled="!canGoNextStep">下一步</Button>
    </div>
  </StepContainer>
</template>
