/**
 * Function/Reports/export-center.js
 * ---------------------------------------------------------------------------
 * EXPORT CENTER
 *
 * Combines the sections other functions provide into a single
 * FullSystemReport.txt. Any module that exports a `reportProvider` shows up
 * here automatically - no list to maintain.
 * ---------------------------------------------------------------------------
 */

'use strict';

const kit = require('../../core/kit');
const system = require('../../core/system');
const reportManager = require('../../core/report-manager');

module.exports = {
  name: 'Export Center',
  menuName: 'Export Center',
  description: 'Combine selected sections from other functions into one full system report.',
  version: '1.0.0',
  author: 'InfinitySniper HFX',
  category: 'Reports',
  order: 10,
  requiredPermissions: 'normal',
  destructive: false,
  dependencies: [],
  minimumAppVersion: '1.0.0',
  permissions: ['system:read', 'wmi:query', 'filesystem:write(reports)'],
  tags: ['export', 'report', 'combine', 'full', 'system'],
  documentation:
    'Every function that can contribute to a report declares a reportProvider; the Export Center ' +
    'lists them automatically and builds one combined TXT file from the sections you tick. ' +
    'A section that fails is noted inside the report instead of aborting the export, so a partial ' +
    'result is still produced. The file is written to reports/<time>_<date>_FullSystemReport.txt.',

  async selfTest(ctx) {
    const providers = reportManager.providers(ctx.modules || []);
    return providers.length
      ? { ok: true, message: `${providers.length} section(s) available` }
      : { ok: false, message: 'no report provider is installed' };
  },

  async execute(ctx) {
    const { ui, prompt } = ctx;
    kit.header('Export Center', ['Build one report out of several functions.']);

    const providers = reportManager.providers(ctx.modules);
    if (!providers.length) {
      ui.blank();
      ui.warning('No installed function offers a report section yet.');
      ui.println('  ' + ui.c.gray('A module joins the Export Center by exporting a reportProvider.'));
      return { ok: false, reason: 'no-providers' };
    }

    // Everything is selected by default - the common case is "give me all of it".
    const selected = new Set(providers.map((provider) => provider.id));

    for (;;) {
      ui.blank();
      ui.section('AVAILABLE SECTIONS');
      ui.blank();
      providers.forEach((provider, index) => {
        const chosen = selected.has(provider.id);
        ui.println(
          '  ' + ui.c.brightYellow(ui.padEnd(`[${index + 1}]`, 6)) +
            (chosen ? ui.c.brightGreen('[x] ') : ui.c.gray('[ ] ')) +
            ui.c.brightWhite(ui.padEnd(provider.label, 28)) +
            ui.c.gray(provider.module.name)
        );
      });

      ui.blank();
      kit.kv('Sections Selected', `${selected.size} of ${providers.length}`);

      ui.blank();
      ui.menu(
        [
          { key: '1', label: 'Toggle a section' },
          { key: '2', label: 'Select all sections' },
          { key: '3', label: 'Clear the selection' },
          { key: '4', label: 'Generate FullSystemReport.txt', color: 'brightGreen' },
          { separator: true },
          { key: '0', label: 'Back', color: 'gray' },
        ],
        { title: 'EXPORT CENTER' }
      );
      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 section?',
          providers.map((provider) => ({
            label: provider.label,
            hint: selected.has(provider.id) ? 'selected' : 'not selected',
          }))
        );
        if (index === null) continue;
        const provider = providers[index];
        if (selected.has(provider.id)) selected.delete(provider.id);
        else selected.add(provider.id);
        continue;
      }

      if (answer === '2') {
        providers.forEach((provider) => selected.add(provider.id));
        continue;
      }

      if (answer === '3') {
        selected.clear();
        continue;
      }

      if (answer === '4') {
        if (!selected.size) {
          ui.blank();
          ui.warning('Select at least one section first.');
          await prompt.pause();
          continue;
        }

        const chosen = providers.filter((provider) => selected.has(provider.id));
        ui.blank();
        ui.info(`Collecting ${chosen.length} section(s) - this can take a minute.`);
        ui.blank();

        const started = Date.now();
        const spin = ui.spinner('Building the report...');
        const result = await reportManager.buildCombined(chosen, ctx, (label, index, total) => {
          spin.update(`Collecting [${index}/${total}] ${label}...`);
        });
        spin.stop();

        ui.blank();
        if (!result.ok) {
          ui.error(`The report could not be written: ${result.error}`);
          await prompt.pause();
          continue;
        }

        ui.section('RESULT');
        ui.blank();
        kit.kv('Report File', 'FullSystemReport.txt');
        kit.kv('Location', result.file, 'brightCyan');
        kit.kv('Size', system.formatBytes(result.size));
        kit.kv('Sections', String(chosen.length));
        kit.kv('Data Points', system.formatNumber(result.fields));
        kit.kv('Duration', `${((Date.now() - started) / 1000).toFixed(1)}s`);

        if (result.failures.length) {
          ui.blank();
          ui.warning(`${result.failures.length} section(s) could not be collected:`);
          for (const failure of result.failures) {
            ui.println('      ' + ui.c.gray(`${failure.label}: ${ui.truncate(failure.error, 40)}`));
          }
          ui.println('  ' + ui.c.gray('They are marked inside the report as well.'));
        }

        ui.blank();
        ui.completed('Full system report generated.');
        await prompt.pause();
      }
    }

    return kit.done('Export Center closed.');
  },
};
