<template>
  <div class="book org">
    <ProjectMenu cur-key="org/offlinepackageauth" />

    <el-row>
      <el-button type="primary" @click="dialogFormEdit = true">创建授权</el-button>
    </el-row>
    <el-divider />
    <div id="query-form">
      <el-form inline>
        <el-form-item prop="book_name" label="教材">
          <el-input v-model="queryForm.book_name" clearable />
        </el-form-item>
        <el-form-item prop="auth_code" label="授权码">
          <el-input v-model="queryForm.auth_code" clearable />
        </el-form-item>
        <el-form-item prop="memo" label="备注">
          <el-input v-model="queryForm.memo" clearable />
        </el-form-item>
        <el-form-item class="search-box">
          <el-button class="search-btn" type="primary" @click="queryList">查询</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="book-list">
      <el-table :data="list">
        <el-table-column label="序号" width="60" align="center" header-align="center" class-name="index-column">
          <template slot-scope="{ $index }">
            {{ cur_page_begin_index + $index }}
          </template>
        </el-table-column>
        <el-table-column prop="book_name" min-width="200" label="教材" />
        <el-table-column prop="auth_code" label="授权码" width="180" align="center" />
        <el-table-column prop="effective_count" label="有效次数" width="100" align="right" />
        <el-table-column label="激活状态" width="100" align="center">
          <template slot-scope="{ row }">
            {{ isTrue(row.is_activated) ? '已激活' : '未激活' }}
          </template>
        </el-table-column>
        <el-table-column label="激活时间" width="160" align="center">
          <template slot-scope="{ row }">
            <span v-if="isTrue(row.is_activated)">{{ row.activate_time }}</span>
            <span v-else>--</span>
          </template>
        </el-table-column>
        <el-table-column label="有效截止日期" width="120" align="center">
          <template slot-scope="{ row }">
            <span v-if="isTrue(row.is_disabled)" style="color: red">已废弃</span>
            <span v-else>{{ row.effective_end_date }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="creator_name" label="创建人" width="120" align="center" />
        <el-table-column prop="create_time" label="创建时间" width="160" align="center" />
        <el-table-column label="操作" fixed="right" width="180" align="center">
          <template slot-scope="{ row }">
            <span class="link" @click="selectDirectory(row.id)">导出离线包</span>
            <el-divider direction="vertical" />
            <span class="link" @click="handleDisable(row.id)">废弃</span>
            <el-divider direction="vertical" />
            <span class="link" @click="handleDel(row.id)">删除</span>
          </template>
        </el-table-column>
        <el-table-column prop="memo" label="备注" />
      </el-table>

      <PaginationPage :total="total" @getList="pageList" />
    </div>

    <el-dialog title="创建授权" width="500px" :visible.sync="dialogFormEdit" :close-on-click-modal="false">
      <el-form ref="editForm" :model="editForm" :rules="rules" label-width="120px">
        <el-form-item label="教材" prop="book_name">
          <el-input v-model="editForm.book_name" disabled class="input-with-select" placeholder="请选择教材">
            <el-button slot="append" icon="el-icon-search" @click="handleSearchBook('')" />
          </el-input>
        </el-form-item>
        <el-form-item label="有效次数" prop="effective_count">
          <el-input v-model.number="editForm.effective_count" placeholder="请输入有效次数" />
        </el-form-item>
        <el-form-item label="有效截止日期" prop="effective_end_date">
          <el-date-picker
            v-model="editForm.effective_end_date"
            type="date"
            placeholder="选择日期"
            value-format="yyyy-MM-dd"
          />
        </el-form-item>
        <el-form-item label="备注" prop="memo">
          <el-input v-model="editForm.memo" type="textarea" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormEdit = false">取 消</el-button>
        <el-button type="primary" @click="handleSave('editForm')">确 定</el-button>
      </div>
    </el-dialog>

    <el-dialog title="选择教材" width="950px" :visible.sync="dialogSearchBook" :close-on-click-modal="false">
      <el-table :data="bookList">
        <el-table-column label="序号" width="60" align="center" header-align="center" class-name="index-column">
          <template slot-scope="{ $index }">
            {{ cur_page_begin_index + $index }}
          </template>
        </el-table-column>
        <el-table-column prop="sn" label="编号" width="120" header-align="center" />
        <el-table-column prop="name" label="名称" min-width="240" header-align="center" />
        <el-table-column prop="project_sn" label="项目编号" width="120" header-align="center" />
        <el-table-column prop="project_name" label="项目名称" width="240" header-align="center" />
        <el-table-column label="操作" width="80">
          <template #default="{ row }">
            <el-button type="primary" @click="selectBook(row)">选择</el-button>
          </template>
        </el-table-column>
      </el-table>
      <PaginationPage :total="bookTotal" @getList="pageBookList" />
    </el-dialog>

    <CommonProgress
      :percentage="percentage"
      :visible.sync="visible"
      title="导出离线包"
      :text="`正在导出离线包，请稍候...`"
    />
  </div>
</template>

<script>
import ProjectMenu from '@/views/project_manage/common/ProjectMenu.vue';
import PaginationPage from '@/components/PaginationPage.vue';
import CommonProgress from '@/components/CommonProgress.vue';

import { PageQueryYSJBookList_OrgManager } from '@/api/list';
import {
  AddBookOfflinePackAuth,
  DeleteBookOfflinePackAuth,
  DisableBookOfflinePackAuth,
  PageQueryBookOfflinePackAuthList,
  CreateBookOfflinePackChapterStructFileList,
  CreateOfflinePackCoursewareFileList,
} from '@/api/offline';
import { isTrue } from '@/utils/validate';

export default {
  name: 'OrgProjectManageOfflinePackAuth',
  components: {
    ProjectMenu,
    PaginationPage,
    CommonProgress,
  },
  data() {
    return {
      list: [],
      total: 0,
      cur_page_begin_index: 0,
      bookList: [],
      bookTotal: 0,
      bookPageIndex: 0,
      isTrue,
      dialogFormEdit: false,
      dialogSearchBook: false,
      queryForm: {
        book_name: '',
        auth_code: '',
        memo: '',
        page_capacity: 10,
        cur_page: 1,
      },
      editForm: {
        book_id: '',
        book_name: '',
        effective_count: null,
        effective_end_date: '',
        memo: '',
      },
      rules: {
        book_name: [{ required: true, message: '请选择教材', trigger: 'blur' }],
        effective_count: [
          { required: true, message: '请填写有效次数', trigger: 'blur' },
          { type: 'number', message: '有效次数必须为数字值' },
        ],
        effective_end_date: [{ required: true, message: '请选择有效截止日期', trigger: 'blur' }],
      },
      tempDir: '', // 临时目录，用于存放下载的文件
      savePath: '', // 保存离线包的路径
      packageName: 'EEP 离线包', // 离线包名称
      file_info_list: [], // 章节结构文件列表
      downloadTotal: 0, // 下载总数
      downloadCompleted: 0, // 已下载数量
      downloadWatcher: null, // 下载进度监听器
      visible: false,
      percentage: 0,
    };
  },
  computed: {
    downloadProgress() {
      if (this.downloadTotal === 0) return 0;
      return (this.downloadCompleted / this.downloadTotal) * 100;
    },
  },
  watch: {
    dialogFormEdit: {
      handler(val) {
        if (!val) {
          this.$refs.editForm.resetFields();
        }
      },
      deep: true,
    },
  },
  beforeDestroy() {
    // 删除临时目录及其内容
    if (this.tempDir && this.tempDir.length > 0) {
      window.fileAPI.deleteTempDir(this.tempDir);
      this.tempDir = '';
    }

    // 删除 watch 监听器
    if (this.downloadWatcher) {
      this.downloadWatcher();
      this.downloadWatcher = null;
    }
  },
  methods: {
    queryList() {
      this.pageList(this.queryForm);
    },

    pageList(data) {
      Object.assign(this.queryForm, data);
      PageQueryBookOfflinePackAuthList(this.queryForm).then(
        ({ total_count, offline_pack_auth_list, cur_page_begin_index }) => {
          this.list = offline_pack_auth_list;
          this.total = total_count;
          this.cur_page_begin_index = cur_page_begin_index;
        },
      );
    },
    pageBookList(data) {
      this.handleSearchBook(data);
    },
    handleSearchBook(data) {
      let page = data || {
        cur_page: 1,
        page_capacity: 10,
      };
      PageQueryYSJBookList_OrgManager(page).then(({ total_count, book_list, cur_page_begin_index }) => {
        this.bookList = book_list;
        this.bookTotal = total_count;
        this.bookPageIndex = cur_page_begin_index;
        this.dialogSearchBook = true;
      });
    },
    selectBook(book) {
      this.editForm.book_name = book.name;
      this.editForm.book_id = book.id;
      this.dialogSearchBook = false;
    },
    handleSave(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          let data = this.editForm;
          this.dialogSearchBook = false;
          AddBookOfflinePackAuth(data).then((res) => {
            if (res && res.status === 1) {
              this.dialogFormEdit = false;
              this.queryList();
            }
          });
        } else {
          return false;
        }
      });
    },

    async handleDisable(id) {
      this.$confirm('确定要废弃此条数据吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          DisableBookOfflinePackAuth({ id }).then(() => {
            this.queryList();
          });
        })
        .catch(() => {});
    },
    async handleDel(id) {
      this.$confirm('确定要删除此条数据吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          DeleteBookOfflinePackAuth({ id }).then(() => {
            this.queryList();
          });
        })
        .catch(() => {});
    },

    /**
     * 选择保存离线包的目录
     * @param {String} book_id 教材ID
     */
    async selectDirectory(book_id) {
      const result = await window.fileAPI.openFileDialog({
        title: '选择保存离线包的文件夹',
        properties: ['openDirectory', 'createDirectory'],
      });
      if (result.canceled) {
        this.$message.warning('未选择文件夹，操作已取消');
        return;
      }
      this.savePath = result.filePaths[0];
      this.downloadOfflinePackage(book_id);
    },

    /**
     * 下载离线包
     * @param {String} offline_pack_auth_id 离线包授权ID
     */
    async downloadOfflinePackage(offline_pack_auth_id) {
      const { file_info_list, courseware_id_list } = await CreateBookOfflinePackChapterStructFileList({
        offline_pack_auth_id,
      });

      this.file_info_list = file_info_list;
      if (file_info_list.length === 0) {
        this.$message.error('章节结构文件生成失败，无法下载离线包');
        return;
      }

      if (this.tempDir.length === 0) {
        this.tempDir = window.fileAPI.createTempDir(); // 创建临时保存目录
      }

      this.visible = true;

      for (const { dir_name, file_name, file_url } of this.file_info_list) {
        const dirPath = dir_name.length > 0 ? `${this.tempDir}\\${dir_name}` : this.tempDir;
        await window.fileAPI.downloadFile(file_url, `${dirPath}\\${file_name}`);
      }

      const struct = await this.readFileContent('struct.json'); // 读取章节结构文件内容

      if (struct.node_list && struct.node_list.length > 0) {
        this.packageName = struct.node_list[0].name; // 设置离线包名称为课件名称
      }

      if (courseware_id_list && courseware_id_list.length > 0) {
        Promise.all(
          courseware_id_list.map((courseware_id) => this.CreateOfflinePackCoursewareFileList(courseware_id)),
        ).then(() => {
          this.downloadWatcher = this.$watch(
            'downloadProgress',
            (newVal) => {
              if (newVal >= 100) {
                this.downloadWatcher();
                this.startCompress();
              } else {
                this.percentage = (
                  (this.downloadCompleted / (this.downloadTotal + this.downloadTotal * 0.1)) *
                  100
                ).toFixed(2);
              }
            },
            { immediate: true },
          );
        });
      }
    },

    /**
     * 下载课件文件列表
     * @param {Number} courseware_id 课件ID
     * @return {Promise} Promise对象
     */
    async CreateOfflinePackCoursewareFileList(courseware_id) {
      const { file_info_list } = await CreateOfflinePackCoursewareFileList({ courseware_id });
      this.downloadTotal += file_info_list.length;

      file_info_list.forEach((fileInfo) => {
        const { file_name, file_url, dir_name } = fileInfo;
        // 如果有子目录，则判断是否有，没有就创建子目录
        if (dir_name.split('/').length > 1) {
          if (!window.fileAPI.existsSync(`${this.tempDir}\\${dir_name}`)) {
            window.fileAPI.mkdirSync(`${this.tempDir}\\${dir_name}`);
          }
        }

        window.fileAPI.downloadFile(file_url, `${this.tempDir}\\${dir_name}\\${file_name}`).then(() => {
          this.downloadCompleted += 1;
        });
      });
    },

    /**
     * 开始压缩
     */
    async startCompress() {
      if (this.downloadWatcher) {
        this.downloadWatcher = null;
      }
      const sources = [`${this.tempDir}\\resource`, `${this.tempDir}\\courseware`]; // 要压缩的文件或文件夹路径数组
      this.file_info_list.forEach(({ dir_name, file_name }) => {
        const dirPath = dir_name.length > 0 ? `${this.tempDir}\\${dir_name}` : this.tempDir;
        sources.push(`${dirPath}\\${file_name}`);
      });
      const dest = `${this.savePath}\\${this.packageName}.eep`; // 压缩包保存路径
      try {
        const offErr = window.fileAPI.onStderr((text) => console.warn('7z stderr:', text));

        await window.fileAPI.compress({
          sources,
          dest,
          format: 'zip',
          level: 5,
          password: '1234567a',
          recurse: true,
        });
        offErr();
      } catch (e) {
        console.error('压缩失败：', e);
        this.$message.error('离线包下载失败，请重试！');
        this.tempDir = '';
        this.visible = false;
        return;
      } finally {
        this.percentage = 100;
        this.visible = false;
      }

      // 删除临时目录及其内容
      try {
        await window.fileAPI.deleteTempDir(this.tempDir);
        this.tempDir = '';
      } catch (e) {
        console.error('删除临时目录失败：', e);
        this.tempDir = '';
      } finally {
        this.percentage = 0;
      }

      this.$message.success('离线包下载并保存成功！');
    },

    /**
     * 读取文件内容
     * @param entryName 文件条目名称
     * @param subdirectory 子目录
     */
    async readFileContent(entryName, subdirectory = '') {
      const content = await window.fileAPI.readZipFileSync(`${this.tempDir}/${subdirectory}`, entryName);
      const text = new TextDecoder().decode(content);
      const obj = JSON.parse(text);
      return obj;
    },
  },
};
</script>

<style lang="scss" scoped>
@use '@/styles/mixin.scss' as *;

.book {
  @include page-base;
  @include table-list;
}

.el-divider--horizontal {
  margin: 10px 0 !important;
}

.el-form-item__content > * {
  width: 100%;
}
</style>
