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.GeneralDC.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.Machine, as: 'machine', attributes: ['id', 'machine_code', 'machine_description', 'location'] },
      { model: db.BusinessPartner, as: 'vendor', attributes: ['id', 'bp_number', 'name', 'legal_name'] },
      {
        model: db.GeneralDCItem,
        as: 'items',
        include: [
          { model: db.Machine, as: 'machine', attributes: ['machine_code', 'machine_description'] },
          { model: db.StorageLocation, as: 'storageLocation', attributes: ['storage_location_code'] }
        ]
      }
    ],
    order: [[{ model: db.GeneralDCItem, as: 'items' }, 'line_number', 'ASC']]
  });

  if (!dc) return sendError(res, 'General DC 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.dc_number || dc.id).replace(/[^\w.-]+/g, '_');
  const safeVendor = String(dc.vendor?.name || dc.vendor?.legal_name || 'Vendor').replace(/[^\w.-]+/g, '_');
  const filename = `General_DC_${safeNo}_${safeVendor}.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 drawKV = (label, value, x, y, labelW = 92, fontSize = 8, valueW = 220) => {
    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('Helvetica').fontSize(fontSize).text(String(value || ''), x + labelW + 8, y, { width: valueW });
  };

  let y = margin;

  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 (_) {}
  }
  if (certPath) {
    try { doc.image(certPath, certX, certY, { fit: [certBoxW, certBoxH], align: 'center', valign: 'center' }); } catch (_) {}
  }

  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' });
  drawBorder(margin, y, contentWidth, headerH);
  y += headerH;

  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, 110);
  drawBorder(margin + leftW, y, rightW, 110);

  let ly = y + 6;
  const leftLabelW = 98;
  const leftValueW = leftW - leftLabelW - 18;
  drawKV('Vendor', dc.vendor?.name || dc.vendor?.legal_name || '', margin + 5, ly, leftLabelW, 8, leftValueW);
  ly += 12;
  drawKV('Vendor Code', dc.vendor?.bp_number || '', margin + 5, ly, leftLabelW, 8, leftValueW);
  ly += 12;
  const primaryMachine = (dc.items || []).find((it) => it.machine)?.machine || null;
  drawKV('Machine', primaryMachine ? `${primaryMachine.machine_code || ''}${primaryMachine.machine_description ? ` - ${primaryMachine.machine_description}` : ''}` : '', margin + 5, ly, leftLabelW, 8, leftValueW);
  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 = [
    ['DC Number', dc.dc_number || ''],
    ['DC Date', fmtDate(dc.dc_date)],
    ['Total Sent Qty', toNum(dc.total_sent_qty).toFixed(3)],
    ['Total Rec. Qty', toNum(dc.total_received_qty).toFixed(3)]
  ];
  rightRows.forEach(([k, v]) => {
    drawKV(k, v, margin + leftW + 5, ry, 70, 7, rightW - 83);
    ry += 11;
  });
  y += 110;

  const cols = [
    { label: 'No', w: 24 },
    { label: 'Machine', w: 100 },
    { label: 'Machine Work', w: 150 },
    { label: 'Warehouse', w: 70 },
    { label: 'Sent Qty', w: 52 },
    { label: 'Rate/Qty', w: 60 },
    { label: 'Amount', w: contentWidth - 456 }
  ];
  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(it.line_number || idx + 1),
      it.machine ? `${it.machine.machine_code || ''}${it.machine.machine_description ? ` - ${it.machine.machine_description}` : ''}` : '',
      it.machine_work || '',
      it.storageLocation?.storage_location_code || '',
      toNum(it.sent_quantity).toFixed(3),
      toNum(it.unit_price).toFixed(2),
      toNum(it.line_total).toFixed(2)
    ];
    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 >= 5 ? 'right' : 'left' });
      rx += c.w;
    });
    y += rowH;
  });

  const totalRowH = 18;
  drawBorder(margin, y, contentWidth, totalRowH);
  doc.font('Helvetica-Bold').fontSize(8).text('Total Amount', margin + contentWidth - 175, y + 5, { width: 95, align: 'right' });
  doc.font('Helvetica-Bold').fontSize(8).text(toNum(dc.total_amount).toFixed(2), margin + contentWidth - 78, y + 5, { width: 72, align: 'right' });
  y += totalRowH;

  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);
  drawKV('Vehicle No', dc.vehicle_no || '', margin + 5, y + 24, 76, 8, colW - 90);
  drawKV('E-Way Bill No', dc.eway_bill_no || '', margin + 5, y + 40, 76, 8, colW - 90);
  drawKV('Driver Name', dc.driver_name || '', margin + colW + 5, y + 8, 70, 8, colW - 84);
  drawKV('Driver Phone', dc.driver_phone || '', margin + colW + 5, y + 24, 70, 8, colW - 84);
  drawKV('Remarks', dc.remarks || '', margin + colW + 5, y + 40, 70, 8, colW - 84);
  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.driver_name || '', margin + 5, y + 8, 76, 8, colW - 90);
  drawKV('Received By', dc.vendor?.name || dc.vendor?.legal_name || '', margin + 5, y + 24, 76, 8, colW - 90);
  drawKV('Delivery Date/Time', `${fmtDate(dc.dc_date)} `, margin + 5, y + 40, 76, 8, colW - 90);
  drawKV('Remarks', dc.remarks || '', margin + 5, y + 56, 76, 8, colW - 90);
  drawKV('Receiver Signature', '', margin + colW + 5, y + 8, 92, 8, colW - 106);

  doc.end();
});
