import PDFDocument from 'pdfkit';
import * as fs from 'fs';
import * as path from 'path';
import { DailyReportData, MonthlyReportData, FinancialReportData, AuditReportData } from './reportDataService';

type PDFDocumentType = InstanceType<typeof PDFDocument>;

export class PDFGenerator {
  // Font path for Unicode font
  private static unicodeFontPath: string | null = null;
  
  /**
   * Initialize Unicode font if available
   */
  private static initializeUnicodeFont(): void {
    if (this.unicodeFontPath) return; // Already initialized
    
    // Try custom font first
    const fontPath = path.join(__dirname, '../fonts/NotoSans-Regular.ttf');
    if (fs.existsSync(fontPath)) {
      this.unicodeFontPath = fontPath;
      return;
    }
    
    // Try system fonts on Windows
    if (process.platform === 'win32') {
      const systemFonts = [
        'C:\\Windows\\Fonts\\arial.ttf',
        'C:\\Windows\\Fonts\\times.ttf',
        'C:\\Windows\\Fonts\\tahoma.ttf'
      ];
      
      for (const sysFont of systemFonts) {
        if (fs.existsSync(sysFont)) {
          this.unicodeFontPath = sysFont;
          return;
        }
      }
    }
  }
  
  /**
   * Get font name to use (Unicode if available, otherwise default)
   */
  private static getFontName(bold: boolean = false): string {
    this.initializeUnicodeFont();
    if (this.unicodeFontPath) {
      return 'Unicode';
    }
    // Fallback to Helvetica (limited Unicode support)
    return bold ? 'Helvetica-Bold' : 'Helvetica';
  }
  
  /**
   * Register Unicode font in PDF document
   */
  private static registerUnicodeFont(doc: PDFDocumentType): void {
    this.initializeUnicodeFont();
    if (this.unicodeFontPath) {
      try {
        doc.registerFont('Unicode', this.unicodeFontPath);
      } catch (err) {
        console.warn('Could not register Unicode font:', err);
      }
    }
  }
  /**
   * Draw professional header on each page
   */
  private static drawHeader(doc: PDFDocumentType, reportType: string, projectName?: string): void {
    const pageWidth = 612;
    const headerHeight = 80;
    const margin = 50;
    
    // Header background with gradient effect (using rectangle)
    doc.rect(margin, margin, pageWidth - 2 * margin, headerHeight)
       .fillColor('#1e40af') // Blue background
       .fill();
    
    // White border line
    doc.rect(margin, margin, pageWidth - 2 * margin, headerHeight)
       .lineWidth(0.5)
       .strokeColor('#ffffff')
       .stroke();
    
    // Company/System name
    doc.fontSize(18).font(this.getFontName(true));
    doc.fillColor('#ffffff');
    doc.text('HỆ THỐNG QUẢN LÝ O&M', margin + 15, margin + 15, {
      width: pageWidth - 2 * margin - 30,
      align: 'left'
    });
    
    // Report type
    doc.fontSize(12).font(this.getFontName(false));
    doc.fillColor('#e0e7ff'); // Light blue
    const reportTypeText = {
      'Daily': 'BÁO CÁO NGÀY',
      'Monthly': 'BÁO CÁO THÁNG',
      'Financial': 'BÁO CÁO TÀI CHÍNH',
      'Audit': 'BÁO CÁO KIỂM TOÁN'
    }[reportType] || 'BÁO CÁO';
    doc.text(reportTypeText, margin + 15, margin + 40, {
      width: pageWidth - 2 * margin - 30,
      align: 'left'
    });
    
    // Project name (if available)
    if (projectName) {
      doc.fontSize(10).font(this.getFontName(false));
      doc.fillColor('#c7d2fe'); // Lighter blue
      doc.text(`Dự án: ${projectName}`, margin + 15, margin + 60, {
        width: pageWidth - 2 * margin - 30,
        align: 'left'
      });
    }
    
    // Date on right side
    doc.fontSize(9).font(this.getFontName(false));
    doc.fillColor('#ffffff');
    const dateStr = new Date().toLocaleDateString('vi-VN', {
      year: 'numeric',
      month: 'long',
      day: 'numeric'
    });
    doc.text(`Ngày tạo: ${dateStr}`, margin + 15, margin + 50, {
      width: pageWidth - 2 * margin - 30,
      align: 'right'
    });
    
    // Reset fill color
    doc.fillColor('black');
  }

  /**
   * Draw professional footer on each page
   */
  private static drawFooter(doc: PDFDocumentType, pageNumber: number, totalPages: number): void {
    const pageWidth = 612;
    const pageHeight = 792;
    const margin = 50;
    const footerY = pageHeight - margin - 20;
    
    // Footer line
    doc.moveTo(margin, footerY)
       .lineTo(pageWidth - margin, footerY)
       .lineWidth(0.5)
       .strokeColor('#94a3b8')
       .stroke();
    
    // Page number
    doc.fontSize(9).font(this.getFontName(false));
    doc.fillColor('#64748b');
    doc.text(`Trang ${pageNumber} / ${totalPages}`, margin, footerY + 5, {
      width: pageWidth - 2 * margin,
      align: 'center'
    });
    
    // Confidential notice
    doc.fontSize(8).font(this.getFontName(false));
    doc.fillColor('#94a3b8');
    doc.text('Tài liệu bảo mật - Chỉ dùng cho mục đích nội bộ', margin, footerY + 18, {
      width: pageWidth - 2 * margin,
      align: 'center'
    });
    
    // Reset fill color
    doc.fillColor('black');
  }

  /**
   * Generate PDF content from report data using pdfkit
   * Returns a Promise that resolves to base64 string
   */
  static async generatePDF(reportType: string, reportData: any, title: string): Promise<string> {
    return new Promise((resolve, reject) => {
      try {
        const doc = new PDFDocument({
          size: 'A4',
          margins: { top: 50, bottom: 50, left: 50, right: 50 },
          bufferPages: true,
          autoFirstPage: true
        });

        // Register Unicode font if available
        this.registerUnicodeFont(doc);

        // Collect PDF chunks
        const chunks: Buffer[] = [];
        
        doc.on('data', (chunk: Buffer) => {
          chunks.push(chunk);
        });

        doc.on('end', () => {
          try {
            // Return base64
            if (chunks.length > 0) {
              const pdfBuffer = Buffer.concat(chunks);
              resolve(pdfBuffer.toString('base64'));
            } else {
              reject(new Error('No PDF chunks collected'));
            }
          } catch (err: any) {
            reject(err);
          }
        });

        doc.on('error', (err: Error) => {
          reject(err);
        });

        // Draw header on each page
        doc.on('pageAdded', () => {
          const pageWidth = 612;
          const pageHeight = 792;
          const margin = 50;
          
          // Get project name from reportData
          const projectName = reportData?.project?.name || reportData?.project?.code || undefined;
          
          // Draw header
          this.drawHeader(doc, reportType, projectName);
        });

        // Generate content based on report type
        try {
          switch (reportType) {
            case 'Daily':
              this.renderDailyReport(doc, reportData as DailyReportData, title);
              break;
            case 'Monthly':
              this.renderMonthlyReport(doc, reportData as MonthlyReportData, title);
              break;
            case 'Financial':
              this.renderFinancialReport(doc, reportData as FinancialReportData, title);
              break;
            case 'Audit':
              this.renderAuditReport(doc, reportData as AuditReportData, title);
              break;
            default:
              this.renderDefaultReport(doc, title);
          }
        } catch (renderError: any) {
          reject(new Error(`Error rendering PDF: ${renderError.message}`));
          return;
        }

        // After all pages are added, draw footers with correct page numbers
        // Note: bufferedPageRange() works with bufferPages: true
        try {
          const pageRange = doc.bufferedPageRange();
          const totalPages = pageRange.count;
          if (totalPages > 0) {
            for (let i = pageRange.start; i < pageRange.start + totalPages; i++) {
              doc.switchToPage(i);
              this.drawFooter(doc, i - pageRange.start + 1, totalPages);
            }
          }
        } catch (footerError: any) {
          // If footer drawing fails, continue anyway (non-critical)
          console.warn('Error drawing footers:', footerError.message);
        }

        // Finalize PDF
        doc.end();
      } catch (err: any) {
        reject(err);
      }
    });
  }

  /**
   * Format number with Vietnamese locale
   */
  private static formatNumber(num: number): string {
    return num.toLocaleString('vi-VN');
  }

  /**
   * Format currency
   */
  private static formatCurrency(num: number): string {
    return `${this.formatNumber(num)} VND`;
  }

  /**
   * Format date Vietnamese
   */
  private static formatDate(date: Date | string): string {
    const d = typeof date === 'string' ? new Date(date) : date;
    return d.toLocaleDateString('vi-VN', {
      year: 'numeric',
      month: 'long',
      day: 'numeric'
    });
  }

  /**
   * Format month Vietnamese
   */
  private static formatMonth(monthStr: string): string {
    const [year, month] = monthStr.split('-');
    const date = new Date(parseInt(year), parseInt(month) - 1, 1);
    return date.toLocaleDateString('vi-VN', { month: 'long', year: 'numeric' });
  }

  /**
   * Create a formatted line with label and value
   */
  private static createLine(label: string, value: string | number, indent: number = 0): string {
    const spaces = ' '.repeat(indent * 2);
    const valueStr = typeof value === 'number' ? this.formatNumber(value) : value;
    return `${spaces}${label}: ${valueStr}\\n`;
  }

  /**
   * Create a section header
   */
  private static createSectionHeader(title: string): string {
    return `\\n${title}\\n${'='.repeat(50)}\\n\\n`;
  }

  /**
   * Create a subsection header
   */
  private static createSubsectionHeader(title: string): string {
    return `\\n${title}\\n${'-'.repeat(40)}\\n`;
  }

  /**
   * Draw a KPI Card similar to Finance.tsx
   */
  private static drawKPICard(
    doc: PDFDocumentType,
    x: number,
    y: number,
    width: number,
    height: number,
    title: string,
    value: string,
    subtext: string,
    colorHex: string
  ): void {
    // Draw card border
    doc.rect(x, y, width, height)
       .lineWidth(1)
       .strokeColor('#e2e8f0')
       .stroke()
       .fillColor('#ffffff')
       .fill();

    // Draw colored accent bar on left
    doc.rect(x, y, 4, height)
       .fillColor(colorHex)
       .fill();

    // Title
    doc.fontSize(9).font(this.getFontName(true));
    doc.fillColor('#64748b');
    doc.text(title, x + 10, y + 8, { width: width - 20, align: 'left' });

    // Value
    doc.fontSize(16).font(this.getFontName(true));
    doc.fillColor('#1e293b');
    doc.text(value, x + 10, y + 25, { width: width - 20, align: 'left' });

    // Subtext
    doc.fontSize(8).font(this.getFontName(false));
    doc.fillColor('#94a3b8');
    doc.text(subtext, x + 10, y + 50, { width: width - 20, align: 'left' });

    // Reset fill color
    doc.fillColor('black');
  }

  /**
   * Draw a table using pdfkit
   * @param y - Top position of the table
   * @returns Bottom position of the table (for next content)
   */
  private static drawTable(
    doc: PDFDocumentType,
    x: number,
    y: number,
    headers: string[],
    rows: string[][],
    colWidths: number[],
    rowHeight: number = 20
  ): number {
    const tableWidth = colWidths.reduce((sum, w) => sum + w, 0);
    const tableHeight = (rows.length + 1) * rowHeight; // +1 for header row
    const bottomY = y + tableHeight;

    // Draw outer border
    doc.rect(x, y, tableWidth, tableHeight)
       .lineWidth(1.5)
       .stroke();

    // Draw header background (light gray)
    doc.rect(x, y, tableWidth, rowHeight)
       .fillColor('#E5E5E5')
       .fill()
       .fillColor('black'); // Reset to black

    // Draw column borders (vertical lines)
    let currentX = x;
    for (let i = 0; i < colWidths.length - 1; i++) {
      currentX += colWidths[i];
      doc.moveTo(currentX, y)
         .lineTo(currentX, bottomY)
         .lineWidth(0.5)
         .stroke();
    }

    // Draw row borders (horizontal lines)
    let currentY = y + rowHeight; // Start after header
    for (let i = 0; i < rows.length; i++) {
      doc.moveTo(x, currentY)
         .lineTo(x + tableWidth, currentY)
         .lineWidth(0.5)
         .stroke();
      currentY += rowHeight;
    }

    // Draw header text (centered vertically in header row)
    doc.fontSize(10).font(this.getFontName(true));
    const headerTextY = y + rowHeight / 2 - 3; // Center vertically (adjust for font baseline)
    currentX = x + 5; // Left padding
    headers.forEach((header, idx) => {
      doc.text(header, currentX, headerTextY, { 
        width: colWidths[idx] - 10, 
        align: 'left' 
      });
      currentX += colWidths[idx];
    });

    // Draw row text
    doc.font(this.getFontName(false)); // Reset to regular font
    rows.forEach((row, rowIdx) => {
      const rowTopY = y + rowHeight * (rowIdx + 1); // Top of this data row
      const rowTextY = rowTopY + rowHeight / 2 - 3; // Center vertically
      currentX = x + 5; // Left padding
      row.forEach((cell, colIdx) => {
        doc.text(cell, currentX, rowTextY, { 
          width: colWidths[colIdx] - 10, 
          align: 'left' 
        });
        currentX += colWidths[colIdx];
      });
    });

    return bottomY + 10; // Return Y position below table with spacing
  }

  /**
   * Render Monthly Report using pdfkit
   */
  private static renderMonthlyReport(doc: PDFDocumentType, data: MonthlyReportData, title: string): void {
    const monthStr = this.formatMonth(data.month);
    let yPos = 140; // Start below header

    // Page 1: Title and Summary
    doc.fontSize(18).font(this.getFontName(true));
    doc.fillColor('#1e40af'); // Blue color
    doc.y = yPos;
    doc.text('BÁO CÁO THÁNG', { align: 'center' });
    yPos += 30;
    
    doc.fillColor('black'); // Reset color

    // Info box with background
    const infoBoxY = yPos;
    const infoBoxHeight = 80;
    doc.rect(50, infoBoxY, 512, infoBoxHeight)
       .fillColor('#f8fafc')
       .fill()
       .lineWidth(1)
       .strokeColor('#e2e8f0')
       .stroke();
    
    doc.fontSize(11).font(this.getFontName(false));
    doc.fillColor('#475569');
    doc.text(`Tháng báo cáo: ${monthStr}`, 60, infoBoxY + 10);
    doc.text(`Dự án: ${data.project.name}`, 60, infoBoxY + 25);
    doc.text(`Mã dự án: ${data.project.code}`, 60, infoBoxY + 40);
    doc.text(`Công suất: ${data.project.capacityMWp} MWp`, 60, infoBoxY + 55);
    
    doc.fillColor('black'); // Reset
    yPos = infoBoxY + infoBoxHeight + 25;

    // Section: TÓM TẮT ĐIỀU HÀNH
    doc.fontSize(16).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.text('TÓM TẮT ĐIỀU HÀNH', 50, yPos);
    yPos += 25; // Space after header
    
    doc.fillColor('black'); // Reset

    // KPI Cards in 2x2 grid
    const cardWidth = 240;
    const cardHeight = 70;
    const cardGap = 20;
    let cardX = 50;
    let cardY = yPos;
    
    // Card 1: Sản lượng
    this.drawKPICard(doc, cardX, cardY, cardWidth, cardHeight,
      'SẢN LƯỢNG TỔNG CỘNG',
      `${(data.kpi.totalProduction / 1000).toFixed(1)} MWh`,
      'Tổng sản lượng điện trong tháng',
      '#3b82f6');
    cardX += cardWidth + cardGap;
    
    // Card 2: PR
    this.drawKPICard(doc, cardX, cardY, cardWidth, cardHeight,
      'PERFORMANCE RATIO',
      `${data.kpi.avgPR}%`,
      'Tỷ lệ hiệu suất trung bình',
      '#10b981');
    cardY += cardHeight + cardGap;
    cardX = 50;
    
    // Card 3: Availability
    this.drawKPICard(doc, cardX, cardY, cardWidth, cardHeight,
      'TỶ LỆ SẴN SÀNG',
      `${data.kpi.avgAvailability}%`,
      'Thời gian hoạt động / Tổng thời gian',
      '#f59e0b');
    cardX += cardWidth + cardGap;
    
    // Card 4: Specific Yield
    this.drawKPICard(doc, cardX, cardY, cardWidth, cardHeight,
      'SPECIFIC YIELD',
      `${data.kpi.avgSpecificYield} kWh/kWp`,
      'Sản lượng trên đơn vị công suất',
      '#8b5cf6');
    
    yPos = cardY + cardHeight + 30;

    if (data.financial.revenue > 0 || data.financial.opex > 0) {
      doc.fontSize(12).font(this.getFontName(true)).text('Tài chính', 50, yPos);
      yPos += 18; // Space after subsection header
      doc.fontSize(10).font(this.getFontName(false));
      doc.text(`Doanh thu: ${this.formatCurrency(data.financial.revenue)}`, 70, yPos);
      yPos += 18;
      doc.text(`Chi phí vận hành (OPEX): ${this.formatCurrency(data.financial.opex)}`, 70, yPos);
      yPos += 18;
      doc.text(`Lợi nhuận ròng: ${this.formatCurrency(data.financial.netProfit)}`, 70, yPos);
      yPos += 25;
    }

    // Page 2: KPI Details
    doc.addPage();
    yPos = 140; // Start below header

    doc.fontSize(16).font(this.getFontName(true));
    doc.y = yPos;
    doc.text('BÁO CÁO THÁNG (Tiếp theo)', { align: 'center' });
    yPos += 30;
    doc.fontSize(10).font(this.getFontName(false));
    doc.text(`Tháng: ${monthStr} - Dự án: ${data.project.name}`, 50, yPos);
    yPos += 20;

    // Draw separator
    doc.moveTo(50, yPos).lineTo(562, yPos).stroke();
    yPos += 20;

    doc.fontSize(14).font(this.getFontName(true)).text('1. CHỈ SỐ HIỆU SUẤT (KPI)', 50, yPos);
    yPos += 20; // Space after section header
    doc.fontSize(12).font(this.getFontName(true)).text('Chỉ số kỹ thuật', 50, yPos);
    yPos += 18; // Space after subsection header
    doc.fontSize(10).font(this.getFontName(false));
    doc.text(`Performance Ratio (PR) trung bình: ${data.kpi.avgPR}%`, 70, yPos);
    yPos += 18;
    doc.text(`Tỷ lệ sẵn sàng trung bình: ${data.kpi.avgAvailability}%`, 70, yPos);
    yPos += 18;
    doc.text(`Tổng sản lượng: ${this.formatNumber(data.kpi.totalProduction)} kWh`, 70, yPos);
    yPos += 18;
    doc.text(`Specific Yield trung bình: ${data.kpi.avgSpecificYield} kWh/kWp`, 70, yPos);
    yPos += 18;
    doc.text(`Bức xạ trung bình: ${data.kpi.avgIrradiation} kWh/m²`, 70, yPos);
    yPos += 30;

    // Page 3: Tickets and Work Orders
    doc.addPage();
    yPos = 140; // Start below header

    doc.fontSize(16).font(this.getFontName(true));
    doc.y = yPos;
    doc.text('BÁO CÁO THÁNG (Tiếp theo)', { align: 'center' });
    yPos += 30;
    doc.fontSize(10).font(this.getFontName(false));
    doc.text(`Tháng: ${monthStr} - Dự án: ${data.project.name}`, 50, yPos);
    yPos += 20;

    // Draw separator
    doc.moveTo(50, yPos).lineTo(562, yPos).stroke();
    yPos += 20;

    doc.fontSize(14).font(this.getFontName(true)).text('2. TICKETS', 50, yPos);
    yPos += 20; // Space after section header
    doc.fontSize(10).font(this.getFontName(false));
    doc.text(`Tổng số tickets: ${data.tickets.total}`, 50, yPos);
    yPos += 18;
    doc.text(`Tickets đã giải quyết: ${data.tickets.resolved}`, 50, yPos);
    yPos += 18;
    if (data.tickets.avgResolutionTime > 0) {
      doc.text(`Thời gian giải quyết TB: ${data.tickets.avgResolutionTime} giờ`, 50, yPos);
      yPos += 18;
    }
    yPos += 10;

    if (Object.keys(data.tickets.byCategory).length > 0) {
      doc.fontSize(12).font(this.getFontName(true)).text('Phân bố theo loại', 50, yPos);
      yPos += 18; // Space after subsection header before table

      // Create table for tickets by category
      const categoryHeaders = ['Loại', 'Số lượng'];
      const categoryRows = Object.entries(data.tickets.byCategory).map(([category, count]) => [
        category,
        count.toString()
      ]);
      const colWidths = [400, 112];
      yPos = this.drawTable(doc, 50, yPos, categoryHeaders, categoryRows, colWidths);
    }

    doc.fontSize(14).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.text('3. WORK ORDERS', 50, yPos);
    yPos += 25;
    
    doc.fillColor('black');
    doc.fontSize(10).font(this.getFontName(false));
    doc.text(`Tổng số: ${data.workOrders.total}`, 50, yPos);
    yPos += 18;
    doc.text(`Hoàn thành: ${data.workOrders.completed}`, 50, yPos);
    yPos += 18;
    doc.text(`Tổng chi phí: ${this.formatCurrency(data.workOrders.totalCost)}`, 50, yPos);
    yPos += 25;

    // Cost breakdown summary
    if (data.workOrders.totalCost > 0) {
      doc.fontSize(12).font(this.getFontName(true));
      doc.fillColor('#1e40af');
      doc.text('Phân tích chi phí', 50, yPos);
      yPos += 20;
      
      doc.fillColor('black');
      doc.fontSize(10).font(this.getFontName(false));
      const costHeaders = ['Loại chi phí', 'Giá trị'];
      const costRows = [
        ['Nhân công', this.formatCurrency(data.workOrders.costBreakdown.labor)],
        ['Vật tư', this.formatCurrency(data.workOrders.costBreakdown.material)],
        ['Thuê ngoài', this.formatCurrency(data.workOrders.costBreakdown.external)]
      ];
      const colWidths = [400, 112];
      yPos = this.drawTable(doc, 50, yPos, costHeaders, costRows, colWidths);
      yPos += 20;
    }

    // Detailed Work Orders List
    if (data.workOrders.list && data.workOrders.list.length > 0) {
      // Check if we need a new page
      if (yPos > 650) {
        doc.addPage();
        yPos = 140;
        doc.fontSize(16).font(this.getFontName(true));
        doc.y = yPos;
        doc.text('BÁO CÁO THÁNG (Tiếp theo)', { align: 'center' });
        yPos += 30;
        doc.fontSize(10).font(this.getFontName(false));
        doc.text(`Tháng: ${monthStr} - Dự án: ${data.project.name}`, 50, yPos);
        yPos += 20;
        doc.moveTo(50, yPos).lineTo(562, yPos).stroke();
        yPos += 20;
      }

      doc.fontSize(12).font(this.getFontName(true));
      doc.fillColor('#1e40af');
      doc.text('Chi tiết Work Orders', 50, yPos);
      yPos += 20;

      doc.fillColor('black');
      
      // Check if any work order has cost > 0
      const hasCost = data.workOrders.list.some(wo => (wo.totalCost || 0) > 0);
      
      // Calculate available width (page width - margins)
      const pageWidth = 612;
      const margin = 50;
      const availableWidth = pageWidth - (2 * margin); // 512px
      
      // Table for work orders details - simplified columns
      // Columns: Mã WO, Tiêu đề & PM Info, Trạng thái, Thời gian, [Chi phí - optional]
      const woHeaders = hasCost 
        ? ['Mã WO', 'Tiêu đề & PM Schedule', 'Trạng thái', 'Thời gian', 'Chi phí']
        : ['Mã WO', 'Tiêu đề & PM Schedule', 'Trạng thái', 'Thời gian'];
      
      // Calculate column widths proportionally to fit available width
      const woColWidths = hasCost
        ? [
            Math.floor(availableWidth * 0.15),  // Mã WO: 15% (~77px)
            Math.floor(availableWidth * 0.45),  // Tiêu đề: 45% (~230px)
            Math.floor(availableWidth * 0.15),  // Trạng thái: 15% (~77px)
            Math.floor(availableWidth * 0.15),  // Thời gian: 15% (~77px)
            Math.floor(availableWidth * 0.10)   // Chi phí: 10% (~51px)
          ]
        : [
            Math.floor(availableWidth * 0.15),  // Mã WO: 15% (~77px)
            Math.floor(availableWidth * 0.50),  // Tiêu đề: 50% (~256px)
            Math.floor(availableWidth * 0.18),  // Trạng thái: 18% (~92px)
            Math.floor(availableWidth * 0.17)   // Thời gian: 17% (~87px)
          ];
      
      // Adjust last column to fill remaining space
      const totalWidth = woColWidths.reduce((sum, w) => sum + w, 0);
      const diff = availableWidth - totalWidth;
      if (diff !== 0) {
        woColWidths[woColWidths.length - 1] += diff;
      }
      
      const woRowHeight = 45; // Reduced height for cleaner look

      // Draw table header
      const woTableY = yPos;
      const woTableWidth = woColWidths.reduce((sum, w) => sum + w, 0);
      
      doc.rect(50, woTableY, woTableWidth, woRowHeight)
         .fillColor('#1e40af')
         .fill()
         .lineWidth(1)
         .stroke();

      doc.fontSize(9).font(this.getFontName(true));
      doc.fillColor('#ffffff');
      let woHeaderX = 50 + 5;
      woHeaders.forEach((header, idx) => {
        doc.text(header, woHeaderX, woTableY + woRowHeight / 2 - 3, {
          width: woColWidths[idx] - 10,
          align: 'left'
        });
        woHeaderX += woColWidths[idx];
      });

      doc.fillColor('black');
      yPos = woTableY + woRowHeight;

      // Draw work orders rows
      data.workOrders.list.forEach((wo, index) => {
        // Check if we need a new page
        if (yPos + woRowHeight > 750) {
          doc.addPage();
          yPos = 140;
          doc.fontSize(16).font(this.getFontName(true));
          doc.y = yPos;
          doc.text('BÁO CÁO THÁNG (Tiếp theo)', { align: 'center' });
          yPos += 30;
          doc.fontSize(10).font(this.getFontName(false));
          doc.text(`Tháng: ${monthStr} - Dự án: ${data.project.name}`, 50, yPos);
          yPos += 20;
          doc.moveTo(50, yPos).lineTo(562, yPos).stroke();
          yPos += 20;
          
          // Redraw header
          doc.rect(50, yPos, woTableWidth, woRowHeight)
             .fillColor('#1e40af')
             .fill()
             .lineWidth(1)
             .stroke();
          doc.fontSize(9).font(this.getFontName(true));
          doc.fillColor('#ffffff');
          woHeaderX = 50 + 5;
          woHeaders.forEach((header, idx) => {
            doc.text(header, woHeaderX, yPos + woRowHeight / 2 - 3, {
              width: woColWidths[idx] - 10,
              align: 'left'
            });
            woHeaderX += woColWidths[idx];
          });
          doc.fillColor('black');
          yPos += woRowHeight;
        }

        // Row background (alternating)
        if (index % 2 === 0) {
          doc.rect(50, yPos, woTableWidth, woRowHeight)
             .fillColor('#f8fafc')
             .fill();
        }

        // Row border
        doc.rect(50, yPos, woTableWidth, woRowHeight)
           .lineWidth(0.5)
           .strokeColor('#e2e8f0')
           .stroke();

        // Column borders
        let colX = 50;
        for (let i = 0; i < woColWidths.length - 1; i++) {
          colX += woColWidths[i];
          doc.moveTo(colX, yPos)
             .lineTo(colX, yPos + woRowHeight)
             .lineWidth(0.5)
             .strokeColor('#e2e8f0')
             .stroke();
        }

        // Cell content
        doc.fontSize(8).font(this.getFontName(false));
        doc.fillColor('#1e293b');
        
        let cellX = 50 + 5;
        let cellY = yPos + 5;

        // Column 1: WO Code
        doc.text(wo.woCode || 'N/A', cellX, cellY, { width: woColWidths[0] - 10 });
        cellX += woColWidths[0];

        // Column 2: Title with PM Schedule info (includes Type)
        let titleText = wo.title || 'N/A';
        // Add type to title if available
        if (wo.workOrderType) {
          titleText = `[${wo.workOrderType}] ${titleText}`;
        }
        if (wo.pmSchedule) {
          titleText += `\nTần suất: ${wo.pmSchedule.frequency || 'N/A'}`;
          if (wo.pmSchedule.lastPerformed) {
            titleText += ` | Lần cuối: ${this.formatDate(wo.pmSchedule.lastPerformed)}`;
          }
          if (wo.pmSchedule.nextDue) {
            titleText += `\nĐến hạn tiếp: ${this.formatDate(wo.pmSchedule.nextDue)}`;
          }
        }
        doc.text(titleText, cellX, cellY, { width: woColWidths[1] - 10, align: 'left' });
        cellX += woColWidths[1];

        // Column 3: Status
        doc.text(wo.status || 'N/A', cellX, cellY, { width: woColWidths[2] - 10 });
        cellX += woColWidths[2];

        // Column 4: Time details (simplified)
        let timeText = '';
        if (wo.actualStart) {
          timeText = `${this.formatDate(wo.actualStart)}`;
          if (wo.actualEnd) {
            timeText += `\n→ ${this.formatDate(wo.actualEnd)}`;
            const start = new Date(wo.actualStart);
            const end = new Date(wo.actualEnd);
            const duration = Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)) + 1;
            timeText += `\n(${duration} ngày)`;
          }
        } else if (wo.scheduledStart) {
          timeText = `${this.formatDate(wo.scheduledStart)}`;
          if (wo.scheduledEnd) {
            timeText += `\n→ ${this.formatDate(wo.scheduledEnd)}`;
          }
        } else if (wo.createdAt) {
          timeText = `Tạo: ${this.formatDate(wo.createdAt)}`;
        } else {
          timeText = 'N/A';
        }
        doc.text(timeText, cellX, cellY, { width: woColWidths[3] - 10, align: 'left' });
        cellX += woColWidths[3];

        // Column 5: Cost (only if hasCost is true)
        if (hasCost) {
          let costText = '';
          if (wo.totalCost > 0) {
            costText = this.formatCurrency(wo.totalCost);
          } else {
            costText = '0 VND';
          }
          doc.text(costText, cellX, cellY, { width: woColWidths[4] - 10, align: 'left' });
        }

        yPos += woRowHeight;
      });

      // Draw outer border
      doc.rect(50, woTableY, woTableWidth, yPos - woTableY)
         .lineWidth(1.5)
         .stroke();
    }

    // Page 4: Financial Summary
    if (data.financial.revenue > 0 || data.financial.opex > 0) {
      doc.addPage();
      yPos = 140; // Start below header

      doc.fontSize(16).font(this.getFontName(true));
    doc.y = yPos;
    doc.text('BÁO CÁO THÁNG (Tiếp theo)', { align: 'center' });
      yPos += 30;
      doc.fontSize(10).font(this.getFontName(false));
      doc.text(`Tháng: ${monthStr} - Dự án: ${data.project.name}`, 50, yPos);
      yPos += 20;

      // Draw separator
      doc.moveTo(50, yPos).lineTo(562, yPos).stroke();
      yPos += 20;

      doc.fontSize(14).font(this.getFontName(true)).text('4. TÀI CHÍNH', 50, yPos);
      yPos += 20; // Space after section header
      doc.fontSize(12).font(this.getFontName(true)).text('Kết quả tháng', 50, yPos);
      yPos += 18; // Space after subsection header
      doc.fontSize(10).font(this.getFontName(false));
      doc.text(`Doanh thu: ${this.formatCurrency(data.financial.revenue)}`, 70, yPos);
      yPos += 18;
      doc.text(`Chi phí vận hành (OPEX): ${this.formatCurrency(data.financial.opex)}`, 70, yPos);
      yPos += 18;
      doc.text(`Lợi nhuận ròng: ${this.formatCurrency(data.financial.netProfit)}`, 70, yPos);
    }
  }

  /**
   * Render Daily Report using pdfkit
   */
  private static renderDailyReport(doc: PDFDocumentType, data: DailyReportData, title: string): void {
    const dateStr = this.formatDate(data.date);
    let yPos = 140; // Start below header

    doc.fontSize(18).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.y = yPos;
    doc.text('BÁO CÁO NGÀY', { align: 'center' });
    yPos += 30;
    
    doc.fillColor('black'); // Reset

    // Info box
    const infoBoxY = yPos;
    const infoBoxHeight = 60;
    doc.rect(50, infoBoxY, 512, infoBoxHeight)
       .fillColor('#f8fafc')
       .fill()
       .lineWidth(1)
       .strokeColor('#e2e8f0')
       .stroke();
    
    doc.fontSize(11).font(this.getFontName(false));
    doc.fillColor('#475569');
    doc.text(`Ngày báo cáo: ${dateStr}`, 60, infoBoxY + 10);
    doc.text(`Dự án: ${data.project.name}`, 60, infoBoxY + 25);
    doc.text(`Mã dự án: ${data.project.code}`, 60, infoBoxY + 40);
    
    doc.fillColor('black'); // Reset
    yPos = infoBoxY + infoBoxHeight + 25;

    doc.fontSize(16).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.text('1. TỔNG QUAN', 50, yPos);
    yPos += 25;
    
    doc.fillColor('black'); // Reset
    doc.fontSize(10).font(this.getFontName(false));
    doc.text(`Tổng số Ticket: ${data.tickets.total}`, 50, yPos);
    yPos += 18;
    doc.text(`Ticket đang mở: ${data.summary.openTickets}`, 50, yPos);
    yPos += 18;
    doc.text(`Ticket đã giải quyết: ${data.summary.resolvedTickets}`, 50, yPos);
    yPos += 18;
    doc.text(`Work Order hoàn thành: ${data.summary.completedWorkOrders}`, 50, yPos);
    yPos += 25;

    if (data.workOrders.total > 0) {
      doc.fontSize(12).font(this.getFontName(true)).text('Chi phí Work Order', 50, yPos);
      yPos += 20;
      doc.fontSize(10).font(this.getFontName(false));
      doc.text(`Tổng chi phí: ${this.formatCurrency(data.workOrders.totalCost)}`, 70, yPos);
    }
  }

  /**
   * Render Financial Report using pdfkit
   * Layout matches Finance.tsx page structure
   */
  private static renderFinancialReport(doc: PDFDocumentType, data: FinancialReportData, title: string): void {
    const pageWidth = 612;
    const pageHeight = 792;
    const margin = 50;
    const contentWidth = pageWidth - 2 * margin;
    let yPos = 140; // Start below header

    // Page 1: Title and Info
    doc.fontSize(18).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.y = yPos;
    doc.text('BÁO CÁO TÀI CHÍNH (P&L)', { align: 'center' });
    yPos += 30;
    
    doc.fillColor('black'); // Reset
    
    // Info box
    const infoBoxY = yPos;
    const infoBoxHeight = 50;
    doc.rect(margin, infoBoxY, contentWidth, infoBoxHeight)
       .fillColor('#f8fafc')
       .fill()
       .lineWidth(1)
       .strokeColor('#e2e8f0')
       .stroke();
    
    doc.fontSize(11).font(this.getFontName(false));
    doc.fillColor('#475569');
    doc.text(`Chu kỳ báo cáo: ${data.period}`, margin + 10, infoBoxY + 10);
    doc.text(`Dự án: ${data.project.name}`, margin + 10, infoBoxY + 25);
    doc.text(`Mã dự án: ${data.project.code}`, margin + 10, infoBoxY + 38);
    
    doc.fillColor('black'); // Reset
    yPos = infoBoxY + infoBoxHeight + 25;

    // Title: Tài chính & ROI (Financial Modeling)
    doc.fontSize(16).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.text('Tài chính & ROI (Financial Modeling)', margin, yPos);
    yPos += 30;
    
    doc.fillColor('black'); // Reset

    // KPI Cards Section (4 cards in 2x2 grid)
    const cardWidth = (contentWidth - 20) / 2; // 2 columns with gap
    const cardHeight = 80;
    const cardGap = 20;
    let cardX = margin;
    let cardY = yPos;

    // Card 1: Tổng doanh thu (YTD)
    this.drawKPICard(doc, cardX, cardY, cardWidth, cardHeight, 
      'TỔNG DOANH THU (YTD)', 
      `${(data.summary.totalRevenue / 1000000000).toFixed(1)} Tỷ VNĐ`,
      'Doanh thu bán điện thực tế',
      '#3b82f6');
    cardX += cardWidth + cardGap;

    // Card 2: Chi phí vận hành (OPEX)
    this.drawKPICard(doc, cardX, cardY, cardWidth, cardHeight,
      'CHI PHÍ VẬN HÀNH (OPEX)',
      `${(data.summary.totalOpex / 1000000000).toFixed(1)} Tỷ VNĐ`,
      'Bao gồm bảo trì, nhân sự, bảo hiểm',
      '#ef4444');
    cardY += cardHeight + cardGap;
    cardX = margin;

    // Card 3: Lợi nhuận ròng (Net)
    this.drawKPICard(doc, cardX, cardY, cardWidth, cardHeight,
      'LỢI NHUẬN RÒNG (NET)',
      `${(data.summary.totalNetProfit / 1000000000).toFixed(1)} Tỷ VNĐ`,
      `Biên lợi nhuận: ${data.summary.profitMargin?.toFixed(1) || '0.0'}%`,
      '#10b981');
    cardX += cardWidth + cardGap;

    // Card 4: ROI Lũy kế
    this.drawKPICard(doc, cardX, cardY, cardWidth, cardHeight,
      'ROI LŨY KẾ',
      `${data.summary.currentROI?.toFixed(1) || '0.0'}%`,
      'Tỷ suất hoàn vốn đầu tư',
      '#8b5cf6');
    
    yPos = cardY + cardHeight + 30;

    // Check if we need a new page
    if (yPos > pageHeight - 200) {
      doc.addPage();
      yPos = 140; // Start below header
    }

    // Charts Section Title
    doc.fontSize(14).font(this.getFontName(true));
    doc.text('Doanh thu & Chi phí (Theo tháng)', margin, yPos);
    yPos += 25;

    // Chart data summary (since we can't render actual charts, show data table)
    if (data.financials && data.financials.length > 0) {
      const chartHeaders = ['Tháng', 'Doanh thu (Tỷ)', 'OPEX (Tỷ)', 'Lợi nhuận (Tỷ)', 'ROI (%)'];
      const chartRows = data.financials.slice(0, 6).map(f => [
        f.month,
        (f.revenue / 1000000000).toFixed(2),
        (f.opex / 1000000000).toFixed(2),
        (f.netProfit / 1000000000).toFixed(2),
        f.cumulativeROI.toFixed(1)
      ]);
      const chartColWidths = [100, 100, 100, 100, 80];
      yPos = this.drawTable(doc, margin, yPos, chartHeaders, chartRows, chartColWidths, 20);
      yPos += 15;
    }

    // Cost Breakdown Section
    if (data.costBreakdown && data.costBreakdown.length > 0) {
      doc.fontSize(14).font(this.getFontName(true));
      doc.text('Cơ cấu chi phí (Cost Breakdown)', margin, yPos);
      yPos += 25;

      const totalCost = data.costBreakdown.reduce((sum, item) => sum + item.value, 0);
      const breakdownRows = data.costBreakdown.map(item => {
        const percent = totalCost > 0 ? (item.value / totalCost * 100).toFixed(1) : '0.0';
        return [
          item.name,
          `${(item.value / 1000000).toFixed(1)} Triệu`,
          `${percent}%`
        ];
      });
      const breakdownHeaders = ['Loại chi phí', 'Giá trị', 'Tỷ lệ'];
      const breakdownColWidths = [250, 150, 100];
      yPos = this.drawTable(doc, margin, yPos, breakdownHeaders, breakdownRows, breakdownColWidths, 18);
      yPos += 20;
    }

    // Check if we need a new page for financial table
    if (yPos > pageHeight - 250) {
      doc.addPage();
      yPos = 140; // Start below header
    }

    // Financial Table Section
    doc.fontSize(14).font(this.getFontName(true));
    doc.text('Chi tiết dòng tiền (Cashflow)', margin, yPos);
    yPos += 25;

    if (data.financials && data.financials.length > 0) {
      const tableHeaders = ['Tháng', 'Doanh thu (Tỷ)', 'OPEX (Tỷ)', 'Lợi nhuận ròng (Tỷ)', 'ROI Lũy kế (%)'];
      const tableRows = data.financials.map(f => [
        f.month,
        (f.revenue / 1000000000).toFixed(2),
        (f.opex / 1000000000).toFixed(2),
        (f.netProfit / 1000000000).toFixed(2),
        f.cumulativeROI.toFixed(1)
      ]);
      
      // Add totals row
      tableRows.push([
        'Tổng cộng',
        (data.summary.totalRevenue / 1000000000).toFixed(2),
        (data.summary.totalOpex / 1000000000).toFixed(2),
        (data.summary.totalNetProfit / 1000000000).toFixed(2),
        '-'
      ]);

      const tableColWidths = [100, 100, 100, 120, 90];
      yPos = this.drawTable(doc, margin, yPos, tableHeaders, tableRows, tableColWidths, 18);
    }

    // Deprecated: Screenshot support (keeping for backward compatibility)
    // If screenshot exists, render it instead of the above content
    // NOTE: When screenshot is used, it replaces all the above content
    if (data.screenshot) {
      try {
        // Extract base64 data from data URL if needed
        let base64Data = data.screenshot;
        let imageFormat = 'png'; // Default format
        
        if (base64Data.startsWith('data:image')) {
          // Extract format from data URL
          const formatMatch = base64Data.match(/data:image\/(\w+);/);
          if (formatMatch) {
            imageFormat = formatMatch[1];
          }
          base64Data = base64Data.split(',')[1];
        }

        // Decode base64 to buffer
        const imageBuffer = Buffer.from(base64Data, 'base64');
        
        // Calculate image dimensions to fit page width - FULL WIDTH
        // Note: PDFDocument has default margins (50 points each side)
        // We need to account for these margins when calculating full width
        const pageWidth = 612; // A4 width in points
        const pageHeight = 792; // A4 height in points
        const docLeftMargin = 50; // Document's left margin
        const docRightMargin = 50; // Document's right margin
        const docBottomMargin = 50; // Document's bottom margin
        
        // Calculate full usable width (page width minus document margins)
        const fullUsableWidth = pageWidth - docLeftMargin - docRightMargin; // 512 points
        const availableHeight = pageHeight - yPos - docBottomMargin; // Available height
        
        // Use minimal additional margin for screenshot (just 5 points each side for visual spacing)
        const screenshotMargin = 5;
        const screenshotWidth = fullUsableWidth - (2 * screenshotMargin); // 502 points (~98% of usable width)
        const screenshotX = docLeftMargin + screenshotMargin; // Start position
        
        // Add image to PDF with FULL WIDTH display
        // pdfkit's image() method can handle Buffer directly
        // Use 'fit' option with width priority - image will scale to fill full width
        // pdfkit will automatically create new pages if image is too tall
        // Position is already set by screenshotX, so no need for align
        doc.image(imageBuffer, screenshotX, yPos, {
          fit: [screenshotWidth, availableHeight]
        });
        
        // Image will now use ~98% of usable width (502 points out of 512 usable points)
        // This maximizes the screenshot display while respecting document margins
        
        // Update yPos after image is added (doc.y is updated automatically by pdfkit)
        // If image spans multiple pages, doc.y will be on the last page
        yPos = doc.y + 20;
        
        // Ensure we're on a new page for summary if needed
        // Check if we're near the bottom of current page
        if (yPos > pageHeight - 100) {
          doc.addPage();
          yPos = 50;
        } else {
          // Add some spacing before summary
          yPos += 10;
        }
      } catch (imageError: any) {
        console.error('Error rendering screenshot:', imageError);
        // Fallback to text summary if image fails
        doc.fontSize(14).font(this.getFontName(true)).text('TÓM TẮT TÀI CHÍNH', 50, yPos);
        yPos += 25;
        doc.fontSize(10).font(this.getFontName(false));
        doc.text(`Tổng doanh thu: ${this.formatCurrency(data.summary.totalRevenue)}`, 50, yPos);
        yPos += 18;
        doc.text(`Tổng chi phí vận hành: ${this.formatCurrency(data.summary.totalOpex)}`, 50, yPos);
        yPos += 18;
        doc.text(`Tổng lợi nhuận ròng: ${this.formatCurrency(data.summary.totalNetProfit)}`, 50, yPos);
        yPos += 18;
        doc.text(`ROI trung bình: ${data.summary.avgROI}%`, 50, yPos);
        return; // Exit early if screenshot fails
      }
      // If screenshot renders successfully, don't render summary again
      return;
    }

    // Summary Section (only render if no screenshot was used)
    // Check if we have enough space on current page
    if (yPos > pageHeight - 150) {
      doc.addPage();
      yPos = 140; // Start below header
    }
    
    yPos += 20;
    doc.fontSize(14).font(this.getFontName(true));
    doc.text('TÓM TẮT TÀI CHÍNH', margin, yPos);
    yPos += 20;
    doc.fontSize(10).font(this.getFontName(false));
    doc.text(`Tổng doanh thu: ${this.formatCurrency(data.summary.totalRevenue)}`, margin + 10, yPos);
    yPos += 18;
    doc.text(`Tổng chi phí vận hành: ${this.formatCurrency(data.summary.totalOpex)}`, margin + 10, yPos);
    yPos += 18;
    doc.text(`Tổng lợi nhuận ròng: ${this.formatCurrency(data.summary.totalNetProfit)}`, margin + 10, yPos);
    yPos += 18;
    doc.text(`ROI trung bình: ${data.summary.avgROI}%`, margin + 10, yPos);
    if (data.summary.profitMargin !== undefined) {
      yPos += 18;
      doc.text(`Biên lợi nhuận: ${data.summary.profitMargin.toFixed(1)}%`, margin + 10, yPos);
    }
  }

  /**
   * Render Audit Report using pdfkit
   */
  private static renderAuditReport(doc: PDFDocumentType, data: AuditReportData, title: string): void {
    const startStr = this.formatDate(data.period.start);
    const endStr = this.formatDate(data.period.end);
    let yPos = 140; // Start below header

    doc.fontSize(18).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.y = yPos;
    doc.text('BÁO CÁO KIỂM TOÁN', { align: 'center' });
    yPos += 30;
    
    doc.fillColor('black'); // Reset

    // Info box
    const infoBoxY = yPos;
    let infoBoxHeight = 60;
    if (data.project) {
      infoBoxHeight = 80;
    }
    doc.rect(50, infoBoxY, 512, infoBoxHeight)
       .fillColor('#f8fafc')
       .fill()
       .lineWidth(1)
       .strokeColor('#e2e8f0')
       .stroke();
    
    doc.fontSize(11).font(this.getFontName(false));
    doc.fillColor('#475569');
    doc.text(`Từ ngày: ${startStr}`, 60, infoBoxY + 10);
    doc.text(`Đến ngày: ${endStr}`, 60, infoBoxY + 25);
    if (data.project) {
      doc.text(`Dự án: ${data.project.name}`, 60, infoBoxY + 40);
      doc.text(`Mã dự án: ${data.project.code}`, 60, infoBoxY + 55);
    }
    
    doc.fillColor('black'); // Reset
    yPos = infoBoxY + infoBoxHeight + 25;

    doc.fontSize(16).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.text('TÓM TẮT', 50, yPos);
    yPos += 25;
    
    doc.fillColor('black'); // Reset
    doc.fontSize(10).font(this.getFontName(false));
    doc.text(`Tổng số hành động: ${data.summary.totalActions}`, 50, yPos);
  }

  /**
   * Render Default Report using pdfkit
   */
  private static renderDefaultReport(doc: PDFDocumentType, title: string): void {
    let yPos = 140; // Start below header

    doc.fontSize(18).font(this.getFontName(true));
    doc.fillColor('#1e40af');
    doc.y = yPos;
    doc.text('BÁO CÁO', { align: 'center' });
    yPos += 30;
    
    doc.fillColor('black'); // Reset
    
    doc.fontSize(12).font(this.getFontName(false));
    doc.y = yPos;
    doc.text(title, { align: 'center' });
    yPos += 30;
    doc.text(`Được tạo vào: ${new Date().toLocaleString('vi-VN')}`, 50, yPos);
  }

}
