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

exports.generatePDF = asyncHandler(async (req, res) => {
  const { materialId } = req.params;
  const { startDate, endDate, storageLocationId } = req.query;
  const companyId = req.user?.companyId || req.query.companyId;
  const plantId = req.user?.plantId || req.query.plantId;

  if (!companyId || !plantId || !materialId) {
    return sendError(res, 'Company ID, Plant ID, and Material ID are required', 400);
  }

  // Fetch material details
  const material = await db.Material.findByPk(materialId, {
    include: [
      { model: db.UOM, as: 'baseUOM', attributes: ['id', 'uom_code', 'uom_name'] },
      { model: db.MaterialType, as: 'materialType', attributes: ['id', 'type_code', 'type_name'] }
    ]
  });

  if (!material) {
    return sendError(res, 'Material not found', 404);
  }

  // Fetch stock transactions from InventoryStockLedger
  const where = {
    company_id: companyId,
    plant_id: plantId,
    material_id: materialId
  };

  if (storageLocationId) {
    where.storage_location = storageLocationId;
  }

  if (startDate && endDate) {
    where.transaction_date = { [db.Sequelize.Op.between]: [startDate, endDate] };
  } else if (startDate) {
    where.transaction_date = { [db.Sequelize.Op.gte]: startDate };
  } else if (endDate) {
    where.transaction_date = { [db.Sequelize.Op.lte]: endDate };
  }

  const transactions = await db.InventoryStockLedger.findAll({
    where,
    order: [['transaction_date', 'ASC'], ['id', 'ASC']]
  });

  // Fetch company, document, and print header info
  const company = await db.Company.findByPk(companyId);
  const document = await db.Document.findOne({
    where: { company_id: companyId, erp_module: 'STOCK_REGISTER', status: 'ACTIVE' },
    order: [['id', 'DESC']]
  });
  const printHeader = await db.PrintHeader.findOne({
    where: { company_id: companyId, status: 'ACTIVE' },
    order: [['id', 'DESC']]
  });

  // Create PDF
  const doc = new PDFDocument({ margin: 20, size: 'A4', layout: 'landscape', bufferPages: true });
  const filename = `Stock_Register_${material.material_number}_${Date.now()}.pdf`;

  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  doc.pipe(res);

  const pageWidth = 841.89; // A4 landscape width
  const pageHeight = 595.28; // A4 landscape height
  const margin = 20;
  const contentWidth = pageWidth - (margin * 2);

  // Resolve logo path
  let logoPath = null;
  if (printHeader && printHeader.logo_path) {
    // Try multiple possible paths for the logo
    const possiblePaths = [
      path.join(__dirname, '..', 'uploads', printHeader.logo_path),
      path.join(__dirname, '..', printHeader.logo_path),
      path.join(__dirname, '..', 'uploads', 'print-headers', path.basename(printHeader.logo_path))
    ];

    for (const testPath of possiblePaths) {
      if (fs.existsSync(testPath)) {
        logoPath = testPath;
        console.log('Logo found at:', testPath);
        break;
      }
    }
  }

  const formatDate = (dateString) => {
    if (!dateString) return '';
    const d = new Date(dateString);
    const day = String(d.getDate()).padStart(2, '0');
    const month = String(d.getMonth() + 1).padStart(2, '0');
    const year = d.getFullYear();
    return `${day}.${month}.${year}`;
  };

  const formatNumber = (value) => {
    if (!value) return '0.000';
    return parseFloat(value).toFixed(3);
  };

  let currentPage = 1;

  // Draw header function
  function drawHeader(y, isFirstPage = false) {
    doc.save();

    const headerHeight = isFirstPage ? 115 : 70;
    const headerStartY = y;

    // Draw outer border
    doc.rect(margin, y, contentWidth, headerHeight).stroke('#000000');

    // Logo and company name section (left - only in top portion)
    const logoSectionWidth = contentWidth * 0.3;
    const logoX = margin + 15;
    const logoY = y + 15;
    const logoSectionMaxWidth = 220; // Constrain logo section width

    if (logoPath && isFirstPage) {
      try {
        const img = doc.openImage(logoPath);
        const maxLogoWidth = 50;
        const maxLogoHeight = 45;

        let finalWidth = maxLogoWidth;
        let finalHeight = maxLogoHeight;
        
        const aspectRatio = img.width / img.height;
        if (aspectRatio > 1) {
          finalHeight = maxLogoWidth / aspectRatio;
        } else {
          finalWidth = maxLogoHeight * aspectRatio;
        }

        doc.image(logoPath, logoX, logoY, {
          width: finalWidth,
          height: finalHeight
        });

        // Company name next to logo - with width constraint
        const textX = logoX + finalWidth + 12;
        const textMaxWidth = logoSectionMaxWidth - finalWidth - 27;
        doc.fontSize(16).font('Helvetica-Bold').fillColor('#000000');
        doc.text('RAM', textX, logoY + 8, { 
          width: textMaxWidth, 
          lineBreak: false, 
          continued: false 
        });
        doc.fontSize(13).font('Helvetica-Bold');
        doc.text('INDUSTRIES', textX, logoY + 26, { 
          width: textMaxWidth, 
          lineBreak: false, 
          continued: false 
        });
      } catch (error) {
        console.error('Error loading logo:', error.message);
        // Fallback to text with width constraint
        doc.fontSize(18).font('Helvetica-Bold').fillColor('#000000');
        doc.text('RAM', logoX, logoY + 8, { 
          width: logoSectionMaxWidth, 
          lineBreak: false, 
          continued: false 
        });
        doc.fontSize(14).font('Helvetica-Bold');
        doc.text('INDUSTRIES', logoX, logoY + 28, { 
          width: logoSectionMaxWidth, 
          lineBreak: false, 
          continued: false 
        });
      }
    } else if (isFirstPage) {
      // Text fallback if no logo - with width constraint
      doc.fontSize(18).font('Helvetica-Bold').fillColor('#000000');
      doc.text('RAM', logoX, logoY + 8, { 
        width: logoSectionMaxWidth, 
        lineBreak: false, 
        continued: false 
      });
      doc.fontSize(14).font('Helvetica-Bold');
      doc.text('INDUSTRIES', logoX, logoY + 28, { 
        width: logoSectionMaxWidth, 
        lineBreak: false, 
        continued: false 
      });
    }

    // Title section (center - 40% width)
    const titleSectionX = margin + 240; // Start after logo section
    const titleSectionWidth = contentWidth - 240 - 160; // Space between logo and doc box
    doc.fontSize(16).font('Helvetica-Bold').fillColor('#000000');
    doc.text('STOCK REGISTER', titleSectionX, y + 22, { 
      width: titleSectionWidth, 
      align: 'center', 
      lineBreak: false, 
      continued: false 
    });

    // Document number box (right - 30% width)
    const docBoxWidth = 140;
    const docBoxHeight = 50;
    const docBoxX = pageWidth - margin - docBoxWidth - 10;
    const docBoxY = y + 10;
    
    doc.rect(docBoxX, docBoxY, docBoxWidth, docBoxHeight).stroke('#000000');
    
    doc.fontSize(9).font('Helvetica-Bold').fillColor('#000000');
    doc.text('Doc No: RI/PUR/F/04', docBoxX + 5, docBoxY + 8, { 
      width: docBoxWidth - 10, 
      align: 'left', 
      lineBreak: false, 
      continued: false 
    });
    
    doc.fontSize(9).font('Helvetica');
    doc.text(`Page: ${currentPage}`, docBoxX + 5, docBoxY + 28, { 
      width: docBoxWidth - 10, 
      align: 'left', 
      lineBreak: false, 
      continued: false 
    });

    // Material details section (only on first page)
    if (isFirstPage) {
      // Add horizontal divider line
      const dividerY = y + 65;
      doc.moveTo(margin, dividerY).lineTo(margin + contentWidth, dividerY).stroke('#000000');

      const detailsY = y + 72;
      const leftColumnX = margin + 10;
      const leftColumnWidth = contentWidth / 2 - 20;
      const rightColumnX = margin + contentWidth / 2 + 10;
      const rightColumnWidth = contentWidth / 2 - 30;
      
      // First row - Name of Articles and Cost Rate
      doc.fontSize(10).font('Helvetica').fillColor('#000000');
      
      // Left: Name of Articles
      const articleText = `Name of Articles : ${material.description || material.material_number}`;
      doc.text(articleText, leftColumnX, detailsY, { 
        width: leftColumnWidth, 
        lineBreak: false, 
        continued: false,
        ellipsis: true
      });
      
      // Right: Cost Rate
      const costRate = material.standard_price || 0;
      doc.text(`Cost Rate : ${formatNumber(costRate)}`, rightColumnX, detailsY, { 
        width: rightColumnWidth, 
        align: 'right', 
        lineBreak: false, 
        continued: false 
      });

      // Second row - Material Number and UOM
      const detailsY2 = detailsY + 18;
      
      // Left: Material Number
      doc.text(`Material Number : ${material.material_number}`, leftColumnX, detailsY2, { 
        width: leftColumnWidth, 
        lineBreak: false, 
        continued: false,
        ellipsis: true
      });

      // Right: UOM
      doc.text(`UOM : ${material.baseUOM?.uom_code || ''}`, rightColumnX, detailsY2, { 
        width: rightColumnWidth, 
        align: 'right', 
        lineBreak: false, 
        continued: false 
      });
    }

    doc.restore();
    return headerStartY + headerHeight + 2;
  }

  // Draw table header
  function drawTableHeader(y) {
    doc.save();

    const headerHeight = 38;
    doc.rect(margin, y, contentWidth, headerHeight).fillAndStroke('#e0e0e0', '#000000');

    // Define column widths
    const cols = [
      { label: 'Date', x: margin + 3, width: 60, align: 'center' },
      { label: 'PARTICULARS', x: margin + 63, width: 200, align: 'left' },
      { label: 'Voucher\nNo', x: margin + 263, width: 60, align: 'center' },
      { label: 'RECEIPT\nQuantity', x: margin + 323, width: 70, align: 'center' },
      { label: 'ISSUED\nQuantity', x: margin + 393, width: 70, align: 'center' },
      { label: 'BALANCE\nQuantity', x: margin + 463, width: 70, align: 'center' }
    ];

    doc.fillColor('#000000').fontSize(9).font('Helvetica-Bold');
    cols.forEach((col, i) => {
      if (i > 0) {
        doc.moveTo(col.x, y).lineTo(col.x, y + headerHeight).stroke();
      }
      const lines = col.label.split('\n');
      const lineH = 12;
      const startY = y + (headerHeight - (lines.length * lineH)) / 2 + 2;
      lines.forEach((line, idx) => {
        doc.text(line, col.x + 2, startY + (idx * lineH), { width: col.width - 4, align: col.align, lineBreak: false, continued: false, height: lineH });
      });
    });

    doc.restore();
    return y + headerHeight;
  }

  // Draw transaction row
  function drawRow(y, transaction, runningBalance, isOpeningRow = false) {
    doc.save();

    const rowHeight = 22;
    doc.rect(margin, y, contentWidth, rowHeight).stroke('#000000');

    const quantityIn = parseFloat(transaction.quantity_in || 0);
    const quantityOut = parseFloat(transaction.quantity_out || 0);

    const cols = [
      { x: margin + 3, width: 60, value: isOpeningRow ? 'Opening' : formatDate(transaction.transaction_date), align: 'center' },
      { x: margin + 63, width: 200, value: isOpeningRow ? 'Opening Stock' : `${transaction.reference_type || ''} - ${transaction.reference_number || transaction.transaction_type}`.substring(0, 50), align: 'left' },
      { x: margin + 263, width: 60, value: isOpeningRow ? '' : (transaction.reference_number || ''), align: 'center' },
      { x: margin + 323, width: 70, value: quantityIn > 0 ? formatNumber(quantityIn) : '', align: 'right' },
      { x: margin + 393, width: 70, value: quantityOut > 0 ? formatNumber(quantityOut) : '', align: 'right' },
      { x: margin + 463, width: 70, value: formatNumber(runningBalance), align: 'right' }
    ];

    cols.forEach((col, i) => {
      if (i > 0) {
        doc.moveTo(col.x, y).lineTo(col.x, y + rowHeight).stroke();
      }
    });

    const fontSize = isOpeningRow ? 9 : 8.5;
    const font = isOpeningRow ? 'Helvetica-Bold' : 'Helvetica';
    doc.fontSize(fontSize).font(font).fillColor('#000000');
    cols.forEach(col => {
      doc.text(col.value, col.x + 2, y + 6, { width: col.width - 4, align: col.align, ellipsis: true, lineBreak: false, continued: false, height: rowHeight - 12 });
    });

    doc.restore();
    return y + rowHeight;
  }

  // Generate PDF
  let y = margin;

  // First page header with material info
  y = drawHeader(y, true);
  y = drawTableHeader(y);

  // Calculate opening balance
  let runningBalance = material.opening_stock || 0;

  // Opening stock row
  y += 2;
  if (y + 22 > pageHeight - margin - 20) {
    doc.addPage();
    currentPage++;
    y = margin;
    y = drawHeader(y, false);
    y = drawTableHeader(y);
  }

  // Create a dummy transaction object for opening stock
  const openingTransaction = {
    transaction_date: startDate || new Date(),
    reference_type: '',
    reference_number: '',
    quantity_in: 0,
    quantity_out: 0
  };
  y = drawRow(y, openingTransaction, runningBalance, true);

  // Transaction rows
  transactions.forEach((transaction) => {
    if (y + 22 > pageHeight - margin - 20) {
      doc.addPage();
      currentPage++;
      y = margin;
      y = drawHeader(y, false);
      y = drawTableHeader(y);
    }

    const quantityIn = parseFloat(transaction.quantity_in || 0);
    const quantityOut = parseFloat(transaction.quantity_out || 0);
    runningBalance += quantityIn - quantityOut;

    y = drawRow(y, transaction, runningBalance, false);
  });

  doc.end();
});
