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 receipt = await db.SubcontractReceipt.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: 'vendor', attributes: ['id', 'bp_number', 'name', 'legal_name'] },
      {
        model: db.SubcontractDC,
        as: 'subcontractDC',
        attributes: ['id', 'dc_number', 'dc_date', 'operation_type', 'subcontract_po_ref', 'purpose', 'customer_po_id'],
        include: [
          { model: db.CustomerPO, as: 'customerPO', attributes: ['id', 'po_number'], required: false }
        ]
      },
      {
        model: db.SubcontractReceiptItem,
        as: 'items',
        include: [
          { model: db.Material, as: 'material', attributes: ['material_number', 'description'] },
          { model: db.UOM, as: 'uom', attributes: ['uom_code'] },
          { model: db.StorageLocation, as: 'storageLocation', attributes: ['storage_location_code'] },
          { model: db.SubcontractDCItem, as: 'subcontractDCItem', attributes: ['unit_price'] }
        ]
      }
    ],
    order: [[{ model: db.SubcontractReceiptItem, as: 'items' }, 'line_number', 'ASC']]
  });

  if (!receipt) return sendError(res, 'Subcontract Receipt not found', 404);

  const printHeader = await db.PrintHeader.findOne({
    where: { company_id: receipt.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(receipt.receipt_number || receipt.id).replace(/[^\w.-]+/g, '_');
  const safeVendor = String(receipt.vendor?.name || receipt.vendor?.legal_name || 'Vendor').replace(/[^\w.-]+/g, '_');
  const filename = `Subcontract_Receipt_${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 || receipt.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 || receipt.company?.email || receipt.plant?.email || '';
  const headerPhone = printHeader?.phone || receipt.company?.phone || receipt.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('SUBCONTRACT RECEIPT', 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 = 98;
  const leftValueW = leftW - leftLabelW - 18;
  drawKV('Subcontractor', receipt.vendor?.name || receipt.vendor?.legal_name || '', margin + 5, ly, leftLabelW, 8, leftValueW);
  ly += 12;
  drawKV('Vendor Code', receipt.vendor?.bp_number || '', margin + 5, ly, leftLabelW, 8, leftValueW);
  ly += 12;
  drawKV('Reference DC', receipt.subcontractDC?.dc_number || '', margin + 5, ly, leftLabelW, 8, leftValueW);
  ly += 12;
  drawKV('DC Date', fmtDate(receipt.subcontractDC?.dc_date), margin + 5, ly, leftLabelW, 8, leftValueW);
  ly += 12;
  drawKV('Operation', receipt.subcontractDC?.operation_type || '', margin + 5, ly, leftLabelW, 8, leftValueW);
  ly += 12;
  drawKV('Customer PO', receipt.subcontractDC?.customerPO?.po_number || receipt.subcontractDC?.subcontract_po_ref || '', margin + 5, ly, leftLabelW, 8, leftValueW);
  ly += 12;
  drawKV('Purpose', receipt.subcontractDC?.purpose || '', margin + 5, ly, leftLabelW, 8, leftValueW);

  const totalAmount = (receipt.items || []).reduce((sum, it) => {
    const unitPrice = toNum(it.unit_price || it.subcontractDCItem?.unit_price);
    return sum + (toNum(it.received_quantity) * unitPrice);
  }, 0);

  let ry = y + 6;
  const rightRows = [
    ['Receipt No', receipt.receipt_number || ''],
    ['Receipt Date', fmtDate(receipt.receipt_date)],
    ['Status', String(receipt.status || 'POSTED')],
    ['Total Rec. Qty', toNum(receipt.total_received_qty).toFixed(3)],
    ['Total Rej. Qty', toNum(receipt.total_rejection_qty).toFixed(3)]
  ];
  rightRows.forEach(([k, v]) => {
    drawKV(k, v, margin + leftW + 5, ry, 76, 7, rightW - 89);
    ry += 11;
  });
  y += 95;

  const cols = [
    { label: 'No', w: 24 },
    { label: 'Material', w: 110 },
    { label: 'Description', w: 85 },
    { label: 'UOM', w: 30 },
    { label: 'Warehouse', w: 52 },
    { label: 'Sent', w: 40 },
    { label: 'Received', w: 48 },
    { label: 'Rejected', w: 46 },
    { label: 'Rate/Qty', w: 46 },
    { label: 'Amount', w: contentWidth - 481 }
  ];
  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;

  (receipt.items || []).forEach((it, idx) => {
    const rowH = 18;
    const unitPrice = toNum(it.unit_price || it.subcontractDCItem?.unit_price);
    const amount = toNum(it.received_quantity) * unitPrice;
    drawBorder(margin, y, contentWidth, rowH);
    const vals = [
      String(it.line_number || idx + 1),
      it.material?.material_number || '',
      it.description || it.material?.description || '',
      it.uom?.uom_code || '',
      it.storageLocation?.storage_location_code || '',
      toNum(it.sent_quantity).toFixed(3),
      toNum(it.received_quantity).toFixed(3),
      toNum(it.rejection_quantity).toFixed(3),
      unitPrice.toFixed(2),
      amount.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(totalAmount.toFixed(2), margin + contentWidth - 78, y + 5, { width: 72, align: 'right' });
  y += totalRowH;

  const remarksH = 32;
  drawBorder(margin, y, contentWidth, remarksH);
  drawKV('Remarks', receipt.remarks || '', margin + 5, y + 10, 56, 8, contentWidth - 72);

  doc.end();
});
