function generateReport(run, issues, pages) {
  var critical = issues.filter(function(i){ return i.severity === 'critical'; });
  var warnings = issues.filter(function(i){ return i.severity === 'warning'; });
  var info = issues.filter(function(i){ return i.severity === 'info'; });

  var html = '<!DOCTYPE html><html><head><meta charset="UTF-8">' +
    '<title>QA Report - ' + esc2(run.project_name || run.url) + '</title>' +
    '<style>' +
    'body{font-family:Arial,sans-serif;margin:0;padding:0;color:#1c1c1a;font-size:13px}' +
    '.cover{background:#4f46e5;color:#fff;padding:60px 40px;min-height:200px}' +
    '.cover h1{font-size:28px;margin:0 0 8px}' +
    '.cover p{margin:4px 0;opacity:.85;font-size:14px}' +
    '.cover .badge{display:inline-block;background:rgba(255,255,255,.2);padding:4px 12px;border-radius:20px;font-size:12px;margin-top:12px}' +
    '.summary{display:grid;grid-template-columns:repeat(4,1fr);gap:0;border-bottom:1px solid #e5e5e4}' +
    '.sum-box{padding:20px 24px;border-right:1px solid #e5e5e4}' +
    '.sum-box:last-child{border-right:none}' +
    '.sum-box .num{font-size:32px;font-weight:700;margin-bottom:4px}' +
    '.sum-box .lbl{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:#737370}' +
    '.sum-box.c .num{color:#dc2626} .sum-box.w .num{color:#d97706} .sum-box.i .num{color:#2563eb} .sum-box.p .num{color:#16a34a}' +
    '.section{padding:24px 32px;border-bottom:1px solid #f0f0f0}' +
    '.section h2{font-size:14px;font-weight:700;margin:0 0 16px;padding-bottom:8px;border-bottom:2px solid #f0f0f0}' +
    '.section h2.critical{border-color:#dc2626;color:#dc2626}' +
    '.section h2.warning{border-color:#d97706;color:#d97706}' +
    '.section h2.info{border-color:#2563eb;color:#2563eb}' +
    '.issue{margin-bottom:12px;padding:12px 14px;border-radius:6px;border-left:3px solid #ddd;background:#fafaf9}' +
    '.issue.c{border-color:#dc2626;background:#fef2f2}' +
    '.issue.w{border-color:#d97706;background:#fffbeb}' +
    '.issue.i{border-color:#2563eb;background:#eff6ff}' +
    '.issue .msg{font-weight:600;font-size:13px;margin-bottom:4px}' +
    '.issue .url{font-size:11px;color:#737370;margin-bottom:8px;word-break:break-all}' +
    '.issue .fix{font-size:12px;color:#444}' +
    '.issue .fix-title{font-weight:600;color:#16a34a;margin-bottom:6px}' +
    '.issue .steps{margin:0;padding-left:16px}' +
    '.issue .steps li{margin-bottom:3px;line-height:1.5}' +
    '.pages-section{padding:24px 32px}' +
    '.pages-section h2{font-size:14px;font-weight:700;margin:0 0 12px}' +
    'table{width:100%;border-collapse:collapse;font-size:12px}' +
    'th{text-align:left;padding:8px 10px;background:#f5f5f4;font-weight:600;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:#737370}' +
    'td{padding:8px 10px;border-bottom:1px solid #f0f0f0}' +
    'tr:last-child td{border-bottom:none}' +
    '.fast{color:#16a34a;font-weight:600} .ok{color:#d97706;font-weight:600} .slow{color:#dc2626;font-weight:600}' +
    '.footer{padding:20px 32px;background:#f5f5f4;font-size:11px;color:#737370;display:flex;justify-content:space-between}' +
    '@media print{body{-webkit-print-color-adjust:exact;print-color-adjust:exact}}' +
    '</style></head><body>';

  // Cover
  html += '<div class="cover">' +
    '<h1>' + esc2(run.project_name || run.url) + '</h1>' +
    '<p>' + esc2(run.url) + '</p>' +
    '<p>Tested: ' + new Date(run.created_at).toLocaleString() + '</p>' +
    '<p>Pages tested: ' + (run.pages_tested || 0) + ' &nbsp;|&nbsp; Total issues: ' + issues.length + '</p>' +
    '<span class="badge">QA Report — Generated by BugTreat QA Tool</span>' +
    '</div>';

  // Summary boxes
  html += '<div class="summary">' +
    '<div class="sum-box c"><div class="num">' + critical.length + '</div><div class="lbl">Critical</div></div>' +
    '<div class="sum-box w"><div class="num">' + warnings.length + '</div><div class="lbl">Warnings</div></div>' +
    '<div class="sum-box i"><div class="num">' + info.length + '</div><div class="lbl">Info</div></div>' +
    '<div class="sum-box p"><div class="num">' + (run.pages_tested||0) + '</div><div class="lbl">Pages</div></div>' +
    '</div>';

  // Critical issues
  if (critical.length > 0) {
    html += '<div class="section"><h2 class="critical">Critical Issues (' + critical.length + ')</h2>';
    critical.forEach(function(issue) {
      var sol = issue.solution || {};
      var steps = (sol.steps || []).map(function(s, i) { return '<li>' + esc2(s) + '</li>'; }).join('');
      html += '<div class="issue c">' +
        '<div class="msg">' + esc2(issue.message) + '</div>' +
        '<div class="url">' + esc2(issue.page_url) + '</div>' +
        '<div class="fix"><div class="fix-title">How to fix: ' + esc2(sol.title||'Review manually') + '</div>' +
        '<ol class="steps">' + steps + '</ol></div>' +
        '</div>';
    });
    html += '</div>';
  }

  // Warnings
  if (warnings.length > 0) {
    html += '<div class="section"><h2 class="warning">Warnings (' + warnings.length + ')</h2>';
    warnings.forEach(function(issue) {
      var sol = issue.solution || {};
      var steps = (sol.steps || []).map(function(s) { return '<li>' + esc2(s) + '</li>'; }).join('');
      html += '<div class="issue w">' +
        '<div class="msg">' + esc2(issue.message) + '</div>' +
        '<div class="url">' + esc2(issue.page_url) + '</div>' +
        '<div class="fix"><div class="fix-title">How to fix: ' + esc2(sol.title||'Review manually') + '</div>' +
        '<ol class="steps">' + steps + '</ol></div>' +
        '</div>';
    });
    html += '</div>';
  }

  // Info
  if (info.length > 0) {
    html += '<div class="section"><h2 class="info">Info (' + info.length + ')</h2>';
    info.forEach(function(issue) {
      var sol = issue.solution || {};
      var steps = (sol.steps || []).map(function(s) { return '<li>' + esc2(s) + '</li>'; }).join('');
      html += '<div class="issue i">' +
        '<div class="msg">' + esc2(issue.message) + '</div>' +
        '<div class="url">' + esc2(issue.page_url) + '</div>' +
        '<div class="fix"><div class="fix-title">How to fix: ' + esc2(sol.title||'Review manually') + '</div>' +
        '<ol class="steps">' + steps + '</ol></div>' +
        '</div>';
    });
    html += '</div>';
  }

  // Pages tested
  html += '<div class="pages-section"><h2>Pages Tested (' + pages.length + ')</h2>' +
    '<table><thead><tr><th>URL</th><th>Status</th><th>Load Time</th></tr></thead><tbody>';
  pages.forEach(function(p) {
    var lt = p.load_time || 0;
    var ltClass = lt < 2000 ? 'fast' : lt < 4000 ? 'ok' : 'slow';
    var sc = p.status_code || 0;
    html += '<tr>' +
      '<td style="word-break:break-all">' + esc2(p.url) + '</td>' +
      '<td style="color:' + (sc >= 400 ? '#dc2626' : '#16a34a') + ';font-weight:600">' + (sc||'--') + '</td>' +
      '<td class="' + ltClass + '">' + (lt ? (lt/1000).toFixed(2)+'s' : '--') + '</td>' +
      '</tr>';
  });
  html += '</tbody></table></div>';

  // Footer
  html += '<div class="footer">' +
    '<span>BugTreat QA Tool — Automated Report</span>' +
    '<span>Generated: ' + new Date().toLocaleString() + '</span>' +
    '</div>';

  html += '</body></html>';
  return html;
}

function downloadReport(run, issues, pages) {
  var html = generateReport(run, issues, pages);
  var blob = new Blob([html], { type: 'text/html' });
  var url = URL.createObjectURL(blob);
  var a = document.createElement('a');
  a.href = url;
  a.download = 'QA-Report-' + (run.project_name || 'report').replace(/[^a-zA-Z0-9]/g, '-') + '-' + new Date().toISOString().slice(0,10) + '.html';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

function printReport(run, issues, pages) {
  var html = generateReport(run, issues, pages);
  var win = window.open('', '_blank');
  win.document.write(html);
  win.document.close();
  setTimeout(function(){ win.print(); }, 500);
}

function esc2(s) {
  return String(s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}

function addDownloadButton(run, issues, pages) {
  var existing = document.getElementById('qa-download-bar');
  if (existing) existing.remove();
  var bar = document.createElement('div');
  bar.id = 'qa-download-bar';
  bar.style.cssText = 'display:flex;gap:8px;margin-bottom:16px;flex-wrap:wrap';
  bar.innerHTML =
    '<button onclick="downloadReport(currentRun,allIssues,currentPages)" style="padding:8px 16px;background:#4f46e5;color:#fff;border:none;border-radius:6px;font-size:13px;cursor:pointer;font-weight:500">Download Report (HTML)</button>' +
    '<button onclick="printReport(currentRun,allIssues,currentPages)" style="padding:8px 16px;background:#f5f5f4;color:#1c1c1a;border:1px solid #e5e5e4;border-radius:6px;font-size:13px;cursor:pointer;font-weight:500">Print / Save as PDF</button>';
  var panel = document.getElementById('report-panel');
  if (panel) panel.insertBefore(bar, panel.firstChild);
}
