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');

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 fmtQty = (value) => {
  if (value === null || value === undefined || value === '') return '';
  const n = Number(value);
  if (!Number.isFinite(n)) return String(value);
  return String(n).replace(/\.0+$/, '').replace(/(\.\d*?)0+$/, '$1');
};

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;
};

const cleanText = (value) => String(value ?? '').replace(/[\r\n\t]+/g, ' ').replace(/\s+/g, ' ').trim();

const isTickMark = (value) => {
  const v = String(value ?? '').trim();
  if (!v) return false;
  const u = v.toUpperCase();
  return ['✓', '✔', 'Y', 'YES', 'TRUE', '1', 'TICK', 'CHECK', 'CHECKED', ',', '\'', '`'].includes(v) ||
    ['Y', 'YES', 'TRUE', '1', 'TICK', 'CHECK', 'CHECKED'].includes(u);
};

exports.generatePDF = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const report = await db.WeldingFinalInspectionReport.findByPk(id, {
    include: [
      { model: db.BusinessPartner, as: 'customer', attributes: ['id', 'name', 'legal_name'], required: false },
      { model: db.WeldingFinalInspectionReportDetail, as: 'details', separate: true, order: [['line_no', 'ASC']] }
    ]
  });
  if (!report) return sendError(res, 'Welding Final Inspection Report not found', 404);

  // Resolve product/date from Work Order (format only; no data changes)
  const workOrder = report.won ? await db.WorkOrder.findOne({
    where: {
      company_id: report.company_id,
      work_order_number: report.won
    },
    include: [{ model: db.Material, as: 'finishedMaterial', attributes: ['material_number', 'description'], required: false }],
    attributes: ['planned_start_date', 'created_at', 'createdAt']
  }) : null;
  const productCode = workOrder?.finishedMaterial?.material_number || report.model || '';
  const productName = workOrder?.finishedMaterial?.description || report.model || '';
  const workOrderDate = workOrder?.planned_start_date || workOrder?.created_at || workOrder?.createdAt || report.wfir_date;

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

  // Keep landscape for 20 frame columns, but use welding-visual styled layout
  const doc = new PDFDocument({ size: 'A4', layout: 'landscape', margins: { top: 16, bottom: 16, left: 16, right: 16 } });
  const filename = `WFIR_${report.wfir_no || report.id}.pdf`;
  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  doc.pipe(res);
  doc.lineWidth(0.7).lineJoin('miter').lineCap('square');

  const margin = 16;
  const pageW = doc.page.width - margin * 2;
  const pageH = doc.page.height - margin * 2;
  const pageBottom = margin + pageH;

  const drawCell = (x, y, w, h, lw = 0.7) => doc.lineWidth(lw).rect(x, y, w, h).stroke();
  const drawText = (text, x, y, w, align = 'left', size = 7, bold = false, top = 3) => {
    doc.font(bold ? 'Helvetica-Bold' : 'Helvetica').fontSize(size).text(String(text ?? ''), x + 2, y + top, {
      width: w - 4,
      align,
      lineBreak: false,
      ellipsis: true
    });
  };
  const drawLabeledValue = (x, y, w, h, label, value) => {
    const labelW = Math.min(108, Math.floor(w * 0.42));
    drawText(label, x, y, labelW, 'left', 7, true);
    drawText(`: ${value || ''}`, x + labelW, y, w - labelW, 'left', 7, false);
  };
  const drawTick = (x, y, w, h) => {
    const size = Math.max(5, Math.min(9, Math.floor(Math.min(w, h) * 0.45)));
    const sx = x + (w - size) / 2;
    const sy = y + (h - size) / 2;
    doc.save();
    doc.lineWidth(1);
    doc.moveTo(sx + 0.8, sy + size * 0.58).lineTo(sx + size * 0.42, sy + size - 0.9).lineTo(sx + size - 0.7, sy + 0.8).stroke();
    doc.restore();
  };

  let y = margin;

  drawCell(margin, y, pageW, 18);
  drawText('WELDING - FINAL INSPECTION REPORT', margin, y, pageW, 'center', 10, true, 4);
  y += 18;

  const headerH = 62;
  drawCell(margin, y, pageW, headerH);
  const logoW = 70;
  const leftW = 420;
  const rightW = pageW - logoW - leftW;
  const logoX = margin;
  const leftX = logoX + logoW;
  const rightX = leftX + leftW;
  const hr = 15.5;

  doc.moveTo(leftX, y).lineTo(leftX, y + headerH).stroke();
  doc.moveTo(rightX, y).lineTo(rightX, y + headerH).stroke();
  for (let i = 1; i < 4; i += 1) {
    doc.moveTo(leftX, y + i * hr).lineTo(rightX, y + i * hr).stroke();
  }

  if (logoPath) {
    try {
      doc.image(logoPath, logoX + 1, y + 1, { fit: [logoW - 2, headerH - 2], align: 'center', valign: 'center' });
    } catch (_) {}
  }

  drawLabeledValue(leftX + 2, y, leftW - 4, hr, 'WON', report.won);
  drawLabeledValue(leftX + 2, y + hr, leftW - 4, hr, 'WO QTY', fmtQty(report.total_qty));
  drawLabeledValue(leftX + 2, y + hr * 2, leftW - 4, hr, 'PRODUCT CODE', productCode);
  drawLabeledValue(leftX + 2, y + hr * 3, leftW - 4, hr, 'PRODUCT NAME', productName);

  drawLabeledValue(rightX + 2, y, rightW - 4, hr, 'DATE', fmtDate(workOrderDate));
  drawLabeledValue(rightX + 2, y + hr, rightW - 4, hr, 'NO.OF SAMPLES', fmtQty(report.sample_qty));
  drawLabeledValue(rightX + 2, y + hr * 2, rightW - 4, hr, 'CUSTOMER', report.customer_name || report.customer?.name || report.customer?.legal_name);
  drawLabeledValue(rightX + 2, y + hr * 3, rightW - 4, hr, 'FABRICATOR', report.fabricator_name || '');
  y += headerH;

  const metaH = 16;
  drawCell(margin, y, pageW, metaH);
  const metaDocW = 180;
  const metaRevW = pageW - metaDocW;
  doc.moveTo(margin + metaDocW, y).lineTo(margin + metaDocW, y + metaH).stroke();
  drawLabeledValue(margin + 2, y, metaDocW - 4, metaH, 'Doc No', report.doc_no || 'RI/QA/F/04');
  drawLabeledValue(margin + metaDocW + 2, y, metaRevW - 4, metaH, 'Rev No / Date', `${report.rev_no || '0'} / ${fmtDate(report.rev_date)}`);
  y += metaH;

  const cols = [
    { k: 'line_no', l: 'S.No', w: 30, align: 'center' },
    { k: 'description', l: 'Description', w: 250, align: 'left' },
    { k: 'qty', l: 'Q/S', w: 50, align: 'center' },
    ...Array.from({ length: 20 }).map((_, i) => ({ k: `frame_${i + 1}`, l: String(i + 1), w: 0, align: 'center', frame: true }))
  ];
  const fixedW = cols.slice(0, 3).reduce((s, c) => s + c.w, 0);
  const frameW = Math.floor((pageW - fixedW) / 20);
  cols.forEach((c) => { if (c.frame) c.w = frameW; });
  cols[cols.length - 1].w += pageW - cols.reduce((s, c) => s + c.w, 0);

  const headH = 14;
  let x = margin;
  cols.forEach((c) => { drawCell(x, y, c.w, headH); drawText(c.l, x, y, c.w, 'center', 7, true, 2.5); x += c.w; });
  y += headH;

  const rowH = 14;
  const maxRowsByPage = Math.floor((pageBottom - y - 36) / rowH);
  const details = report.details || [];
  const rowsToRender = Math.min(details.length, Math.max(0, maxRowsByPage));
  for (let i = 0; i < rowsToRender; i += 1) {
    const r = details[i];
    x = margin;
    cols.forEach((c) => {
      drawCell(x, y, c.w, rowH, 0.5);
      const value = r?.[c.k];
      if (c.frame && isTickMark(value)) {
        drawTick(x, y, c.w, rowH);
      } else if (c.k === 'qty') {
        drawText(fmtQty(value), x, y, c.w, 'center', 7);
      } else {
        drawText(cleanText(value), x, y, c.w, c.align, 7);
      }
      x += c.w;
    });
    y += rowH;
  }

  y += 8;
  if (y < pageBottom - 14) {
    drawText(`Remarks: ${cleanText(report.remarks || '')}`, margin, y, pageW * 0.7, 'left', 8, true);
    drawText(`QC Sign: ${cleanText(report.qc_sign || '')}`, margin + pageW * 0.7, y, pageW * 0.3, 'right', 8, true);
  }

  doc.end();
});

module.exports = exports;
