const db = require('../models');
const { Op } = require('sequelize');
const NumberFormatService = require('../services/numberFormatService');

const getCtx = (req) => ({
  companyId: req.user?.companyId || req.user?.company_id || req.body?.company_id || req.query?.companyId || req.query?.company_id,
  plantId: req.user?.plantId || req.user?.plant_id || req.body?.plant_id || req.query?.plantId || req.query?.plant_id
});

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) => {
  if (isPressBrakeRequest(req)) {
    return {
      headerModel: db.DimensionalPressBrakeReport,
      detailModel: db.DimensionalPressBrakeReportDetail,
      reportType: 'PRESS_BRAKE',
      numberModule: 'DIMENSIONAL_REPORT_PRESS_BRAKE'
    };
  }
  return {
    headerModel: db.DimensionalReport,
    detailModel: db.DimensionalReportDetail,
    reportType: 'LASER_TURRET',
    numberModule: 'DIMENSIONAL_REPORT'
  };
};

const generateDimensionalReportNumber = async (companyId, fiscalYearId, transaction, req) => {
  const { headerModel, numberModule } = getReportModels(req);
  try {
    return await NumberFormatService.generateNextNumber(
      companyId,
      numberModule,
      fiscalYearId,
      transaction
    );
  } catch (err) {
    const year = new Date().getFullYear();
    const prefix = `DR${year}`;
    const last = await headerModel.findOne({
      where: {
        company_id: companyId,
        report_no: { [Op.like]: `${prefix}%` }
      },
      attributes: ['report_no'],
      order: [['report_no', 'DESC']],
      ...(transaction ? { transaction } : {})
    });
    const next = (parseInt(String(last?.report_no || '').slice(-4), 10) || 0) + 1;
    return `${prefix}${String(next).padStart(4, '0')}`;
  }
};

const parseNumberOrNull = (value) => {
  if (value === '' || value === null || value === undefined) return null;
  const n = Number(value);
  return Number.isFinite(n) ? n : null;
};

const parseOperationMaterialDetails = (jsonText) => {
  if (!jsonText) return [];
  try {
    const arr = JSON.parse(jsonText);
    if (!Array.isArray(arr)) return [];
    return arr
      .map((entry) => {
        if (!entry || typeof entry !== 'object') return null;
        const materialId = parseInt(entry.material_id || entry.materialId || entry.id || entry.value, 10);
        if (!Number.isFinite(materialId) || materialId <= 0) return null;
        const row = {
          material_id: materialId,
          qty: parseNumberOrNull(entry.qty ?? entry.quantity),
          width: parseNumberOrNull(entry.width),
          length: parseNumberOrNull(entry.length),
          height: parseNumberOrNull(entry.height),
          thickness: parseNumberOrNull(entry.thickness),
          tol_width: entry.tol_width != null ? String(entry.tol_width) : '',
          tol_length: entry.tol_length != null ? String(entry.tol_length) : '',
          tol_height: entry.tol_height != null ? String(entry.tol_height) : '',
          tol_thickness: entry.tol_thickness != null ? String(entry.tol_thickness) : '',
          qa_menus: Array.isArray(entry.qa_menus)
            ? Array.from(new Set(entry.qa_menus.map((m) => String(m || '').trim().toUpperCase()).filter(Boolean)))
            : []
        };
        for (let i = 1; i <= 10; i += 1) {
          row[`dim_${i}`] = parseNumberOrNull(entry[`dim_${i}`]);
          row[`tol_${i}`] = entry[`tol_${i}`] != null ? String(entry[`tol_${i}`]) : '';
        }
        return row;
      })
      .filter(Boolean);
  } catch (_) {
    return [];
  }
};

// Get work order options for Dimensional Report header prefill
exports.getWorkOrderOptions = async (req, res) => {
  try {
    const companyId = req.user?.companyId || req.user?.company_id || req.query?.companyId;
    const plantId = req.user?.plantId || req.user?.plant_id || req.query?.plantId;
    if (!companyId) {
      return res.status(400).json({
        success: false,
        message: 'Company context is required'
      });
    }

    const where = {
      company_id: companyId
    };
    if (plantId) where.plant_id = plantId;

    const workOrders = await db.WorkOrder.findAll({
      where,
      attributes: ['id', 'work_order_number'],
      include: [
        {
          model: db.Material,
          as: 'finishedMaterial',
          attributes: ['id', 'material_number', 'description'],
          required: false
        }
      ],
      order: [['id', 'DESC']]
    });

    const data = workOrders.map((wo) => ({
      id: wo.id,
      work_order_number: wo.work_order_number,
      item_code: wo.finishedMaterial?.material_number || '',
      item_name: wo.finishedMaterial?.description || '',
      label: `${wo.work_order_number} | ${wo.finishedMaterial?.material_number || '-'} | ${wo.finishedMaterial?.description || '-'}`
    }));

    res.json({
      success: true,
      data
    });
  } catch (error) {
    console.error('Error fetching work order options:', error);
    res.status(500).json({
      success: false,
      message: 'Error fetching work order options',
      error: error.message
    });
  }
};

// Get work order prefill data for Dimensional Report header
exports.getWorkOrderPrefill = async (req, res) => {
  try {
    const { workOrderId } = req.params;
    const companyId = req.user?.companyId || req.user?.company_id || req.query?.companyId;
    const plantId = req.user?.plantId || req.user?.plant_id || req.query?.plantId;
    const { reportType: routeReportType } = getReportModels(req);
    const reportType = isPressBrakeRequest(req) ? routeReportType : normalizeReportType(req.query?.report_type);

    const workOrder = await db.WorkOrder.findOne({
      where: {
        id: workOrderId,
        company_id: companyId,
        ...(plantId ? { plant_id: plantId } : {})
      },
      include: [
        {
          model: db.BusinessPartner,
          as: 'customer',
          attributes: ['id', 'bp_number', 'name', 'legal_name'],
          required: false
        },
        {
          model: db.Material,
          as: 'finishedMaterial',
          attributes: ['id', 'material_number', 'description', 'drawing_number', 'revision_number'],
          required: false
        },
        {
          model: db.ProductionOrder,
          as: 'productionOrder',
          attributes: ['id', 'start_date'],
          required: false,
          include: [{ model: db.BOMHeader, as: 'bom', attributes: ['id', 'drawing_number', 'revision_number'], required: false }]
        },
        {
          model: db.WorkOrderOperationPlan,
          as: 'operations',
          required: false,
          include: [{ model: db.Machine, as: 'machine', attributes: ['id', 'machine_code', 'machine_description'], required: false }]
        },
        {
          model: db.Routing,
          as: 'routing',
          required: false,
          include: [
            {
              model: db.RoutingOperation,
              as: 'operations',
              required: false,
              include: [{ model: db.Machine, as: 'machine', attributes: ['id', 'machine_code', 'machine_description'], required: false }]
            }
          ]
        }
      ],
      order: [
        [{ model: db.WorkOrderOperationPlan, as: 'operations' }, 'operation_sequence_no', 'ASC'],
        [{ model: db.Routing, as: 'routing' }, { model: db.RoutingOperation, as: 'operations' }, 'operation_number', 'ASC']
      ]
    });

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

    const firstOperationWithMachine = (workOrder.operations || []).find((op) => op?.machine?.id);
    const bom = workOrder.productionOrder?.bom || null;

    const payload = {
      work_order_id: workOrder.id,
      work_order_number: workOrder.work_order_number || '',
      customer_id: workOrder.customer?.id || null,
      customer_name: workOrder.customer?.name || workOrder.customer?.legal_name || '',
      item_code: workOrder.finishedMaterial?.material_number || '',
      item_name: workOrder.finishedMaterial?.description || '',
      drawing_no: bom?.drawing_number || workOrder.finishedMaterial?.drawing_number || '',
      revision_no: bom?.revision_number || workOrder.finishedMaterial?.revision_number || '',
      machine_id: firstOperationWithMachine?.machine?.id || null,
      machine_code: firstOperationWithMachine?.machine?.machine_code || '',
      machine_name: firstOperationWithMachine?.machine?.machine_description || '',
      operator_name: '',
      work_order_qty: workOrder.work_order_quantity || workOrder.order_quantity || 0,
      work_order_date: workOrder.planned_start_date || workOrder.productionOrder?.start_date || null,
      dimensional_details_template: []
    };

    // Build Dimensional template from Routing -> Operation -> Create Materials.
    // Include only rows where QA menu switch is enabled for this report.
    const routingOperations = Array.isArray(workOrder.routing?.operations) ? workOrder.routing.operations : [];
    const dimensionalMenuKey = reportType === 'PRESS_BRAKE'
      ? 'DIMENSIONAL_REPORT_PRESS_BRAKE'
      : 'DIMENSIONAL_REPORT';
    const dimensionalRoutingOperations = [];
    const templateRows = [];
    const materialIds = new Set();
    routingOperations.forEach((op) => {
      const details = parseOperationMaterialDetails(op.operation_materials_json);
      const selectedDetails = details.filter((detail) =>
        Array.isArray(detail.qa_menus) && detail.qa_menus.includes(dimensionalMenuKey)
      );
      if (selectedDetails.length > 0) {
        dimensionalRoutingOperations.push(op);
      }
      selectedDetails.forEach((detail) => {
        templateRows.push(detail);
        materialIds.add(detail.material_id);
      });
    });

    if (templateRows.length > 0) {
      const materials = await db.Material.findAll({
        where: { id: { [Op.in]: Array.from(materialIds) } },
        attributes: ['id', 'material_number', 'description']
      });
      const materialById = new Map(materials.map((m) => [m.id, m]));
      const rows = [];
      templateRows.forEach((detail) => {
        const material = materialById.get(detail.material_id);
        const itemCode = material?.material_number || '';
        const itemName = material?.description || '';

        const sourceRows = reportType === 'PRESS_BRAKE'
          ? Array.from({ length: 10 }, (_, idx) => {
            const n = idx + 1;
            return {
              key: `DIM-${n}`,
              value: detail[`dim_${n}`],
              tol: detail[`tol_${n}`]
            };
          })
          : [
            { key: 'LENGTH', value: detail.length, tol: detail.tol_length || detail.tol_width },
            { key: 'WIDTH', value: detail.width, tol: detail.tol_width || detail.tol_length },
            { key: 'HEIGHT', value: detail.height, tol: detail.tol_height || '' },
            { key: 'THICK', value: detail.thickness, tol: detail.tol_thickness || '' },
            { key: 'QTY', value: detail.qty, tol: '' }
          ];

        sourceRows.forEach((src) => {
          rows.push({
            item_code: itemCode,
            item_name: itemName,
            dimension: src.key,
            description: itemName || src.key,
            drg_dim: src.value != null && src.value !== '' ? String(src.value) : '',
            tol: src.tol != null && src.tol !== '' ? String(src.tol) : '',
            reading_1: '',
            reading_2: '',
            reading_3: '',
            reading_4: '',
            reading_5: '',
            no_of_rew: '',
            no_of_rej: '',
            laser_turret: '',
            remarks: ''
          });
        });
      });

      payload.dimensional_details_template = rows.map((r, idx) => ({
        ...r,
        line_no: idx + 1
      }));
    }

    // Machine should come from dimensional-enabled operation; else fallback.
    const selectedRoutingOperation = dimensionalRoutingOperations.find((op) => op?.machine?.id)
      || dimensionalRoutingOperations[0]
      || null;
    const qaOperationCode = String(selectedRoutingOperation?.operation_code || '').trim().toUpperCase();
    const qaOperationName = String(selectedRoutingOperation?.operation_description || '').trim().toUpperCase();
    const qaOperationNo = parseInt(selectedRoutingOperation?.operation_number, 10);
    const normalized = (s) => String(s || '').trim().toUpperCase();

    let matchedWorkOrderOperation = null;
    if ((qaOperationCode || qaOperationName) || Number.isFinite(qaOperationNo)) {
      matchedWorkOrderOperation = (workOrder.operations || []).find((op) => {
        if (Number.isFinite(qaOperationNo) && parseInt(op?.operation_sequence_no, 10) === qaOperationNo) return true;
        const opName = normalized(op?.operation_name);
        return (qaOperationCode && opName.includes(qaOperationCode)) || (qaOperationName && opName.includes(qaOperationName));
      }) || null;
    }
    const matchedRoutingOperation = (workOrder.routing?.operations || []).find((op) => {
      if (Number.isFinite(qaOperationNo) && parseInt(op?.operation_number, 10) === qaOperationNo) return true;
      const opCode = normalized(op?.operation_code);
      const opDesc = normalized(op?.operation_description);
      return (qaOperationCode && (opCode === qaOperationCode || opDesc.includes(qaOperationCode))) ||
        (qaOperationName && opDesc.includes(qaOperationName));
    }) || null;
    const fallbackWorkOrderOperation = (workOrder.operations || []).find((op) => op?.machine?.id) || null;
    const fallbackRoutingOperation = (workOrder.routing?.operations || []).find((op) => op?.machine?.id) || null;
    const chosenMachineOp =
      (matchedWorkOrderOperation?.machine?.id && matchedWorkOrderOperation) ||
      (matchedRoutingOperation?.machine?.id && matchedRoutingOperation) ||
      fallbackWorkOrderOperation ||
      fallbackRoutingOperation;
    if (chosenMachineOp?.machine?.id) {
      payload.machine_id = chosenMachineOp.machine.id;
      payload.machine_code = chosenMachineOp.machine.machine_code || '';
      payload.machine_name = chosenMachineOp.machine.machine_description || '';
    }

    // Operator should come from latest Route Card operation mapped by selected dimensional operation.
    const routeCard = await db.RouteCard.findOne({
      where: { work_order_id: workOrder.id },
      attributes: ['id', 'route_card_number'],
      include: [
        {
          model: db.RouteCardOperation,
          as: 'operations',
          required: false,
          include: [{ model: db.ProductionOperator, as: 'operator', attributes: ['id', 'operator_name'], required: false }]
        }
      ],
      order: [
        ['id', 'DESC'],
        [{ model: db.RouteCardOperation, as: 'operations' }, 'operation_sequence_no', 'ASC']
      ]
    });

    let matchedRouteCardOperation = null;
    if ((qaOperationCode || qaOperationName) || Number.isFinite(qaOperationNo)) {
      matchedRouteCardOperation = (routeCard?.operations || []).find((op) => {
        if (Number.isFinite(qaOperationNo) && parseInt(op?.operation_sequence_no, 10) === qaOperationNo) return true;
        const opCode = normalized(op?.operation_code);
        const opName = normalized(op?.operation_name);
        return (qaOperationCode && (opCode === qaOperationCode || opName.includes(qaOperationCode))) ||
          (qaOperationName && opName.includes(qaOperationName));
      }) || null;
    }
    const fallbackRouteCardOperation = (routeCard?.operations || []).find((op) => op?.operator?.operator_name || op?.operator_ids) || null;
    const chosenRouteCardOperation = matchedRouteCardOperation || fallbackRouteCardOperation;
    if (chosenRouteCardOperation?.operator?.operator_name) {
      payload.operator_name = chosenRouteCardOperation.operator.operator_name;
    } else if (chosenRouteCardOperation?.operator_ids) {
      const parseIds = () => {
        const raw = String(chosenRouteCardOperation.operator_ids || '').trim();
        if (!raw) return [];
        try {
          const arr = JSON.parse(raw);
          if (Array.isArray(arr)) return arr.map((v) => parseInt(v, 10)).filter(Number.isFinite);
        } catch (_) {
          // ignore
        }
        return raw.split(',').map((v) => parseInt(v.trim(), 10)).filter(Number.isFinite);
      };
      const opIds = parseIds();
      if (opIds.length) {
        const operators = await db.ProductionOperator.findAll({
          where: { id: { [Op.in]: opIds } },
          attributes: ['id', 'operator_name']
        });
        payload.operator_name = operators.map((o) => o.operator_name).filter(Boolean).join(', ');
      }
    }

    // Work order date from Work Order planned date; fallback to Work Order created date; persist if missing.
    const createdDate = (workOrder.created_at || workOrder.createdAt)
      ? new Date(workOrder.created_at || workOrder.createdAt).toISOString().slice(0, 10)
      : new Date().toISOString().slice(0, 10);
    if (!workOrder.planned_start_date) {
      await workOrder.update({ planned_start_date: createdDate });
      payload.work_order_date = createdDate;
    } else {
      payload.work_order_date = workOrder.planned_start_date;
    }

    res.json({
      success: true,
      data: payload
    });
  } catch (error) {
    console.error('Error fetching work order prefill:', error);
    res.status(500).json({
      success: false,
      message: 'Error fetching work order prefill',
      error: error.message
    });
  }
};

// Get all dimensional reports with filters
exports.getAll = async (req, res) => {
  try {
    const { companyId, plantId } = getCtx(req);
    if (!companyId) {
      return res.status(400).json({
        success: false,
        message: 'Company context is required'
      });
    }

    const {
      page = 1,
      limit = 10,
      search,
      status,
      customerId,
      partName,
      startDate,
      endDate,
      report_type
    } = req.query;

    const { headerModel, reportType: routeReportType } = getReportModels(req);
    const reportType = isPressBrakeRequest(req) ? routeReportType : normalizeReportType(report_type);
    const offset = (page - 1) * limit;
    const where = {
      company_id: companyId,
      ...(plantId ? { plant_id: plantId } : {}),
      report_type: reportType
    };

    // Apply filters
    if (search) {
      where[Op.or] = [
        { report_no: { [Op.like]: `%${search}%` } },
        { part_name: { [Op.like]: `%${search}%` } },
        { item_code: { [Op.like]: `%${search}%` } },
        { drawing_no: { [Op.like]: `%${search}%` } },
        { order_no: { [Op.like]: `%${search}%` } }
      ];
    }

    if (status) {
      where.status = status;
    }

    if (customerId) {
      where.customer_id = customerId;
    }

    if (partName) {
      where.part_name = { [Op.like]: `%${partName}%` };
    }

    if (startDate && endDate) {
      where.report_date = {
        [Op.between]: [startDate, endDate]
      };
    } else if (startDate) {
      where.report_date = { [Op.gte]: startDate };
    } else if (endDate) {
      where.report_date = { [Op.lte]: endDate };
    }

    const { count, rows } = await headerModel.findAndCountAll({
      where,
      include: [
        {
          model: db.BusinessPartner,
          as: 'customer',
          attributes: ['id', 'name', 'bp_number']
        },
        {
          model: db.Machine,
          as: 'machine',
          attributes: ['id', 'machine_code', 'machine_description']
        },
        {
          model: db.User,
          as: 'inspector',
          attributes: ['id', 'first_name', 'last_name']
        }
      ],
      order: [['report_date', 'DESC'], ['report_no', 'DESC']],
      limit: parseInt(limit),
      offset: parseInt(offset)
    });

    res.json({
      success: true,
      data: rows,
      pagination: {
        total: count,
        page: parseInt(page),
        limit: parseInt(limit),
        totalPages: Math.ceil(count / limit)
      }
    });
  } catch (error) {
    console.error('Error fetching dimensional reports:', error);
    res.status(500).json({
      success: false,
      message: 'Error fetching dimensional reports',
      error: error.message
    });
  }
};

// Get single dimensional report by ID
exports.getById = async (req, res) => {
  try {
    const { id } = req.params;
    const { companyId, plantId } = getCtx(req);

    const { headerModel, detailModel } = getReportModels(req);
    const report = await headerModel.findOne({
      where: {
        id,
        company_id: companyId,
        ...(plantId ? { plant_id: plantId } : {})
      },
      include: [
        {
          model: db.BusinessPartner,
          as: 'customer',
          attributes: ['id', 'name', 'bp_number']
        },
        {
          model: db.Machine,
          as: 'machine',
          attributes: ['id', 'machine_code', 'machine_description']
        },
        {
          model: db.User,
          as: 'inspector',
          attributes: ['id', 'first_name', 'last_name']
        },
        {
          model: detailModel,
          as: 'details',
          separate: true,
          order: [['line_no', 'ASC']]
        }
      ]
    });

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

    res.json({
      success: true,
      data: report
    });
  } catch (error) {
    console.error('Error fetching dimensional report:', error);
    res.status(500).json({
      success: false,
      message: 'Error fetching dimensional report',
      error: error.message
    });
  }
};

// Create new dimensional report
exports.create = async (req, res) => {
  const transaction = await db.sequelize.transaction();

  try {
    const { companyId, plantId } = getCtx(req);
    if (!companyId) throw new Error('Company context is required');
    if (!plantId) throw new Error('Plant context is required');

    const {
      report_date,
      report_type,
      work_order_id,
      part_name,
      item_code,
      drawing_no,
      order_no,
      order_qty,
      customer_id,
      customer_name,
      revision_no,
      machine_id,
      machine_name,
      quantity,
      operator_name,
      remarks,
      inspected_by,
      inspected_by_user_id,
      inspection_date,
      status = 'DRAFT',
      details = []
    } = req.body;
    const { headerModel, detailModel, reportType: routeReportType } = getReportModels(req);
    const reportType = isPressBrakeRequest(req) ? routeReportType : normalizeReportType(report_type);

    // Generate report number
    const fiscalYear = await db.FiscalYear.findOne({
      where: {
        company_id: companyId,
        status: 'ACTIVE',
        is_closed: false
      }
    });

    if (!fiscalYear) {
      throw new Error('No active fiscal year found');
    }

    const report_no = await generateDimensionalReportNumber(companyId, fiscalYear.id, transaction, req);

    // Create header
    const report = await headerModel.create({
      company_id: companyId,
      plant_id: plantId,
      fiscal_year_id: fiscalYear.id,
      report_no,
      report_date,
      report_type: reportType,
      work_order_id,
      part_name,
      item_code,
      drawing_no,
      order_no,
      order_qty,
      customer_id,
      customer_name,
      revision_no,
      machine_id,
      machine_name,
      quantity,
      operator_name,
      remarks,
      inspected_by,
      inspected_by_user_id,
      inspection_date,
      status,
      created_by: req.user.id,
      updated_by: req.user.id
    }, { transaction });

    // Create details
    if (details && details.length > 0) {
      const detailRecords = details.map((detail, index) => ({
        report_id: report.id,
        line_no: detail.line_no || index + 1,
        description: detail.description,
        drg_dim: detail.drg_dim,
        tol: detail.tol,
        reading_1: detail.reading_1,
        reading_2: detail.reading_2,
        reading_3: detail.reading_3,
        reading_4: detail.reading_4,
        reading_5: detail.reading_5,
        no_of_rew: detail.no_of_rew,
        no_of_rej: detail.no_of_rej,
        laser_turret: detail.laser_turret,
        remarks: detail.remarks
      }));

      await detailModel.bulkCreate(detailRecords, { transaction });
    }

    await transaction.commit();

    // Fetch complete report with associations
    const completeReport = await headerModel.findByPk(report.id, {
      include: [
        {
          model: db.BusinessPartner,
          as: 'customer'
        },
        {
          model: db.Machine,
          as: 'machine'
        },
        {
          model: db.User,
          as: 'inspector'
        },
        {
          model: detailModel,
          as: 'details',
          separate: true,
          order: [['line_no', 'ASC']]
        }
      ]
    });

    res.status(201).json({
      success: true,
      message: 'Dimensional report created successfully',
      data: completeReport
    });
  } catch (error) {
    await transaction.rollback();
    console.error('Error creating dimensional report:', error);
    res.status(500).json({
      success: false,
      message: 'Error creating dimensional report',
      error: error.message
    });
  }
};

// Update dimensional report
exports.update = async (req, res) => {
  const transaction = await db.sequelize.transaction();

  try {
    const { id } = req.params;
    const { companyId, plantId } = getCtx(req);
    const {
      report_date,
      report_type,
      work_order_id,
      part_name,
      item_code,
      drawing_no,
      order_no,
      order_qty,
      customer_id,
      customer_name,
      revision_no,
      machine_id,
      machine_name,
      quantity,
      operator_name,
      remarks,
      inspected_by,
      inspected_by_user_id,
      inspection_date,
      status,
      details = []
    } = req.body;
    // Find report
    const { headerModel, detailModel, reportType: routeReportType } = getReportModels(req);
    const report = await headerModel.findOne({
      where: {
        id,
        company_id: companyId,
        ...(plantId ? { plant_id: plantId } : {})
      },
      transaction
    });

    if (!report) {
      await transaction.rollback();
      return res.status(404).json({
        success: false,
        message: 'Dimensional report not found'
      });
    }
    const reportType = isPressBrakeRequest(req) ? routeReportType : normalizeReportType(report_type || report?.report_type);

    // Update header
    await report.update({
      report_date,
      report_type: reportType,
      work_order_id,
      part_name,
      item_code,
      drawing_no,
      order_no,
      order_qty,
      customer_id,
      customer_name,
      revision_no,
      machine_id,
      machine_name,
      quantity,
      operator_name,
      remarks,
      inspected_by,
      inspected_by_user_id,
      inspection_date,
      status,
      updated_by: req.user.id
    }, { transaction });

    // Delete existing details
    await detailModel.destroy({
      where: { report_id: id },
      transaction
    });

    // Create new details
    if (details && details.length > 0) {
      const detailRecords = details.map((detail, index) => ({
        report_id: report.id,
        line_no: detail.line_no || index + 1,
        description: detail.description,
        drg_dim: detail.drg_dim,
        tol: detail.tol,
        reading_1: detail.reading_1,
        reading_2: detail.reading_2,
        reading_3: detail.reading_3,
        reading_4: detail.reading_4,
        reading_5: detail.reading_5,
        no_of_rew: detail.no_of_rew,
        no_of_rej: detail.no_of_rej,
        laser_turret: detail.laser_turret,
        remarks: detail.remarks
      }));

      await detailModel.bulkCreate(detailRecords, { transaction });
    }

    await transaction.commit();

    // Fetch complete report with associations
    const completeReport = await headerModel.findByPk(report.id, {
      include: [
        {
          model: db.BusinessPartner,
          as: 'customer'
        },
        {
          model: db.Machine,
          as: 'machine'
        },
        {
          model: db.User,
          as: 'inspector'
        },
        {
          model: detailModel,
          as: 'details',
          separate: true,
          order: [['line_no', 'ASC']]
        }
      ]
    });

    res.json({
      success: true,
      message: 'Dimensional report updated successfully',
      data: completeReport
    });
  } catch (error) {
    await transaction.rollback();
    console.error('Error updating dimensional report:', error);
    res.status(500).json({
      success: false,
      message: 'Error updating dimensional report',
      error: error.message
    });
  }
};

// Delete dimensional report
exports.delete = async (req, res) => {
  const transaction = await db.sequelize.transaction();

  try {
    const { id } = req.params;
    const { companyId, plantId } = getCtx(req);

    const { headerModel, detailModel } = getReportModels(req);
    const report = await headerModel.findOne({
      where: {
        id,
        company_id: companyId,
        ...(plantId ? { plant_id: plantId } : {})
      },
      transaction
    });

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

    // Delete details (cascade will handle this, but being explicit)
    await detailModel.destroy({
      where: { report_id: id },
      transaction
    });

    // Delete header
    await report.destroy({ transaction });

    await transaction.commit();

    res.json({
      success: true,
      message: 'Dimensional report deleted successfully'
    });
  } catch (error) {
    await transaction.rollback();
    console.error('Error deleting dimensional report:', error);
    res.status(500).json({
      success: false,
      message: 'Error deleting dimensional report',
      error: error.message
    });
  }
};

// Update dimensional report status only
exports.updateStatus = async (req, res) => {
  try {
    const { id } = req.params;
    const { companyId, plantId } = getCtx(req);
    const status = String(req.body?.status || '').toUpperCase();

    if (!['DRAFT', 'SUBMITTED', 'APPROVED', 'CANCELLED'].includes(status)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid status'
      });
    }

    const { headerModel } = getReportModels(req);
    const report = await headerModel.findOne({
      where: {
        id,
        company_id: companyId,
        ...(plantId ? { plant_id: plantId } : {})
      }
    });

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

    await report.update({
      status,
      updated_by: req.user?.id || req.user?.userId || null
    });

    return res.json({
      success: true,
      message: `Dimensional report marked as ${status}`,
      data: report
    });
  } catch (error) {
    console.error('Error updating dimensional report status:', error);
    return res.status(500).json({
      success: false,
      message: 'Error updating dimensional report status',
      error: error.message
    });
  }
};
