// PDFReports.jsx — AegisComply Audit-Ready PDF Report Generator
// Uses jsPDF + jspdf-autotable (loaded via CDN in index.html)
//
// Public functions exposed on window:
//   - window.AegisPDF.exportCalibrationAudit(user, equipment, calRecords)
//   - window.AegisPDF.exportPPEAudit(user, inventory, issuances)
//   - window.AegisPDF.exportROIReport(user, metrics)

const BRAND_NAVY    = [11, 31, 58];     // #0B1F3A
const BRAND_TEAL    = [13, 148, 136];   // #0D9488
const BRAND_GREY    = [100, 116, 139];  // #64748B
const BRAND_LIGHT   = [248, 250, 252];  // #F8FAFC
const BRAND_RED     = [220, 38, 38];    // #DC2626
const BRAND_AMBER   = [217, 119, 6];    // #D97706
const BRAND_GREEN   = [22, 163, 74];    // #16A34A

function pdfFmtDate(d) {
  if (!d) return '—';
  try { return new Date(d).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }); }
  catch { return d; }
}

function pdfFmtDateTime(d) {
  if (!d) return '—';
  try { return new Date(d).toLocaleString('en-MY', { dateStyle: 'medium', timeStyle: 'short' }); }
  catch { return d; }
}

function getDoc() {
  const lib = window.jspdf;
  if (!lib || !lib.jsPDF) throw new Error('jsPDF library not loaded. Please refresh the page.');
  return new lib.jsPDF({ unit: 'mm', format: 'a4', orientation: 'portrait' });
}

// ── Header + Footer for every page ──────────────────────────────────────────
function drawHeader(doc, title, subtitle, user) {
  const pageW = doc.internal.pageSize.getWidth();

  // Navy band
  doc.setFillColor(...BRAND_NAVY);
  doc.rect(0, 0, pageW, 22, 'F');

  doc.setFont('helvetica', 'bold');
  doc.setFontSize(16);
  doc.setTextColor(255, 255, 255);
  doc.text('AegisComply', 14, 11);

  doc.setFont('helvetica', 'normal');
  doc.setFontSize(9);
  doc.setTextColor(180, 200, 220);
  doc.text('Industrial Compliance Management Platform', 14, 17);

  // Title block
  doc.setFont('helvetica', 'bold');
  doc.setFontSize(18);
  doc.setTextColor(...BRAND_NAVY);
  doc.text(title, 14, 36);

  doc.setFont('helvetica', 'normal');
  doc.setFontSize(10);
  doc.setTextColor(...BRAND_GREY);
  doc.text(subtitle, 14, 43);

  // Company info (right side)
  doc.setFontSize(9);
  doc.setTextColor(...BRAND_GREY);
  const companyText = user?.company || '—';
  const userText    = user?.name ? `Generated by ${user.name}` : '';
  const dateText    = `Generated ${pdfFmtDateTime(new Date())}`;
  doc.text(companyText, pageW - 14, 36, { align: 'right' });
  doc.text(userText,    pageW - 14, 41, { align: 'right' });
  doc.text(dateText,    pageW - 14, 46, { align: 'right' });

  // Separator
  doc.setDrawColor(226, 232, 240);
  doc.line(14, 50, pageW - 14, 50);

  return 56; // y position to start content
}

function drawFooter(doc, pageNum, totalPages) {
  const pageW = doc.internal.pageSize.getWidth();
  const pageH = doc.internal.pageSize.getHeight();

  doc.setDrawColor(226, 232, 240);
  doc.line(14, pageH - 14, pageW - 14, pageH - 14);

  doc.setFont('helvetica', 'normal');
  doc.setFontSize(8);
  doc.setTextColor(...BRAND_GREY);
  doc.text('AegisComply · Audit-defensible compliance records', 14, pageH - 8);
  doc.text(`Page ${pageNum} of ${totalPages}`, pageW - 14, pageH - 8, { align: 'right' });
}

function finalizeAllPages(doc) {
  const total = doc.internal.getNumberOfPages();
  for (let i = 1; i <= total; i++) {
    doc.setPage(i);
    drawFooter(doc, i, total);
  }
}

// ── KPI card row ────────────────────────────────────────────────────────────
function drawKPIs(doc, y, kpis) {
  const pageW = doc.internal.pageSize.getWidth();
  const margin = 14;
  const innerW = pageW - margin * 2;
  const cardW = (innerW - 6 * (kpis.length - 1)) / kpis.length;

  kpis.forEach((kpi, i) => {
    const x = margin + i * (cardW + 6);

    // Card
    doc.setFillColor(...BRAND_LIGHT);
    doc.setDrawColor(226, 232, 240);
    doc.roundedRect(x, y, cardW, 22, 2, 2, 'FD');

    // Label
    doc.setFont('helvetica', 'normal');
    doc.setFontSize(8);
    doc.setTextColor(...BRAND_GREY);
    doc.text(kpi.label.toUpperCase(), x + 4, y + 6);

    // Value
    doc.setFont('helvetica', 'bold');
    doc.setFontSize(18);
    doc.setTextColor(...(kpi.color || BRAND_NAVY));
    doc.text(String(kpi.value), x + 4, y + 16);

    // Sub
    if (kpi.sub) {
      doc.setFont('helvetica', 'normal');
      doc.setFontSize(7);
      doc.setTextColor(...BRAND_GREY);
      doc.text(kpi.sub, x + 4, y + 20);
    }
  });

  return y + 28;
}

// ── Section heading ─────────────────────────────────────────────────────────
function drawSectionHead(doc, y, title) {
  doc.setFont('helvetica', 'bold');
  doc.setFontSize(12);
  doc.setTextColor(...BRAND_NAVY);
  doc.text(title, 14, y);

  // Teal underline
  doc.setDrawColor(...BRAND_TEAL);
  doc.setLineWidth(0.5);
  doc.line(14, y + 1, 14 + doc.getTextWidth(title), y + 1);
  doc.setLineWidth(0.2);

  return y + 6;
}

// ── Signature section at end ────────────────────────────────────────────────
function drawSignatures(doc, y) {
  const pageW = doc.internal.pageSize.getWidth();
  if (y > 220) { doc.addPage(); y = 56; }

  doc.setFont('helvetica', 'bold');
  doc.setFontSize(10);
  doc.setTextColor(...BRAND_NAVY);
  doc.text('Authorisation & Sign-Off', 14, y);
  y += 8;

  const colW = (pageW - 14 * 2 - 12) / 2;
  ['Prepared by', 'Approved by'].forEach((role, i) => {
    const x = 14 + i * (colW + 12);
    // Line for signature
    doc.setDrawColor(180, 188, 200);
    doc.line(x, y + 20, x + colW, y + 20);

    doc.setFont('helvetica', 'normal');
    doc.setFontSize(9);
    doc.setTextColor(...BRAND_GREY);
    doc.text(role, x, y + 25);
    doc.text('Signature / Name', x, y + 30);
    doc.text('Date: __________________', x, y + 35);
  });

  return y + 42;
}

// ═══════════════════════════════════════════════════════════════════════════
// REPORT 1: Calibration Audit
// ═══════════════════════════════════════════════════════════════════════════
async function exportCalibrationAudit(user, equipment, calRecords) {
  const doc = getDoc();
  let y = drawHeader(
    doc,
    'Calibration Audit Report',
    'Complete calibration register and compliance status — DOSH-defensible record',
    user
  );

  // KPIs
  const total      = equipment.length;
  const expired    = equipment.filter(e => e.status === 'expired' || e.status === 'overdue').length;
  const expiring   = equipment.filter(e => e.status === 'expiring').length;
  const compliant  = equipment.filter(e => e.status === 'active' || e.status === 'pending_calibration').length;
  const score      = total > 0 ? Math.round((compliant / total) * 100) : 0;
  const onTimeCals = calRecords.filter(r => (r.days_diff || 0) <= 7).length;
  const onTimePct  = calRecords.length > 0 ? Math.round((onTimeCals / calRecords.length) * 100) : 0;

  y = drawKPIs(doc, y, [
    { label: 'Total Equipment', value: total, color: BRAND_NAVY },
    { label: 'Compliance Score', value: `${score}%`, color: score >= 85 ? BRAND_GREEN : score >= 60 ? BRAND_AMBER : BRAND_RED },
    { label: 'On-Time Cal. Rate', value: `${onTimePct}%`, color: onTimePct >= 80 ? BRAND_GREEN : BRAND_AMBER, sub: `${calRecords.length} total records` },
    { label: 'Overdue / Expired', value: expired, color: expired > 0 ? BRAND_RED : BRAND_GREEN, sub: `${expiring} expiring soon` },
  ]);

  // Equipment register table
  y = drawSectionHead(doc, y, 'Equipment Register');

  const rows = equipment.map((e, i) => [
    String(i + 1),
    e.name || '—',
    e.serial_number || '—',
    e.brand_model || '—',
    e.location || '—',
    pdfFmtDate(e.last_cal_date),
    pdfFmtDate(e.calibration_due),
    (e.status || '').toUpperCase(),
  ]);

  doc.autoTable({
    startY: y,
    margin: { left: 14, right: 14 },
    head: [['#', 'Equipment', 'Serial', 'Brand / Model', 'Location', 'Last Cal.', 'Next Due', 'Status']],
    body: rows,
    theme: 'striped',
    headStyles: { fillColor: BRAND_NAVY, textColor: 255, fontSize: 8, fontStyle: 'bold' },
    bodyStyles: { fontSize: 8, textColor: [51, 65, 85] },
    alternateRowStyles: { fillColor: BRAND_LIGHT },
    columnStyles: {
      0: { cellWidth: 8, halign: 'right' },
      2: { font: 'courier', fontSize: 7 },
      5: { fontSize: 7 },
      6: { fontSize: 7 },
      7: { fontSize: 7, halign: 'center' },
    },
    didParseCell: (data) => {
      // Colour status cells
      if (data.column.index === 7 && data.section === 'body') {
        const s = String(data.cell.raw || '').toLowerCase();
        if (s === 'expired' || s === 'overdue') data.cell.styles.textColor = BRAND_RED;
        else if (s === 'expiring')              data.cell.styles.textColor = BRAND_AMBER;
        else                                    data.cell.styles.textColor = BRAND_GREEN;
        data.cell.styles.fontStyle = 'bold';
      }
    },
  });

  y = doc.lastAutoTable.finalY + 12;

  // Issues found
  const issues = calRecords.filter(r => r.has_issue);
  if (issues.length > 0) {
    if (y > 230) { doc.addPage(); y = 56; }
    y = drawSectionHead(doc, y, `Issues & Non-Conformances (${issues.length})`);

    const issueRows = issues.map(r => {
      const eq = equipment.find(e => e.id === r.equipment_id);
      return [
        pdfFmtDate(r.cal_date),
        eq ? `${eq.name}\n${eq.serial_number}` : 'Unknown',
        r.lab_provider || '—',
        r.result || '—',
        r.issue_note || '—',
      ];
    });

    doc.autoTable({
      startY: y,
      margin: { left: 14, right: 14 },
      head: [['Date', 'Equipment / Serial', 'Lab', 'Result', 'Issue Note']],
      body: issueRows,
      theme: 'plain',
      headStyles: { fillColor: BRAND_RED, textColor: 255, fontSize: 8, fontStyle: 'bold' },
      bodyStyles: { fontSize: 8 },
      columnStyles: { 1: { fontSize: 7 }, 4: { fontSize: 8 } },
    });

    y = doc.lastAutoTable.finalY + 12;
  }

  y = drawSignatures(doc, y);
  finalizeAllPages(doc);

  const filename = `AegisComply_Calibration_Audit_${new Date().toISOString().slice(0, 10)}.pdf`;
  doc.save(filename);
}

// ═══════════════════════════════════════════════════════════════════════════
// REPORT 2: PPE Stock Audit
// ═══════════════════════════════════════════════════════════════════════════
async function exportPPEAudit(user, inventory, issuances) {
  const doc = getDoc();
  let y = drawHeader(
    doc,
    'PPE Stock Audit Report',
    'Full inventory register, issuance log, and stock health — audit-defensible',
    user
  );

  // KPIs
  const totalItems  = inventory.length;
  const lowCount    = inventory.filter(p => p.status === 'low' || p.status === 'critical').length;
  const criticalCount = inventory.filter(p => p.status === 'critical').length;
  const totalUnits  = inventory.reduce((s, p) => s + (p.balance || 0), 0);
  const totalIssued = issuances.reduce((s, i) => s + (i.qty || 0), 0);

  y = drawKPIs(doc, y, [
    { label: 'PPE Items (SKUs)', value: totalItems, color: BRAND_NAVY },
    { label: 'Total Units on Hand', value: totalUnits, color: BRAND_TEAL },
    { label: 'Below Min Stock', value: lowCount, color: lowCount > 0 ? BRAND_AMBER : BRAND_GREEN, sub: `${criticalCount} critical` },
    { label: 'Total Issued (lifetime)', value: totalIssued, color: BRAND_NAVY, sub: `${issuances.length} transactions` },
  ]);

  // Inventory table
  y = drawSectionHead(doc, y, 'PPE Inventory Register');

  const invRows = inventory.map((p, i) => [
    String(i + 1),
    p.item_code || '—',
    `${p.name}${p.size ? ' [' + p.size + ']' : ''}`,
    p.brand_model || '—',
    p.category || '—',
    String(p.min_stock || 0),
    String(p.balance || 0),
    p.unit || 'pcs',
    (p.status || '').toUpperCase(),
  ]);

  doc.autoTable({
    startY: y,
    margin: { left: 14, right: 14 },
    head: [['#', 'Code', 'Product', 'Brand', 'Category', 'Min', 'Balance', 'Unit', 'Status']],
    body: invRows,
    theme: 'striped',
    headStyles: { fillColor: BRAND_NAVY, textColor: 255, fontSize: 8, fontStyle: 'bold' },
    bodyStyles: { fontSize: 7, textColor: [51, 65, 85] },
    alternateRowStyles: { fillColor: BRAND_LIGHT },
    columnStyles: {
      0: { cellWidth: 8, halign: 'right' },
      1: { font: 'courier', fontSize: 6 },
      5: { halign: 'right' },
      6: { halign: 'right', fontStyle: 'bold' },
      8: { halign: 'center' },
    },
    didParseCell: (data) => {
      if (data.column.index === 8 && data.section === 'body') {
        const s = String(data.cell.raw || '').toLowerCase();
        if (s === 'critical')   { data.cell.styles.textColor = BRAND_RED;   data.cell.styles.fontStyle = 'bold'; }
        else if (s === 'low')   { data.cell.styles.textColor = BRAND_AMBER; data.cell.styles.fontStyle = 'bold'; }
        else                    { data.cell.styles.textColor = BRAND_GREEN; }
      }
    },
  });

  y = doc.lastAutoTable.finalY + 12;

  // Issuance log
  if (issuances.length > 0) {
    if (y > 230) { doc.addPage(); y = 56; }
    y = drawSectionHead(doc, y, `Issuance Log (${issuances.length} records)`);

    const issRows = issuances.slice(0, 100).map(iss => [
      pdfFmtDate(iss.issued_at),
      iss.item_code || '—',
      iss.ppe_item_name + (iss.size ? ` [${iss.size}]` : ''),
      String(iss.qty || 0),
      iss.emp_name || '—',
      iss.emp_id || '—',
      iss.department || '—',
    ]);

    doc.autoTable({
      startY: y,
      margin: { left: 14, right: 14 },
      head: [['Date', 'Code', 'Product', 'Qty', 'Issued To', 'Emp. ID', 'Dept.']],
      body: issRows,
      theme: 'plain',
      headStyles: { fillColor: BRAND_TEAL, textColor: 255, fontSize: 8, fontStyle: 'bold' },
      bodyStyles: { fontSize: 7 },
      columnStyles: {
        1: { font: 'courier', fontSize: 6 },
        3: { halign: 'right', fontStyle: 'bold' },
        5: { font: 'courier', fontSize: 6 },
      },
    });

    y = doc.lastAutoTable.finalY + 12;

    if (issuances.length > 100) {
      doc.setFont('helvetica', 'italic');
      doc.setFontSize(8);
      doc.setTextColor(...BRAND_GREY);
      doc.text(`Showing first 100 of ${issuances.length} issuance records. Full data available via Excel export.`, 14, y);
      y += 8;
    }
  }

  y = drawSignatures(doc, y);
  finalizeAllPages(doc);

  const filename = `AegisComply_PPE_Audit_${new Date().toISOString().slice(0, 10)}.pdf`;
  doc.save(filename);
}

// ═══════════════════════════════════════════════════════════════════════════
// REPORT 3: ROI Report
// ═══════════════════════════════════════════════════════════════════════════
async function exportROIReport(user, metrics, period) {
  const doc = getDoc();
  let y = drawHeader(
    doc,
    'ROI & Compliance Report',
    `Operational metrics + estimated savings — period: ${period || 'All Time'}`,
    user
  );

  y = drawKPIs(doc, y, [
    { label: 'Compliance Score', value: `${metrics.complianceScore}%`, color: metrics.complianceScore >= 85 ? BRAND_GREEN : metrics.complianceScore >= 60 ? BRAND_AMBER : BRAND_RED, sub: `${metrics.eqCompliant}/${metrics.eqTotal} compliant` },
    { label: 'On-Time Cal. Rate', value: `${metrics.onTimePct}%`, color: metrics.onTimePct >= 80 ? BRAND_GREEN : BRAND_AMBER, sub: `${metrics.totalCals} total cals` },
    { label: 'Est. Penalties Avoided', value: `RM ${metrics.penaltyAvoided.toLocaleString()}`, color: BRAND_TEAL, sub: `RM 500 per on-time cal` },
    { label: 'Est. PPE Savings', value: `RM ${metrics.ppeSavings.toLocaleString()}`, color: BRAND_GREEN, sub: `~RM 8 per tracked issuance` },
  ]);

  y = drawSectionHead(doc, y, 'Operational Summary');

  doc.autoTable({
    startY: y,
    margin: { left: 14, right: 14 },
    head: [['Metric', 'Value', 'Notes']],
    body: [
      ['Total Equipment',           String(metrics.eqTotal),           'Currently tracked'],
      ['Compliant Equipment',       String(metrics.eqCompliant),       'Active + at-lab'],
      ['Overdue / Expired',         String(metrics.eqOverdue),         metrics.eqOverdue > 0 ? 'Requires immediate action' : 'All clear'],
      ['Calibration Records',       String(metrics.totalCals),         'Historical events'],
      ['On-Time Calibrations',      `${metrics.onTimePct}%`,           'Within 7-day grace'],
      ['Calibrations with Issues',  String(metrics.issuesCals),        metrics.issuesCals > 0 ? 'Review needed' : '—'],
      ['Total PPE Units Issued',    String(metrics.totalUnits),        'All time'],
      ['Low-Stock PPE Items',       String(metrics.lowStock),          metrics.lowStock > 0 ? 'Restock recommended' : '—'],
    ],
    theme: 'striped',
    headStyles: { fillColor: BRAND_NAVY, textColor: 255, fontSize: 9, fontStyle: 'bold' },
    bodyStyles: { fontSize: 9 },
    alternateRowStyles: { fillColor: BRAND_LIGHT },
    columnStyles: { 1: { halign: 'right', fontStyle: 'bold' } },
  });

  y = doc.lastAutoTable.finalY + 12;

  y = drawSectionHead(doc, y, 'Estimated Savings Breakdown');

  doc.autoTable({
    startY: y,
    margin: { left: 14, right: 14 },
    head: [['Category', 'Basis', 'Estimated Saving']],
    body: [
      ['Calibration Penalty Avoidance', `RM 500 × ${Math.floor(metrics.penaltyAvoided / 500)} on-time calibrations`, `RM ${metrics.penaltyAvoided.toLocaleString()}`],
      ['PPE Wastage Reduction',         `~RM 8 × ${metrics.totalUnits} tracked issuances`,                          `RM ${metrics.ppeSavings.toLocaleString()}`],
    ],
    theme: 'striped',
    foot: [['', 'TOTAL ESTIMATED SAVINGS', `RM ${metrics.totalSavings.toLocaleString()}`]],
    headStyles: { fillColor: BRAND_TEAL, textColor: 255, fontSize: 9, fontStyle: 'bold' },
    bodyStyles: { fontSize: 9 },
    footStyles: { fillColor: BRAND_GREEN, textColor: 255, fontSize: 10, fontStyle: 'bold' },
    alternateRowStyles: { fillColor: BRAND_LIGHT },
    columnStyles: { 2: { halign: 'right', fontStyle: 'bold' } },
  });

  y = doc.lastAutoTable.finalY + 14;

  // Methodology note
  if (y > 240) { doc.addPage(); y = 56; }
  doc.setFont('helvetica', 'bold');
  doc.setFontSize(10);
  doc.setTextColor(...BRAND_NAVY);
  doc.text('Methodology', 14, y);
  y += 5;

  doc.setFont('helvetica', 'normal');
  doc.setFontSize(8);
  doc.setTextColor(...BRAND_GREY);
  const methodology = doc.splitTextToSize(
    'Compliance Score = (Active + At-Lab equipment) / Total equipment. ' +
    'On-Time Rate = calibrations completed within 7 days of due date / total calibrations. ' +
    'Penalty estimate uses an industry benchmark of RM 500 per on-time certificate (avoided DOSH/internal audit fines). ' +
    'PPE savings estimate uses RM 8 per tracked issuance (wastage reduction vs. untracked baseline; based on Malaysian process industry averages). ' +
    'All financial figures are illustrative — actual savings depend on your specific baseline costs and should be verified against your accounts before being used externally.',
    doc.internal.pageSize.getWidth() - 28
  );
  doc.text(methodology, 14, y);
  y += methodology.length * 4 + 6;

  y = drawSignatures(doc, y);
  finalizeAllPages(doc);

  const filename = `AegisComply_ROI_Report_${new Date().toISOString().slice(0, 10)}.pdf`;
  doc.save(filename);
}

// Expose globally
window.AegisPDF = { exportCalibrationAudit, exportPPEAudit, exportROIReport };
