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.CorrectiveActionReportInterim, as: 'interimActions' },
  { model: db.CorrectiveActionReportPermanent, as: 'permanentActions' },
  { model: db.CorrectiveActionReportBatch, as: 'batchDetails' }
];

const includeOrder = [
  [db.CorrectiveActionReportInterim, 'line_no', 'ASC'],
  [db.CorrectiveActionReportPermanent, 'line_no', 'ASC'],
  [db.CorrectiveActionReportBatch, '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}%` } },
      { nc_ref: { [Op.like]: `%${search}%` } },
      { customer_name: { [Op.like]: `%${search}%` } },
      { part_name: { [Op.like]: `%${search}%` } },
      { part_number: { [Op.like]: `%${search}%` } }
    ];
  }
  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 db.CorrectiveActionReport.findAndCountAll({
    where,
    limit: parseInt(limit, 10),
    offset,
    order: [['report_date', 'DESC'], ['id', 'DESC']],
    distinct: true
  });

  return sendSuccess(res, 'Corrective action reports 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 report = await db.CorrectiveActionReport.findOne({
    where: buildWhere(req),
    include: includeDetails,
    order: includeOrder
  });
  if (!report) return sendError(res, 'Corrective action report not found', 404);
  return sendSuccess(res, 'Report fetched successfully', report);
});

exports.create = asyncHandler(async (req, res) => {
  const userId = req.user?.id;
  const transaction = await db.sequelize.transaction();
  try {
    const {
      interimActions = [],
      permanentActions = [],
      batchDetails = [],
      ...header
    } = req.body;
    const report = await db.CorrectiveActionReport.create(
      { ...header, created_by: userId, updated_by: userId },
      { transaction }
    );
    if (interimActions.length > 0) {
      await db.CorrectiveActionReportInterim.bulkCreate(
        interimActions.map((d) => ({ ...d, report_id: report.id })),
        { transaction }
      );
    }
    if (permanentActions.length > 0) {
      await db.CorrectiveActionReportPermanent.bulkCreate(
        permanentActions.map((d) => ({ ...d, report_id: report.id })),
        { transaction }
      );
    }
    if (batchDetails.length > 0) {
      await db.CorrectiveActionReportBatch.bulkCreate(
        batchDetails.map((d) => ({ ...d, report_id: report.id })),
        { transaction }
      );
    }
    await transaction.commit();
    const created = await db.CorrectiveActionReport.findByPk(report.id, { include: includeDetails, order: includeOrder });
    return sendSuccess(res, 'Corrective action report 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 report = await db.CorrectiveActionReport.findOne({ where: buildWhere(req) });
  if (!report) return sendError(res, 'Corrective action report not found', 404);
  const transaction = await db.sequelize.transaction();
  try {
    const { interimActions, permanentActions, batchDetails, ...header } = req.body;
    await report.update({ ...header, updated_by: userId }, { transaction });
    await db.CorrectiveActionReportInterim.destroy({ where: { report_id: id }, transaction });
    await db.CorrectiveActionReportPermanent.destroy({ where: { report_id: id }, transaction });
    await db.CorrectiveActionReportBatch.destroy({ where: { report_id: id }, transaction });
    if (interimActions?.length > 0) {
      await db.CorrectiveActionReportInterim.bulkCreate(
        interimActions.map((d) => ({ ...d, report_id: parseInt(id, 10) })),
        { transaction }
      );
    }
    if (permanentActions?.length > 0) {
      await db.CorrectiveActionReportPermanent.bulkCreate(
        permanentActions.map((d) => ({ ...d, report_id: parseInt(id, 10) })),
        { transaction }
      );
    }
    if (batchDetails?.length > 0) {
      await db.CorrectiveActionReportBatch.bulkCreate(
        batchDetails.map((d) => ({ ...d, report_id: parseInt(id, 10) })),
        { transaction }
      );
    }
    await transaction.commit();
    const updated = await db.CorrectiveActionReport.findByPk(id, { include: includeDetails, order: includeOrder });
    return sendSuccess(res, 'Corrective action report updated successfully', updated);
  } catch (err) {
    await transaction.rollback();
    throw err;
  }
});

exports.delete = asyncHandler(async (req, res) => {
  const report = await db.CorrectiveActionReport.findOne({ where: buildWhere(req) });
  if (!report) return sendError(res, 'Corrective action report not found', 404);
  await report.destroy();
  return sendSuccess(res, 'Corrective action report deleted successfully');
});
