import { Injectable } from '@nestjs/common';
import * as Handlebars from 'handlebars';
import chromium from '@sparticuz/chromium';
import puppeteer, { Browser, Page } from 'puppeteer';

@Injectable()
export class PdfService {

    /**
     * Renders a single template into a PDF.
     *
     * @param template
     * @param data
     * @param format
     * @param landscape
     */
    async render(template: string, data: any, format: PdfFormat, landscape: boolean = false): Promise<Uint8Array> {
        const compiledTemplate: HandlebarsTemplateDelegate = Handlebars.compile(template);
        const htmlContent: string = compiledTemplate(data);
console.log("chrome path " + await chromium.executablePath());
        const browser: Browser = await puppeteer.launch({
            executablePath: await chromium.executablePath(),
            args: chromium.args,
            headless: chromium.headless,
        });

        const page: Page = await browser.newPage();
        await page.setContent(htmlContent, { waitUntil: 'networkidle0' });

        const pdfBuffer: Uint8Array = await page.pdf({ format, landscape });
        await browser.close();

        return pdfBuffer;
    }


    /**
     * Renders multiple templates into a single PDF.
     *
     * @param templates
     * @param data
     * @param format
     * @param addPageBreaks
     * @param styles
     * @param landscape
     */
    async renderMultiple(
        templates: string[],
        data: any[],
        format: PdfFormat,
        addPageBreaks: boolean = true,
        styles?: string,
        landscape: boolean = false
    ): Promise<Uint8Array> {
        const defaultStyles = this.getDefaultCss(addPageBreaks);
        const appliedStyles: string = styles || defaultStyles;

        let htmlContent: string = `<body>${appliedStyles}`;
        for (let i = 0; i < templates.length; i++) {
            const compiledTemplate: HandlebarsTemplateDelegate = Handlebars.compile(templates[i]);
            const renderedContent = compiledTemplate(data[i]);
            htmlContent += `<div class="page">${renderedContent}</div>`;
        }
        htmlContent += `</body>`;
        console.log('Chromium Path:', await chromium.executablePath())

        const browser: Browser = await puppeteer.launch({ headless: 'shell' });
        const page: Page = await browser.newPage();
        await page.setContent(htmlContent, { waitUntil: 'networkidle0' });

        const pdfBuffer: Uint8Array = await page.pdf({ format, landscape, printBackground: true });
        await browser.close();

        return pdfBuffer;
    }


    /**
     * Generates HTML content from multiple templates.
     *
     * @param templates
     * @param data
     * @param addPageBreaks
     * @param styles
     */
    async generateHtml(templates: string[], data: any[], addPageBreaks: boolean = true, styles?: string): Promise<string> {
        // Default styles if none are provided
        const defaultStyles = `
    <style>
      body {
        margin: 0;
        padding: 0;
        width: 100%;
        overflow-x: hidden; /* Prevent horizontal scrolling */
      }
      .page {
        width: 100%;
        max-width: 800px; /* Constrain content width */
        margin: 0 auto; /* Center content */
        padding: 20px; /* Add padding for better readability */
        box-sizing: border-box;
        ${addPageBreaks ? 'page-break-after: always;' : ''} /* Optional page break */
      }
      .page:last-child {
        page-break-after: auto; /* Avoid unnecessary blank page at the end */
      }
    </style>
  `;

        // Use provided styles or fallback to default
        const appliedStyles: string = styles || defaultStyles;

        // Combine all templates into a single HTML string
        let htmlContent: string = `<body>${appliedStyles}`;
        for (let i = 0; i < templates.length; i++) {
            const compiledTemplate: HandlebarsTemplateDelegate = Handlebars.compile(templates[i]);
            const renderedContent = compiledTemplate(data[i]);
            htmlContent += `<div class="page">${renderedContent}</div>`;
        }
        htmlContent += `</body>`;

        return htmlContent;
    }

    private getDefaultCss(addPageBreaks: boolean): string {
        return  `
    <style>
      body {
        margin: 0;
        padding: 0;
        width: 100%;
        overflow-x: hidden;
      }
      .page {
        width: 100%;
        max-width: 800px;
        margin: 0 auto;
        padding: 20px;
        box-sizing: border-box;
        ${addPageBreaks ? 'page-break-after: always;' : ''}
      }
      .page:last-child {
        page-break-after: auto;
      }
    </style>
  `;
    }
}
// Enum for PDF formats
export enum PdfFormat {
    A3 = 'A3',
    A4 = 'A4',
    A5 = 'A5',
    Letter = 'letter',
    Legal = 'legal'
}