const PDFDocument = require('pdfkit');
const db = require('../models');
const fs = require('fs');
const path = require('path');
const { Op } = require('sequelize');

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 getCtx = (req) => ({
  companyId: req.user?.companyId || req.user?.company_id || req.query?.companyId || req.query?.company_id,
  plantId: req.user?.plantId || req.user?.plant_id || req.query?.plantId || req.query?.plant_id
});

const DIM_KEYS = ['LENGTH', 'WIDTH', 'HEIGHT', 'THICK', 'QTY'];
const normalizeReportType = (value) => {
  const key = String(value || '').trim().toUpperCase();
  return key === 'PRESS_BRAKE' ? 'PRESS_BRAKE' : 'LASER_TURRET';
};
const isPressBrakeRequest = (req) =>
  String(req?.baseUrl || '').includes('/qa/dimensional-report-press-brake');
const getReportModels = (req) => (
  isPressBrakeRequest(req)
    ? { headerModel: db.DimensionalPressBrakeReport, detailModel: db.DimensionalPressBrakeReportDetail, reportType: 'PRESS_BRAKE' }
    : { headerModel: db.DimensionalReport, detailModel: db.DimensionalReportDetail, reportType: 'LASER_TURRET' }
);

const parseDescriptionParts = (description = '') => {
  const text = String(description || '').trim();
  if (!text) return { item_code: '', item_name: '', dimension: '' };
  const dimNumberMatch = text.match(/^(.*)\s-\s(DIM-\d+)$/i);
  if (dimNumberMatch) {
    const head = (dimNumberMatch[1] || '').trim();
    const codeNameMatch = head.match(/^(.*?)\s-\s(.*)$/);
    if (codeNameMatch) {
      return {
        item_code: (codeNameMatch[1] || '').trim(),
        item_name: (codeNameMatch[2] || '').trim(),
        dimension: (dimNumberMatch[2] || '').toUpperCase()
      };
    }
    return { item_code: '', item_name: head, dimension: (dimNumberMatch[2] || '').toUpperCase() };
  }
  const parts = text.split(' - ').map((p) => p.trim()).filter(Boolean);
  if (parts.length >= 3) {
    const last = (parts[parts.length - 1] || '').toUpperCase();
    if (DIM_KEYS.includes(last)) {
      return {
        item_code: parts[0] || '',
        item_name: parts.slice(1, -1).join(' - ') || '',
        dimension: last
      };
    }
  }
  const upper = text.toUpperCase();
  const hit = DIM_KEYS.find((k) => upper.endsWith(` - ${k}`) || upper === k);
  if (hit) {
    const base = text.replace(new RegExp(`\\s*-\\s*${hit}$`, 'i'), '').trim();
    return { item_code: '', item_name: base, dimension: hit };
  }
  return { item_code: '', item_name: text, dimension: '' };
};

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 = async (req, res) => {
  try {
    const { id } = req.params;
    const { companyId, plantId } = getCtx(req);

    // Fetch the report with all details
    const { headerModel, detailModel, reportType: routeReportType } = getReportModels(req);
    const report = await headerModel.findOne({
      where: {
        id,
        ...(companyId ? { company_id: companyId } : {}),
        ...(plantId ? { plant_id: plantId } : {})
      },
      include: [
        {
          model: db.Company,
          as: 'company',
          attributes: ['name', 'address_line1', 'address_line2', 'pincode']
        },
        {
          model: db.BusinessPartner,
          as: 'customer',
          attributes: ['id', 'name', 'bp_number']
        },
        {
          model: db.Machine,
          as: 'machine',
          attributes: ['machine_code', 'machine_description']
        },
        {
          model: detailModel,
          as: 'details',
          separate: true,
          order: [['line_no', 'ASC']]
        }
      ]
    });

    if (!report) {
      return res.status(404).json({
        success: false,
        message: 'Dimensional report not found'
      });
    }

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

    // Date in PDF should be Work Order Date (fallback to report date)
    let workOrderDateText = fmtDate(report.report_date);
    if (report.work_order_id) {
      const workOrder = await db.WorkOrder.findOne({
        where: {
          id: report.work_order_id,
          company_id: report.company_id
        },
        attributes: ['planned_start_date', 'created_at', 'createdAt']
      });
      if (workOrder) {
        const woDate =
          workOrder.planned_start_date ||
          workOrder.created_at ||
          workOrder.createdAt;
        if (woDate) {
          workOrderDateText = fmtDate(woDate);
        }
      }
    }

    const reportType = isPressBrakeRequest(req)
      ? routeReportType
      : normalizeReportType(report.report_type);

    // Document No from Organization -> Document Master
    let documentNumber = 'RI/QA/F/02';
    const exactTitleDoc = await db.Document.findOne({
      where: {
        company_id: report.company_id,
        status: 'ACTIVE',
        title: {
          [Op.like]: reportType === 'PRESS_BRAKE'
            ? 'DIMENSIONAL REPORT (PRESS BRAKE)%'
            : 'DIMENSIONAL REPORT%'
        }
      },
      order: [['id', 'DESC']]
    });

    const moduleDoc = !exactTitleDoc ? await db.Document.findOne({
      where: {
        company_id: report.company_id,
        status: 'ACTIVE',
        erp_module: reportType === 'PRESS_BRAKE'
          ? 'DIMENSIONAL_REPORT_PRESS_BRAKE'
          : 'DIMENSIONAL_REPORT'
      },
      order: [['id', 'DESC']]
    }) : null;

    if (exactTitleDoc?.document_number) {
      documentNumber = exactTitleDoc.document_number;
    } else if (moduleDoc?.document_number) {
      documentNumber = moduleDoc.document_number;
    }

    // Create PDF document
    const doc = new PDFDocument({
      size: 'A4',
      margins: { top: 30, bottom: 30, left: 30, right: 30 }
    });

    // Set response headers
    res.setHeader('Content-Type', 'application/pdf');
    const filePrefix = reportType === 'PRESS_BRAKE' ? 'dimensional-report-press-brake' : 'dimensional-report';
    res.setHeader('Content-Disposition', `attachment; filename=${filePrefix}-${report.report_no}.pdf`);

    // Pipe PDF to response
    doc.pipe(res);
    doc.lineWidth(0.8).lineJoin('miter').lineCap('square');

    const margin = 18;
    const contentWidth = doc.page.width - margin * 2;
    const pageBottom = doc.page.height - margin;
    const rowH = 15;
    const headerH = 22;

    const drawCell = (x, y, w, h, txt, opts = {}) => {
      doc.rect(x, y, w, h).stroke();
      const font = opts.bold ? 'Helvetica-Bold' : 'Helvetica';
      doc.font(font).fontSize(opts.fontSize || 7);
      doc.text(String(txt || ''), x + 2, y + (opts.top || 4), {
        width: w - 4,
        align: opts.align || 'center',
        lineBreak: false,
        ellipsis: true
      });
    };

    const cols = [
      { key: 'sno', label: 'S.No', w: 20 },
      { key: 'item_code', label: 'Item Code', w: 72 },
      { key: 'item_name', label: 'Item Name', w: 96 },
      { key: 'dimension_type', label: '', w: 38 },
      { key: 'drg_dim', label: 'Dimension', w: 48 },
      { key: 'tol', label: 'TOL', w: 30 },
      { key: 'reading_1', label: '1 (Sheet)', w: 38 },
      { key: 'reading_2', label: '2 (Operator)', w: 38 },
      { key: 'reading_3', label: '3 (For QC)', w: 38 },
      { key: 'reading_4', label: '4', w: 26 },
      { key: 'reading_5', label: '5', w: 26 },
      { key: 'no_of_rew', label: 'No of REW', w: 30 },
      { key: 'no_of_rej', label: 'No of REJ', w: 30 },
      { key: 'laser_turret', label: 'Laser/Turret', w: 29 }
    ];
    const pressBrakeCols = [
      { key: 'sno', label: 'S.No', w: 20 },
      { key: 'item_code', label: 'Item Code', w: 68 },
      { key: 'item_name', label: 'Item Name', w: 86 },
      { key: 'section', label: 'Section', w: 42 },
      { key: 'type', label: 'Type', w: 34 },
      ...Array.from({ length: 10 }, (_, idx) => ({ key: `dim_${idx + 1}`, label: `Dim-${idx + 1}`, w: 28.5 }))
    ];
    const pressBrakeColsTotal = pressBrakeCols.reduce((sum, c) => sum + c.w, 0);
    const pbDiff = contentWidth - pressBrakeColsTotal;
    if (Math.abs(pbDiff) > 0.001) {
      pressBrakeCols[pressBrakeCols.length - 1].w += pbDiff;
    }

    const xAt = (index, activeCols = cols) => margin + activeCols.slice(0, index).reduce((a, c) => a + c.w, 0);

    const drawTopHeader = () => {
      let y = margin;
      const title = reportType === 'PRESS_BRAKE'
        ? 'DIMENSIONAL REPORT (PRESS BRAKE)'
        : 'DIMENSIONAL REPORT (LASER & TURRET)';
      drawCell(margin, y, contentWidth, 20, title, { bold: true, fontSize: 10, top: 5 });
      doc.font('Helvetica').fontSize(7).text(documentNumber, margin + contentWidth - 90, y + 3, {
        width: 86,
        align: 'right',
        lineBreak: false,
        ellipsis: true
      });
      y += 20;

      // Header info grid (similar to provided hard-copy format)
      const headerInfoH = 74;
      drawCell(margin, y, contentWidth, headerInfoH, '', { fontSize: 7 });
      const logoW = 74;
      const leftW = 212;
      const centerW = 120;
      const rightW = contentWidth - logoW - leftW - centerW;
      const leftStartX = margin + logoW;
      const centerStartX = leftStartX + leftW;
      const rightStartX = centerStartX + centerW;

      // Vertical separators (continuous)
      doc.moveTo(leftStartX, y).lineTo(leftStartX, y + headerInfoH).stroke();
      doc.moveTo(centerStartX, y).lineTo(centerStartX, y + headerInfoH).stroke();
      doc.moveTo(rightStartX, y).lineTo(rightStartX, y + headerInfoH).stroke();
      // Left section row separators
      doc.moveTo(leftStartX, y + 24).lineTo(centerStartX, y + 24).stroke();
      doc.moveTo(leftStartX, y + 49).lineTo(centerStartX, y + 49).stroke();

      // Logo in left block (replaces text area like sample sheet)
      if (logoPath) {
        try {
          doc.image(logoPath, margin + 1, y + 1, {
            fit: [logoW - 2, headerInfoH - 2],
            align: 'center',
            valign: 'center'
          });
        } catch (_) {
          // Ignore image errors and continue PDF rendering
        }
      }

      doc.font('Helvetica-Bold').fontSize(7);
      doc.text('WORK ORDER NO', leftStartX + 4, y + 8, { width: 82, align: 'left' });
      doc.text('PRODUCT NAME', leftStartX + 4, y + 32, { width: 82, align: 'left' });
      doc.text('PRODUCT CODE', leftStartX + 4, y + 56, { width: 82, align: 'left' });

      doc.font('Helvetica-Bold').fontSize(8);
      doc.text(report.order_no || '-', leftStartX + 88, y + 8, { width: leftW - 92, align: 'left', lineBreak: false, ellipsis: true });
      doc.text(report.part_name || '-', leftStartX + 88, y + 32, { width: leftW - 92, align: 'left', lineBreak: false, ellipsis: true });
      doc.text(report.item_code || '-', leftStartX + 88, y + 56, { width: leftW - 92, align: 'left', lineBreak: false, ellipsis: true });

      const centerRows = [
        ['Date', workOrderDateText],
        ['REV.No', report.revision_no || ''],
        ['WO.QTY', fmtQty(report.order_qty || report.quantity || '')]
      ];
      centerRows.forEach(([k, v], idx) => {
        const yy = y + 9 + idx * 23;
        doc.font('Helvetica-Bold').fontSize(6.5).text(k, centerStartX + 4, yy, { width: 38 });
        doc.font('Helvetica').fontSize(7).text(`: ${v || ''}`, centerStartX + 42, yy, { width: centerW - 46, lineBreak: false, ellipsis: true });
      });

      const machineCode = report.machine?.machine_code || '';
      const machineName = report.machine?.machine_description || report.machine_name || '';
      const rightRows = [
        ['Customer Name', report.customer?.name || report.customer_name || ''],
        ['Machine Name & Code', [machineName, machineCode].filter(Boolean).join(' / ')],
        ['Operator Name', report.operator_name || ''],
        ['Inspected Date', fmtDate(report.inspection_date || report.report_date)]
      ];
      const rightLabelW = 56;
      rightRows.forEach(([k, v], idx) => {
        const yy = y + 7 + idx * 16;
        const x = rightStartX + 3;
        doc.font('Helvetica-Bold').fontSize(6.2).text(k, x, yy, { width: rightLabelW, lineBreak: false, ellipsis: true });
        doc.font('Helvetica').fontSize(6.6).text(`: ${v || ''}`, x + rightLabelW, yy, { width: rightW - rightLabelW - 6, lineBreak: false, ellipsis: true });
      });

      return y + headerInfoH;
    };

    const drawTableHeader = (y, activeCols = cols) => {
      activeCols.forEach((c, idx) => drawCell(xAt(idx, activeCols), y, c.w, headerH, c.label, { bold: true, fontSize: 6.8, top: 7 }));
      return y + headerH;
    };

    const normalizedRows = (report.details || []).map((d) => {
      const parsed = parseDescriptionParts(d.description);
      const normalizedItemCode = String(parsed.item_code || report.item_code || '')
        .replace(/[\r\n\t ]+/g, '')
        .trim();
      return {
        item_code: normalizedItemCode,
        item_name: parsed.item_name || report.part_name || '',
        dimension_type: parsed.dimension || '',
        drg_dim: d.drg_dim || '',
        tol: d.tol || '',
        reading_1: d.reading_1 || '',
        reading_2: d.reading_2 || '',
        reading_3: d.reading_3 || '',
        reading_4: d.reading_4 || '',
        reading_5: d.reading_5 || '',
        no_of_rew: d.no_of_rew || '',
        no_of_rej: d.no_of_rej || '',
        laser_turret: d.laser_turret || ''
      };
    });

    const groups = [];
    let current = null;
    normalizedRows.forEach((r) => {
      const key = `${String(r.item_code || '').trim()}|${String(r.item_name || '').trim()}`;
      if (!current || current.key !== key) {
        current = { key, item_code: r.item_code, item_name: r.item_name, rows: [] };
        groups.push(current);
      }
      current.rows.push(r);
    });

    let y = drawTopHeader();
    if (reportType === 'PRESS_BRAKE') {
      y = drawTableHeader(y, pressBrakeCols);
      groups.forEach((group, groupIndex) => {
        const blockRows = 5; // Drawing: Dim/Tol, Actual: D-x/D-y/Pos
        const blockH = blockRows * rowH;
        if (y + blockH > pageBottom - 30) {
          doc.addPage();
          y = margin;
          y = drawTableHeader(y, pressBrakeCols);
        }

        const dimMap = new Map();
        group.rows.forEach((r) => {
          const m = String(r.dimension_type || '').match(/^DIM-(\d+)$/i);
          const dimNo = m ? parseInt(m[1], 10) : NaN;
          if (Number.isFinite(dimNo) && dimNo >= 1 && dimNo <= 10) {
            dimMap.set(dimNo, r);
          }
        });

        const dStart = groupIndex * 2 + 1;
        const stageRows = [
          { section: 'Drawing', type: 'Dim', field: 'drg_dim' },
          { section: 'Drawing', type: 'Tol', field: 'tol' },
          { section: 'Actual', type: `D-${dStart}`, field: 'reading_1' },
          { section: 'Actual', type: `D-${dStart + 1}`, field: 'reading_2' },
          { section: 'Actual', type: 'Pos', field: 'reading_3' }
        ];

        drawCell(xAt(0, pressBrakeCols), y, pressBrakeCols[0].w, blockH, String(groupIndex + 1), { fontSize: 7, top: 6 });
        drawCell(xAt(1, pressBrakeCols), y, pressBrakeCols[1].w, blockH, group.item_code || '-', { align: 'left', top: 4, fontSize: 6 });
        drawCell(xAt(2, pressBrakeCols), y, pressBrakeCols[2].w, blockH, group.item_name || '-', { align: 'left', top: 4 });

        stageRows.forEach((sr, srIdx) => {
          if (srIdx === 0) {
            drawCell(xAt(3, pressBrakeCols), y, pressBrakeCols[3].w, rowH * 2, 'Drawing', { bold: true });
          }
          if (srIdx === 2) {
            drawCell(xAt(3, pressBrakeCols), y, pressBrakeCols[3].w, rowH * 3, 'Actual', { bold: true });
          }
          drawCell(xAt(4, pressBrakeCols), y, pressBrakeCols[4].w, rowH, sr.type, { bold: true });

          for (let n = 1; n <= 10; n += 1) {
            const dimRow = dimMap.get(n);
            const txt = dimRow ? (dimRow[sr.field] || '') : '';
            const colIndex = 4 + n;
            drawCell(xAt(colIndex, pressBrakeCols), y, pressBrakeCols[colIndex].w, rowH, txt);
          }
          y += rowH;
        });
      });
    } else {
      y = drawTableHeader(y);
      groups.forEach((group, groupIndex) => {
        const blockH = Math.max(group.rows.length, 1) * rowH;
        if (y + blockH > pageBottom - 30) {
          doc.addPage();
          y = margin;
          y = drawTableHeader(y);
        }

        drawCell(xAt(0), y, cols[0].w, blockH, String(groupIndex + 1), { fontSize: 7, top: 6 });
        drawCell(xAt(1), y, cols[1].w, blockH, group.item_code || '-', { align: 'left', top: 4, fontSize: 6 });
        drawCell(xAt(2), y, cols[2].w, blockH, group.item_name || '-', { align: 'left', top: 4 });

        group.rows.forEach((r) => {
          drawCell(xAt(3), y, cols[3].w, rowH, r.dimension_type || '', { bold: true });
          drawCell(xAt(4), y, cols[4].w, rowH, r.drg_dim || '');
          drawCell(xAt(5), y, cols[5].w, rowH, r.tol || '');
          drawCell(xAt(6), y, cols[6].w, rowH, r.reading_1 || '');
          drawCell(xAt(7), y, cols[7].w, rowH, r.reading_2 || '');
          drawCell(xAt(8), y, cols[8].w, rowH, r.reading_3 || '');
          drawCell(xAt(9), y, cols[9].w, rowH, r.reading_4 || '');
          drawCell(xAt(10), y, cols[10].w, rowH, r.reading_5 || '');
          drawCell(xAt(11), y, cols[11].w, rowH, r.no_of_rew || '');
          drawCell(xAt(12), y, cols[12].w, rowH, r.no_of_rej || '');
          drawCell(xAt(13), y, cols[13].w, rowH, r.laser_turret || '');
          y += rowH;
        });
      });
    }

    if (y + 16 <= pageBottom) {
      doc.font('Helvetica').fontSize(8);
      doc.text(`Inspected By: ${report.inspected_by || ''}`, margin, y + 8, { width: contentWidth, align: 'right' });
    }

    // Finalize PDF
    doc.end();

  } catch (error) {
    console.error('Error generating dimensional report PDF:', error);
    if (!res.headersSent) {
      res.status(500).json({
        success: false,
        message: 'Error generating PDF',
        error: error.message
      });
    }
  }
};
