<script lang="ts" setup>
/**
 * 金方 Excel 导入选文件弹窗
 * - 点击 / 拖拽：UploadDragger
 * - 粘贴：点「开始监听粘贴」后 Ctrl+V，成功拿到文件后自动结束监听
 * 确认后由父级解析并打开预览弹窗
 */
import { ref } from 'vue';

import { useVbenModal } from '@vben/common-ui';

import { InboxOutlined } from '@ant-design/icons-vue';
import {
  Button,
  UploadDragger,
  message,
  type UploadFile,
} from 'ant-design-vue';

import { usePasteUploadListen } from '#/utils/use-paste-upload-listen';

const ACCEPT = '.xlsx,.xls';
const selectedFile = ref<File | null>(null);
const fileList = ref<UploadFile[]>([]);
/** 父级传入：选中文件确认后回调（解析 Excel） */
const onConfirmFile = ref<null | ((file: File) => void | Promise<void>)>(null);

const {
  listening: pasteListening,
  start: startPasteListen,
  stop: stopPasteListen,
} = usePasteUploadListen({
  accept: ACCEPT,
  // Excel 体积放宽到 30MB
  maxSize: 30 * 1024 * 1024,
  autoStopOnSuccess: true,
  onFiles: (files) => {
    const file = files[0];
    if (!file) return;
    applySelectedFile(file);
  },
});

const [Modal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel() {
    resetState();
    modalApi.close();
  },
  onConfirm: async () => {
    if (!selectedFile.value) {
      message.warning('请先选择、拖入或粘贴 Excel 文件');
      return;
    }
    const file = selectedFile.value;
    const cb = onConfirmFile.value;
    modalApi.setState({ confirmLoading: true });
    try {
      if (typeof cb === 'function') {
        await cb(file);
      }
      // 解析成功才关弹窗；失败则保留文件便于重选/重试
      resetState();
      modalApi.close();
    } catch {
      // 错误提示由父级 handleImportFile 负责
    } finally {
      modalApi.setState({ confirmLoading: false });
    }
  },
  onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      resetState();
      return;
    }
    const data = modalApi.getData<{
      onConfirmFile?: (file: File) => void | Promise<void>;
    }>() || {};
    onConfirmFile.value =
      typeof data.onConfirmFile === 'function' ? data.onConfirmFile : null;
  },
});

/** 重置选中与粘贴监听 */
function resetState() {
  selectedFile.value = null;
  fileList.value = [];
  onConfirmFile.value = null;
  stopPasteListen();
}

/** 统一写入选中文件（点击/拖拽/粘贴共用） */
function applySelectedFile(file: File) {
  const name = (file.name || '').toLowerCase();
  if (!name.endsWith('.xlsx') && !name.endsWith('.xls')) {
    message.warning('仅支持 .xlsx / .xls 文件');
    return;
  }
  selectedFile.value = file;
  fileList.value = [
    {
      uid: `gf-${Date.now()}`,
      name: file.name,
      status: 'done',
      originFileObj: file as any,
    },
  ];
  message.success(`已选择：${file.name}`);
}

/**
 * Dragger 选中变化：before-upload 已拦截实际上传，这里只取本地 File
 */
function handleChange(info: { file: UploadFile; fileList: UploadFile[] }) {
  const { file } = info;
  if (file.status === 'removed') {
    selectedFile.value = null;
    fileList.value = [];
    return;
  }
  const raw = (file.originFileObj || file) as File;
  if (raw instanceof File) {
    applySelectedFile(raw);
  }
}

/** 切换粘贴监听：开始时提示；手动停止时也提示 */
function handlePasteListenClick() {
  if (pasteListening.value) {
    stopPasteListen();
    message.info('已停止粘贴监听');
    return;
  }
  startPasteListen();
  message.success('已开启粘贴监听，请 Ctrl+V 粘贴 Excel（成功后自动结束）');
}
</script>
<template>
  <Modal title="导入金方 Excel" class="w-[560px]">
    <div v-if="selectedFile" class="gf-import-selected">
      已选择文件：{{ selectedFile.name }}
    </div>
    <UploadDragger
      v-model:file-list="fileList"
      :before-upload="() => false"
      :max-count="1"
      :accept="ACCEPT"
      name="file"
      @change="handleChange"
    >
      <p class="gf-import-icon">
        <InboxOutlined />
      </p>
      <p class="ant-upload-text">点击或拖拽 Excel 到此区域</p>
      <p class="ant-upload-hint">仅支持 .xlsx / .xls，确认后进入导入预览</p>
    </UploadDragger>
    <div class="gf-import-paste">
      <Button
        :type="pasteListening ? 'primary' : 'default'"
        :danger="pasteListening"
        @click="handlePasteListenClick"
      >
        {{ pasteListening ? '停止监听粘贴' : '开始监听粘贴' }}
      </Button>
      <span v-if="pasteListening" class="gf-import-paste-tip">
        监听中：Ctrl+V 粘贴 Excel，成功后自动结束
      </span>
      <span v-else class="gf-import-paste-tip">
        也可点击开始监听后粘贴文件
      </span>
    </div>
  </Modal>
</template>
<style scoped>
.gf-import-selected {
  margin-bottom: 12px;
  padding: 10px 12px;
  border: 1px solid hsl(var(--primary) / 0.35);
  border-radius: 8px;
  background: hsl(var(--primary) / 0.08);
  color: hsl(var(--foreground));
  font-size: 13px;
}
.gf-import-icon {
  display: flex;
  justify-content: center;
  margin-bottom: 8px;
  font-size: 48px;
  color: hsl(var(--primary));
}
.gf-import-paste {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
}
.gf-import-paste-tip {
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}
</style>
