const packageRepo = require('../repositories/packageRepository');
const { successResponse, errorResponse, paginate } = require('../utils/helpers');
const { logAudit } = require('../middleware/auditLog');

async function getAll(req, res, next) {
  try {
    const { page, limit, search, status } = req.query;
    const { limit: l, offset, page: p } = paginate(page, limit);
    const { rows, total } = await packageRepo.findAll({ limit: l, offset, search, status });
    return successResponse(res, { data: rows, total, page: p, limit: l, totalPages: Math.ceil(total / l) });
  } catch (err) { next(err); }
}

async function getActive(req, res, next) {
  try {
    const packages = await packageRepo.findActive();
    return successResponse(res, packages);
  } catch (err) { next(err); }
}

async function getById(req, res, next) {
  try {
    const pkg = await packageRepo.findById(req.params.id);
    if (!pkg) return errorResponse(res, 'Package not found', 404);
    return successResponse(res, pkg);
  } catch (err) { next(err); }
}

async function create(req, res, next) {
  try {
    const { name, description, selling_price, status, items } = req.body;
    if (!name || selling_price === undefined) return errorResponse(res, 'name and selling_price are required', 400);
    if (!items || !items.length) return errorResponse(res, 'Package must have at least one item', 400);
    const pkg = await packageRepo.create({ name, description, selling_price, status });
    for (const item of items) {
      if (!item.product_id || !item.qty) return errorResponse(res, 'Each item needs product_id and qty', 400);
      await packageRepo.addItem(pkg.id, item);
    }
    const full = await packageRepo.findById(pkg.id);
    await logAudit({ userId: req.user.id, action: 'create_package', entity: 'packages', entityId: pkg.id, newData: full, req });
    return successResponse(res, full, 'Package created', 201);
  } catch (err) { next(err); }
}

async function update(req, res, next) {
  try {
    const { id } = req.params;
    const old = await packageRepo.findById(id);
    if (!old) return errorResponse(res, 'Package not found', 404);
    const { name, description, selling_price, status, items } = req.body;
    await packageRepo.update(id, { name, description, selling_price, status });
    if (items && items.length > 0) {
      await packageRepo.clearItems(id);
      for (const item of items) await packageRepo.addItem(id, item);
    }
    const updated = await packageRepo.findById(id);
    await logAudit({ userId: req.user.id, action: 'update_package', entity: 'packages', entityId: id, oldData: old, newData: updated, req });
    return successResponse(res, updated, 'Package updated');
  } catch (err) { next(err); }
}

async function remove(req, res, next) {
  try {
    const { id } = req.params;
    const pkg = await packageRepo.findById(id);
    if (!pkg) return errorResponse(res, 'Package not found', 404);
    await packageRepo.remove(id);
    await logAudit({ userId: req.user.id, action: 'delete_package', entity: 'packages', entityId: id, oldData: pkg, req });
    return successResponse(res, null, 'Package deleted');
  } catch (err) { next(err); }
}

module.exports = { getAll, getActive, getById, create, update, remove };
