import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';

const COMPANY_LONG_NAME: Record<'QRS' | 'TQS' | 'NEW', string> = {
  QRS: 'Quality Registrar Systems',
  TQS: 'Quality Registrar Systems',
  NEW: 'Quality Registrar Systems',
};

const AUDITOR_DESIGNATION: Record<'QRS' | 'TQS' | 'NEW', string> = {
  QRS: 'QRS Lead Auditor',
  TQS: 'QRS Lead Auditor',
  NEW: 'QRS Lead Auditor',
};

export interface ClosureTemplateFinding {
  /** Position in the FULL ncr_entries list (1-based, padded for display) */
  originalIndex: number;
  ncType: string;
  clause: string;
  evidenceReceived: string;
  submittedDocs: string;
  accepted: boolean;
}

export interface ClosureTemplateInput {
  source: 'QRS' | 'TQS' | 'NEW';
  ncId: number;
  ncCode: string;
  companyName: string;
  auditorName: string;
  closureDate: string;          // YYYY-MM-DD
  verificationText: string;
  findings: ClosureTemplateFinding[];
  signatureAbsPath: string | null;

  /** Pre-computed page numbers (verification page is always the LAST) */
  currentPage: number;
  totalPages: number;

  /** Optional content hash — shown in footer if provided */
  contentHash?: string;
}

/**
 * Render the verification page HTML.
 * Returns the HTML string plus the SHA-256 hash of the rendered HTML body
 * (this hash is stable and visible in the page footer).
 */
export function renderVerificationHtml(
  input: ClosureTemplateInput,
): { html: string; contentHash: string } {
  const formattedDate = formatLongDate(input.closureDate);
  const stampDate = formatStampDate(input.closureDate);
  const auditorDesig = AUDITOR_DESIGNATION[input.source];
  const generatedAt = formatGeneratedAt();

  // Read signature as data URL
  const signatureDataUrl = readSignatureAsDataUrl(input.signatureAbsPath);

  // Build findings rows
  const findingRows = input.findings
    .map((f) => {
      const numStr = String(f.originalIndex).padStart(2, '0');
      const ncTypeColor = ncTypeColorClass(f.ncType);
      const docs = (f.submittedDocs || '').trim();
      const docsMuted = !docs;
      return `<tr>
      <td class="col-num">${escapeHtml(numStr)}</td>
      <td class="col-evidence">${escapeHtml(f.evidenceReceived || '—')}</td>
      <td class="col-type"><span class="${ncTypeColor}">${escapeHtml(prettifyNcType(f.ncType))}</span></td>
      <td class="col-clause">${escapeHtml(f.clause || '—')}</td>
      <td class="col-documents ${docsMuted ? 'muted' : ''}">${docsMuted ? 'Not provided' : escapeHtml(docs)}</td>
      <td class="col-result">${
        f.accepted
          ? '<span class="result-accepted">✓ Accepted</span>'
          : '<span class="result-rejected">✗ Not Acc.</span>'
      }</td>
    </tr>`;
    })
    .join('');

  // Compute content hash on a stable subset (data only — independent of layout)
  const canonical = JSON.stringify({
    ncCode: input.ncCode,
    company: input.companyName,
    auditor: input.auditorName,
    closureDate: input.closureDate,
    verification: input.verificationText,
    findings: input.findings.map((f) => ({
      i: f.originalIndex,
      t: f.ncType,
      c: f.clause,
      e: f.evidenceReceived,
      d: f.submittedDocs,
      a: f.accepted,
    })),
  });
  const contentHash =
    input.contentHash ||
    crypto.createHash('sha256').update(canonical).digest('hex');

  const html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Verification Comments — ${escapeHtml(input.ncCode)}</title>
<style>
  @import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@500;600;700&family=Libre+Baskerville:wght@400;700&display=swap');
  @page { size: A4 landscape; margin: 0; }
  * { box-sizing: border-box; }
  body {
    font-family: 'Helvetica', 'Arial', sans-serif;
    font-size: 9.5pt;
    color: #1a1a1a;
    margin: 0;
    padding: 12mm 16mm 10mm 16mm;
    line-height: 1.4;
    position: relative;
    height: 210mm;
    overflow: hidden;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  /* ──── Top accent bar ──── */
  .top-accent {
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 5px;
    background: linear-gradient(90deg, #185FA5 0%, #185FA5 50%, #0F6E56 100%);
  }
  /* ──── Top-right page label ──── */
  .page-label {
    position: absolute;
    top: 8mm; right: 16mm;
    font-size: 7.5pt;
    color: #94a3b8;
    letter-spacing: 0.18em;
    font-weight: 600;
  }
  /* ──── Title ──── */
  .doc-title {
    text-align: center;
    font-size: 15pt;
    font-weight: bold;
    letter-spacing: 0.07em;
    color: #0b1220;
    margin: 3mm 0 1.5mm;
  }
  .doc-subtitle {
    text-align: center;
    font-size: 9pt;
    color: #64748b;
    margin-bottom: 5mm;
    letter-spacing: 0.02em;
  }
  /* ──── Findings table ──── */
  .findings-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 9pt;
    margin-bottom: 5mm;
    table-layout: fixed;
  }
  .findings-table thead th {
    text-align: left;
    padding: 7px 10px;
    border-bottom: 1.5px solid #185FA5;
    color: #185FA5;
    font-size: 8pt;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
  }
  .findings-table tbody td {
    padding: 6px 10px;
    border-bottom: 0.5px solid #e8edf2;
    vertical-align: top;
    word-wrap: break-word;
    overflow-wrap: anywhere;
  }
  .findings-table tbody tr:nth-child(even) td {
    background: #fafbfc;
  }
  .findings-table tbody tr:last-child td {
    border-bottom: none;
  }
  .col-num {
    width: 5%;
    color: #64748b;
    font-family: 'Courier New', monospace;
    font-weight: 600;
  }
  .col-evidence { width: 22%; }
  .col-type { width: 10%; font-weight: 600; }
  .col-clause { width: 13%; color: #475569; font-size: 8.5pt; }
  .col-documents { width: 34%; color: #334155; }
  .col-documents.muted { font-style: italic; color: #94a3b8; }
  .col-result { width: 16%; font-weight: 600; white-space: nowrap; }
  .nc-major-color { color: #A32D2D; }
  .nc-minor-color { color: #854F0B; }
  .nc-observation-color { color: #0C447C; }
  .nc-unknown-color { color: #64748b; }
  .result-accepted { color: #0F6E56; }
  .result-rejected { color: #A32D2D; }
  /* ──── Verification block ──── */
  .verification-label {
    font-size: 8.5pt;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: #475569;
    text-transform: uppercase;
    margin-bottom: 2mm;
  }
  .verification-text {
    background: #f8fafc;
    border-left: 3px solid #185FA5;
    border-radius: 0 4px 4px 0;
    padding: 8px 13px;
    font-style: italic;
    font-size: 9pt;
    color: #334155;
    line-height: 1.5;
    margin-bottom: 5mm;
    max-height: 26mm;
    overflow: hidden;
    word-wrap: break-word;
    white-space: pre-wrap;
  }
  .verification-empty { color: #94a3b8; }
  /* ──── Bottom section (signature + seal locked together) ──── */
  .bottom-section {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 24mm;
    border-top: 0.5px dashed #cbd5e1;
    padding-top: 5mm;
    margin-top: 3mm;
    page-break-inside: avoid;
    break-inside: avoid;
  }
  .auditor-block { flex: 1; max-width: 60%; }
  .auditor-label {
    font-size: 8.5pt;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: #475569;
    text-transform: uppercase;
    margin-bottom: 2.5mm;
  }
  .auditor-sig-wrap {
    height: 15mm;
    margin-bottom: 1mm;
    display: flex;
    align-items: flex-end;
  }
  .auditor-sig-image {
    max-height: 15mm;
    max-width: 70mm;
  }
  .auditor-sig-typed {
    font-family: 'Brush Script MT', 'Lucida Handwriting', cursive;
    font-size: 22pt;
    color: #1a3a8a;
    font-style: italic;
    line-height: 1;
    padding-bottom: 1mm;
  }
  .auditor-sig-line {
    width: 70mm;
    border-bottom: 0.5px solid #cbd5e1;
    margin-bottom: 2.5mm;
  }
  .auditor-name {
    font-size: 11pt;
    font-weight: 700;
    color: #0b1220;
    margin-bottom: 0.5mm;
  }
  .auditor-designation {
    font-size: 8.5pt;
    color: #64748b;
    margin-bottom: 3mm;
  }
  .closure-date-label {
    font-size: 8.5pt;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: #475569;
    text-transform: uppercase;
    margin-bottom: 0.5mm;
  }
  .closure-date {
    font-size: 11pt;
    font-weight: 600;
    color: #0b1220;
  }
  /* ──── Stamp (circular seal) ──── */
  .stamp-block {
    margin-bottom: 3mm;
  }
  .verified-stamp {
    display: inline-block;
    transform: rotate(-6deg);
  }
  .verified-stamp svg {
    width: 36mm;
    height: 36mm;
    display: block;
  }
  .seal-ring-text {
    font-family: 'Cinzel', Georgia, 'Times New Roman', serif;
    fill: #0F6E56;
  }
  .seal-main {
    font-family: 'Cinzel', Georgia, 'Times New Roman', serif;
    font-weight: 700;
    fill: #0F6E56;
  }
  .seal-date {
    font-family: 'Libre Baskerville', Georgia, serif;
    fill: #0F6E56;
  }
  .seal-foot {
    font-family: 'Libre Baskerville', Georgia, serif;
    fill: #0F6E56;
  }
  /* ──── Footer ──── */
  .doc-footer {
    position: absolute;
    bottom: 6mm;
    left: 16mm;
    right: 16mm;
    display: flex;
    justify-content: space-between;
    font-size: 7pt;
    color: #94a3b8;
    font-family: 'Courier New', monospace;
    letter-spacing: 0.04em;
  }
  .doc-footer .sha {
    word-break: break-all;
    max-width: 60%;
  }
</style>
</head>
<body>
  <div class="top-accent"></div>
  <div class="page-label">PAGE ${input.currentPage} OF ${input.totalPages} · AUTO-GENERATED</div>

  <div class="doc-title">VERIFICATION COMMENTS OF AUDITOR</div>
  <div class="doc-subtitle">${input.findings.length} NC${input.findings.length === 1 ? '' : 's'} closed · ${escapeHtml(input.companyName)}</div>

  <table class="findings-table">
    <thead>
      <tr>
        <th>#</th>
        <th>Evidence</th>
        <th>Type</th>
        <th>Clause</th>
        <th>Document Received</th>
        <th>Result</th>
      </tr>
    </thead>
    <tbody>${findingRows}</tbody>
  </table>

  <div class="verification-label">Verification by Auditor:</div>
  <div class="verification-text">${
    input.verificationText?.trim()
      ? escapeHtml(input.verificationText)
      : '<span class="verification-empty">(No verification comment provided)</span>'
  }</div>

  <div class="bottom-section">
    <div class="auditor-block">
      <div class="auditor-label">Auditor name &amp; signature</div>
      <div class="auditor-sig-wrap">
        ${
          signatureDataUrl
            ? `<img class="auditor-sig-image" src="${signatureDataUrl}" alt="Signature" />`
            : `<span class="auditor-sig-typed">${escapeHtml(input.auditorName) || '—'}</span>`
        }
      </div>
      <div class="auditor-sig-line"></div>
      <div class="auditor-name">${escapeHtml(input.auditorName) || '—'}</div>
      <div class="auditor-designation">${escapeHtml(auditorDesig)}</div>
      <div class="closure-date-label">Date of Closure</div>
      <div class="closure-date">${formattedDate}</div>
    </div>
    <div class="stamp-block">
      <div class="verified-stamp">
        <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Digital verification seal">
          <circle cx="100" cy="100" r="96" fill="rgba(255,255,255,0.96)" stroke="#0F6E56" stroke-width="2" />
          <circle cx="100" cy="100" r="87" fill="none" stroke="#0F6E56" stroke-width="0.75" />
          <circle cx="100" cy="100" r="64" fill="none" stroke="#0F6E56" stroke-width="1.25" />
          <defs>
            <path id="seal-arc-top" d="M 24 100 A 76 76 0 0 1 176 100" />
            <path id="seal-arc-bot" d="M 24 100 A 76 76 0 0 0 176 100" />
          </defs>
          <text class="seal-ring-text" font-size="9" font-weight="600" letter-spacing="2.4">
            <textPath href="#seal-arc-top" startOffset="50%" text-anchor="middle">QUALITY REGISTRAR SYSTEMS</textPath>
          </text>
          <text class="seal-ring-text" font-size="8" font-weight="500" letter-spacing="2.2">
            <textPath href="#seal-arc-bot" startOffset="50%" text-anchor="middle">DIGITAL VERIFICATION SEAL</textPath>
          </text>
          <text class="seal-ring-text" x="19" y="104" font-size="11" text-anchor="middle">★</text>
          <text class="seal-ring-text" x="181" y="104" font-size="11" text-anchor="middle">★</text>
          <text class="seal-main" x="100" y="92" font-size="18" letter-spacing="2" text-anchor="middle">VERIFIED</text>
          <line x1="60" y1="100" x2="140" y2="100" stroke="#0F6E56" stroke-width="0.5" opacity="0.45" />
          <text class="seal-date" x="100" y="116" font-size="8.5" letter-spacing="0.6" text-anchor="middle">${escapeHtml(stampDate)}</text>
          <text class="seal-foot" x="100" y="130" font-size="6" letter-spacing="1.4" text-anchor="middle" opacity="0.85">SHA-256 SEALED</text>
        </svg>
      </div>
    </div>
  </div>

  <div class="doc-footer">
    <div class="sha">SHA-256: ${escapeHtml(contentHash)}</div>
    <div>Generated by ${escapeHtml(COMPANY_LONG_NAME[input.source])} · ${generatedAt}</div>
  </div>
</body>
</html>`;

  return { html, contentHash };
}

// ─── Helpers ───────────────────────────────────────────────────────────

function escapeHtml(s: string | null | undefined): string {
  if (s === null || s === undefined) return '';
  return String(s)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}

function readSignatureAsDataUrl(absPath: string | null): string {
  if (!absPath || !fs.existsSync(absPath)) return '';
  try {
    const buffer = fs.readFileSync(absPath);
    const ext = path.extname(absPath).slice(1).toLowerCase();
    const mimeType =
      ext === 'png'
        ? 'image/png'
        : ext === 'jpg' || ext === 'jpeg'
          ? 'image/jpeg'
          : ext === 'webp'
            ? 'image/webp'
            : 'image/png';
    return `data:${mimeType};base64,${buffer.toString('base64')}`;
  } catch {
    return '';
  }
}

function ncTypeColorClass(t: string | null | undefined): string {
  const v = (t || '').toLowerCase();
  if (v.includes('major')) return 'nc-major-color';
  if (v.includes('minor')) return 'nc-minor-color';
  if (v.includes('observ')) return 'nc-observation-color';
  return 'nc-unknown-color';
}

function prettifyNcType(t: string | null | undefined): string {
  const v = (t || '').toLowerCase();
  if (v.includes('major')) return 'Major';
  if (v.includes('minor')) return 'Minor';
  if (v.includes('observ')) return 'Observation';
  return t || 'NA';
}

function formatLongDate(iso: string): string {
  try {
    const d = new Date(iso);
    if (isNaN(d.getTime())) return iso || '—';
    return d.toLocaleDateString('en-GB', {
      day: '2-digit',
      month: 'short',
      year: 'numeric',
    });
  } catch {
    return iso || '—';
  }
}

function formatStampDate(iso: string): string {
  // Returns "25 · MAY · 2026"
  try {
    const d = new Date(iso);
    if (isNaN(d.getTime())) return iso || '—';
    const dd = String(d.getDate()).padStart(2, '0');
    const mm = d.toLocaleDateString('en-GB', { month: 'short' }).toUpperCase();
    const yy = d.getFullYear();
    return `${dd} · ${mm} · ${yy}`;
  } catch {
    return iso || '—';
  }
}

function formatGeneratedAt(): string {
  const now = new Date();
  const datePart = now.toLocaleDateString('en-GB', {
    day: '2-digit',
    month: 'short',
    year: 'numeric',
  });
  const timePart =
    String(now.getUTCHours()).padStart(2, '0') +
    ':' +
    String(now.getUTCMinutes()).padStart(2, '0');
  return `${datePart} ${timePart} UTC`;
}