<template>
  <div class="app-container">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>知识库详情：{{ knowledgeInfo.knowledgeName }}</span>
        <el-button style="float: right; padding: 3px 0" type="text" @click="goBack">返回</el-button>
      </div>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="知识库名称">{{ knowledgeInfo.knowledgeName }}</el-descriptions-item>
        <el-descriptions-item label="知识库描述">{{ knowledgeInfo.knowledgeDesc || '无' }}</el-descriptions-item>
        <el-descriptions-item label="文件数量">{{ knowledgeInfo.fileCount || 0 }}</el-descriptions-item>
        <el-descriptions-item label="状态">
          <dict-tag :options="dict.type.sys_normal_disable" :value="knowledgeInfo.status"/>
        </el-descriptions-item>
        <el-descriptions-item label="创建时间">{{ parseTime(knowledgeInfo.createTime) }}</el-descriptions-item>
        <el-descriptions-item label="备注">{{ knowledgeInfo.remark || '无' }}</el-descriptions-item>
      </el-descriptions>
    </el-card>

    <el-card class="box-card" style="margin-top: 20px">
      <div slot="header" class="clearfix">
        <span>文件列表</span>
        <el-button 
          style="float: right; padding: 3px 0" 
          type="text" 
          @click="handleUpload"
          v-hasPermi="['flood:knowledge:add']"
        >上传文件</el-button>
      </div>

      <el-table v-loading="fileLoading" :data="fileList" border>
        <el-table-column label="序号" type="index" width="60" align="center" />
        <el-table-column label="原始文件名" prop="originalName" :show-overflow-tooltip="true" />
        <el-table-column label="文件类型" prop="fileType" width="100" align="center" />
        <el-table-column label="文件大小" prop="fileSize" width="120" align="center">
          <template slot-scope="scope">
            {{ formatFileSize(scope.row.fileSize) }}
          </template>
        </el-table-column>
        <el-table-column label="上传时间" prop="createTime" width="180" align="center">
          <template slot-scope="scope">
            <span>{{ parseTime(scope.row.createTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200" align="center" class-name="small-padding fixed-width">
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="text"
              icon="el-icon-view"
              @click="handlePreview(scope.row)"
            >预览</el-button>
            <el-button
              size="mini"
              type="text"
              icon="el-icon-download"
              @click="handleDownload(scope.row)"
            >下载</el-button>
            <el-button
              size="mini"
              type="text"
              icon="el-icon-delete"
              @click="handleDeleteFile(scope.row)"
              v-hasPermi="['flood:knowledge:remove']"
            >删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 文件上传对话框 -->
    <el-dialog title="上传文件" :visible.sync="uploadOpen" width="600px" append-to-body>
      <el-upload
        ref="upload"
        :action="uploadUrl"
        :headers="uploadHeaders"
        :data="uploadData"
        :file-list="fileList2"
        :on-success="handleUploadSuccess"
        :on-error="handleUploadError"
        :before-upload="beforeUpload"
        :on-remove="handleRemove"
        multiple
        drag
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <div class="el-upload__tip" slot="tip">支持图片、PDF、Word、PPT等格式，单个文件不超过200MB</div>
      </el-upload>
      <div slot="footer" class="dialog-footer">
        <el-button @click="uploadOpen = false">取 消</el-button>
        <el-button type="primary" @click="submitUpload">确 定</el-button>
      </div>
    </el-dialog>

    <!-- 文件预览对话框 -->
    <el-dialog 
      :title="'文件预览：' + (previewFile ? previewFile.originalName : '')" 
      :visible.sync="previewOpen" 
      width="90%" 
      append-to-body
      :close-on-click-modal="false"
    >
      <div v-if="previewFile" style="text-align: center; min-height: 500px;">
        <!-- 图片预览 -->
        <el-image
          v-if="isImage(previewFile.fileType)"
          :src="previewFile.fileUrl"
          fit="contain"
          style="max-width: 100%; max-height: 70vh;"
          :preview-src-list="[previewFile.fileUrl]"
        />
        <!-- PDF预览 -->
        <div v-else-if="isPdf(previewFile.fileType)" style="width: 100%; height: 70vh; position: relative;">
          <!-- 使用blob URL预览PDF，支持认证 -->
          <iframe
            v-if="!pdfError && pdfBlobUrl"
            :src="pdfBlobUrl"
            style="width: 100%; height: 100%; border: none;"
            frameborder="0"
            @error="handlePdfError"
          ></iframe>
          <!-- 加载中 -->
          <div v-if="pdfLoading" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center;">
            <i class="el-icon-loading" style="font-size: 40px; color: #409EFF;"></i>
            <p style="margin-top: 20px; color: #606266;">正在加载PDF文件...</p>
          </div>
          <!-- 错误提示 -->
          <div v-if="pdfError" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; width: 100%; z-index: 10; background: white; padding: 40px;">
            <i class="el-icon-warning" style="font-size: 60px; color: #E6A23C;"></i>
            <p style="margin-top: 20px; color: #606266; font-size: 16px;">PDF预览失败，请尝试下载后查看</p>
            <p style="margin-top: 10px; color: #909399; font-size: 14px;">如果文件较大，可能需要等待加载</p>
            <el-button type="primary" @click="retryPdfPreview" style="margin-top: 20px; margin-right: 10px;">重试</el-button>
            <el-button type="success" @click="handleDownload(previewFile)" style="margin-top: 20px;">下载文件</el-button>
            <!-- 备选方案：在新窗口打开 -->
            <el-button type="info" @click="openPdfInNewWindow" style="margin-top: 20px; margin-left: 10px;">在新窗口打开</el-button>
          </div>
        </div>
        <!-- Office文件预览（Word、Excel、PPT）- 使用 kkFileView -->
        <div v-else-if="isOfficeFile(previewFile.fileType)" style="width: 100%; height: 70vh; position: relative;">
          <!-- 使用 kkFileView 预览 -->
          <iframe
            v-if="!officeError && officePreviewUrl"
            :src="officePreviewUrl"
            style="width: 100%; height: 100%; border: none;"
            frameborder="0"
            @error="handleOfficeError"
            @load="handleOfficeLoad"
          ></iframe>
          <!-- 加载中 -->
          <div v-if="officeLoading" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; z-index: 5; background: rgba(255, 255, 255, 0.9); padding: 30px; border-radius: 8px;">
            <i class="el-icon-loading" style="font-size: 40px; color: #409EFF;"></i>
            <p style="margin-top: 20px; color: #606266;">正在加载文件预览...</p>
            <p style="margin-top: 10px; color: #909399; font-size: 12px;">首次加载可能需要较长时间</p>
          </div>
          <!-- 错误提示 -->
          <div v-if="officeError" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; width: 90%; max-width: 600px; z-index: 10; background: white; padding: 40px; border-radius: 8px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);">
            <i class="el-icon-warning" style="font-size: 60px; color: #E6A23C;"></i>
            <p style="margin-top: 20px; color: #606266; font-size: 16px;">文件预览失败</p>
            <p style="margin-top: 10px; color: #909399; font-size: 14px;">kkFileView 服务可能未启动或无法访问</p>
            <div style="margin-top: 30px;">
              <el-button type="primary" @click="retryOfficePreview" style="margin-right: 10px;">重试预览</el-button>
              <el-button type="success" @click="handleDownload(previewFile)">下载文件</el-button>
              <el-button type="info" @click="openOfficeInNewWindow" style="margin-left: 10px;">在新窗口打开</el-button>
            </div>
          </div>
        </div>
        <!-- 其他文件类型 -->
        <div v-else style="padding: 40px;">
          <i class="el-icon-document" style="font-size: 100px; color: #909399;"></i>
          <p style="margin-top: 20px; color: #606266; font-size: 16px;">{{ previewFile.originalName }}</p>
          <p style="margin-top: 10px; color: #909399; font-size: 14px;">该文件类型暂不支持在线预览</p>
          <el-button type="primary" @click="handleDownload(previewFile)" style="margin-top: 20px;">下载文件</el-button>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button @click="handleDownload(previewFile)" v-if="previewFile">下载</el-button>
        <el-button @click="previewOpen = false">关 闭</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getKnowledge } from "@/api/flood/knowledge";
import { listKnowledgeFiles, delKnowledgeFile, getKkFileViewUrl } from "@/api/flood/knowledge";
import { getToken } from "@/utils/auth";
import request from "@/utils/request";

export default {
  name: "KnowledgeDetail",
  dicts: ['sys_normal_disable'],
  data() {
    return {
      knowledgeId: null,
      knowledgeInfo: {},
      fileList: [],
      fileLoading: false,
      uploadOpen: false,
      previewOpen: false,
      previewFile: null,
      pdfError: false,
      pdfLoading: false,
      pdfBlobUrl: null,
      officeError: false,
      officeLoading: false,
      officePreviewUrl: null,
      uploadUrl: process.env.VUE_APP_BASE_API + "/flood/knowledge/upload",
      uploadHeaders: {
        Authorization: "Bearer " + getToken()
      },
      uploadData: {
        knowledgeId: null
      },
      fileList2: []
    };
  },
  created() {
    this.knowledgeId = this.$route.query.knowledgeId;
    if (this.knowledgeId) {
      this.getKnowledgeInfo();
      this.getFileList();
    }
  },
  methods: {
    /** 获取知识库信息 */
    getKnowledgeInfo() {
      getKnowledge(this.knowledgeId).then(response => {
        this.knowledgeInfo = response.data;
      });
    },
    /** 获取文件列表 */
    getFileList() {
      this.fileLoading = true;
      listKnowledgeFiles(this.knowledgeId).then(response => {
        this.fileList = response.data;
        this.fileLoading = false;
      });
    },
    /** 上传文件 */
    handleUpload() {
      this.uploadData.knowledgeId = this.knowledgeId;
      this.uploadOpen = true;
      this.fileList2 = [];
    },
    /** 提交上传 */
    submitUpload() {
      this.$refs.upload.submit();
    },
    /** 上传成功 */
    handleUploadSuccess(response, file, fileList) {
      if (response.code === 200) {
        this.$modal.msgSuccess("上传成功");
        this.uploadOpen = false;
        this.getFileList();
        this.getKnowledgeInfo(); // 刷新知识库信息
      } else {
        this.$modal.msgError(response.msg || "上传失败");
      }
    },
    /** 上传失败 */
    handleUploadError(err, file, fileList) {
      this.$modal.msgError("上传失败：" + (err.message || "未知错误"));
    },
    /** 上传前校验 */
    beforeUpload(file) {
      const maxSize = 200; // 200MB
      const fileSizeMB = file.size / 1024 / 1024;
      if (fileSizeMB > maxSize) {
        this.$modal.msgError(`上传文件大小不能超过 ${maxSize}MB! 当前文件大小: ${fileSizeMB.toFixed(2)}MB`);
        return false;
      }
      return true;
    },
    /** 移除文件 */
    handleRemove(file, fileList) {
      this.fileList2 = fileList;
    },
    /** 预览文件 */
    handlePreview(row) {
      this.previewFile = row;
      this.previewOpen = true;
      this.pdfError = false; // 重置PDF错误状态
      this.pdfBlobUrl = null; // 重置blob URL
      this.officeError = false; // 重置Office错误状态
      this.officePreviewUrl = null; // 重置Office预览URL
      
      // 如果是PDF文件，需要先加载
      if (this.isPdf(row.fileType)) {
        this.loadPdfFile(row.fileId);
      } else if (this.isOfficeFile(row.fileType)) {
        // Office文件使用在线预览
        this.loadOfficeFile(row);
      }
    },
    /** 关闭预览对话框 */
    handlePreviewClose() {
      // 释放blob URL，避免内存泄漏
      if (this.pdfBlobUrl) {
        URL.revokeObjectURL(this.pdfBlobUrl);
        this.pdfBlobUrl = null;
      }
      if (this.officePreviewUrl && this.officePreviewUrl.startsWith('blob:')) {
        URL.revokeObjectURL(this.officePreviewUrl);
        this.officePreviewUrl = null;
      }
      this.pdfError = false;
      this.pdfLoading = false;
      this.officeError = false;
      this.officeLoading = false;
    },
    /** 判断是否为图片 */
    isImage(fileType) {
      const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
      return imageTypes.includes(fileType.toLowerCase());
    },
    /** 判断是否为PDF */
    isPdf(fileType) {
      return fileType && fileType.toLowerCase() === 'pdf';
    },
    /** 判断是否为Office文件（Word、Excel、PPT） */
    isOfficeFile(fileType) {
      if (!fileType) return false;
      const lowerType = fileType.toLowerCase();
      return ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(lowerType);
    },
    /** 获取PDF预览URL（处理跨域和编码问题） */
    getPdfUrl(fileUrl) {
      if (!fileUrl) return '';
      // 如果URL已经包含参数，使用&连接，否则使用?
      const separator = fileUrl.includes('?') ? '&' : '?';
      // 添加参数以确保PDF正确显示
      return fileUrl + separator + '#toolbar=1&navpanes=1&scrollbar=1';
    },
    /** 获取PDF预览URL（使用后端代理接口，支持认证） */
    getPdfPreviewUrl(fileId) {
      if (!fileId) return '';
      // 使用后端代理接口，这样可以传递认证信息
      return process.env.VUE_APP_BASE_API + '/flood/knowledge/previewPdf/' + fileId;
    },
    /** 加载PDF文件（通过axios获取，自动携带token） */
    loadPdfFile(fileId) {
      if (!fileId) {
        this.pdfError = true;
        return;
      }
      
      this.pdfLoading = true;
      this.pdfError = false;
      
      // 通过axios获取PDF文件，会自动携带Authorization头
      request({
        url: '/flood/knowledge/preview/' + fileId,
        method: 'get',
        responseType: 'blob', // 重要：指定响应类型为blob
        timeout: 300000 // 5分钟超时，支持大文件
      }).then(response => {
        // 创建blob URL
        const blob = new Blob([response], { type: 'application/pdf' });
        this.pdfBlobUrl = URL.createObjectURL(blob);
        this.pdfLoading = false;
      }).catch(error => {
        this.pdfLoading = false;
        this.pdfError = true;
        console.error('加载PDF文件失败', error);
        this.$modal.msgError('PDF文件加载失败，请尝试下载后查看');
      });
    },
    /** 加载Office文件（使用 kkFileView 预览） */
    loadOfficeFile(file) {
      if (!file || !file.fileId) {
        this.officeError = true;
        return;
      }
      
      this.officeLoading = true;
      this.officeError = false;
      
      // 获取当前用户的token，用于文件预览认证
      const token = getToken();
      
      // 调用后端接口获取 kkFileView 预览URL
      getKkFileViewUrl(file.fileId, token).then(response => {
        // 注意：响应拦截器已经返回 res.data，所以 response 直接是 {code: 200, msg: '...', previewUrl: '...', fileUrl: '...'}
        // 而不是 {code: 200, data: {previewUrl: '...', fileUrl: '...'}}
        if (response.code === 200 && response.previewUrl) {
          // 确保URL是完整的（如果是相对路径，转换为完整URL）
          let previewUrl = response.previewUrl;
          if (previewUrl.startsWith('/') && !previewUrl.startsWith('//')) {
            // 相对路径，转换为完整URL
            previewUrl = process.env.VUE_APP_BASE_API + previewUrl;
          }
          this.officePreviewUrl = previewUrl;
          this.officeLoading = false;
          console.log('kkFileView 预览URL:', previewUrl);
        } else {
          this.officeError = true;
          this.officeLoading = false;
          const errorMsg = response.msg || '获取预览URL失败';
          console.error('获取 kkFileView 预览URL失败:', errorMsg, response);
          this.$modal.msgError(errorMsg);
        }
      }).catch(error => {
        this.officeError = true;
        this.officeLoading = false;
        console.error('获取 kkFileView 预览URL失败', error);
        // 根据错误类型给出更详细的提示
        let errorMsg = '文件预览服务不可用，请尝试下载后查看';
        if (error.response) {
          if (error.response.status === 404) {
            errorMsg = '预览服务未找到，请检查服务配置';
          } else if (error.response.status === 500) {
            errorMsg = '预览服务内部错误，请稍后重试';
          } else if (error.response.data && error.response.data.msg) {
            errorMsg = error.response.data.msg;
          }
        }
        this.$modal.msgError(errorMsg);
      });
    },
    /** Office文件加载完成处理 */
    handleOfficeLoad() {
      this.officeLoading = false;
      // iframe 加载完成，清除错误状态
      this.officeError = false;
    },
    /** Office文件加载错误处理 */
    handleOfficeError() {
      this.officeError = true;
      this.officeLoading = false;
      console.error('Office文件预览失败，kkFileView 服务可能不可用');
    },
    /** 重试Office预览 */
    retryOfficePreview() {
      if (this.previewFile) {
        // 释放旧的blob URL
        if (this.officePreviewUrl && this.officePreviewUrl.startsWith('blob:')) {
          URL.revokeObjectURL(this.officePreviewUrl);
        }
        this.officePreviewUrl = null;
        // 重新加载
        this.loadOfficeFile(this.previewFile);
      }
    },
    /** 在新窗口打开Office文件 */
    openOfficeInNewWindow() {
      if (this.previewFile && this.previewFile.fileUrl) {
        window.open(this.previewFile.fileUrl, '_blank');
      }
    },
    /** PDF加载错误处理 */
    handlePdfError() {
      this.pdfError = true;
      console.error('PDF预览失败，文件URL:', this.previewFile.fileUrl);
      this.$modal.msgWarning('PDF文件预览失败，请尝试下载后查看');
    },
    /** 重试PDF预览 */
    retryPdfPreview() {
      if (this.previewFile && this.previewFile.fileId) {
        // 释放旧的blob URL
        if (this.pdfBlobUrl) {
          URL.revokeObjectURL(this.pdfBlobUrl);
          this.pdfBlobUrl = null;
        }
        // 重新加载PDF
        this.loadPdfFile(this.previewFile.fileId);
      }
    },
    /** 在新窗口打开PDF */
    openPdfInNewWindow() {
      if (this.previewFile && this.previewFile.fileUrl) {
        window.open(this.previewFile.fileUrl, '_blank');
      }
    },
    /** 下载文件 */
    handleDownload(row) {
      window.open(row.fileUrl, '_blank');
    },
    /** 删除文件 */
    handleDeleteFile(row) {
      this.$modal.confirm('是否确认删除文件"' + row.originalName + '"？').then(() => {
        return delKnowledgeFile(row.fileId);
      }).then(() => {
        this.getFileList();
        this.getKnowledgeInfo();
        this.$modal.msgSuccess("删除成功");
      }).catch(() => {});
    },
    /** 格式化文件大小 */
    formatFileSize(size) {
      if (!size) return '0 B';
      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(size) / Math.log(k));
      return Math.round(size / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
    },
    /** 返回 */
    goBack() {
      this.$router.go(-1);
    }
  }
};
</script>

<style scoped>
.box-card {
  margin-bottom: 20px;
}
</style>
