/**
 * Function/Reports/backup-history.js
 * ---------------------------------------------------------------------------
 * BACKUP HISTORY
 *
 * Every backup created by the Backup Center: name, date, size, what it
 * contains and whether it is still valid.
 * ---------------------------------------------------------------------------
 */

'use strict';

const { execFile } = require('child_process');
const kit = require('../../core/kit');
const system = require('../../core/system');
const backup = require('../../core/backup');

module.exports = {
  name: 'Backup History',
  menuName: 'Backup History',
  description: 'Lists the backups with date, size, included data and status.',
  version: '1.0.0',
  author: 'InfinitySniper HFX',
  category: 'Reports',
  order: 50,
  requiredPermissions: 'normal',
  destructive: false,
  dependencies: [],
  minimumAppVersion: '1.0.0',
  permissions: ['filesystem:read(backups)', 'filesystem:write(reports)'],
  tags: ['backup', 'history', 'restore', 'archive'],
  documentation:
    'Lists the backups in the backups folder with their creation date, size, file count and what ' +
    'they contain (configuration, Function modules), plus the application version they were made ' +
    'with. A backup without a readable manifest is flagged as incomplete. Creating, restoring and ' +
    'deleting backups happens in the Backup Center - this function only reports.',

  async selfTest() {
    const list = backup.list();
    return { ok: true, message: `${list.length} backup(s) stored` };
  },

  async execute(ctx) {
    const { ui, prompt } = ctx;
    kit.header('Backup History', ['Backups created by the Backup Center.']);

    for (;;) {
      const list = backup.list();

      ui.blank();
      ui.section('SUMMARY');
      ui.blank();
      kit.kv('Backups Stored', system.formatNumber(list.length));
      kit.kv('Total Size', system.formatBytes(list.reduce((sum, entry) => sum + entry.bytes, 0)));
      kit.kv('Folder', ctx.paths.backups);
      kit.kv('Newest Backup', list.length ? list[0].created || system.isoLocal(list[0].modified) : null);

      if (!list.length) {
        ui.blank();
        ui.info('No backup has been created yet.');
        ui.println('  ' + ui.c.gray('Create one from the main menu: Backup Center > Create Backup.'));
        await prompt.pause('Press ENTER to go back');
        return { ok: true, backups: 0 };
      }

      ui.blank();
      ui.section('BACKUPS');
      ui.blank();
      kit.table(
        ['NAME', 'DATE', 'SIZE', 'FILES', 'CONTENT'],
        list.map((entry) => [
          ui.c.brightWhite(ui.truncate(entry.name, 22)),
          ui.c.gray(ui.truncate(entry.created || system.isoLocal(entry.modified), 19)),
          ui.c.brightCyan(system.formatBytes(entry.bytes)),
          ui.c.gray(system.formatNumber(entry.files)),
          entry.valid
            ? ui.c.brightGreen(entry.included.map((item) => item.id).join(', ') || 'empty')
            : ui.c.brightRed('no manifest'),
        ]),
        { align: ['left', 'left', 'right', 'right', 'left'], limit: 20 }
      );

      ui.blank();
      ui.menu(
        [
          { key: '1', label: 'Show the details of a backup' },
          { key: '2', label: 'Open the backups folder' },
          { key: '3', label: 'Export the history as a TXT report' },
          { separator: true },
          { key: '0', label: 'Back', color: 'gray' },
        ],
        { title: 'BACKUP HISTORY' }
      );
      ui.blank();

      const answer = await prompt.select();
      if (!answer && prompt.isClosed()) break;
      if (answer === '0') break;

      if (answer === '1') {
        const index = await prompt.choose(
          'Which backup?',
          list.map((entry) => ({ label: entry.name, hint: `${system.formatBytes(entry.bytes)} - ${entry.created || ''}` }))
        );
        if (index === null) continue;
        const entry = list[index];

        ui.blank();
        ui.section(ui.truncate(entry.name.toUpperCase(), 44));
        ui.blank();
        kit.kv('Backup Name', entry.name);
        kit.kv('Created', entry.created || system.isoLocal(entry.modified));
        kit.kv('Application Version', entry.version);
        kit.kv('Size', system.formatBytes(entry.bytes));
        kit.kv('Files', system.formatNumber(entry.files));
        kit.kv('Status', entry.valid ? 'Valid (manifest present)' : 'Incomplete (no manifest)', entry.valid ? 'brightGreen' : 'brightRed');
        kit.kv('Location', entry.path);

        if (entry.included.length) {
          ui.blank();
          ui.section('INCLUDED DATA');
          ui.blank();
          for (const item of entry.included) {
            kit.kv(item.label || item.id, `${system.formatNumber(item.files)} file(s), ${system.formatBytes(item.bytes)}`);
          }
        }
        await prompt.pause();
      } else if (answer === '2') {
        try {
          execFile('explorer.exe', [ctx.paths.backups], { windowsHide: false }, () => {});
          ui.blank();
          ui.ok('Explorer window requested.');
        } catch (err) {
          ui.error(`The folder could not be opened: ${err.message}`);
        }
        await prompt.pause();
      } else if (answer === '3') {
        const report = kit.report('Backup History Report');
        const section = report.section('SUMMARY');
        section.add('Backups Stored', system.formatNumber(list.length));
        section.add('Total Size', system.formatBytes(list.reduce((sum, entry) => sum + entry.bytes, 0)));
        section.add('Folder', ctx.paths.backups);

        const history = report.section('BACKUPS');
        list.forEach((entry, index) => {
          const group = history.group(`${index + 1}. ${entry.name}`);
          group.add('Created', entry.created || system.isoLocal(entry.modified));
          group.add('Application Version', entry.version);
          group.add('Size', system.formatBytes(entry.bytes));
          group.add('Files', system.formatNumber(entry.files));
          group.add('Included Data', entry.included.map((item) => item.label || item.id).join(', '));
          group.add('Status', entry.valid ? 'Valid' : 'Incomplete');
          group.add('Location', entry.path);
        });
        kit.saveReport(report, 'BackupHistory');
        await prompt.pause();
      } else {
        ui.warning('Enter one of the numbers shown above, or 0 to go back.');
        await prompt.pause();
      }
    }

    return kit.done('Backup history closed.');
  },
};
