<template>
  <!-- 更新提示对话框 -->
  <el-dialog
    v-model="visible"
    :width="300"
    draggable
    alignCenter
    style="--el-dialog-padding-primary: 0"
    :showClose="false"
    destroyOnClose
    :closeOnClickModal="false"
    :closeOnPressEscape="false"
  >
    <div style="position: relative; background: #ffffff; border-radius: 8px">
      <div class="update-dialog-bg"></div>
      <div class="update-dialog-content">
        <p class="content-name">发现新版本 {{ newVersion }}</p>
        <div class="version-box">
          <p class="version-time">更新时间: {{ releaseDate }}</p>
        </div>
        <div v-if="updateInfoList.length > 0" class="update-info">
          <el-scrollbar :maxHeight="60">
            <div class="update-info-list">
              <p v-for="(info, index) in updateInfoList" :key="index" class="update-info-item">{{ info }}</p>
            </div>
          </el-scrollbar>
        </div>
      </div>
      <div class="dialog-footer">
        <el-button v-if="downloadState !== 'downloading'" round type="primary" size="large" style="width: 90px; margin-right: 20px" plain @click="ignoreUpdate">
          忽略
        </el-button>
        <rest-download-button style="flex: 1" :progress="progress" :state="downloadState" @click="downloadButtonClick"></rest-download-button>
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
  import dayjs from 'dayjs';
  import { $mitt, APP_UPDATE } from '@/utils/mitt-event';
  import type { Update } from '@tauri-apps/plugin-updater';
  import { relaunch } from '@tauri-apps/plugin-process';

  let update: Update | null = null;

  const visible = ref(false);
  const newVersion = ref('');
  const updateInfoList = ref<string[]>([]);
  const releaseDate = ref('');
  const progress = ref<number>(0);
  const downloadState = ref<'downloading' | 'error' | 'init' | 'succeed'>('init');

  onMounted(() => {
    $mitt.on(APP_UPDATE, (data) => {
      show(data);
    });
  });

  onUnmounted(() => {
    $mitt.off(APP_UPDATE);
    update = null;
  });

  /**
   * 显示更新对话框
   */
  function show(data: Update) {
    visible.value = true;
    update = data;
    newVersion.value = data.version;
    updateInfoList.value = String(data.body || '').split('\n');
    releaseDate.value = dayjs(data.date).format('YYYY-MM-DD HH:mm:ss');
  }

  /** 隐藏 */
  function hide() {
    visible.value = false;
  }

  /**
   * 点击下载按钮进行操作
   * 如果正在下载中，则取消下载
   * 如果下载完成，则安装更新
   */
  async function downloadButtonClick() {
    switch (downloadState.value) {
      case 'init':
      case 'error':
        update && (await initDownload(update));
        break;
      case 'succeed':
        try {
          downloadState.value = 'succeed';
          progress.value = 0;
          update && (await update.install());
          hide();
          await relaunch();
        } catch (error) {
          Toast.error('安装更新失败');
        }
        break;
      default:
        break;
    }
  }

  /**
   * 初始化下载
   */
  async function initDownload(_update: Update) {
    let downloaded = 0;
    let contentLength = 0;
    try {
      downloadState.value = 'downloading';
      await nextTick();
      await _update.download((event) => {
        switch (event.event) {
          case 'Started':
            progress.value = 0;
            contentLength = event.data.contentLength || 0;
            console.log('开始下载 :>> ', event);
            break;
          case 'Progress':
            downloadState.value = 'downloading';
            progress.value = 0;
            downloaded += event.data.chunkLength;
            progress.value = Math.round((downloaded / contentLength) * 10000) / 100;
            break;
          case 'Finished':
            downloadState.value = 'succeed';
            progress.value = 0;
            console.log('下载完成 :>> ', event);
            break;
          default:
            break;
        }
      });
    } catch (error) {
      downloadState.value = 'downloading';
      progress.value = 0;
      Toast.error('下载更新失败');
    }
  }

  /**
   * 忽略更新
   */
  async function ignoreUpdate() {
    downloadState.value = 'init';
    progress.value = 0;
    update && (await update.close());
    hide();
  }

  defineExpose({
    show,
    hide,
  });
</script>

<style scoped lang="scss">
  .update-dialog-bg {
    position: relative;
    top: -30px;
    width: 100%;
    background-image: url('@/assets/images/bg/bg-3.png');
    background-size: 100% 100%;
    aspect-ratio: 304 / 122;
  }

  .update-dialog-content {
    padding: 20px;
    padding-top: 0;

    .content-name {
      font-size: 20px;
      font-weight: bold;
      color: #0c8af1;
    }

    .version-box {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-top: 10px;
      font-size: 12px;

      .version-time {
        margin-left: 6px;
        font-size: 14px;
        color: #666666;
      }
    }
  }

  .update-info {
    margin-top: 15px;
    background: #f8fafe;
    border: 0;
    border-radius: 4px;

    .update-info-list {
      padding: 8px 10px;

      .update-info-item {
        padding: 3px;
        font-size: 12px;
      }
    }
  }

  .dialog-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px;
  }
</style>
