const os = require('os');
const path = require('path');
const { execFile } = require('child_process');
const { readdir, rm, stat } = require('fs/promises');

function runCommand(command, args = [], timeout = 15000) {
  return new Promise((resolve) => {
    execFile(command, args, { timeout, windowsHide: true }, (error, stdout, stderr) => {
      resolve({
        ok: !error,
        command: [command, ...args].join(' '),
        output: String(stdout || '').trim(),
        error: String(stderr || error?.message || '').trim()
      });
    });
  });
}

async function folderSize(target) {
  try {
    const info = await stat(target);
    if (!info.isDirectory()) return info.size;
    const entries = await readdir(target, { withFileTypes: true });
    let total = 0;
    for (const entry of entries) {
      total += await folderSize(path.join(target, entry.name));
    }
    return total;
  } catch {
    return 0;
  }
}

function bytesToGb(bytes) {
  return Math.round((Number(bytes || 0) / 1024 / 1024 / 1024) * 10) / 10;
}

async function cleanDirectoryContents(target) {
  const before = await folderSize(target);
  let removed = 0;
  let skipped = 0;
  try {
    const entries = await readdir(target, { withFileTypes: true });
    for (const entry of entries) {
      const fullPath = path.join(target, entry.name);
      try {
        await rm(fullPath, { recursive: true, force: true, maxRetries: 2 });
        removed += 1;
      } catch {
        skipped += 1;
      }
    }
  } catch {
    skipped += 1;
  }
  const after = await folderSize(target);
  return { target, removed, skipped, beforeGb: bytesToGb(before), afterGb: bytesToGb(after), freedGb: Math.max(0, bytesToGb(before - after)) };
}

function oncallSupportDataTargets() {
  const home = os.homedir();
  const appData = process.platform === 'win32'
    ? process.env.APPDATA || path.join(home, 'AppData', 'Roaming')
    : path.join(home, 'Library', 'Application Support');
  const cacheDir = process.platform === 'win32'
    ? process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local')
    : path.join(home, 'Library', 'Caches');
  return [
    path.join(appData, 'OnCallTechSA Support App'),
    path.join(appData, 'oncalltechsa-support-app'),
    path.join(cacheDir, 'OnCallTechSA Support App'),
    path.join(cacheDir, 'oncalltechsa-support-app'),
    path.join(os.tmpdir(), 'oncalltechsa'),
    path.join(os.tmpdir(), 'oncalltechsa-support-app')
  ];
}

async function repairAction(action) {
  if (action === 'fix-security-baseline') {
    const result = process.platform === 'win32'
      ? await runCommand('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', 'Start-Process windowsdefender:'])
      : await runCommand('/usr/bin/open', ['x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension']);
    return {
      ok: result.ok,
      action,
      title: 'Security fix assistant opened',
      detail: result.ok
        ? 'Review the flagged security controls, enable the recommended protection, then run Rescan after fix. OnCallTechSA does not store or request your admin password.'
        : result.error,
      command: result.command,
      nextSteps: process.platform === 'win32'
        ? [
            'Turn on Microsoft Defender real-time protection if it is disabled.',
            'Open Firewall & network protection and enable firewall profiles.',
            'Open BitLocker Drive Encryption if device encryption is flagged.',
            'Restart if Windows Update or security settings require it, then rescan.'
          ]
        : [
            'Enable FileVault if encryption is flagged.',
            'Enable Firewall if firewall is flagged.',
            'Keep Gatekeeper enabled for downloaded app protection.',
            'SIP changes require Recovery Mode and should be specialist-approved.',
            'Rescan after each change.'
          ]
    };
  }

  if (action === 'open-firewall-settings') {
    const result = process.platform === 'win32'
      ? await runCommand('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', 'Start-Process wf.msc'])
      : await runCommand('/usr/bin/open', ['x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension']);
    return { ok: result.ok, action, title: 'Firewall settings opened', detail: result.ok ? 'Enable firewall protection, approve any OS prompt, then rescan.' : result.error, command: result.command };
  }

  if (action === 'open-encryption-settings') {
    const result = process.platform === 'win32'
      ? await runCommand('control.exe', ['/name', 'Microsoft.BitLockerDriveEncryption'])
      : await runCommand('/usr/bin/open', ['x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension']);
    return { ok: result.ok, action, title: process.platform === 'win32' ? 'BitLocker settings opened' : 'FileVault settings opened', detail: result.ok ? 'Enable disk encryption only when you have recovery key handling in place. Rescan after the OS confirms protection is enabled.' : result.error, command: result.command };
  }

  if (action === 'open-antivirus-settings') {
    const result = process.platform === 'win32'
      ? await runCommand('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', 'Start-Process windowsdefender:'])
      : await runCommand('/usr/bin/open', ['x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension']);
    return { ok: result.ok, action, title: process.platform === 'win32' ? 'Defender settings opened' : 'Security settings opened', detail: result.ok ? 'Enable real-time protection or confirm the approved endpoint security tool is active, then rescan.' : result.error, command: result.command };
  }

  if (action === 'cleanup-caches') {
    const targets = oncallSupportDataTargets().filter((target) => /oncalltechsa/i.test(target));
    const results = [];
    for (const target of [...new Set(targets)]) {
      results.push(await cleanDirectoryContents(target));
    }
    const freedGb = Math.round(results.reduce((sum, item) => sum + item.freedGb, 0) * 10) / 10;
    return {
      ok: true,
      action,
      title: 'OnCallTechSA support cache cleanup complete',
      detail: `Cleared only OnCallTechSA support-app cache/session folders. No user documents, browser data, mail, photos, or third-party app caches were touched. Estimated freed space: ${freedGb}GB.`,
      results
    };
  }

  if (action === 'deactivate-once-off-session') {
    const targets = oncallSupportDataTargets().filter((target) => /oncalltechsa/i.test(target));
    const results = [];
    for (const target of [...new Set(targets)]) {
      results.push(await cleanDirectoryContents(target));
    }
    return {
      ok: true,
      action,
      title: 'Once-off support session deactivated',
      detail: 'Local OnCallTechSA support session data was cleared. Use the operating system uninstall flow to remove the app package; the app will not remove user files or silently delete itself.',
      uninstallInstructions: process.platform === 'win32'
        ? ['Open Windows Settings > Apps > Installed apps.', 'Search for OnCallTechSA Support App.', 'Choose Uninstall and approve the Windows prompt.']
        : ['Quit OnCallTechSA Support App.', 'Open Applications.', 'Move OnCallTechSA Support App to Trash.', 'Empty Trash only if you are sure you no longer need the app.'],
      results
    };
  }

  if (action === 'open-storage-settings') {
    const result = process.platform === 'win32'
      ? await runCommand('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', 'Start-Process ms-settings:storagesense'])
      : await runCommand('/usr/bin/open', ['x-apple.systempreferences:com.apple.settings.Storage']);
    return { ok: result.ok, action, title: 'Storage settings opened', detail: result.ok ? 'Review large files, downloads, applications, and local cloud sync storage.' : result.error, command: result.command };
  }

  if (action === 'open-software-update') {
    const result = process.platform === 'win32'
      ? await runCommand('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', 'Start-Process ms-settings:windowsupdate'])
      : await runCommand('/usr/bin/open', ['x-apple.systempreferences:com.apple.Software-Update-Settings.extension']);
    return { ok: result.ok, action, title: 'Software update opened', detail: result.ok ? 'Use the operating system update screen to install updates. Admin approval or restart may be required.' : result.error, command: result.command };
  }

  if (action === 'open-security-settings') {
    const result = process.platform === 'win32'
      ? await runCommand('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', 'Start-Process windowsdefender:'])
      : await runCommand('/usr/bin/open', ['x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension']);
    return { ok: result.ok, action, title: 'Security settings opened', detail: result.ok ? 'Use the operating system security screen for FileVault, firewall, Defender, and privacy controls. Admin approval may be required.' : result.error, command: result.command };
  }

  if (action === 'flush-dns') {
    const result = process.platform === 'win32'
      ? await runCommand('ipconfig.exe', ['/flushdns'])
      : await runCommand('/usr/bin/dscacheutil', ['-flushcache']);
    return { ok: result.ok, action, title: 'DNS cache flushed', detail: result.ok ? 'DNS resolver cache was refreshed. Re-test connectivity if a website or email host was failing.' : result.error, command: result.command, output: result.output };
  }

  return { ok: false, action, error: 'Unsupported repair action.' };
}

module.exports = { repairAction };
