const db = require('../models');
const { sendResponse, sendError } = require('../utils/response');
const asyncHandler = require('../middlewares/asyncHandler');
const PDFDocument = require('pdfkit');
const path = require('path');
const fs = require('fs');

/**
 * Generate Professional PDF for Purchase Requisition Slip
 * Enterprise-grade format similar to SAP/Oracle ERP
 */
exports.generatePDF = asyncHandler(async (req, res) => {
  const { id } = req.params;

  // Fetch Purchase Requisition with all related data
  const pr = await db.PurchaseRequisition.findByPk(id, {
    include: [
      { model: db.Company, as: 'company', attributes: ['id', 'code', 'name', 'legal_name'] },
      { model: db.Plant, as: 'plant', attributes: ['id', 'code', 'name'] },
      { model: db.FiscalYear, as: 'fiscalYear', attributes: ['id', 'fiscal_year', 'start_date', 'end_date'] },
      { model: db.Department, as: 'department', attributes: ['id', 'department_code', 'department_name'] },
      { model: db.CostCenter, as: 'costCenter', attributes: ['id', 'cost_center_code', 'description'] },
      {
        model: db.PurchaseRequisitionItem,
        as: 'items',
        include: [
          { 
            model: db.Material, 
            as: 'material',
            attributes: ['id', 'material_number', 'description']
          },
          { model: db.UOM, as: 'uom', attributes: ['id', 'uom_code', 'uom_name'] }
        ],
        order: [['line_number', 'ASC']]
      },
      { model: db.User, as: 'requestedByUser', attributes: ['id', 'first_name', 'last_name'] },
      { model: db.User, as: 'approvedByUser', attributes: ['id', 'first_name', 'last_name'] }
    ]
  });

  if (!pr) {
    return sendError(res, 'Purchase Requisition not found', 404);
  }

  // Get document number from Document Master
  let documentNumber = 'RI/PUR/F/02';
  const document = await db.Document.findOne({
    where: {
      company_id: pr.company_id,
      erp_module: 'PURCHASE_REQUISITION',
      status: 'ACTIVE'
    },
    order: [['id', 'DESC']]
  });
  
  if (document && document.document_number) {
    documentNumber = document.document_number;
  }

  // Fetch Print Header for company logo
  const printHeader = await db.PrintHeader.findOne({
    where: {
      company_id: pr.company_id,
      status: 'ACTIVE'
    },
    order: [['id', 'DESC']]
  });

  // Get logo paths if exists (company logo + ISO/certificate logo)
  const resolveUploadPath = (relativePath) => {
    if (!relativePath) return null;
    let fullPath = path.join(__dirname, '..', 'uploads', relativePath);
    if (fs.existsSync(fullPath)) return fullPath;
    fullPath = path.join(__dirname, '..', relativePath);
    if (fs.existsSync(fullPath)) return fullPath;
    return null;
  };

  const logoPath = resolveUploadPath(printHeader?.logo_path);
  // Per requirement: Purchase Requisition Slip should NOT display ISO/certification in header.
  // Keep the company logo, but hide certification logo for this document type.
  const certLogoPath = null;

  if (!logoPath) {
    console.log('No print header logo found for company_id:', pr.company_id);
  }

  // Create PDF with professional settings
  const doc = new PDFDocument({ 
    margin: 40,
    size: 'A4',
    layout: 'landscape',
    bufferPages: true // Enable buffering for page number
  });
  
  const filename = `PR_${pr.pr_number || pr.id}.pdf`;
  
  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  
  doc.pipe(res);

  // ==================== CONSTANTS ====================
  const pageWidth = doc.page.width;
  const pageHeight = doc.page.height;
  const margin = 40;
  const contentWidth = pageWidth - (margin * 2);
  
  // Colors - Professional ERP theme
  const primaryColor = '#009688';
  const lightBg = '#E0F2F1';
  const borderColor = '#009688';
  const textColor = '#000000';
  const labelColor = '#555555';
  
  // Layout measurements
  const headerHeight = 80;
  const footerHeight = 50;
  const tableHeaderHeight = 28;
  const rowHeight = 25;
  
  // Calculate available space for rows per page
  const availableHeight = pageHeight - margin - headerHeight - 10 - tableHeaderHeight - footerHeight - margin - 10;
  const maxRowsPerPage = Math.floor(availableHeight / rowHeight);

  // Column widths (optimized for landscape A4)
  const colWidths = {
    sno: 40,
    description: 340,
    unit: 70,
    quantity: 90,
    purpose: 220
  };

  // ==================== HELPER FUNCTIONS ====================
  
  function drawHeader(isFirstPage = false) {
    let y = margin;
    
    // Document number box (top-right corner - VERY PROMINENT)
    const docNumBoxWidth = 130;
    const docNumBoxHeight = 22;
    const docNumBoxX = pageWidth - margin - docNumBoxWidth;
    const docNumBoxY = y - 28;
    
    // Draw document number box with border
    doc.rect(docNumBoxX, docNumBoxY, docNumBoxWidth, docNumBoxHeight).lineWidth(1).stroke(borderColor);
    
    // Document number text - larger and bold
    doc.fontSize(11).font('Helvetica-Bold').fillColor(textColor);
    doc.text(documentNumber, docNumBoxX + 5, docNumBoxY + 5, { 
      width: docNumBoxWidth - 10, 
      align: 'center' 
    });
    
    // Header box
    doc.rect(margin, y, contentWidth, headerHeight).lineWidth(1.5).stroke(borderColor);
    
    // Left section - Company logo/name (30%)
    const logoWidth = contentWidth * 0.28;
    doc.moveTo(margin + logoWidth, y).lineTo(margin + logoWidth, y + headerHeight).lineWidth(1.5).stroke(borderColor);
    
    // Display logo with company name (horizontal layout)
    if (logoPath) {
      try {
        console.log('Attempting to add logo to PDF:', logoPath);
        // Display ONLY the logo (no green "RAM INDUSTRIES" text), fill the left box professionally
        // Use `cover` so the logo occupies the box (cropping extra whitespace if needed).
        // Keep a small padding so the box outline remains visible.
        const padding = 8;
        const logoBoxX = margin + padding;
        const logoBoxY = y + padding;
        const logoBoxW = logoWidth - (padding * 2);
        const logoBoxH = headerHeight - (padding * 2);

        doc.image(logoPath, logoBoxX, logoBoxY, {
          cover: [logoBoxW, logoBoxH],
          align: 'center',
          valign: 'center'
        });
        console.log('Logo added successfully to PDF');

        // Re-stroke top & bottom borders of the left box so the outline is visible above the image
        doc.save();
        doc.lineWidth(1.5).strokeColor(borderColor);
        doc.moveTo(margin, y).lineTo(margin + logoWidth, y).stroke();
        doc.moveTo(margin, y + headerHeight).lineTo(margin + logoWidth, y + headerHeight).stroke();
        doc.restore();
      } catch (error) {
        console.error('Error loading logo into PDF:', error.message);
        // Fallback to text if logo fails to load
        doc.fontSize(18).font('Helvetica-Bold').fillColor(textColor);
        doc.text(pr.company?.name || 'Company', margin + 15, y + 30, { width: logoWidth - 30, align: 'center' });
      }
    } else {
      console.log('No logo path available, using text fallback');
      // No logo - display company name as text only
      doc.fontSize(18).font('Helvetica-Bold').fillColor(textColor);
      doc.text(pr.company?.name || 'Company', margin + 15, y + 30, { width: logoWidth - 30, align: 'center' });
    }
    
    // Middle section - Title (47%)
    const titleWidth = contentWidth * 0.47;
    doc.moveTo(margin + logoWidth + titleWidth, y).lineTo(margin + logoWidth + titleWidth, y + headerHeight).lineWidth(1.5).stroke(borderColor);
    
    doc.fontSize(16).font('Helvetica-Bold').fillColor(primaryColor);
    doc.text('PURCHASE REQUISITION SLIP', margin + logoWidth + 15, y + 12, {
      width: titleWidth - 30,
      align: 'left'
    });
    
    // Divider line
    doc.moveTo(margin + logoWidth + 10, y + 38).lineTo(margin + logoWidth + titleWidth - 10, y + 38).lineWidth(1).stroke(borderColor);
    
    // Department info
    doc.fontSize(10).font('Helvetica').fillColor(labelColor);
    doc.text('Department:', margin + logoWidth + 15, y + 48);
    doc.font('Helvetica-Bold').fillColor(textColor);
    const deptName = pr.department?.department_name || 'N/A';
    doc.text(deptName, margin + logoWidth + 85, y + 48, { width: titleWidth - 100 });
    
    // Right section - SI No. and Date (25%)
    const infoX = margin + logoWidth + titleWidth + 15;
    const certSize = 55;
    const certReservedW = certLogoPath ? (certSize + 20) : 0;
    const infoRightLimit = pageWidth - margin - 10 - certReservedW;
    
    doc.fontSize(9).font('Helvetica').fillColor(labelColor);
    doc.text('SI No.', infoX, y + 15, { width: Math.max(80, infoRightLimit - infoX), align: 'left' });
    doc.font('Helvetica-Bold').fillColor(textColor).fontSize(10);
    doc.text(pr.pr_number || 'N/A', infoX + 50, y + 15, { width: Math.max(80, infoRightLimit - (infoX + 50)), align: 'left' });
    
    // Horizontal divider
    doc.moveTo(margin + logoWidth + titleWidth + 10, y + 35).lineTo(pageWidth - margin - 10, y + 35).lineWidth(1).stroke(borderColor);
    
    doc.fontSize(9).font('Helvetica').fillColor(labelColor);
    doc.text('Date:', infoX, y + 48, { width: Math.max(80, infoRightLimit - infoX), align: 'left' });
    doc.font('Helvetica-Bold').fillColor(textColor).fontSize(10);
    const prDate = pr.pr_date ? new Date(pr.pr_date).toLocaleDateString('en-GB') : 'N/A';
    doc.text(prDate, infoX + 50, y + 48, { width: Math.max(80, infoRightLimit - (infoX + 50)), align: 'left' });

    // Intentionally no ISO/certification logo on Purchase Requisition Slip header.
    
    return y + headerHeight + 10;
  }
  
  function drawTableHeader(y) {
    let x = margin;
    
    // Header background
    doc.rect(margin, y, contentWidth, tableHeaderHeight).fillAndStroke(lightBg, borderColor);
    
    doc.fontSize(10).font('Helvetica-Bold').fillColor(textColor);
    
    // S.No
    doc.text('S.No', x + 5, y + 8, { width: colWidths.sno - 10, align: 'center' });
    doc.moveTo(x + colWidths.sno, y).lineTo(x + colWidths.sno, y + tableHeaderHeight).stroke(borderColor);
    x += colWidths.sno;
    
    // Description
    doc.text('Description', x + 5, y + 8, { width: colWidths.description - 10, align: 'center' });
    doc.moveTo(x + colWidths.description, y).lineTo(x + colWidths.description, y + tableHeaderHeight).stroke(borderColor);
    x += colWidths.description;
    
    // Unit
    doc.text('Unit', x + 5, y + 8, { width: colWidths.unit - 10, align: 'center' });
    doc.moveTo(x + colWidths.unit, y).lineTo(x + colWidths.unit, y + tableHeaderHeight).stroke(borderColor);
    x += colWidths.unit;
    
    // Quantity
    doc.text('Quantity', x + 5, y + 8, { width: colWidths.quantity - 10, align: 'center' });
    doc.moveTo(x + colWidths.quantity, y).lineTo(x + colWidths.quantity, y + tableHeaderHeight).stroke(borderColor);
    x += colWidths.quantity;
    
    // Purpose
    doc.text('Purpose', x + 5, y + 8, { width: colWidths.purpose - 10, align: 'center' });
    
    return y + tableHeaderHeight;
  }
  
  function drawRow(y, item, index) {
    let x = margin;
    
    // Row border
    doc.rect(margin, y, contentWidth, rowHeight).stroke(borderColor);
    
    doc.fontSize(9).font('Helvetica').fillColor(textColor);
    
    // S.No
    if (item) {
      doc.text(String(index + 1), x + 5, y + 7, { width: colWidths.sno - 10, align: 'center' });
    }
    doc.moveTo(x + colWidths.sno, y).lineTo(x + colWidths.sno, y + rowHeight).stroke(borderColor);
    x += colWidths.sno;
    
    // Description
    if (item) {
      const materialDesc = item.material?.description || item.material?.material_number || '';
      const description = item.description || materialDesc;
      doc.text(description, x + 5, y + 7, { 
        width: colWidths.description - 10, 
        height: rowHeight - 14,
        ellipsis: true
      });
    }
    doc.moveTo(x + colWidths.description, y).lineTo(x + colWidths.description, y + rowHeight).stroke(borderColor);
    x += colWidths.description;
    
    // Unit
    if (item) {
      const unit = item.uom?.uom_code || item.uom?.uom_name || '';
      doc.text(unit, x + 5, y + 7, { width: colWidths.unit - 10, align: 'center' });
    }
    doc.moveTo(x + colWidths.unit, y).lineTo(x + colWidths.unit, y + rowHeight).stroke(borderColor);
    x += colWidths.unit;
    
    // Quantity
    if (item) {
      const quantity = parseFloat(item.quantity).toFixed(3);
      doc.text(quantity, x + 5, y + 7, { width: colWidths.quantity - 10, align: 'right' });
    }
    doc.moveTo(x + colWidths.quantity, y).lineTo(x + colWidths.quantity, y + rowHeight).stroke(borderColor);
    x += colWidths.quantity;
    
    // Purpose
    if (item && item.remarks) {
      doc.text(item.remarks, x + 5, y + 7, { 
        width: colWidths.purpose - 10, 
        height: rowHeight - 14,
        ellipsis: true
      });
    }
    
    return y + rowHeight;
  }
  
  function drawFooter(y, isLastPage = false) {
    // Only draw signature section on the last page
    if (!isLastPage) return;
    
    // Ensure footer is at bottom
    const footerY = Math.max(y + 15, pageHeight - footerHeight - margin + 10);
    
    // Requested by (left)
    doc.fontSize(10).font('Helvetica-Bold').fillColor(primaryColor);
    doc.text('Requested by:', margin, footerY);
    
    if (pr.requestedByUser) {
      doc.fontSize(9).font('Helvetica').fillColor(textColor);
      doc.text(`${pr.requestedByUser.first_name} ${pr.requestedByUser.last_name}`, margin, footerY + 18);
    }
    
    // Approved by (right)
    doc.fontSize(10).font('Helvetica-Bold').fillColor(primaryColor);
    doc.text('Approved by:', pageWidth - margin - 150, footerY, { width: 150, align: 'left' });
    
    if (pr.approvedByUser) {
      doc.fontSize(9).font('Helvetica').fillColor(textColor);
      doc.text(`${pr.approvedByUser.first_name} ${pr.approvedByUser.last_name}`, pageWidth - margin - 150, footerY + 18, { width: 150, align: 'left' });
    }
  }

  // ==================== GENERATE PDF ====================
  
  const items = pr.items || [];
  let currentPage = 0;
  let rowsOnCurrentPage = 0;
  let yPosition = 0;
  
  // First page
  currentPage++;
  yPosition = drawHeader(true);
  yPosition = drawTableHeader(yPosition);
  
  // Draw all rows
  for (let i = 0; i < items.length; i++) {
    // Check if we need a new page
    if (rowsOnCurrentPage >= maxRowsPerPage) {
      // Add new page
      doc.addPage({ layout: 'landscape' });
      currentPage++;
      rowsOnCurrentPage = 0;
      yPosition = drawHeader(false);
      yPosition = drawTableHeader(yPosition);
    }
    
    yPosition = drawRow(yPosition, items[i], i);
    rowsOnCurrentPage++;
  }
  
  // Fill empty rows on last page if needed (minimum 10 rows per page for professional look)
  const minRowsPerPage = Math.min(10, maxRowsPerPage);
  while (rowsOnCurrentPage < minRowsPerPage) {
    yPosition = drawRow(yPosition, null, -1);
    rowsOnCurrentPage++;
  }
  
  // Draw footer on last page
  drawFooter(yPosition, true);

  // Finalize PDF
  doc.end();
});
