/**
 * Function/Reports/repair-history.js
 * ---------------------------------------------------------------------------
 * REPAIR HISTORY
 *
 * Every run of the Repair Center: date, mode, problems found, problems fixed
 * and the final status, with the detailed log of each run.
 * ---------------------------------------------------------------------------
 */

'use strict';

const fs = require('fs');
const kit = require('../../core/kit');
const system = require('../../core/system');
const repair = require('../../core/repair');

function statusColor(status) {
  if (status === 'HEALTHY') return 'brightGreen';
  if (status === 'REPAIRED') return 'brightCyan';
  return 'brightYellow';
}

module.exports = {
  name: 'Repair History',
  menuName: 'Repair History',
  description: 'Previous repair runs with mode, problems found, problems fixed and final status.',
  version: '1.0.0',
  author: 'InfinitySniper HFX',
  category: 'Reports',
  order: 40,
  requiredPermissions: 'normal',
  destructive: false,
  dependencies: [],
  minimumAppVersion: '1.0.0',
  permissions: ['filesystem:read(logs)', 'filesystem:write(reports)'],
  tags: ['repair', 'history', 'maintenance', 'logs'],
  documentation:
    'The Repair Center records every run. This function lists them newest first with the repair ' +
    'mode (quick, full, dependency, function or health), how many problems were found and fixed and ' +
    'the resulting status, and can open the detailed log of any run or export the whole history.',

  async selfTest() {
    const entries = repair.history(200);
    return { ok: true, message: `${entries.length} repair run(s) recorded` };
  },

  async execute(ctx) {
    const { ui, prompt } = ctx;
    kit.header('Repair History', ['Previous runs of the Repair Center.']);

    const entries = repair.history(100);

    if (!entries.length) {
      ui.blank();
      ui.info('No repair has been run yet.');
      ui.println('  ' + ui.c.gray('Open the Repair Center from the main menu to run one.'));
      await prompt.pause('Press ENTER to go back');
      return { ok: true, repairs: 0 };
    }

    const totalFound = entries.reduce((sum, entry) => sum + (entry.problemsFound || 0), 0);
    const totalFixed = entries.reduce((sum, entry) => sum + (entry.problemsFixed || 0), 0);

    for (;;) {
      ui.blank();
      ui.section('SUMMARY');
      ui.blank();
      kit.kv('Repair Runs', system.formatNumber(entries.length));
      kit.kv('Problems Found (total)', system.formatNumber(totalFound));
      kit.kv('Problems Fixed (total)', system.formatNumber(totalFixed), 'brightGreen');
      kit.kv('Last Repair', entries[0].date);
      kit.kv('Last Status', entries[0].status, statusColor(entries[0].status));

      ui.blank();
      ui.section('HISTORY');
      ui.blank();
      kit.table(
        ['DATE', 'MODE', 'FOUND', 'FIXED', 'STATUS'],
        entries.map((entry) => [
          ui.c.brightWhite(ui.truncate(entry.date || '-', 20)),
          ui.c.gray(entry.mode || '-'),
          ui.c.brightYellow(String(entry.problemsFound || 0)),
          ui.c.brightGreen(String(entry.problemsFixed || 0)),
          ui.c[statusColor(entry.status)](entry.status || '-'),
        ]),
        { align: ['left', 'left', 'right', 'right', 'left'], limit: 20 }
      );

      ui.blank();
      ui.menu(
        [
          { key: '1', label: 'Open the log of a run' },
          { key: '2', label: 'Export the history as a TXT report' },
          { separator: true },
          { key: '0', label: 'Back', color: 'gray' },
        ],
        { title: 'REPAIR 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 run?',
          entries.map((entry) => ({ label: `${entry.date} (${entry.mode})`, hint: entry.status }))
        );
        if (index === null) continue;
        const entry = entries[index];

        ui.blank();
        ui.section('REPAIR RUN');
        ui.blank();
        kit.kv('Date', entry.date);
        kit.kv('Repair Mode', entry.mode);
        kit.kv('Problems Found', String(entry.problemsFound || 0));
        kit.kv('Problems Fixed', String(entry.problemsFixed || 0));
        kit.kv('Final Status', entry.status, statusColor(entry.status));
        kit.kv('Log File', entry.log);

        if (entry.log && fs.existsSync(entry.log)) {
          ui.blank();
          ui.section('LOG');
          ui.blank();
          try {
            const lines = fs.readFileSync(entry.log, 'utf8').split(/\r?\n/).filter((line) => line.trim());
            for (const line of lines.slice(0, 40)) {
              const color = line.includes('FAIL') ? 'brightRed' : line.includes('FIX') ? 'brightGreen' : line.includes('WARN') ? 'yellow' : 'gray';
              ui.println('  ' + ui.c[color](ui.truncate(line, ui.getWidth())));
            }
            if (lines.length > 40) ui.println('  ' + ui.c.gray(`... and ${lines.length - 40} more line(s)`));
          } catch (err) {
            ui.warning(`The log could not be read: ${err.message}`);
          }
        } else {
          ui.blank();
          ui.println('  ' + ui.c.gray('The log file of this run is no longer on disk.'));
        }
        await prompt.pause();
      } else if (answer === '2') {
        const report = kit.report('Repair History Report');
        const section = report.section('SUMMARY');
        section.add('Repair Runs', system.formatNumber(entries.length));
        section.add('Problems Found (total)', system.formatNumber(totalFound));
        section.add('Problems Fixed (total)', system.formatNumber(totalFixed));

        const list = report.section('HISTORY');
        entries.forEach((entry, index) => {
          const group = list.group(`${index + 1}. ${entry.date}`);
          group.add('Repair Mode', entry.mode);
          group.add('Problems Found', String(entry.problemsFound || 0));
          group.add('Problems Fixed', String(entry.problemsFixed || 0));
          group.add('Final Status', entry.status);
          group.add('Log File', entry.log);
        });
        kit.saveReport(report, 'RepairHistory');
        await prompt.pause();
      } else {
        ui.warning('Enter one of the numbers shown above, or 0 to go back.');
        await prompt.pause();
      }
    }

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