<script setup lang="ts">
/**
 * 文件预览组件（主入口）
 *
 * 渲染策略：
 *  1. image / video / audio  →  MediaPreview（原生标签）
 *  2. text                   →  TextPreview（<pre>）
 *  3. pdf / docx / xlsx      →  OfficePreview（@vue-office），失败自动降级到 KkPreview
 *  4. doc / xls / unsupported  →  直接走 KkPreview
 */
import type { PreviewFileKind } from '@af-mobile-client-vue3/utils/fileType'
import { getPreviewFileKind } from '@af-mobile-client-vue3/utils/fileType'
import {
  fetchResourceArrayBuffer,
  fetchResourceText,
  getPreviewPath,
  resolveResourceUrl,
} from '@af-mobile-client-vue3/utils/resourceUrl'
import { Empty as VanEmpty, Loading as VanLoading } from 'vant'
import { ref, shallowRef } from 'vue'
import KkPreview from './components/KkPreview.vue'
import MediaPreview from './components/MediaPreview.vue'
import OfficePreview from './components/OfficePreview.vue'
import TextPreview from './components/TextPreview.vue'

export interface FilePreviewInitOptions {
  /** 后端 f_downloadpath 或完整 URL */
  path: string
  /** 文件名（可选，默认从路径提取） */
  name?: string
}

/** 优先走 @vue-office，失败降级 kk */
const OFFICE_KINDS: PreviewFileKind[] = ['pdf', 'docx', 'xlsx']

/**
 * 直接走 kk 预览的格式：
 *  - doc / xls  旧二进制格式，@vue-office 无法解析
 *  - unsupported  未知格式，交给 kkFileView 服务端判断
 */
const KK_ONLY_KINDS: PreviewFileKind[] = ['doc', 'xls', 'unsupported']

const kind = ref<PreviewFileKind>('unsupported')
const fileSource = shallowRef<string | ArrayBuffer>('')
const textContent = ref('')
const mediaSrc = ref('')
const rawPath = ref('') // 文件相对路径（kk 预览用）
const loading = ref(false)
const errorMsg = ref('')
/** true = office 渲染失败，已降级到 kk 预览 */
const officeFailed = ref(false)

function onOfficeFailed() {
  officeFailed.value = true
}

async function init(options: FilePreviewInitOptions) {
  const path = getPreviewPath(options.path)
  if (!path) {
    errorMsg.value = '文件路径为空'
    return
  }

  const rawUrl = resolveResourceUrl(path)
  kind.value = getPreviewFileKind(path)
  rawPath.value = path
  loading.value = true
  errorMsg.value = ''
  officeFailed.value = false
  fileSource.value = ''
  textContent.value = ''
  mediaSrc.value = ''

  try {
    if (['image', 'video', 'audio'].includes(kind.value)) {
      mediaSrc.value = rawUrl
    }
    else if (kind.value === 'text') {
      textContent.value = await fetchResourceText(rawUrl)
    }
    else if (OFFICE_KINDS.includes(kind.value)) {
      fileSource.value = await fetchResourceArrayBuffer(rawUrl)
    }
    // doc / xls / unsupported 直接走 KkPreview，无需预加载
  }
  catch (e: any) {
    errorMsg.value = e?.message || '文件加载失败'
  }
  finally {
    loading.value = false
  }
}

defineExpose({ init })
</script>

<template>
  <div class="file-preview-root">
    <!-- 加载中 -->
    <VanLoading v-if="loading" class="preview-loading" type="spinner" vertical>
      加载中...
    </VanLoading>

    <!-- 加载/解析出错 -->
    <VanEmpty v-else-if="errorMsg" :description="errorMsg" />

    <template v-else>
      <MediaPreview
        v-if="kind === 'image' || kind === 'video' || kind === 'audio'"
        :kind="kind"
        :src="mediaSrc"
      />

      <TextPreview
        v-else-if="kind === 'text'"
        :content="textContent"
      />

      <!-- office：先 @vue-office，失败降级 kk -->
      <OfficePreview
        v-else-if="OFFICE_KINDS.includes(kind) && fileSource && !officeFailed"
        :kind="kind"
        :src="fileSource"
        @error="onOfficeFailed"
      />

      <!-- kk 预览：office 降级 或 doc/xls/unsupported 直接走 -->
      <KkPreview
        v-else-if="officeFailed || KK_ONLY_KINDS.includes(kind)"
        :file-path="rawPath"
      />

      <VanEmpty v-else description="文件路径异常" />
    </template>
  </div>
</template>

<style scoped>
.file-preview-root {
  width: 100%;
  height: 100%;
  min-height: 200px;
  display: flex;
  flex-direction: column;
  background: #fff;
  overflow: hidden;
}

.preview-loading {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
