<script lang="ts" setup>
/**
 * 通用文件预览：图片用 Ant Image；PDF fetch→blob→iframe；支持多文件切换
 * 开票中心与素材库复用，避免两套预览逻辑
 */
import { computed, onBeforeUnmount, ref, watch } from 'vue';

import { Button, Image, Modal, Spin, message } from 'ant-design-vue';

const props = withDefaults(
  defineProps<{
    /** 是否显示 */
    open: boolean;
    /** 文件 URL 列表 */
    files?: string[];
    /** 弹窗标题前缀 */
    title?: string;
  }>(),
  {
    files: () => [],
    title: '文件预览',
  },
);

const emit = defineEmits<{
  (e: 'update:open', v: boolean): void;
}>();

const currentIndex = ref(0);
const previewIsImage = ref(false);
const previewImageUrl = ref('');
const previewPdfUrl = ref('');
const previewLoading = ref(false);

const visible = computed({
  get: () => props.open,
  set: (v: boolean) => emit('update:open', v),
});

const currentUrl = computed(() => props.files?.[currentIndex.value] || '');

const displayTitle = computed(() => {
  const name = (currentUrl.value || '').split('/').pop() || '';
  const total = props.files?.length || 0;
  if (total > 1) {
    return `${props.title}（${currentIndex.value + 1}/${total}）${name ? ' - ' + name : ''}`;
  }
  return name ? `${props.title} - ${name}` : props.title;
});

function isImageUrl(url: string) {
  return /\.(jpg|jpeg|png|gif|webp|bmp)(\?|$)/i.test(url || '');
}

function revokePdfBlob() {
  if (previewPdfUrl.value && previewPdfUrl.value.startsWith('blob:')) {
    URL.revokeObjectURL(previewPdfUrl.value);
  }
  previewPdfUrl.value = '';
}

/**
 * 加载当前文件到预览区
 */
async function loadCurrent() {
  const url = currentUrl.value;
  revokePdfBlob();
  if (!url) {
    message.info('暂无文件');
    visible.value = false;
    return;
  }
  if (isImageUrl(url)) {
    previewIsImage.value = true;
    previewImageUrl.value = url;
    previewLoading.value = false;
    return;
  }
  previewIsImage.value = false;
  previewLoading.value = true;
  try {
    const resp = await fetch(url);
    if (!resp.ok) throw new Error('文件加载失败');
    const blob = await resp.blob();
    const pdfBlob =
      blob.type && blob.type !== 'application/octet-stream'
        ? blob
        : new Blob([blob], { type: 'application/pdf' });
    previewPdfUrl.value = URL.createObjectURL(pdfBlob);
  } catch {
    message.error('预览失败，请尝试下载后查看');
    visible.value = false;
  } finally {
    previewLoading.value = false;
  }
}

function prevFile() {
  if (currentIndex.value > 0) {
    currentIndex.value -= 1;
  }
}

function nextFile() {
  if (props.files && currentIndex.value < props.files.length - 1) {
    currentIndex.value += 1;
  }
}

function handleClose() {
  visible.value = false;
}

watch(
  () => [props.open, props.files] as const,
  ([open]) => {
    if (open) {
      currentIndex.value = 0;
      loadCurrent();
    } else {
      revokePdfBlob();
    }
  },
);

watch(currentIndex, () => {
  if (props.open) {
    loadCurrent();
  }
});

onBeforeUnmount(() => {
  revokePdfBlob();
});
</script>

<template>
  <Modal
    v-model:open="visible"
    :title="displayTitle"
    :footer="null"
    width="860px"
    destroy-on-close
    @cancel="handleClose"
  >
    <div class="preview-wrap">
      <div v-if="(files?.length || 0) > 1" class="nav">
        <Button size="small" :disabled="currentIndex <= 0" @click="prevFile">上一份</Button>
        <Button
          size="small"
          :disabled="currentIndex >= (files?.length || 0) - 1"
          @click="nextFile"
        >
          下一份
        </Button>
      </div>
      <Spin :spinning="previewLoading">
        <div v-if="previewIsImage" class="img-box">
          <Image :src="previewImageUrl" :preview="true" style="max-width: 100%" />
        </div>
        <iframe
          v-else-if="previewPdfUrl"
          :src="previewPdfUrl"
          class="pdf-frame"
          title="pdf-preview"
        />
      </Spin>
    </div>
  </Modal>
</template>

<style scoped>
.preview-wrap {
  min-height: 240px;
  color: hsl(var(--foreground));
}
.nav {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}
.img-box {
  text-align: center;
  padding: 8px;
  border-radius: 8px;
  background: hsl(var(--muted) / 0.25);
  border: 1px solid hsl(var(--border));
}
.pdf-frame {
  width: 100%;
  height: 70vh;
  border: 1px solid hsl(var(--border));
  border-radius: 8px;
  background: hsl(var(--background));
}
</style>
