import { PDFDocument, StandardFonts, rgb } from '@cantoo/pdf-lib';
import { readFile, writeFile, rename } from 'node:fs/promises';
import type { SignatureFieldData } from '@/lib/db/schema';

/**
 * Fills AcroForm text fields and draws signature rectangles on a PDF.
 * Uses atomic write: write to tmp path, verify %PDF header, rename to final path.
 *
 * @param srcPath     - Absolute path to original PDF
 * @param destPath    - Absolute path to write prepared PDF (e.g. {docId}_prepared.pdf)
 * @param textFields  - Key/value map: { fieldNameOrLabel: value } (agent-provided)
 * @param sigFields   - Signature field array from SignatureFieldData[]
 */
export async function preparePdf(
  srcPath: string,
  destPath: string,
  textFields: Record<string, string>,
  sigFields: SignatureFieldData[],
): Promise<void> {
  const pdfBytes = await readFile(srcPath);
  const pdfDoc = await PDFDocument.load(pdfBytes);
  const helvetica = await pdfDoc.embedFont(StandardFonts.Helvetica);
  const pages = pdfDoc.getPages();

  // Strategy A: fill existing AcroForm fields by name
  // form.flatten() MUST happen before drawing rectangles
  try {
    const form = pdfDoc.getForm();
    for (const [fieldName, value] of Object.entries(textFields)) {
      try {
        form.getTextField(fieldName).setText(value);
      } catch {
        // Field name not found in AcroForm — silently skip
      }
    }
    form.flatten();
  } catch {
    // No AcroForm in this PDF — skip to rectangle drawing
  }

  // Draw signature field placeholders (blue rectangle + "Sign Here" label)
  for (const field of sigFields) {
    const page = pages[field.page - 1]; // page is 1-indexed
    if (!page) continue;
    page.drawRectangle({
      x: field.x,
      y: field.y,
      width: field.width,
      height: field.height,
      borderColor: rgb(0.15, 0.39, 0.92),
      borderWidth: 1.5,
      color: rgb(0.90, 0.94, 0.99),
    });
    page.drawText('Sign Here', {
      x: field.x + 4,
      y: field.y + 4,
      size: 8,
      font: helvetica,
      color: rgb(0.15, 0.39, 0.92),
    });
  }

  const modifiedBytes = await pdfDoc.save();

  // Atomic write: tmp → rename (prevents partial writes from corrupting the only copy)
  const tmpPath = `${destPath}.tmp`;
  await writeFile(tmpPath, modifiedBytes);

  // Verify output is a valid PDF (check magic bytes)
  const magic = modifiedBytes.slice(0, 4);
  const header = Buffer.from(magic).toString('ascii');
  if (!header.startsWith('%PDF')) {
    throw new Error('preparePdf: output is not a valid PDF (magic bytes check failed)');
  }

  await rename(tmpPath, destPath);
}
