const express = require('express');
const { exec }  = require('child_process');
const path      = require('path');
const router    = express.Router();
const PANEL_DIR = path.join(__dirname, '..');

// Run an arbitrary PowerShell command safely using -EncodedCommand (no quoting issues)
function runPS(code) {
  return new Promise(resolve => {
    const encoded = Buffer.from(code, 'utf16le').toString('base64');
    exec(
      `powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${encoded}`,
      { timeout: 12000 },
      (_err, stdout) => resolve((stdout || '').trim())
    );
  });
}

router.get('/', async (req, res) => {
  try {
    const [
      osOut, adminOut, iisOut, dotnetOut, nodeOut,
      chocoOut, dbOut, gitOut, portsOut, diskOut, psOut, ancmOut, unzipperOut
    ] = await Promise.all([
      runPS(`(Get-WmiObject Win32_OperatingSystem).Caption`),
      runPS(`([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)`),
      runPS(`try { $s = Get-Service W3SVC -ErrorAction Stop; $s.Status } catch { 'NotFound' }`),
      runPS(`try { & dotnet --version 2>$null } catch { '' }`),
      runPS(`try { & node --version 2>$null } catch { '' }`),
      runPS(`try { & choco --version 2>$null } catch { '' }`),
      runPS(`(Get-Service -Name 'MySQL*','MSSQLSERVER','MSSQL$*','MariaDB','postgresql*' -ErrorAction SilentlyContinue | Where-Object Status -eq 'Running' | Select-Object -First 1).DisplayName`),
      runPS(`try { & git --version 2>$null } catch { '' }`),
      runPS(`($ports = @(80,443,4080); ($ports | ForEach-Object { if (Get-NetTCPConnection -LocalPort $_ -State Listen -ErrorAction SilentlyContinue) { "$_:LISTEN" } else { "$_:FREE" } }) -join ',')`),
      runPS(`[math]::Round((Get-PSDrive C -ErrorAction SilentlyContinue).Free / 1GB, 1)`),
      runPS(`$PSVersionTable.PSVersion.ToString()`),
      runPS(`try { Import-Module WebAdministration -ErrorAction Stop; $m = (Get-WebConfiguration 'system.webServer/globalModules').Collection | Where-Object { $_.name -like '*AspNetCore*' } | Select-Object -First 1; if ($m) { $m.name } else { '' } } catch { '' }`),
      runPS(`try { & node -e "require.resolve('unzipper')" 2>$null; Write-Output 'ok' } catch { '' }`)
    ]);

    const results = [];

    // OS
    const isServer = /Windows Server/i.test(osOut);
    results.push({ id: 'os', pass: isServer, detail: osOut || 'Unable to detect OS' });

    // Admin rights
    const isAdmin = adminOut.toLowerCase() === 'true';
    results.push({ id: 'admin', pass: isAdmin, detail: isAdmin ? 'Elevated session confirmed' : 'Not running as Administrator' });

    // IIS
    const iisUp = /^running$/i.test(iisOut);
    results.push({
      id: 'iis', pass: iisUp,
      detail: iisUp ? 'IIS W3SVC running' : (iisOut === 'NotFound' ? 'IIS not installed' : `W3SVC is ${iisOut || 'not found'}`)
    });

    // .NET
    const dotnetVer = (dotnetOut.match(/^[\d.]+/) || [])[0];
    results.push({ id: 'dotnet', pass: !!dotnetVer, detail: dotnetVer ? `.NET ${dotnetVer} Runtime detected` : '.NET Hosting Bundle not installed' });

    // Node.js
    const nodeVer = (nodeOut.match(/^v[\d.]+/) || [])[0];
    results.push({ id: 'node', pass: !!nodeVer, detail: nodeVer ? `Node.js ${nodeVer}` : 'Node.js not found in PATH' });

    // Chocolatey
    const chocoVer = (chocoOut.match(/^[\d.]+/) || [])[0];
    results.push({ id: 'choco', pass: !!chocoVer, detail: chocoVer ? `Chocolatey v${chocoVer}` : 'choco not found in PATH' });

    // Database
    const dbName = dbOut.trim();
    results.push({ id: 'db', pass: dbName.length > 0, detail: dbName || 'No supported DB engine detected' });

    // Git
    const gitFound = /git version/i.test(gitOut);
    results.push({ id: 'git', pass: gitFound, detail: gitFound ? gitOut : 'git not found in PATH' });

    // Ports — informational (always pass, show status)
    const listenPorts = [80, 443, 4080].filter(p => portsOut.includes(`${p}:LISTEN`));
    const freePorts   = [80, 443, 4080].filter(p => portsOut.includes(`${p}:FREE`));
    const portsDetail = listenPorts.length
      ? `Ports ${listenPorts.join(', ')} active${freePorts.length ? `; ${freePorts.join(', ')} available` : ''}`
      : 'Ports 80, 443, 4080 available';
    results.push({ id: 'ports', pass: true, detail: portsDetail });

    // Disk space (C:)
    const diskGB = parseFloat(diskOut);
    const diskOk  = !isNaN(diskGB) && diskGB >= 4;
    results.push({
      id: 'disk', pass: diskOk,
      detail: diskOk ? `${diskGB} GB free on C:\\` : (!isNaN(diskGB) ? `Only ${diskGB} GB free — need 4 GB minimum` : 'Unable to check disk space')
    });

    // PowerShell version
    const psMajor = parseInt((psOut || '0').split('.')[0], 10);
    const psOk    = psMajor >= 5;
    results.push({ id: 'ps', pass: psOk, detail: psOk ? `PowerShell ${psOut}` : `PowerShell ${psOut || 'unknown'} — 5.1+ required` });

    // ANCM
    const ancmName = ancmOut.trim();
    results.push({
      id: 'ancm', pass: ancmName.length > 0,
      detail: ancmName ? `${ancmName} registered in IIS` : 'ANCM not found — install .NET Hosting Bundle'
    });

    // unzipper npm package
    const unzipperOk = /ok/i.test(unzipperOut);
    results.push({
      id: 'unzipper', pass: unzipperOk,
      detail: unzipperOk ? 'unzipper package installed' : 'unzipper not installed — run: npm install unzipper'
    });

    res.json(results);
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

// ── Run an install command ─────────────────────────────────
router.post('/install', (req, res) => {
  const { cmd } = req.body;
  if (!cmd) return res.status(400).json({ error: 'cmd required' });

  const encoded = Buffer.from(cmd, 'utf16le').toString('base64');
  exec(
    `powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${encoded}`,
    { timeout: 300000, cwd: PANEL_DIR }, // 5 min — covers slow choco installs
    (err, stdout, stderr) => {
      const output = (stdout || '').trim();
      if (err && !output) {
        return res.status(500).json({ ok: false, error: (stderr || err.message).trim() });
      }
      res.json({ ok: true, output });
    }
  );
});

module.exports = router;
