import { Injectable, Logger } from '@nestjs/common';
import { execFile } from 'child_process';
import { promisify } from 'util';
import * as fs from 'fs/promises';
import * as os from 'os';
import * as path from 'path';
import { PDFDocument } from 'pdf-lib';
import { ReportDocxService } from './report-docx.service';

const run = promisify(execFile);

@Injectable()
export class ReportPdfService {
  private readonly logger = new Logger(ReportPdfService.name);

  constructor(private readonly docx: ReportDocxService) {}

  /**
   * The PDF is the Word file converted by LibreOffice, so it has the same layout as the Word download.
   * The cover is the first page of the Word file, so it is not added again.
   */
  async buildFromVm(vm: any, report?: any): Promise<Buffer> {
    return (await this.buildPdfAndDocx(vm, report)).pdf;
  }

  /**
   * 2026-11-06: the report emails attach the Word file as well as the PDF. Both come from ONE Word build,
   * so the attached .docx is exactly the file the PDF was printed from.
   */
  async buildPdfAndDocx(vm: any, report?: any): Promise<{ pdf: Buffer; docx: Buffer }> {
    const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'rpt-'));
    try {
      const docxBuf = await this.docx.buildFromVm(vm);
      const docxPath = path.join(dir, 'report.docx');
      await fs.writeFile(docxPath, docxBuf);

      await run(
        process.env.SOFFICE_PATH || 'soffice',
        ['--headless', '--convert-to', 'pdf', '--outdir', dir, docxPath],
        { timeout: 120_000 },
      );
      const bodyPdf = await fs.readFile(path.join(dir, 'report.pdf'));

      const out = await PDFDocument.create();
      const doc = await PDFDocument.load(bodyPdf);
      const pages = await out.copyPages(doc, doc.getPageIndices());
      pages.forEach((p) => out.addPage(p));
      out.setTitle(`Audit Report ${vm.meta?.report_no ?? ''}`.trim());
      return { pdf: Buffer.from(await out.save()), docx: docxBuf };
    } finally {
      await fs.rm(dir, { recursive: true, force: true });
    }
  }
}