import { Injectable } from '@nestjs/common';
import PDFDocument from 'pdfkit';

import type { AuditDetailResponse, AuditDetailRow } from './audit-detail-report.service';

// ── Brand ──────────────────────────────
const B = {
  name: 'CERTIFYHUB — QRS & TQS',
  teal: '#0F766E',
  tealDark: '#0B4F4A',
  tealLight: '#D5F2EC',
  white: '#FFFFFF',
  gray50: '#F8F9FB',
  gray100: '#F3F4F6',
  gray200: '#E5E7EB',
  gray500: '#6B7280',
  gray700: '#374151',
  gray900: '#111827',
  blue: '#2563EB',
  green: '#16A34A',
  greenDark: '#15803D',
  orange: '#D97706',
  red: '#DC2626',
  purple: '#7C3AED',
};

const M = 40;

function fmtDate(d?: string | null): string {
  if (!d) return '—';
  const dt = new Date(d);
  if (isNaN(dt.getTime())) return d;
  return dt.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });
}

@Injectable()
export class AuditReportPdfService {
  private createDoc(landscape = true): any {
    return new PDFDocument({
      layout: landscape ? 'landscape' : 'portrait',
      size: 'A4',
      margins: { top: M, bottom: 50, left: M, right: M },
      bufferPages: true,
      info: { Title: 'Audit Report', Author: 'CertifyHub' },
    });
  }

  private addHeader(doc: any, title: string, subtitle: string) {
    const pw = doc.page.width;
    const 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('#FFFFFF').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 addFooters(doc: any) {
    const pages = doc.bufferedPageRange();
    for (let i = 0; i < pages.count; i++) {
      doc.switchToPage(i);
      const pH = doc.page.height;
      const pW = doc.page.width;
      const 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' });
    }
  }

  private addStatCards(doc: any, stats: { label: string; value: string; color: string }[]) {
    const cw = doc.page.width - M * 2;
    const gap = 8;
    const cardW = (cw - gap * (stats.length - 1)) / stats.length;
    const sy = doc.y;
    const cardH = 42;

    stats.forEach((s, i) => {
      const x = M + i * (cardW + gap);
      doc.roundedRect(x, sy, cardW, cardH, 4).fill(B.gray50);
      doc.rect(x, sy + 4, 3, cardH - 8).fill(s.color);
      doc.font('Helvetica-Bold').fontSize(6.5).fillColor(B.gray500)
        .text(s.label.toUpperCase(), x + 9, sy + 8, { width: cardW - 14 });
      doc.font('Helvetica-Bold').fontSize(15).fillColor(s.color)
        .text(s.value, x + 9, sy + 19, { width: cardW - 14 });
    });

    doc.fillColor(B.gray900);
    doc.y = sy + cardH + 14;
  }

  private addSectionTitle(doc: any, title: string) {
    doc.font('Helvetica-Bold').fontSize(11).fillColor(B.gray900).text(title, M, doc.y);
    doc.y += 6;
  }

  private drawTable(
    doc: any,
    headers: { label: string; width: number; align?: string }[],
    rows: { cells: { value: string; color?: string; bold?: boolean }[] }[],
    opts?: { headerColor?: string; totalRow?: { cells: { value: string; color?: string }[] } },
  ) {
    const cw = doc.page.width - M * 2;
    const totalW = headers.reduce((s, h) => s + h.width, 0);
    const scale = cw / totalW;
    const hBg = opts?.headerColor || B.teal;
    const rowH = 20;
    const headerH = 24;
    let y = doc.y;

    if (y + headerH + rowH * 3 > doc.page.height - 60) { doc.addPage(); y = M; }

    const drawHeaderRow = (atY: number) => {
      doc.rect(M, atY, cw, headerH).fill(hBg);
      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 + 7, { width: colW - 8, align: (h.align as any) || 'left' });
        x += colW;
      });
      return atY + headerH;
    };

    y = drawHeaderRow(y);

    rows.forEach((rowItem, idx) => {
      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();

      let x = M;
      rowItem.cells.forEach((cell, ci) => {
        const colW = headers[ci].width * scale;
        doc.font(cell.bold ? 'Helvetica-Bold' : 'Helvetica').fontSize(8).fillColor(cell.color || B.gray700)
          .text(cell.value, x + 4, y + 6, { width: colW - 8, align: (headers[ci].align as any) || 'left' });
        x += colW;
      });
      y += rowH;
    });

    if (opts?.totalRow) {
      doc.moveTo(M, y).lineTo(M + cw, y).strokeColor(B.teal).lineWidth(1.5).stroke();
      doc.rect(M, y, cw, rowH + 4).fill(B.tealLight);
      let x = M;
      opts.totalRow.cells.forEach((cell, ci) => {
        const colW = headers[ci].width * scale;
        doc.font('Helvetica-Bold').fontSize(9).fillColor(cell.color || B.tealDark)
          .text(cell.value, x + 4, y + 7, { width: colW - 8, align: (headers[ci].align as any) || 'left' });
        x += colW;
      });
      doc.moveTo(M, y + rowH + 4).lineTo(M + cw, y + rowH + 4).strokeColor(B.teal).lineWidth(1.5).stroke();
      y += rowH + 4;
    }

    doc.y = y + 12;
    doc.fillColor(B.gray900);
  }

  // ═══════════════════════════════════════════════
  //  AUDIT REPORT PDF
  // ═══════════════════════════════════════════════

  async generateAuditReportPdf(data: AuditDetailResponse, subtitle: string): Promise<Buffer> {
    const doc = this.createDoc(true);
    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);

      const s = data.summary;
      const rows = data.rows;

      this.addHeader(doc, 'Audit Report — Detail', subtitle);

      this.addStatCards(doc, [
        { label: 'Total Assign', value: String(s.total_assigned), color: B.gray900 },
        { label: 'Performed', value: String(s.conducted_count), color: B.blue },
        { label: 'Upcoming', value: String(s.scheduled_count), color: B.purple },
        { label: 'Stage 1 (Up/Miss)', value: `${s.stage1_uploaded}/${s.stage1_missing}`, color: B.green },
        { label: 'Stage 2 (Up/Miss)', value: `${s.stage2_uploaded}/${s.stage2_missing}`, color: B.green },
      ]);

      this.addSectionTitle(doc, 'Audit Detail — by event');

      const reportLabel = (uploaded: boolean, conducted: boolean) =>
        uploaded ? 'Uploaded' : !conducted ? 'Scheduled' : 'Missing';
      const reportColor = (uploaded: boolean, conducted: boolean) =>
        uploaded ? B.greenDark : !conducted ? B.gray500 : B.red;

      this.drawTable(doc,
        [
          { label: 'CLIENT ID', width: 55, align: 'center' },
          { label: 'CLIENT', width: 200 },
          { label: 'AUDITOR', width: 110 },
          { label: 'AUDIT DATE', width: 75, align: 'center' },
          { label: 'TYPE', width: 80, align: 'center' },
          { label: 'STAGE 1', width: 65, align: 'center' },
          { label: 'STAGE 2', width: 65, align: 'center' },
          { label: 'SOURCE', width: 50, align: 'center' },
        ],
        rows.map((r: AuditDetailRow) => ({
          cells: [
            { value: String(r.record_id), bold: true, color: B.teal },
            { value: r.client_name ?? '—', bold: true },
            { value: r.auditor },
            { value: fmtDate(r.audit_date) },
            { value: r.audit_type },
            { value: reportLabel(r.stage1_uploaded, r.conducted), bold: true, color: reportColor(r.stage1_uploaded, r.conducted) },
            { value: reportLabel(r.stage2_uploaded, r.conducted), bold: true, color: reportColor(r.stage2_uploaded, r.conducted) },
            { value: r.source, bold: true, color: r.source === 'QRS' ? B.blue : B.teal },
          ],
        })),
        {
          totalRow: {
            cells: [
              { value: 'TOTAL' },
              { value: `${rows.length} audits` },
              { value: '' }, { value: '' }, { value: '' },
              { value: `${s.stage1_uploaded}/${s.stage1_missing}` },
              { value: `${s.stage2_uploaded}/${s.stage2_missing}` },
              { value: '' },
            ],
          },
        },
      );

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