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

exports.getAll = asyncHandler(async (req, res) => {
  const { page = 1, limit = 25, search, status, companyId, plantId, employeeId, payrollId } = req.query;
  const { limit: limitNum, offset } = getPagination(page, limit);

  const where = {};
  
  if (companyId) {
    where.company_id = companyId;
  } else if (req.user && !req.user.isSuperAdmin) {
    where.company_id = req.user.companyId;
  }

  if (plantId) {
    where.plant_id = plantId;
  }

  if (employeeId) {
    where.employee_id = employeeId;
  }

  if (payrollId) {
    where.payroll_id = payrollId;
  }

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

  if (search) {
    where[Op.or] = [
      { payslip_number: { [Op.like]: `%${search}%` } },
      { remarks: { [Op.like]: `%${search}%` } }
    ];
  }

  const records = await db.Payslip.findAndCountAll({
    where,
    include: [
      { model: db.Company, as: 'company', attributes: ['id', 'code', 'name'] },
      { model: db.Plant, as: 'plant', attributes: ['id', 'code', 'name'], required: false },
      {
        model: db.Payroll,
        as: 'payroll',
        include: [
          { model: db.Employee, as: 'employee', attributes: ['id', 'employee_number', 'first_name', 'last_name'] },
          { model: db.PayrollComponent, as: 'components' },
          { model: db.MusterRoll, as: 'musterRoll' }
        ]
      },
      { model: db.Employee, as: 'employee', attributes: ['id', 'employee_number', 'first_name', 'last_name'] }
    ],
    limit: limitNum,
    offset,
    order: [['payslip_date', 'DESC'], ['id', 'DESC']]
  });

  const response = getPagingData(records, page, limitNum);
  sendResponse(res, 200, true, 'Payslip records retrieved successfully', response);
});

exports.getById = asyncHandler(async (req, res) => {
  const { id } = req.params;

  const payslip = await db.Payslip.findByPk(id, {
    include: [
      { model: db.Company, as: 'company' },
      { model: db.Plant, as: 'plant' },
      {
        model: db.Payroll,
        as: 'payroll',
        include: [
          { model: db.Employee, as: 'employee' },
          { model: db.PayrollComponent, as: 'components', order: [['display_order', 'ASC']] },
          { model: db.MusterRoll, as: 'musterRoll' }
        ]
      },
      { model: db.Employee, as: 'employee' }
    ]
  });

  if (!payslip) {
    return sendError(res, 'Payslip record not found', 404);
  }

  sendResponse(res, 200, true, 'Payslip record retrieved successfully', payslip);
});

exports.create = asyncHandler(async (req, res) => {
  const payslip = await db.Payslip.create(req.body);
  const payslipWithRelations = await db.Payslip.findByPk(payslip.id, {
    include: [
      { model: db.Company, as: 'company' },
      { model: db.Plant, as: 'plant' },
      {
        model: db.Payroll,
        as: 'payroll',
        include: [
          { model: db.Employee, as: 'employee' },
          { model: db.PayrollComponent, as: 'components' },
          { model: db.MusterRoll, as: 'musterRoll' }
        ]
      },
      { model: db.Employee, as: 'employee' }
    ]
  });
  sendResponse(res, 201, true, 'Payslip record created successfully', payslipWithRelations);
});

exports.update = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const payslip = await db.Payslip.findByPk(id);

  if (!payslip) {
    return sendError(res, 'Payslip record not found', 404);
  }

  await payslip.update(req.body);
  const updatedPayslip = await db.Payslip.findByPk(id, {
    include: [
      { model: db.Company, as: 'company' },
      { model: db.Plant, as: 'plant' },
      {
        model: db.Payroll,
        as: 'payroll',
        include: [
          { model: db.Employee, as: 'employee' },
          { model: db.PayrollComponent, as: 'components' },
          { model: db.MusterRoll, as: 'musterRoll' }
        ]
      },
      { model: db.Employee, as: 'employee' }
    ]
  });
  sendResponse(res, 200, true, 'Payslip record updated successfully', updatedPayslip);
});

exports.updateStatus = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const { status } = req.body;
  const payslip = await db.Payslip.findByPk(id);

  if (!payslip) {
    return sendError(res, 'Payslip record not found', 404);
  }

  const updateData = { status };
  if (status === 'SENT') {
    updateData.is_emailed = true;
    updateData.email_sent_date = new Date();
  }

  await payslip.update(updateData);
  const updatedPayslip = await db.Payslip.findByPk(id, {
    include: [
      { model: db.Company, as: 'company' },
      { model: db.Plant, as: 'plant' },
      {
        model: db.Payroll,
        as: 'payroll',
        include: [
          { model: db.Employee, as: 'employee' },
          { model: db.PayrollComponent, as: 'components' },
          { model: db.MusterRoll, as: 'musterRoll' }
        ]
      },
      { model: db.Employee, as: 'employee' }
    ]
  });
  sendResponse(res, 200, true, 'Payslip status updated successfully', updatedPayslip);
});

exports.markDownloaded = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const payslip = await db.Payslip.findByPk(id);

  if (!payslip) {
    return sendError(res, 'Payslip record not found', 404);
  }

  await payslip.update({
    is_downloaded: true,
    downloaded_date: new Date(),
    status: 'DOWNLOADED'
  });

  const updatedPayslip = await db.Payslip.findByPk(id, {
    include: [
      { model: db.Company, as: 'company' },
      { model: db.Plant, as: 'plant' },
      {
        model: db.Payroll,
        as: 'payroll',
        include: [
          { model: db.Employee, as: 'employee' },
          { model: db.PayrollComponent, as: 'components' },
          { model: db.MusterRoll, as: 'musterRoll' }
        ]
      },
      { model: db.Employee, as: 'employee' }
    ]
  });
  sendResponse(res, 200, true, 'Payslip marked as downloaded successfully', updatedPayslip);
});

exports.delete = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const payslip = await db.Payslip.findByPk(id);

  if (!payslip) {
    return sendError(res, 'Payslip record not found', 404);
  }

  await payslip.destroy();
  sendResponse(res, 200, true, 'Payslip record deleted successfully', null);
});

