<script setup>

import { ref, computed, useTemplateRef } from 'vue';
import { ClipboardAction, TableView, Dialog } from '@cloudron/pankow';
import { prettyDuration, prettyLongDate, prettyFileSize } from '@cloudron/pankow/utils';
import AppsModel from '../models/AppsModel.js';
import BackupsModel from '../models/BackupsModel.js';

import { useI18n } from 'vue-i18n';
const i18n = useI18n();
const t = i18n.t;

const appsModel = AppsModel.create();
const backupsModel = BackupsModel.create();

const busy = ref(true);

const backupContentTableColumns = computed(() => {
  const columns = {
    label: {
      label: t('backups.listing.contents'),
      sort: true,
    },
    fileCount: {
      label: t('backup.target.fileCount'),
      sort(a, b, A, B) {
        return A.stats?.upload?.fileCount - B.stats?.upload?.fileCount;
      },
      align: 'right',
    },
    size: {
      label: t('backup.target.size'),
      sort(a, b, A , B) {
        return A.stats?.upload?.size - B.stats?.upload?.size;
      },
      align: 'right',
    },
  };

  if (backup.value.lastIntegrityCheckTime || backup.value.integrityCheckTask) {
    columns.integrity = {
      label: 'Integrity',
      sort: false,
      width: '100px',
      align: 'center',
    };
  }

  return columns;
});

const backup = ref({ contents: [], validStats: false });
const dialog = useTemplateRef('dialog');

defineExpose({
  async open(b) {
    backup.value = JSON.parse(JSON.stringify(b)); // make a copy
    backup.value.contents = [];
    backup.value.validStats = false; // old cloudron version had invalid stats
    busy.value = true;

    dialog.value.open();

    if (backup.value.type === 'app') {
      backup.value.validStats = backup.value.stats?.upload && backup.value.stats?.copy;
      busy.value = false;
      return;
    }

    // amend detailed app info
    const appsById = {};

    const [appsError, apps] = await appsModel.list();
    if (appsError) console.error('Failed to get apps list:', appsError);

    (apps || []).forEach(function (app) {
      appsById[app.id] = app;
    });

    for (const contentId of backup.value.dependsOn) {
      const match = contentId.match(/(mail|app)_(.*?)_.*/); // *? means non-greedy
      if (!match) continue;
      const [error, result] = await backupsModel.get(contentId);
      if (error) console.error(error);
      const content = { id: null, label: null, fqdn: null, stats: null, integrityCheckStatus: null, lastIntegrityCheckTime: null, integrityCheckTask: null };
      content.stats = result.stats;
      content.integrityCheckStatus = result.integrityCheckStatus;
      content.lastIntegrityCheckTime = result.lastIntegrityCheckTime;
      content.integrityCheckTask = result.integrityCheckTask;
      if (match[1] === 'mail') {
        content.id = 'mail';
        content.label = 'Mail Server';
      } else {
        const app = appsById[match[2]];
        if (app) {
          content.id = app.id;
          content.label = app.label;
          content.fqdn = app.fqdn;
        } else { // uninstalled app
          content.id = match[2];
        }
      }
      backup.value.contents.push(content);
    }

    backup.value.validStats = backup.value.stats?.aggregatedUpload && backup.value.stats?.aggregatedCopy;
    busy.value = false;
  }
});

</script>

<template>
  <Dialog ref="dialog"
  :title="$t('backups.backupDetails.title')"
  :reject-label="$t('main.dialog.close')"
  >
    <div class="info-row">
      <div class="info-label">{{ $t('backups.backupDetails.id') }}</div>
      <div class="info-value">{{ backup.id }}</div>
    </div>
    <div class="info-row">
      <div class="info-label">{{ $t('backups.backupEdit.label') }}</div>
      <div class="info-value">{{ backup.label || 'Not set'}}</div>
    </div>
    <div class="info-row">
      <div class="info-label">{{ $t('backups.backupEdit.remotePath') }}</div>
      <div class="info-value">
        <div>
          {{ backup.remotePath }}
          <ClipboardAction plain :value="backup.remotePath"/>
        </div>
      </div>
    </div>
    <div class="info-row">
      <div class="info-label">{{ $t('backups.backupDetails.date') }}</div>
      <div class="info-value">{{ prettyLongDate(backup.creationTime) }}</div>
    </div>
    <div class="info-row">
      <div class="info-label">{{ $t('backups.backupDetails.version') }}</div>
      <div class="info-value">{{ backup.packageVersion }}</div>
    </div>
    <div class="info-row" v-if="backup.validStats">
      <div class="info-label">{{ $t('backups.backupDetails.size') }}</div>
      <div v-if="backup.type === 'box'" class="info-value">{{ prettyFileSize(backup.stats.aggregatedUpload.size) }} | {{ backup.stats.aggregatedUpload.fileCount }} file(s) | {{ backup.appCount }} app(s) </div>
      <div v-else class="info-value">{{ prettyFileSize(backup.stats.upload.size) }} | {{ backup.stats.upload.fileCount }} file(s)</div>
    </div>
    <div class="info-row" v-if="backup.validStats">
      <div class="info-label">{{ $t('backups.backupDetails.duration') }}</div>
      <div v-if="backup.type === 'box'" class="info-value">{{ prettyDuration(backup.stats.aggregatedUpload.duration + backup.stats.aggregatedCopy.duration) }}</div>
      <div v-else class="info-value">{{ prettyDuration(backup.stats.upload.duration + backup.stats.copy.duration) }}</div>
    </div>
    <div class="info-row">
      <div class="info-label">{{ $t('backups.backupDetails.lastIntegrityCheck') }}</div>
      <div class="info-value">
        <a v-if="backup.integrityCheckTask?.active" :href="`/logs.html?taskId=${backup.integrityCheckTask.id}`" target="_blank">{{ $t('backups.backupDetails.integrityInProgress') }}</a>
        <a v-else-if="backup.lastIntegrityCheckTime && backup.integrityCheckTask" :href="`/logs.html?taskId=${backup.integrityCheckTask.id}`" target="_blank">
          <i class="fa-solid" :class="{ 'fa-check-circle text-success': backup.integrityCheckStatus === 'passed', 'fa-times-circle text-danger': backup.integrityCheckStatus === 'failed', 'fa-circle-minus text-warning': backup.integrityCheckStatus === 'skipped' }"></i>
          {{ prettyLongDate(backup.lastIntegrityCheckTime) }}
        </a>
        <span v-else-if="backup.lastIntegrityCheckTime">
          <i class="fa-solid" :class="{ 'fa-check-circle text-success': backup.integrityCheckStatus === 'passed', 'fa-times-circle text-danger': backup.integrityCheckStatus === 'failed', 'fa-circle-minus text-warning': backup.integrityCheckStatus === 'skipped' }"></i>
          {{ prettyLongDate(backup.lastIntegrityCheckTime) }}
        </span>
        <span v-else>{{ $t('backups.backupDetails.integrityNever') }}</span>
      </div>
    </div>
    <div v-if="(backup.integrityCheckStatus === 'failed' || backup.integrityCheckStatus === 'skipped') && backup.integrityCheckResult?.messages?.length">
      <div class="info-label" style="margin-bottom: 5px;">Integrity Issues</div>
      <textarea readonly rows="10" style="width: 100%; resize: vertical;" :value="backup.integrityCheckResult.messages.join('\n')"></textarea>
    </div>

    <hr style="margin: 15px 0" v-if="backup.type === 'box'"/>

    <div v-if="backup.type === 'box'">
      <TableView :columns="backupContentTableColumns" :model="backup.contents" :busy="busy">
        <template #label="{ item:content }">
          <a v-if="content.id === 'mail'" href="/#/mailboxes">{{ content.label }}</a>
          <a v-else-if="content.fqdn" :href="`/#/app/${content.id}/backups`">{{ content.label || content.fqdn }}</a>
          <a v-else :href="`/#/system-eventlog?search=${content.id}`">{{ content.id }}</a>
        </template>
        <template #fileCount="{ item:content }">
          <div v-if="content.stats?.upload" style="text-align: right">{{ content.stats.upload.fileCount }}</div>
          <div v-else style="text-align: right">-</div>
        </template>
        <!-- <td>{{ prettyDuration(content.stats.upload.duration | content.stats.copy.duration) }}</td> -->
        <template #size="{ item:content }">
          <div v-if="content.stats?.upload" style="text-align: right">{{ prettyFileSize(content.stats.upload.size) }}</div>
          <div v-else style="text-align: right">-</div>
        </template>
        <template #integrity="{ item:content }">
          <a v-if="content.lastIntegrityCheckTime && content.integrityCheckTask" :href="`/logs.html?taskId=${content.integrityCheckTask.id}`" target="_blank" style="display: flex; align-items: center; justify-content: center;">
            <i class="fa-solid" :class="{ 'fa-check-circle text-success': content.integrityCheckStatus === 'passed', 'fa-times-circle text-danger': content.integrityCheckStatus === 'failed', 'fa-circle-minus text-warning': content.integrityCheckStatus === 'skipped' }" v-tooltip="prettyLongDate(content.lastIntegrityCheckTime)"></i>
          </a>
          <div v-else-if="content.lastIntegrityCheckTime" style="display: flex; align-items: center; justify-content: center;">
            <i class="fa-solid" :class="{ 'fa-check-circle text-success': content.integrityCheckStatus === 'passed', 'fa-times-circle text-danger': content.integrityCheckStatus === 'failed', 'fa-circle-minus text-warning': content.integrityCheckStatus === 'skipped' }" v-tooltip="prettyLongDate(content.lastIntegrityCheckTime)"></i>
          </div>
          <div v-else style="text-align: center;">-</div>
        </template>
      </TableView>
    </div>
  </Dialog>
</template>