const { app, BrowserWindow, ipcMain, shell, session, Tray, Menu, nativeImage } = require('electron');
const { execFile } = require('child_process');
const os = require('os');
const path = require('path');
const nativeScanner = require('./health-scan');
const { repairAction } = require('./repair-actions');
const { startLocalScanServer, stopLocalScanServer } = require('./local-scan-server');

const supportAppUrl = process.env.ONCALL_SUPPORT_APP_URL || 'https://oncalltechsa.co.za/support-app/';
const allowedOrigin = new URL(supportAppUrl).origin;
const desktopVersion = '0.3.8-bridge-connectivity-rc1';
let localScannerState = {
  ok: false,
  host: '127.0.0.1',
  port: 37879,
  startedAt: '',
  error: '',
  alreadyRunning: false
};
let mainWindow = null;
let tray = null;
let isQuitting = false;
const allowedRepairActions = new Set([
  'cleanup-caches',
  'open-storage-settings',
  'open-software-update',
  'open-security-settings',
  'fix-security-baseline',
  'open-firewall-settings',
  'open-encryption-settings',
  'open-antivirus-settings',
  'flush-dns',
  'deactivate-once-off-session'
]);

function runCommand(command, args = [], timeout = 8000) {
  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()
      });
    });
  });
}

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

function parseMacDisk(dfOutput) {
  const line = dfOutput.split('\n').find((row) => row.includes(' /System/Volumes/Data')) || dfOutput.split('\n').find((row) => row.includes(' /')) || '';
  const parts = line.trim().split(/\s+/);
  if (parts.length < 5) return null;
  return {
    filesystem: parts[0],
    totalGb: Math.round((Number(parts[1] || 0) / 1024 / 1024) * 10) / 10,
    usedGb: Math.round((Number(parts[2] || 0) / 1024 / 1024) * 10) / 10,
    freeGb: Math.round((Number(parts[3] || 0) / 1024 / 1024) * 10) / 10,
    usedPercent: parts[4]
  };
}

function parseDiskutilInfo(output) {
  const valueFor = (label) => {
    const line = output.split('\n').find((row) => row.trim().startsWith(`${label}:`));
    return line ? line.split(':').slice(1).join(':').trim() : '';
  };
  return {
    smartStatus: valueFor('SMART Status'),
    fileVault: valueFor('FileVault'),
    volumeName: valueFor('Volume Name'),
    fileSystem: valueFor('File System Personality'),
    freeSpace: valueFor('Container Free Space'),
    usedSpace: valueFor('Volume Used Space'),
    totalSpace: valueFor('Container Total Space') || valueFor('Disk Size')
  };
}

function parseMacPower(output) {
  const valueFor = (label) => {
    const line = output.split('\n').find((row) => row.trim().startsWith(`${label}:`));
    return line ? line.split(':').slice(1).join(':').trim() : '';
  };
  return {
    cycleCount: valueFor('Cycle Count'),
    condition: valueFor('Condition'),
    maximumCapacity: valueFor('Maximum Capacity'),
    chargeBelowWarning: valueFor('The battery’s charge is below the warning level')
  };
}

function parseMemoryPressure(output) {
  const match = output.match(/System-wide memory free percentage:\s*(\d+)%/i);
  return match ? Number(match[1]) : null;
}

function parseProcessRows(output) {
  return output
    .split('\n')
    .slice(1)
    .map((line) => line.trim().split(/\s+/))
    .filter((parts) => parts.length >= 4)
    .slice(0, 8)
    .map((parts) => ({
      pid: parts[0],
      cpu: parts[1],
      memory: parts[2],
      command: parts.slice(3).join(' ')
    }));
}

function evidenceCheck({ id, title, severity = 'ok', detail, evidence = [], recommendation, category = 'System' }) {
  return {
    id,
    title,
    severity,
    category,
    detail: cleanLine(detail),
    evidence: Array.isArray(evidence) ? evidence.map(cleanLine).filter(Boolean) : [],
    recommendation: cleanLine(recommendation)
  };
}

function cleanLine(value) {
  return String(value || '').replace(/\s+\n/g, '\n').trim();
}

function parseWindowsJson(output, fallback = null) {
  try {
    if (!output) return fallback;
    return JSON.parse(output);
  } catch {
    return fallback;
  }
}

function scoreFinding(severity) {
  if (severity === 'critical') return 18;
  if (severity === 'warning') return 9;
  return 0;
}

function buildScanSummary({ platform, checks }) {
  const findings = [];
  checks.forEach((check) => {
    if (check.severity !== 'ok') findings.push(check);
  });
  const penalty = findings.reduce((sum, finding) => sum + scoreFinding(finding.severity), 0);
  const score = Math.max(0, 100 - penalty);
  return {
    score,
    status: score >= 85 ? 'Good health' : score >= 65 ? 'Needs attention' : 'At risk',
    platform,
    findings: findings.map((item) => item.title),
    recommendations: findings.slice(0, 5).map((item) => item.recommendation)
  };
}

async function scanMac() {
  const [swVers, kernel, hardware, diskData, diskInfoRaw, filevault, firewall, battery, power, uptime, memoryPressure, gatekeeper, sip, dns, route, internet, oncall, processes] = await Promise.all([
    runCommand('/usr/bin/sw_vers'),
    runCommand('/usr/bin/uname', ['-a']),
    runCommand('/usr/sbin/system_profiler', ['SPHardwareDataType', '-detailLevel', 'mini'], 12000),
    runCommand('/bin/df', ['-h', '/System/Volumes/Data']),
    runCommand('/usr/sbin/diskutil', ['info', '/System/Volumes/Data']),
    runCommand('/usr/bin/fdesetup', ['status']),
    runCommand('/usr/libexec/ApplicationFirewall/socketfilterfw', ['--getglobalstate']),
    runCommand('/usr/bin/pmset', ['-g', 'batt']),
    runCommand('/usr/sbin/system_profiler', ['SPPowerDataType', '-detailLevel', 'mini'], 12000),
    runCommand('/usr/bin/uptime'),
    runCommand('/usr/bin/memory_pressure'),
    runCommand('/usr/sbin/spctl', ['--status']),
    runCommand('/usr/bin/csrutil', ['status']),
    runCommand('/usr/sbin/scutil', ['--dns']),
    runCommand('/sbin/route', ['-n', 'get', 'default']),
    runCommand('/usr/bin/nc', ['-vz', '-G', '5', '1.1.1.1', '443']),
    runCommand('/usr/bin/nc', ['-vz', '-G', '5', 'oncalltechsa.co.za', '443']),
    runCommand('/bin/ps', ['ax', '-o', 'pid,%cpu,%mem,comm', '-r'])
  ]);

  const totalMemGb = bytesToGb(os.totalmem());
  const freeMemGb = bytesToGb(os.freemem());
  const diskInfo = parseMacDisk(diskData.output);
  const diskMeta = parseDiskutilInfo(diskInfoRaw.output || '');
  const diskUsed = Number(String(diskInfo?.usedPercent || '0').replace('%', ''));
  const fileVaultOn = filevault.ok && /is on/i.test(filevault.output);
  const firewallOn = /enabled/i.test(firewall.output);
  const batteryText = battery.output || 'No battery information available';
  const powerInfo = parseMacPower(power.output || '');
  const memoryFreePercent = parseMemoryPressure(memoryPressure.output || '');
  const gatekeeperOn = /enabled/i.test(gatekeeper.output);
  const sipOn = /enabled/i.test(sip.output);
  const dnsReady = /nameserver/i.test(dns.output) && /Reachable/i.test(dns.output);
  const routeReady = /gateway:/i.test(route.output) && /interface:/i.test(route.output);
  const internetReady = internet.ok || /succeeded/i.test(`${internet.output} ${internet.error}`);
  const oncallReady = oncall.ok || /succeeded/i.test(`${oncall.output} ${oncall.error}`);
  const topProcesses = parseProcessRows(processes.output || '');
  const hardwareSummary = hardware.output
    .split('\n')
    .map((line) => line.trim())
    .filter((line) => /Model Name|Model Identifier|Chip|Total Number of Cores|Memory:/.test(line))
    .join(' · ');

  const checks = [
    evidenceCheck({
      id: 'os',
      title: 'macOS version detected',
      severity: 'ok',
      category: 'System',
      detail: swVers.output || kernel.output,
      evidence: [kernel.output],
      recommendation: 'Keep macOS current with supported security updates.'
    }),
    evidenceCheck({
      id: 'cpu-memory',
      title: memoryFreePercent !== null && memoryFreePercent < 15 ? 'Memory pressure needs attention' : 'Hardware and memory collected',
      severity: totalMemGb < 8 || (memoryFreePercent !== null && memoryFreePercent < 15) ? 'warning' : 'ok',
      category: 'Performance',
      detail: `${hardwareSummary || os.cpus()[0]?.model || 'Hardware detected'} · ${totalMemGb}GB RAM · ${freeMemGb}GB free memory`,
      evidence: [
        memoryFreePercent !== null ? `System-wide memory free percentage: ${memoryFreePercent}%` : '',
        memoryPressure.output.split('\n').find((line) => line.includes('Swapouts')) || ''
      ],
      recommendation: 'Close unused apps and review startup/background apps if the device feels slow.'
    }),
    evidenceCheck({
      id: 'disk',
      title: diskUsed >= 90 ? 'Disk space critically low' : diskUsed >= 80 ? 'Disk space needs attention' : 'Disk space healthy',
      severity: diskUsed >= 90 ? 'critical' : diskUsed >= 80 ? 'warning' : 'ok',
      category: 'Storage',
      detail: diskInfo ? `${diskInfo.usedPercent} used · ${diskInfo.freeGb || diskInfo.freeGb === 0 ? `${diskInfo.freeGb}GB` : diskInfo.freeGb} free on ${diskInfo.filesystem}` : 'Disk usage unavailable',
      evidence: [
        diskData.output,
        diskMeta.smartStatus ? `SMART Status: ${diskMeta.smartStatus}` : '',
        diskMeta.totalSpace ? `Container total: ${diskMeta.totalSpace}` : '',
        diskMeta.freeSpace ? `Container free: ${diskMeta.freeSpace}` : ''
      ],
      recommendation: diskUsed >= 90
        ? 'Free at least 30-50GB before major updates or remote work. Review Downloads, videos, old installers, cache, and OneDrive local sync.'
        : 'Keep at least 15-20% storage free for updates, app stability, and performance.'
    }),
    evidenceCheck({
      id: 'filevault',
      title: fileVaultOn ? 'FileVault encryption enabled' : filevault.ok ? 'FileVault encryption disabled' : 'FileVault status could not be verified',
      severity: fileVaultOn ? 'ok' : 'warning',
      category: 'Security',
      detail: filevault.output || filevault.error,
      evidence: [diskMeta.fileVault ? `Disk FileVault: ${diskMeta.fileVault}` : ''],
      recommendation: 'Enable FileVault to protect business data if the Mac is lost or stolen.'
    }),
    evidenceCheck({
      id: 'firewall',
      title: firewallOn ? 'macOS firewall enabled' : 'macOS firewall disabled',
      severity: firewallOn ? 'ok' : 'warning',
      category: 'Security',
      detail: firewall.output || firewall.error,
      recommendation: 'Enable the macOS firewall for better protection on untrusted networks.'
    }),
    evidenceCheck({
      id: 'gatekeeper',
      title: gatekeeperOn ? 'Gatekeeper assessments enabled' : 'Gatekeeper assessments disabled',
      severity: gatekeeperOn ? 'ok' : 'critical',
      category: 'Security',
      detail: gatekeeper.output || gatekeeper.error,
      recommendation: 'Keep Gatekeeper enabled so macOS can block untrusted or unsigned apps.'
    }),
    evidenceCheck({
      id: 'sip',
      title: sipOn ? 'System Integrity Protection enabled' : 'System Integrity Protection disabled',
      severity: sipOn ? 'ok' : 'critical',
      category: 'Security',
      detail: sip.output || sip.error,
      recommendation: 'Keep SIP enabled unless a specialist-approved workflow requires otherwise.'
    }),
    evidenceCheck({
      id: 'battery',
      title: /Normal/i.test(powerInfo.condition) ? 'Battery health normal' : 'Battery health needs review',
      severity: /Service Battery|Replace/i.test(`${batteryText} ${powerInfo.condition}`) ? 'warning' : 'ok',
      category: 'Hardware',
      detail: batteryText,
      evidence: [
        powerInfo.cycleCount ? `Cycle Count: ${powerInfo.cycleCount}` : '',
        powerInfo.condition ? `Condition: ${powerInfo.condition}` : '',
        powerInfo.maximumCapacity ? `Maximum Capacity: ${powerInfo.maximumCapacity}` : ''
      ],
      recommendation: 'Review battery condition if macOS reports service or replacement warnings.'
    }),
    evidenceCheck({
      id: 'network',
      title: internetReady && oncallReady ? 'Network and service connectivity verified' : 'Network connectivity needs review',
      severity: internetReady && oncallReady && dnsReady && routeReady ? 'ok' : 'warning',
      category: 'Network',
      detail: `DNS ${dnsReady ? 'reachable' : 'not confirmed'} · default route ${routeReady ? 'detected' : 'not confirmed'} · internet ${internetReady ? 'ok' : 'failed'} · OnCallTechSA ${oncallReady ? 'ok' : 'failed'}`,
      evidence: [
        route.output.split('\n').filter((line) => /gateway|interface/.test(line)).join(' · '),
        dns.output.split('\n').find((line) => line.includes('nameserver')) || '',
        internet.output || internet.error,
        oncall.output || oncall.error
      ],
      recommendation: 'If web apps are slow, compare this result with another network before changing device settings.'
    }),
    evidenceCheck({
      id: 'uptime',
      title: 'System uptime collected',
      severity: 'ok',
      category: 'Performance',
      detail: uptime.output,
      recommendation: 'Restart periodically when troubleshooting performance or update issues.'
    }),
    evidenceCheck({
      id: 'top-processes',
      title: 'Top resource usage captured',
      severity: topProcesses.some((item) => Number(item.cpu) > 80) ? 'warning' : 'ok',
      category: 'Performance',
      detail: topProcesses.length ? topProcesses.map((item) => `${item.command} (${item.cpu}% CPU, ${item.memory}% MEM)`).join('\n') : 'Process usage unavailable',
      evidence: topProcesses.map((item) => `PID ${item.pid}: ${item.command}`),
      recommendation: 'If the Mac feels slow, close the heaviest apps and rerun the scan after a restart.'
    })
  ];

  return {
    generatedAt: new Date().toISOString(),
    platform: 'macOS',
    device: {
      hostname: os.hostname(),
      arch: os.arch(),
      release: os.release(),
      cpu: hardwareSummary || os.cpus()[0]?.model || '',
      totalMemoryGb: totalMemGb,
      freeMemoryGb: freeMemGb
    },
    disk: { ...diskInfo, ...diskMeta },
    evidence: {
      scanType: 'read_only_native_desktop_scan',
      privacy: 'No private files, passwords, browser history, messages, or document contents were read.',
      commands: [swVers, hardware, diskData, diskInfoRaw, filevault, firewall, battery, power, uptime, memoryPressure, gatekeeper, sip, dns, route, internet, oncall, processes]
        .map((item) => item.command)
        .filter(Boolean)
    },
    checks,
    summary: buildScanSummary({ platform: 'macOS', checks })
  };
}

async function scanWindows() {
  const ps = 'powershell.exe';
  const [osInfo, computer, disk, defender, hotfixes, battery] = await Promise.all([
    runCommand(ps, ['-NoProfile', '-Command', 'Get-CimInstance Win32_OperatingSystem | Select-Object Caption,Version,BuildNumber,LastBootUpTime | ConvertTo-Json -Compress']),
    runCommand(ps, ['-NoProfile', '-Command', 'Get-CimInstance Win32_ComputerSystem | Select-Object Manufacturer,Model,TotalPhysicalMemory | ConvertTo-Json -Compress']),
    runCommand(ps, ['-NoProfile', '-Command', 'Get-CimInstance Win32_LogicalDisk -Filter "DeviceID=\'C:\'" | Select-Object Size,FreeSpace | ConvertTo-Json -Compress']),
    runCommand(ps, ['-NoProfile', '-Command', 'Get-MpComputerStatus | Select-Object AMServiceEnabled,AntivirusEnabled,RealTimeProtectionEnabled,AntivirusSignatureLastUpdated | ConvertTo-Json -Compress']),
    runCommand(ps, ['-NoProfile', '-Command', 'Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 1 HotFixID,InstalledOn | ConvertTo-Json -Compress']),
    runCommand(ps, ['-NoProfile', '-Command', 'Get-CimInstance Win32_Battery | Select-Object EstimatedChargeRemaining,BatteryStatus | ConvertTo-Json -Compress'])
  ]);

  const osJson = parseWindowsJson(osInfo.output, {});
  const computerJson = parseWindowsJson(computer.output, {});
  const diskJson = parseWindowsJson(disk.output, {});
  const defenderJson = parseWindowsJson(defender.output, {});
  const hotfixJson = parseWindowsJson(hotfixes.output, {});
  const batteryJson = parseWindowsJson(battery.output, null);
  const totalGb = bytesToGb(diskJson.Size);
  const freeGb = bytesToGb(diskJson.FreeSpace);
  const usedPercent = totalGb ? Math.round(((totalGb - freeGb) / totalGb) * 100) : 0;
  const defenderOk = defenderJson.AntivirusEnabled && defenderJson.RealTimeProtectionEnabled;

  const checks = [
    {
      id: 'os',
      title: 'Windows version detected',
      severity: 'ok',
      detail: `${osJson.Caption || 'Windows'} ${osJson.Version || ''} build ${osJson.BuildNumber || ''}`,
      recommendation: 'Keep Windows current with supported security updates.'
    },
    {
      id: 'cpu-memory',
      title: 'Hardware profile collected',
      severity: bytesToGb(computerJson.TotalPhysicalMemory || os.totalmem()) < 8 ? 'warning' : 'ok',
      detail: `${computerJson.Manufacturer || ''} ${computerJson.Model || ''} · ${bytesToGb(computerJson.TotalPhysicalMemory || os.totalmem())}GB RAM`,
      recommendation: 'Review memory pressure and startup apps if the device feels slow.'
    },
    {
      id: 'disk',
      title: usedPercent >= 90 ? 'Disk space critically low' : usedPercent >= 80 ? 'Disk space needs attention' : 'Disk space healthy',
      severity: usedPercent >= 90 ? 'critical' : usedPercent >= 80 ? 'warning' : 'ok',
      detail: `${usedPercent}% used · ${freeGb}GB free of ${totalGb}GB`,
      recommendation: 'Free storage, remove temporary files, and review local sync/cache usage.'
    },
    {
      id: 'defender',
      title: defenderOk ? 'Antivirus protection active' : 'Antivirus protection needs review',
      severity: defenderOk ? 'ok' : 'critical',
      detail: defender.ok ? JSON.stringify(defenderJson) : defender.error,
      recommendation: 'Enable Defender real-time protection or confirm approved endpoint security is active.'
    },
    {
      id: 'updates',
      title: 'Latest installed hotfix collected',
      severity: hotfixes.ok ? 'ok' : 'warning',
      detail: hotfixes.ok ? JSON.stringify(hotfixJson) : hotfixes.error,
      recommendation: 'Run Windows Update if the latest hotfix is old or missing.'
    },
    {
      id: 'battery',
      title: batteryJson ? 'Battery status collected' : 'Battery status unavailable',
      severity: batteryJson ? 'ok' : 'warning',
      detail: batteryJson ? JSON.stringify(batteryJson) : 'No battery object returned',
      recommendation: 'Review battery health if Windows reports low capacity or service warnings.'
    }
  ];

  return {
    generatedAt: new Date().toISOString(),
    platform: 'Windows',
    device: {
      hostname: os.hostname(),
      arch: os.arch(),
      release: os.release(),
      totalMemoryGb: bytesToGb(computerJson.TotalPhysicalMemory || os.totalmem()),
      freeMemoryGb: bytesToGb(os.freemem())
    },
    disk: { totalGb, freeGb, usedPercent },
    checks,
    summary: buildScanSummary({ platform: 'Windows', checks })
  };
}

async function runHealthScan() {
  if (process.platform === 'darwin') return await scanMac();
  if (process.platform === 'win32') return await scanWindows();
  const checks = [
    {
      id: 'platform',
      title: 'Unsupported desktop scan platform',
      severity: 'warning',
      detail: `${process.platform} ${os.release()}`,
      recommendation: 'Windows and macOS scans are supported first. Linux support is planned.'
    }
  ];
  return {
    generatedAt: new Date().toISOString(),
    platform: process.platform,
    device: { hostname: os.hostname(), arch: os.arch(), release: os.release() },
    checks,
    summary: buildScanSummary({ platform: process.platform, checks })
  };
}

function isTrustedUrl(url) {
  try {
    const parsed = new URL(url);
    return parsed.protocol === 'https:' && parsed.origin === allowedOrigin;
  } catch {
    return false;
  }
}

function isTrustedPermissionOrigin(value) {
  try {
    return new URL(value).origin === allowedOrigin;
  } catch {
    return false;
  }
}

function configureSupportPermissions(targetSession) {
  targetSession.setPermissionRequestHandler((webContents, permission, callback, details = {}) => {
    const requestingUrl = details.requestingUrl || webContents?.getURL() || '';
    const localNetworkPermission = permission === 'local-network-access' || permission === 'private-network-access' || permission === 'unknown';
    callback(localNetworkPermission && isTrustedPermissionOrigin(requestingUrl));
  });
  targetSession.setPermissionCheckHandler((webContents, permission, requestingOrigin, details = {}) => {
    const origin = requestingOrigin || details.requestingUrl || webContents?.getURL() || '';
    const localNetworkPermission = permission === 'local-network-access' || permission === 'private-network-access' || permission === 'unknown';
    return localNetworkPermission && isTrustedPermissionOrigin(origin);
  });
}

function createWindow() {
  if (mainWindow) {
    if (mainWindow.isMinimized()) mainWindow.restore();
    mainWindow.show();
    mainWindow.focus();
    return;
  }

  mainWindow = new BrowserWindow({
    width: 1120,
    height: 820,
    minWidth: 860,
    minHeight: 640,
    title: 'OnCallTechSA Support App',
    webPreferences: {
      preload: `${__dirname}/preload.js`,
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
      webSecurity: true,
      allowRunningInsecureContent: false,
      experimentalFeatures: false,
      enableBlinkFeatures: '',
      disableBlinkFeatures: 'WebSQL',
      webviewTag: false
    }
  });

  configureSupportPermissions(mainWindow.webContents.session);

  mainWindow.webContents.on('will-attach-webview', (event) => {
    event.preventDefault();
  });

  mainWindow.webContents.setWindowOpenHandler(({ url }) => {
    if (isTrustedUrl(url)) return { action: 'deny' };
    if (/^https:\/\//i.test(url)) shell.openExternal(url);
    return { action: 'deny' };
  });

  mainWindow.webContents.on('will-navigate', (event, url) => {
    if (isTrustedUrl(url)) return;
    event.preventDefault();
    if (/^https:\/\//i.test(url)) shell.openExternal(url);
  });

  mainWindow.on('close', (event) => {
    if (isQuitting) return;
    event.preventDefault();
    mainWindow.hide();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  const launchUrl = new URL(supportAppUrl);
  launchUrl.searchParams.set('desktopApp', '1');
  launchUrl.searchParams.set('desktopVersion', desktopVersion);
  launchUrl.searchParams.set('cacheBust', String(Date.now()));
  mainWindow.loadURL(launchUrl.toString());
}

function createTray() {
  if (tray) return;
  const iconPath = path.join(__dirname, '..', 'electron.icns');
  const fallbackIcon = nativeImage.createFromDataURL(
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAKElEQVR42mP8z8AARLJgwiM3NVQ1EwMDA8N/BlTNgAqGk0gAAGd9EwERdM0nAAAAAElFTkSuQmCC'
  );
  const image = nativeImage.createFromPath(iconPath);
  tray = new Tray((image.isEmpty() ? fallbackIcon : image).resize({ width: 18, height: 18 }));
  tray.setToolTip('OnCallTechSA Support App - scanner bridge running');
  tray.setContextMenu(Menu.buildFromTemplate([
    { label: 'Open Support App', click: () => createWindow() },
    { label: 'Scanner bridge running on 127.0.0.1:37879', enabled: false },
    { type: 'separator' },
    {
      label: 'Quit OnCallTechSA Support App',
      click: () => {
        isQuitting = true;
        app.quit();
      }
    }
  ]));
  tray.on('click', () => createWindow());
}

const singleInstanceLock = app.requestSingleInstanceLock();
if (!singleInstanceLock) {
  app.quit();
} else {
app.on('second-instance', () => {
  if (!mainWindow) {
    createWindow();
    return;
  }
  if (mainWindow.isMinimized()) mainWindow.restore();
  mainWindow.focus();
});

app.whenReady().then(async () => {
  app.setName('OnCallTechSA Support App');
  if (process.platform === 'win32') app.setAppUserModelId('za.co.oncalltechsa.supportapp');
  try {
    app.setLoginItemSettings({
      openAtLogin: true,
      openAsHidden: true,
      name: 'OnCallTechSA Support App'
    });
  } catch (error) {
    console.warn(`[startup] Could not register login item: ${error.message}`);
  }
  configureSupportPermissions(session.defaultSession);
  try {
    await session.defaultSession.clearStorageData({
      storages: ['serviceworkers', 'cachestorage']
    });
  } catch (error) {
    console.warn(`[startup] Could not clear stale support-app cache: ${error.message}`);
  }

  ipcMain.handle('device:health-scan', async () => {
    return await nativeScanner.runHealthScan();
  });
  ipcMain.handle('device:bridge-status', async () => ({
    ok: true,
    desktopBridge: true,
    platform: process.platform,
    arch: process.arch,
    version: desktopVersion,
    localScanner: localScannerState,
    supportAppUrl,
    allowedOrigin
  }));
  ipcMain.handle('device:repair-action', async (_event, action) => {
    const requested = String(action || '');
    if (!allowedRepairActions.has(requested)) {
      return { ok: false, action: requested, error: 'Unsupported or blocked repair action.' };
    }
    return await repairAction(requested);
  });
  startLocalScanServer({
    log: (message) => console.log(`[local-scanner] ${message}`)
  }).then((result) => {
    localScannerState = {
      ok: Boolean(result.ok || result.alreadyRunning),
      host: result.host || '127.0.0.1',
      port: result.port || 37879,
      startedAt: new Date().toISOString(),
      error: result.error || '',
      alreadyRunning: Boolean(result.alreadyRunning)
    };
    if (!result.ok && !result.alreadyRunning) {
      console.warn(`[local-scanner] ${result.error || 'Failed to start local scanner.'}`);
    }
  });
  createTray();
  createWindow();
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});
}

app.on('window-all-closed', () => {
  if (isQuitting) app.quit();
});

app.on('before-quit', () => {
  isQuitting = true;
  stopLocalScanServer();
});
