import { Injectable } from '@nestjs/common';
import PDFDocument from 'pdfkit';
import type { NcStatusExportData, NcStatusExportRow } from './audit-nc-status-excel.service';

const B = {
  name: 'CERTIFYHUB — QRS & TQS',
  teal: '#0F766E', tealDark: '#0B4F4A', tealLight: '#D5F2EC',
  white: '#FFFFFF', gray50: '#F8F9FB', gray200: '#E5E7EB', gray500: '#6B7280',
  gray700: '#374151', gray900: '#111827',
  indigo: '#4338CA', green: '#16A34A', greenDark: '#15803D', amber: '#B45309',
};
const M = 40;

function fmtDate(d?: string | null): string {
  if (!d) return '—';
  const dt = new Date(d);
  if (isNaN(dt.getTime())) return String(d);
  return dt.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });
}
const kindLabel = (k: NcStatusExportRow['audit_kind']) =>
  k === 'client' ? 'Initial Audit' : k === 'recertification' ? 'Re-Assessment' : 'Surveillance';

@Injectable()
export class AuditNcStatusPdfService {
  async generate(data: NcStatusExportData, subtitle: string): Promise<Buffer> {
    const doc = new PDFDocument({
      layout: 'landscape', size: 'A4',
      margins: { top: M, bottom: 50, left: M, right: M },
      bufferPages: true, info: { Title: 'Audit NC Status Report', Author: 'CertifyHub' },
    });
    const buffers: Buffer[] = [];
    doc.on('data', (c: Buffer) => buffers.push(c));

    return new Promise((resolve, reject) => {
      doc.on('end', () => resolve(Buffer.concat(buffers)));
      doc.on('error', reject);

      this.addHeader(doc, 'Audit → NC Status — Detail', subtitle);
      this.addStatCards(doc, data.totals);

      // table
      const headers = [
        { label: 'CLIENT', width: 230 },
        { label: 'SOURCE', width: 55, align: 'center' },
        { label: 'AUDIT TYPE', width: 90, align: 'center' },
        { label: 'AUDIT DATE', width: 80, align: 'center' },
        { label: 'AUDITOR', width: 150 },
        { label: 'NC STATUS', width: 80, align: 'center' },
      ];
      this.drawTable(doc, headers, data.rows);

      this.addFooters(doc);
      doc.end();
    });
  }

  private addHeader(doc: any, title: string, subtitle: string) {
    const pw = doc.page.width, cw = pw - M * 2;
    doc.rect(0, 0, pw, 60).fill(B.teal);
    doc.font('Helvetica-Bold').fontSize(14).fillColor(B.white).text(B.name, M, 14, { width: cw / 2 });
    doc.font('Helvetica').fontSize(9).fillColor(B.white).text(title, M, 34, { width: cw / 2 });
    doc.font('Helvetica').fontSize(8).fillColor(B.white)
      .text(`Generated: ${fmtDate(new Date().toISOString())}`, pw / 2, 14, { width: cw / 2, align: 'right' });
    doc.text(subtitle, pw / 2, 28, { width: cw / 2, align: 'right' });
    doc.rect(0, 60, pw, 3).fill(B.tealDark);
    doc.fillColor(B.gray900); doc.y = 75;
  }

  private addStatCards(doc: any, t: { total: number; raised: number; pending: number }) {
    const cw = doc.page.width - M * 2;
    const gap = 10, cardW = (cw - gap * 2) / 3, sy = doc.y, cardH = 50;
    const pct = (n: number) => (t.total ? Math.round((n / t.total) * 100) : 0);
    const cards = [
      { label: 'TOTAL AUDITS', value: String(t.total), sub: 'conducted', accent: B.indigo },
      { label: 'NC RAISED', value: String(t.raised), sub: `${pct(t.raised)}% of audits`, accent: B.greenDark },
      { label: 'NC PENDING', value: String(t.pending), sub: `${pct(t.pending)}% of audits`, accent: B.amber },
    ];
    cards.forEach((c, i) => {
      const x = M + i * (cardW + gap);
      doc.roundedRect(x, sy, cardW, cardH, 5).fill(B.gray50);
      doc.rect(x, sy, cardW, 3).fill(c.accent);
      doc.font('Helvetica-Bold').fontSize(7).fillColor(B.gray500).text(c.label, x + 12, sy + 9, { width: cardW - 24 });
      doc.font('Helvetica-Bold').fontSize(20).fillColor(c.accent).text(c.value, x + 12, sy + 19, { width: cardW - 24 });
      doc.font('Helvetica').fontSize(7.5).fillColor(B.gray500).text(c.sub, x + 12, sy + 40, { width: cardW - 24 });
    });
    doc.fillColor(B.gray900); doc.y = sy + cardH + 16;
  }

  private drawTable(
    doc: any,
    headers: { label: string; width: number; align?: string }[],
    rows: NcStatusExportRow[],
  ) {
    const cw = doc.page.width - M * 2;
    const totalW = headers.reduce((s, h) => s + h.width, 0);
    const scale = cw / totalW;
    const headerH = 24;
    let y = doc.y;

    const drawHeaderRow = (atY: number) => {
      doc.rect(M, atY, cw, headerH).fill(B.teal);
      let x = M;
      headers.forEach((h) => {
        const colW = h.width * scale;
        doc.font('Helvetica-Bold').fontSize(7.5).fillColor(B.white)
          .text(h.label, x + 4, atY + 8, { width: colW - 8, align: (h.align as any) || 'left' });
        x += colW;
      });
      return atY + headerH;
    };
    y = drawHeaderRow(y);

    rows.forEach((r, idx) => {
      const name = r.company_name ?? '—';
      const auditor = r.auditor_names.join(', ') || '—';
      // measure height needed (client + auditor wrap)
      doc.font('Helvetica').fontSize(8);
      const nameH = doc.heightOfString(name, { width: headers[0].width * scale - 8 });
      const audH = doc.heightOfString(auditor, { width: headers[4].width * scale - 8 });
      const rowH = Math.max(20, nameH + 8, audH + 8);

      if (y + rowH > doc.page.height - 60) { doc.addPage(); y = M; y = drawHeaderRow(y); }
      if (idx % 2 === 1) doc.rect(M, y, cw, rowH).fill(B.gray50);
      doc.moveTo(M, y + rowH).lineTo(M + cw, y + rowH).strokeColor(B.gray200).lineWidth(0.3).stroke();

      const raised = r.nc_status === 'NC Raised';
      const cells = [
        { v: name, color: B.gray900, bold: true, align: 'left' },
        { v: r.source, color: r.source === 'QRS' ? B.indigo : B.teal, bold: true, align: 'center' },
        { v: kindLabel(r.audit_kind), color: B.gray700, bold: false, align: 'center' },
        { v: fmtDate(r.audit_date), color: B.gray700, bold: false, align: 'center' },
        { v: auditor, color: B.gray700, bold: false, align: 'left' },
        { v: r.nc_status, color: raised ? B.greenDark : B.amber, bold: true, align: 'center' },
      ];
      let x = M;
      cells.forEach((cell, ci) => {
        const colW = headers[ci].width * scale;
        doc.font(cell.bold ? 'Helvetica-Bold' : 'Helvetica').fontSize(8).fillColor(cell.color)
          .text(cell.v, x + 4, y + 6, { width: colW - 8, align: cell.align as any });
        x += colW;
      });
      y += rowH;
    });

    // total row
    doc.moveTo(M, y).lineTo(M + cw, y).strokeColor(B.teal).lineWidth(1.5).stroke();
    doc.rect(M, y, cw, 22).fill(B.tealLight);
    doc.font('Helvetica-Bold').fontSize(9).fillColor(B.tealDark)
      .text(`TOTAL: ${rows.length} audits`, M + 4, y + 6, { width: cw - 8, align: 'left' });
    y += 22;
    doc.moveTo(M, y).lineTo(M + cw, y).strokeColor(B.teal).lineWidth(1.5).stroke();
    doc.y = y + 12; doc.fillColor(B.gray900);
  }

  private addFooters(doc: any) {
    const pages = doc.bufferedPageRange();
    for (let i = 0; i < pages.count; i++) {
      doc.switchToPage(i);
      const pH = doc.page.height, pW = doc.page.width, cw3 = (pW - M * 2) / 3;
      doc.moveTo(M, pH - 35).lineTo(pW - M, pH - 35).strokeColor(B.gray200).lineWidth(0.5).stroke();
      doc.font('Helvetica').fontSize(7).fillColor(B.gray500);
      doc.text(B.name, M, pH - 28, { width: cw3, align: 'left' });
      doc.text(`Page ${i + 1} of ${pages.count}`, M + cw3, pH - 28, { width: cw3, align: 'center' });
      doc.text(`Printed: ${fmtDate(new Date().toISOString())}`, M + cw3 * 2, pH - 28, { width: cw3, align: 'right' });
    }
  }
}