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

const fmtDate = (v) => {
  if (!v) return '';
  const d = new Date(v);
  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 isChecked = (value) => {
  const v = String(value || '').trim().toUpperCase();
  return ['Y', 'YES', 'TRUE', '1', 'TICK', 'CHECK', 'CHECKED', 'X'].includes(v);
};

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

const truncateToWidth = (doc, value, maxWidth, font = 'Helvetica', fontSize = 7) => {
  const text = cleanText(value);
  if (!text) return '';
  doc.font(font).fontSize(fontSize);
  if (doc.widthOfString(text) <= maxWidth) return text;
  const suffix = '...';
  let out = text;
  while (out.length > 0 && doc.widthOfString(out + suffix) > maxWidth) {
    out = out.slice(0, -1);
  }
  return `${out}${suffix}`;
};

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

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

    const doc = new PDFDocument({ size: 'A4', margins: { top: 20, bottom: 20, left: 18, right: 18 } });
    const filename = `WVIR_${report.wvir_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 = 18;
    const pageW = doc.page.width - margin * 2;
    const pageBottom = doc.page.height - 18;
    const drawCell = (x, y, w, h, lw = 0.7) => doc.lineWidth(lw).rect(x, y, w, h).stroke();
    const drawText = (t, x, y, w, align = 'left', size = 7, bold = false, top = 4) => {
      doc
        .font(bold ? 'Helvetica-Bold' : 'Helvetica')
        .fontSize(size)
        .text(String(t ?? ''), x + 2, y + top, {
          width: w - 4,
          align,
          lineBreak: false,
          ellipsis: true
        });
    };
    const drawLabeledValue = (x, y, w, h, label, value) => {
      const labelW = Math.min(86, Math.floor(w * 0.42));
      drawText(label, x + 1, y, labelW - 2, 'left', 7, true);
      drawText(`: ${value || ''}`, x + labelW, y, w - labelW - 2, 'left', 7, false);
    };
    const drawSampleCheckbox = (x, y, w, h, checked) => {
      const box = Math.min(8, Math.max(6, Math.floor(Math.min(w, h) * 0.52)));
      const cx = x + (w - box) / 2;
      const cy = y + (h - box) / 2;
      doc.lineWidth(0.7).rect(cx, cy, box, box).stroke();
      if (checked) {
        doc
          .lineWidth(0.9)
          .moveTo(cx + 1.3, cy + box * 0.58)
          .lineTo(cx + box * 0.42, cy + box - 1.4)
          .lineTo(cx + box - 1.1, cy + 1.4)
          .stroke();
      }
    };

    let y = margin;
    drawCell(margin, y, pageW, 20);
    drawText('WELDING - VISUAL INSPECTION REPORT', margin, y, pageW, 'center', 10, true, 5);
    y += 20;

    const headerH = 64;
    drawCell(margin, y, pageW, headerH);
    const logoW = 72;
    const leftW = 292;
    const rightW = pageW - logoW - leftW;
    const logoX = margin;
    const leftX = logoX + logoW;
    const rightX = leftX + leftW;
    const hr = 16;

    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 (_) {
        // ignore logo failures and continue pdf
      }
    }

    drawLabeledValue(leftX + 2, y, leftW - 4, hr, 'WO NO', report.won);
    drawLabeledValue(leftX + 2, y + hr, leftW - 4, hr, 'WO QTY', fmtQty(report.work_order_qty));
    drawLabeledValue(leftX + 2, y + hr * 2, leftW - 4, hr, 'PRODUCT CODE', report.item_code);
    drawLabeledValue(leftX + 2, y + hr * 3, leftW - 4, hr, 'PRODUCT NAME', report.item_name);

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

    const cols = [
      { k: 'line_no', l: 'S.No', w: 24, align: 'center' },
      { k: 'sub_part_code', l: 'Sub Part Code', w: 82, align: 'left' },
      { k: 'sub_part_name', l: 'Sub Part Name', w: 124, align: 'left' },
      { k: 'qty', l: 'Qty', w: 28, align: 'center' },
      ...Array.from({ length: 10 }).map((_, i) => ({ k: `sample_${i + 1}`, l: String(i + 1), w: 20, align: 'center', sample: true })),
      { k: 'remark', l: 'Remark', w: 56, align: 'left' },
      { k: 'line_status', l: 'Status', w: 0, align: 'center' }
    ];

    const usedW = cols.slice(0, -1).reduce((s, c) => s + c.w, 0);
    cols[cols.length - 1].w = Math.max(40, pageW - usedW);

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

    const details = report.details || [];
    const rowH = 14;

    for (let i = 0; i < details.length; i += 1) {
      const r = details[i];
      x = margin;
      cols.forEach((c) => {
        drawCell(x, y, c.w, rowH, 0.5);
        const value = r ? r[c.k] : '';
        if (c.sample) {
          drawSampleCheckbox(x, y, c.w, rowH, isChecked(value));
        } else if (c.k === 'qty') {
          drawText(fmtQty(value), x, y, c.w, 'center', 7);
        } else {
          const safe = truncateToWidth(
            doc,
            value,
            Math.max(0, c.w - 6),
            'Helvetica',
            7
          );
          drawText(safe, x, y, c.w, c.align, 7);
        }
        x += c.w;
      });
      y += rowH;
      if (y > pageBottom - 22) break;
    }

    y += 8;
    if (y < pageBottom) {
      drawText(`Inspected By: ${cleanText(report.inspected_by || '')}`, margin, y, pageW, 'right', 8, true);
    }

    doc.end();
  } catch (error) {
    console.error('Error generating welding visual inspection PDF:', error);
    if (!res.headersSent) {
      return res.status(500).json({
        success: false,
        message: 'Error generating PDF',
        error: error.message
      });
    }
  }
});

