<template>
  <div class="source-file-preview">
    <div class="d-flex flex-column" style="height: 100%;" elevation="5">
      <div class="d-flex justify-end mr-3 my-3">
        <v-btn color="primary" small @click="handleViewParsedData">
          <v-icon left>mdi-table-eye</v-icon>
          查看解析数据
        </v-btn>
      </div>
      <div class="preview-content" v-loading="loading">
        <!-- Excel 预览 -->
        <ExcelPage
          v-if="fileType === 'xls' || fileType === 'xlsx'"
          ref="excelPage"
          :data-source="fileData"
          :render-sheet="false"
        ></ExcelPage>

        <!-- PDF 预览 -->
        <iframe v-else-if="fileType === 'pdf'" :src="pdfUrl" style="width: 100%; height: 100%; border: none;"></iframe>

        <!-- DOCX 预览 -->
        <div v-else-if="fileType === 'docx'" ref="docxContainer" class="docx-container"></div>

        <!-- SQL 预览 -->
        <div v-else-if="fileType === 'sql'" class="sql-preview" v-html="highlightedSql"></div>

        <!-- TXT 预览 -->
        <div v-else-if="fileType === 'txt'" class="txt-preview">{{ txtContent }}</div>

        <!-- 不支持的文件类型 -->
        <div v-else class="d-flex align-center justify-center" style="height: 100%;">
          <div class="text-center">
            <v-icon size="64" color="grey">mdi-file-question</v-icon>
            <div class="mt-4 grey--text">不支持的文件类型</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import ExcelPage from './excel.vue'
import hljs from 'highlight.js'
import 'highlight.js/styles/monokai.css'
import { renderAsync } from 'docx-preview'
import { handleReadFile } from '@/utils/file'

export default {
  name: 'SourceFilePreview',
  components: {
    ExcelPage
  },
  props: {
    file: {
      type: File,
      default: null
    },
    fileType: {
      type: String,
      default: null
    },
    fileUrl: {
      type: String,
      default: null
    }
  },
  data () {
    return {
      loading: false,
      fileData: null,
      pdfUrl: null,
      sqlContent: '',
      txtContent: '',
      currentFile: null // 内部文件对象，避免直接修改 prop
    }
  },
  computed: {
    highlightedSql () {
      if (!this.sqlContent) {
        return ''
      }
      try {
        // highlight.js 9.x 版本使用 highlight 方法
        const result = hljs.highlight('sql', this.sqlContent)
        return `<pre><code class="hljs sql">${result.value}</code></pre>`
      } catch (error) {
        console.error('SQL 高亮错误:', error)
        // 如果高亮失败，返回转义后的纯文本
        return `<pre><code>${this.escapeHtml(this.sqlContent)}</code></pre>`
      }
    }
  },
  watch: {
    file: {
      handler (val) {
        if (val) {
          this.currentFile = val
          this.loadFile()
        }
      },
      immediate: true
    },
    fileUrl: {
      handler (val) {
        if (val && !this.file) {
          this.loadFileFromUrl()
        }
      },
      immediate: true
    }
  },
  methods: {
    async loadFile () {
      const fileToLoad = this.currentFile || this.file
      if (!fileToLoad) {
        return
      }

      this.loading = true
      try {
        if (this.fileType === 'xls' || this.fileType === 'xlsx') {
          // Excel 文件处理
          if (this.fileType === 'xls') {
            // xls 文件需要转换为 xlsx
            handleReadFile(fileToLoad, 'xls', (result) => {
              // result 是转换后的 File 对象
              this.fileData = result
              this.loading = false
            })
          } else {
            // xlsx 文件直接传递 File 对象，@vue-office/excel 支持 File
            this.fileData = fileToLoad
            this.loading = false
          }
        } else if (this.fileType === 'pdf') {
          // PDF 文件
          this.pdfUrl = URL.createObjectURL(fileToLoad)
          this.loading = false
        } else if (this.fileType === 'docx') {
          // DOCX 文件
          await this.renderDocx(fileToLoad)
          this.loading = false
        } else if (this.fileType === 'sql') {
          // SQL 文件
          const reader = new FileReader()
          reader.onload = (e) => {
            this.sqlContent = e.target.result
            this.loading = false
          }
          reader.onerror = () => {
            this.$snackbar.error('文件读取失败')
            this.loading = false
          }
          reader.readAsText(fileToLoad, 'UTF-8')
        } else if (this.fileType === 'txt') {
          // TXT 文件
          const reader = new FileReader()
          reader.onload = (e) => {
            this.txtContent = e.target.result
            this.loading = false
          }
          reader.onerror = () => {
            this.$snackbar.error('文件读取失败')
            this.loading = false
          }
          reader.readAsText(fileToLoad, 'UTF-8')
        }
      } catch (error) {
        console.error('文件加载错误:', error)
        this.$snackbar.error('文件加载失败')
        this.loading = false
      }
    },
    async loadFileFromUrl () {
      if (!this.fileUrl) {
        return
      }

      this.loading = true
      try {
        const { api } = await import('@/api/dataGovernance')
        const { data } = await api.downloadFile({ url: this.fileUrl })

        // 根据文件类型创建 File 对象
        const blob = new Blob([data], { type: this.getMimeType(this.fileType) })
        const file = new File([blob], this.fileUrl.split('/').pop(), { type: blob.type })

        // 使用内部变量存储文件对象，避免直接修改 prop
        this.currentFile = file
        await this.loadFile()
      } catch (error) {
        console.error('从URL加载文件错误:', error)
        this.$snackbar.error('文件加载失败')
        this.loading = false
      }
    },
    async renderDocx (file) {
      try {
        const arrayBuffer = await file.arrayBuffer()
        await renderAsync(arrayBuffer, this.$refs.docxContainer)
      } catch (error) {
        console.error('DOCX 渲染错误:', error)
        this.$snackbar.error('DOCX 文件预览失败')
      }
    },
    getMimeType (fileType) {
      const mimeTypes = {
        pdf: 'application/pdf',
        docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        xls: 'application/vnd.ms-excel',
        xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        sql: 'text/plain',
        txt: 'text/plain'
      }
      return mimeTypes[fileType] || 'application/octet-stream'
    },
    handleViewParsedData () {
      this.$emit('viewParsedData')
    },
    escapeHtml (text) {
      const div = document.createElement('div')
      div.textContent = text
      return div.innerHTML
    }
  },
  beforeDestroy () {
    // 清理 PDF URL
    if (this.pdfUrl) {
      URL.revokeObjectURL(this.pdfUrl)
    }
  }
}
</script>

<style lang="scss" scoped>
.source-file-preview {
  width: 100%;
  height: 100%;
}

.preview-content {
  flex: 1;
  overflow: hidden;
  position: relative;
  min-height: 0;

  // 确保 ExcelPage 有正确的高度
  > div {
    height: 100%;
  }
}

.docx-container {
  width: 100%;
  height: 100%;
  overflow: auto;
  padding: 20px;
}

.sql-preview {
  width: 100%;
  height: 100%;
  overflow: auto;
  padding: 16px;
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
  line-height: 1.5;

  ::v-deep pre {
    margin: 0;
    padding: 0;
    background: transparent;
    border: none;
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
    height: 100%;
  }

  ::v-deep code {
    display: block;
    width: 100%;
    padding: 0;
    margin: 0;
    background: transparent;
    border: none;
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
    white-space: pre;
    overflow-wrap: normal;
    overflow-x: auto;
  }
}

.txt-preview {
  width: 100%;
  height: 100%;
  overflow: auto;
  padding: 16px;
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.title {
  color: #1976D2;
  font-weight: 600;
}
</style>
