const mongoose = require('mongoose');
const Salary = require('../models/Salary');
const Employee = require('../models/Employee');

function validateSalaryBody(body) {
  const { employee, grossSalary, totalDeduction, monthOfPayment, paymentDate } = body || {};

  if (!employee || !mongoose.Types.ObjectId.isValid(employee)) return 'employee must be a valid employee id';
  if (grossSalary == null || typeof grossSalary !== 'number') return 'grossSalary is required and must be a number';
  if (totalDeduction == null || typeof totalDeduction !== 'number') return 'totalDeduction is required and must be a number';
  if (!monthOfPayment || typeof monthOfPayment !== 'string' || monthOfPayment.trim().length < 2) return 'monthOfPayment is required';

  const pd = new Date(paymentDate);
  if (Number.isNaN(pd.getTime())) return 'paymentDate must be a valid date';

  if (grossSalary < 0) return 'grossSalary cannot be negative';
  if (totalDeduction < 0) return 'totalDeduction cannot be negative';
  if (totalDeduction > grossSalary) return 'totalDeduction cannot exceed grossSalary';

  return null;
}

async function createSalary(req, res, next) {
  try {
    const errMsg = validateSalaryBody(req.body);
    if (errMsg) return res.status(400).json({ message: errMsg });

    const emp = await Employee.findById(req.body.employee);
    if (!emp) return res.status(404).json({ message: 'Employee not found' });

    const netSalary = req.body.grossSalary - req.body.totalDeduction;

    const salary = await Salary.create({
      employee: req.body.employee,
      grossSalary: req.body.grossSalary,
      totalDeduction: req.body.totalDeduction,
      netSalary,
      monthOfPayment: req.body.monthOfPayment.trim(),
      paymentDate: new Date(req.body.paymentDate)
    });

    const populated = await Salary.findById(salary._id)
      .populate({
        path: 'employee',
        populate: { path: 'department', model: 'Department' }
      });

    return res.status(201).json(populated);
  } catch (err) {
    return next(err);
  }
}

async function getAllSalaries(req, res, next) {
  try {
    const salaries = await Salary.find().populate({
      path: 'employee',
      populate: { path: 'department', model: 'Department' }
    }).sort({ createdAt: -1 });

    return res.status(200).json(salaries);
  } catch (err) {
    return next(err);
  }
}

async function getSalaryById(req, res, next) {
  try {
    const { id } = req.params;
    if (!mongoose.Types.ObjectId.isValid(id)) return res.status(400).json({ message: 'Invalid id' });

    const salary = await Salary.findById(id).populate({
      path: 'employee',
      populate: { path: 'department', model: 'Department' }
    });

    if (!salary) return res.status(404).json({ message: 'Salary record not found' });
    return res.status(200).json(salary);
  } catch (err) {
    return next(err);
  }
}

async function updateSalary(req, res, next) {
  try {
    const { id } = req.params;
    if (!mongoose.Types.ObjectId.isValid(id)) return res.status(400).json({ message: 'Invalid id' });

    const errMsg = validateSalaryBody(req.body);
    if (errMsg) return res.status(400).json({ message: errMsg });

    const emp = await Employee.findById(req.body.employee);
    if (!emp) return res.status(404).json({ message: 'Employee not found' });

    const netSalary = req.body.grossSalary - req.body.totalDeduction;

    const updated = await Salary.findByIdAndUpdate(
      id,
      {
        employee: req.body.employee,
        grossSalary: req.body.grossSalary,
        totalDeduction: req.body.totalDeduction,
        netSalary,
        monthOfPayment: req.body.monthOfPayment.trim(),
        paymentDate: new Date(req.body.paymentDate)
      },
      { new: true, runValidators: true }
    );

    if (!updated) return res.status(404).json({ message: 'Salary record not found' });

    const populated = await Salary.findById(updated._id).populate({
      path: 'employee',
      populate: { path: 'department', model: 'Department' }
    });

    return res.status(200).json(populated);
  } catch (err) {
    return next(err);
  }
}

async function deleteSalary(req, res, next) {
  try {
    const { id } = req.params;
    if (!mongoose.Types.ObjectId.isValid(id)) return res.status(400).json({ message: 'Invalid id' });

    const deleted = await Salary.findByIdAndDelete(id);
    if (!deleted) return res.status(404).json({ message: 'Salary record not found' });
    return res.status(200).json({ message: 'Salary deleted successfully' });
  } catch (err) {
    return next(err);
  }
}

module.exports = {
  createSalary,
  getAllSalaries,
  getSalaryById,
  updateSalary,
  deleteSalary
};

