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

const toNum = (value) => {
  const parsed = parseFloat(value);
  return Number.isFinite(parsed) ? parsed : 0;
};

const fmtDate = (value) => {
  if (!value) return '';
  const d = new Date(value);
  if (Number.isNaN(d.getTime())) return '';
  const dd = String(d.getDate()).padStart(2, '0');
  const mm = String(d.getMonth() + 1).padStart(2, '0');
  return `${dd}/${mm}/${d.getFullYear()}`;
};

const resolveFile = (relativePath) => {
  if (!relativePath) return null;
  const uploadPath = path.join(__dirname, '..', 'uploads', relativePath);
  if (fs.existsSync(uploadPath)) return uploadPath;
  const directPath = path.join(__dirname, '..', relativePath);
  if (fs.existsSync(directPath)) return directPath;
  return null;
};

exports.generatePDF = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const dc = await db.DeliveryChallan.findByPk(id, {
    include: [
      { model: db.Company, as: 'company', attributes: ['id', 'name', 'email', 'phone'] },
      { model: db.Plant, as: 'plant', attributes: ['id', 'name', 'email', 'phone'] },
      { model: db.BusinessPartner, as: 'customer', attributes: ['id', 'bp_number', 'name'] },
      { model: db.FGDispatch, as: 'dispatch', attributes: ['id', 'dispatch_no', 'dispatch_date'] },
      { model: db.SalesInvoice, as: 'invoice', attributes: ['id', 'invoice_number', 'invoice_date'] },
      {
        model: db.DeliveryChallanItem,
        as: 'items',
        include: [
          { model: db.Material, as: 'material', attributes: ['material_number', 'description'] },
          { model: db.UOM, as: 'uom', attributes: ['uom_code'] }
        ]
      }
    ],
    order: [[{ model: db.DeliveryChallanItem, as: 'items' }, 'item_number', 'ASC']]
  });

  if (!dc) return sendError(res, 'Delivery challan not found', 404);

  const printHeader = await db.PrintHeader.findOne({
    where: { company_id: dc.company_id, status: 'ACTIVE' },
    order: [['id', 'DESC']]
  });
  const logoPath = resolveFile(printHeader?.logo_path);
  const certPath = resolveFile(printHeader?.quality_certification_logo_path);

  const doc = new PDFDocument({ margin: 30, size: 'A4' });
  const safeNo = String(dc.challan_no || dc.id).replace(/[^\w.-]+/g, '_');
  const safeCustomer = String(dc.customer?.name || 'Customer').replace(/[^\w.-]+/g, '_');
  const filename = `Delivery_Challan_${safeNo}_${safeCustomer}.pdf`;
  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  doc.pipe(res);

  const pageWidth = 595.28;
  const margin = 30;
  const contentWidth = pageWidth - margin * 2;
  const drawBorder = (x, y, w, h) => doc.rect(x, y, w, h).stroke('#000000');
  const deliveryStatus = String(dc.delivery_status || dc.status || 'IN_TRANSIT').toUpperCase();
  const drawKV = (label, value, x, y, labelW = 78, fontSize = 8, valueW = 220, boldValue = false) => {
    doc.font('Helvetica-Bold').fontSize(fontSize).text(label, x, y, { width: labelW, lineBreak: false });
    doc.font('Helvetica-Bold').fontSize(fontSize).text(':', x + labelW, y, { width: 8, lineBreak: false });
    doc.font(boldValue ? 'Helvetica-Bold' : 'Helvetica').fontSize(fontSize).text(String(value || ''), x + labelW + 8, y, { width: valueW });
  };

  let y = margin;

  // Header block (aligned with Purchase Order style)
  const headerH = 92;
  drawBorder(margin, y, contentWidth, headerH);
  const sidePadding = 4;
  const logoBoxW = Math.min(170, contentWidth * 0.30);
  const logoBoxH = headerH - 2;
  const certBoxW = Math.min(135, contentWidth * 0.24);
  const certBoxH = logoBoxH;
  const logoX = margin + sidePadding;
  const logoY = y + 1;
  const certX = margin + contentWidth - certBoxW - sidePadding;
  const certY = y + 1;

  if (logoPath) {
    try {
      doc.image(logoPath, logoX, logoY, {
        cover: [logoBoxW, logoBoxH],
        align: 'center',
        valign: 'center'
      });
    } catch (_) {
      // Ignore image draw failures; PDF should still be generated.
    }
  }
  if (certPath) {
    try {
      doc.image(certPath, certX, certY, { fit: [certBoxW, certBoxH], align: 'center', valign: 'center' });
    } catch (_) {
      // Ignore image draw failures; PDF should still be generated.
    }
  }

  const centerX = margin + logoBoxW + (sidePadding * 2);
  const centerW = contentWidth - logoBoxW - certBoxW - (sidePadding * 4);
  doc.font('Helvetica-Bold').fontSize(14).text(printHeader?.company_name || dc.company?.name || 'Company Name', centerX, y + 6, { width: centerW, align: 'center' });
  if (printHeader?.address) {
    doc.font('Helvetica').fontSize(7).text(printHeader.address, centerX, y + 24, { width: centerW, align: 'center', lineGap: 1 });
  }
  const headerEmail = printHeader?.email || dc.company?.email || dc.plant?.email || '';
  const headerPhone = printHeader?.phone || dc.company?.phone || dc.plant?.phone || '';
  if (headerEmail) doc.font('Helvetica').fontSize(7).text(`Email: ${headerEmail}`, centerX, y + 56, { width: centerW, align: 'center' });
  if (headerPhone) doc.font('Helvetica').fontSize(7).text(`Contact: ${headerPhone}`, centerX, y + 65, { width: centerW, align: 'center' });
  if (printHeader?.gstin) doc.font('Helvetica').fontSize(7).text(`GSTIN: ${printHeader.gstin}`, centerX, y + 74, { width: centerW, align: 'center' });
  // Re-stroke header border so top line is never hidden behind images.
  drawBorder(margin, y, contentWidth, headerH);
  y += headerH;

  // Title row
  drawBorder(margin, y, contentWidth, 20);
  doc.font('Helvetica-Bold').fontSize(12).text('DELIVERY CHALLAN', margin, y + 6, { width: contentWidth, align: 'center' });
  y += 20;

  const leftW = contentWidth * 0.55;
  const rightW = contentWidth - leftW;
  drawBorder(margin, y, leftW, 95);
  drawBorder(margin + leftW, y, rightW, 95);

  let ly = y + 6;
  const leftLabelW = 86;
  const leftValueW = leftW - leftLabelW - 18;
  drawKV('Customer', dc.customer?.name || '', margin + 5, ly, leftLabelW, 8, leftValueW, false);
  ly += 12;
  drawKV('Customer PO', dc.customer_po_no || '', margin + 5, ly, leftLabelW, 8, leftValueW, false);
  ly += 12;
  doc.font('Helvetica-Bold').fontSize(8).text('Delivery Address', margin + 5, ly, { width: leftLabelW, lineBreak: false });
  doc.font('Helvetica-Bold').fontSize(8).text(':', margin + 5 + leftLabelW, ly, { width: 8, lineBreak: false });
  doc.font('Helvetica').fontSize(8).text(String(dc.delivery_address || ''), margin + 5 + leftLabelW + 8, ly, { width: leftValueW });

  let ry = y + 6;
  const rightRows = [
    ['Challan No', dc.challan_no || ''],
    ['DC Date', fmtDate(dc.dc_date)],
    ['Dispatch No', dc.dispatch?.dispatch_no || ''],
    ['Dispatch Date', fmtDate(dc.dispatch_date || dc.dispatch?.dispatch_date)],
    ['Invoice No', dc.invoice?.invoice_number || ''],
    ['Status', deliveryStatus]
  ];
  rightRows.forEach(([k, v]) => {
    drawKV(k, v, margin + leftW + 5, ry, 72, 7, rightW - 85, false);
    ry += 11;
  });
  y += 95;

  const cols = [
    { label: 'No', w: 24 },
    { label: 'Item', w: 190 },
    { label: 'HSN', w: 60 },
    { label: 'UOM', w: 45 },
    { label: 'Order Qty', w: 70 },
    { label: 'Invoice Qty', w: 70 },
    { label: 'Delivered Qty', w: contentWidth - 459 }
  ];
  const tableHeaderH = 20;
  drawBorder(margin, y, contentWidth, tableHeaderH);
  let x = margin;
  cols.forEach((c, idx) => {
    if (idx > 0) doc.moveTo(x, y).lineTo(x, y + tableHeaderH).stroke();
    doc.font('Helvetica-Bold').fontSize(7).text(c.label, x + 2, y + 6, { width: c.w - 4, align: 'center' });
    x += c.w;
  });
  y += tableHeaderH;

  (dc.items || []).forEach((it, idx) => {
    const rowH = 18;
    drawBorder(margin, y, contentWidth, rowH);
    const vals = [
      String(idx + 1),
      `${it.item_code || it.material?.material_number || ''} ${it.item_name || it.material?.description || ''}`.trim(),
      it.hsn_code || '',
      it.uom?.uom_code || '',
      toNum(it.order_qty).toFixed(3),
      toNum(it.invoice_qty).toFixed(3),
      toNum(it.delivered_qty).toFixed(3)
    ];
    let rx = margin;
    cols.forEach((c, cIdx) => {
      if (cIdx > 0) doc.moveTo(rx, y).lineTo(rx, y + rowH).stroke();
      doc.font('Helvetica').fontSize(7).text(vals[cIdx], rx + 2, y + 5, { width: c.w - 4, align: cIdx === 1 ? 'left' : 'right' });
      rx += c.w;
    });
    y += rowH;
  });

  // Transport + Driver section (left/right aligned)
  const transportH = 66;
  const colW = contentWidth / 2;
  drawBorder(margin, y, contentWidth, transportH);
  doc.moveTo(margin + colW, y).lineTo(margin + colW, y + transportH).stroke();
  drawKV('Transport Name', dc.transport_name || '', margin + 5, y + 8, 76, 8, colW - 90, false);
  drawKV('Vehicle No', dc.vehicle_no || '', margin + 5, y + 24, 76, 8, colW - 90, false);
  drawKV('E-Way Bill No', dc.eway_bill_no || '', margin + 5, y + 40, 76, 8, colW - 90, false);
  drawKV('Driver Name', dc.driver_name || '', margin + colW + 5, y + 8, 70, 8, colW - 84, false);
  drawKV('Driver Phone', dc.driver_phone || '', margin + colW + 5, y + 24, 70, 8, colW - 84, false);
  y += transportH;

  const signH = 78;
  drawBorder(margin, y, contentWidth, signH);
  doc.moveTo(margin + colW, y).lineTo(margin + colW, y + signH).stroke();
  drawKV('Delivered By', dc.delivered_by_name || '', margin + 5, y + 8, 76, 8, colW - 90, false);
  drawKV('Received By', dc.received_by || '', margin + 5, y + 24, 76, 8, colW - 90, false);
  drawKV('Delivery Date/Time', `${fmtDate(dc.delivery_date)} ${dc.delivery_time || ''}`, margin + 5, y + 40, 76, 8, colW - 90, false);
  drawKV('Remarks', dc.remarks || '', margin + 5, y + 56, 76, 8, colW - 90, false);
  drawKV('Receiver Signature', dc.receiver_signature || '', margin + colW + 5, y + 8, 92, 8, colW - 106, false);

  doc.end();
});

