const db = require('../models');
const { sendSuccess, sendError } = require('../utils/response');
const asyncHandler = require('../middlewares/asyncHandler');
const { Op } = require('sequelize');

const buildWhere = (req) => {
  const where = { id: req.params.id };
  if (req.user?.company_id) where.company_id = req.user.company_id;
  return where;
};

const includeDetails = [{ model: db.RejectionReworkRecordDetail, as: 'details' }];
const includeOrder = [[db.RejectionReworkRecordDetail, 'line_no', 'ASC']];

exports.getAll = asyncHandler(async (req, res) => {
  const { page = 1, limit = 10, search = '', startDate, endDate } = req.query;
  const offset = (parseInt(page, 10) - 1) * parseInt(limit, 10);
  const where = {};
  if (req.user?.company_id) where.company_id = req.user.company_id;
  if (search) {
    where[Op.or] = [
      { report_no: { [Op.like]: `%${search}%` } }
    ];
  }
  if (startDate && endDate) where.record_date = { [Op.between]: [startDate, endDate] };
  else if (startDate) where.record_date = { [Op.gte]: startDate };
  else if (endDate) where.record_date = { [Op.lte]: endDate };

  const { count, rows } = await db.RejectionReworkRecord.findAndCountAll({
    where,
    limit: parseInt(limit, 10),
    offset,
    order: [['record_date', 'DESC'], ['id', 'DESC']],
    distinct: true
  });

  return sendSuccess(res, 'Rejection/Rework records fetched successfully', {
    data: rows,
    pagination: {
      total: count,
      page: parseInt(page, 10),
      limit: parseInt(limit, 10),
      totalPages: Math.ceil(count / parseInt(limit, 10))
    }
  });
});

exports.getById = asyncHandler(async (req, res) => {
  const record = await db.RejectionReworkRecord.findOne({
    where: buildWhere(req),
    include: includeDetails,
    order: includeOrder
  });
  if (!record) return sendError(res, 'Rejection/Rework record not found', 404);
  return sendSuccess(res, 'Record fetched successfully', record);
});

exports.create = asyncHandler(async (req, res) => {
  const userId = req.user?.id;
  const transaction = await db.sequelize.transaction();
  try {
    const { details = [], ...header } = req.body;
    const record = await db.RejectionReworkRecord.create(
      { ...header, created_by: userId, updated_by: userId },
      { transaction }
    );
    if (details.length > 0) {
      await db.RejectionReworkRecordDetail.bulkCreate(
        details.map((d) => ({ ...d, record_id: record.id })),
        { transaction }
      );
    }
    await transaction.commit();
    const created = await db.RejectionReworkRecord.findByPk(record.id, { include: includeDetails, order: includeOrder });
    return sendSuccess(res, 'Rejection/Rework record created successfully', created, null, 201);
  } catch (err) {
    await transaction.rollback();
    throw err;
  }
});

exports.update = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const userId = req.user?.id;
  const record = await db.RejectionReworkRecord.findOne({ where: buildWhere(req) });
  if (!record) return sendError(res, 'Rejection/Rework record not found', 404);
  const transaction = await db.sequelize.transaction();
  try {
    const { details, ...header } = req.body;
    await record.update({ ...header, updated_by: userId }, { transaction });
    await db.RejectionReworkRecordDetail.destroy({ where: { record_id: id }, transaction });
    if (details?.length > 0) {
      await db.RejectionReworkRecordDetail.bulkCreate(
        details.map((d) => ({ ...d, record_id: parseInt(id, 10) })),
        { transaction }
      );
    }
    await transaction.commit();
    const updated = await db.RejectionReworkRecord.findByPk(id, { include: includeDetails, order: includeOrder });
    return sendSuccess(res, 'Rejection/Rework record updated successfully', updated);
  } catch (err) {
    await transaction.rollback();
    throw err;
  }
});

exports.delete = asyncHandler(async (req, res) => {
  const record = await db.RejectionReworkRecord.findOne({ where: buildWhere(req) });
  if (!record) return sendError(res, 'Rejection/Rework record not found', 404);
  await record.destroy();
  return sendSuccess(res, 'Rejection/Rework record deleted successfully');
});
