import { Injectable, Logger } from '@nestjs/common';
import * as PDFDocument from 'pdfkit';
import * as path from 'path';
import * as fs from 'fs';
import { ConfigService } from '@nestjs/config';

export interface PdfColumn {
  header: string;
  key: string;
  width?: number;
}

export interface PdfExportOptions {
  columns: PdfColumn[];
  data: any[];
  title?: string;
  subtitle?: string;
  orientation?: 'portrait' | 'landscape';
}

@Injectable()
export class PdfExportService {
  private readonly logger = new Logger(PdfExportService.name);
  private readonly storagePath: string;

  constructor(private readonly configService: ConfigService) {
    this.storagePath = this.configService.get<string>(
      'FILE_STORAGE_PATH',
      './storage/reports',
    );
  }

  async export(
    fileName: string,
    options: PdfExportOptions,
  ): Promise<{ filePath: string; fileSize: number }> {
    return new Promise((resolve, reject) => {
      const doc = new PDFDocument({
        size: 'A4',
        layout: options.orientation || 'portrait',
        margins: { top: 50, bottom: 50, left: 50, right: 50 },
      });

      // Ensure storage directory exists
      const fullPath = path.join(this.storagePath, fileName);
      const dir = path.dirname(fullPath);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }

      const stream = fs.createWriteStream(fullPath);
      doc.pipe(stream);

      // Title
      if (options.title) {
        doc.fontSize(18).text(options.title, { align: 'center' });
        doc.moveDown();
      }

      // Subtitle
      if (options.subtitle) {
        doc.fontSize(12).text(options.subtitle, { align: 'center' });
        doc.moveDown();
      }

      // Calculate column widths
      const pageWidth =
        doc.page.width - doc.page.margins.left - doc.page.margins.right;
      const columnCount = options.columns.length;
      const defaultWidth = pageWidth / columnCount;

      // Draw table header
      doc.fontSize(10);
      let x = doc.page.margins.left;
      const headerY = doc.y;

      // Header background
      doc
        .fillColor('#e0e0e0')
        .rect(x, headerY - 5, pageWidth, 20)
        .fill();

      // Header text
      doc.fillColor('#000000');
      options.columns.forEach((col) => {
        const width = col.width || defaultWidth;
        doc.text(col.header, x, headerY, {
          width: width - 5,
          align: 'left',
        });
        x += width;
      });

      doc.moveDown();

      // Draw data rows
      options.data.forEach((row, rowIndex) => {
        // Check if we need a new page
        if (doc.y > doc.page.height - 100) {
          doc.addPage();
        }

        x = doc.page.margins.left;
        const rowY = doc.y;

        // Alternate row background
        if (rowIndex % 2 === 1) {
          doc
            .fillColor('#f5f5f5')
            .rect(x, rowY - 5, pageWidth, 15)
            .fill();
        }

        doc.fillColor('#000000');
        options.columns.forEach((col) => {
          const width = col.width || defaultWidth;
          const value = row[col.key];
          const displayValue =
            value === null || value === undefined ? '' : String(value);
          doc.text(displayValue, x, rowY, {
            width: width - 5,
            align: 'left',
          });
          x += width;
        });

        doc.moveDown(0.5);
      });

      // Footer
      doc
        .fontSize(8)
        .text(
          `Generated at: ${new Date().toISOString()}`,
          doc.page.margins.left,
          doc.page.height - 30,
          { align: 'center' },
        );

      doc.end();

      stream.on('finish', () => {
        const stats = fs.statSync(fullPath);
        this.logger.log(`PDF file exported: ${fullPath} (${stats.size} bytes)`);
        resolve({
          filePath: fullPath,
          fileSize: stats.size,
        });
      });

      stream.on('error', reject);
    });
  }
}
