import express from 'express';
import Payroll from '../models/Payroll.js';
import Employee from '../models/Employee.js';
import { protect } from '../middleware/auth.js';
import { calcPayrollFromEmployee, monthLabel } from '../utils/payrollCalc.js';

const router = express.Router();
router.use(protect);

router.get('/', async (req, res, next) => {
  try {
    const { month, year, status, employee } = req.query;
    const filter = {};
    if (month) filter.month = Number(month);
    if (year) filter.year = Number(year);
    if (status) filter.status = status;
    if (employee) filter.employee = employee;
    const payrolls = await Payroll.find(filter)
      .populate({
        path: 'employee',
        select: 'firstName lastName employeeId role email',
        populate: { path: 'department', select: 'name code' },
      })
      .populate('processedBy', 'name')
      .sort({ year: -1, month: -1, createdAt: -1 });
    res.json(payrolls);
  } catch (err) {
    next(err);
  }
});

router.get('/summary', async (req, res, next) => {
  try {
    const { month, year } = req.query;
    const m = Number(month) || new Date().getMonth() + 1;
    const y = Number(year) || new Date().getFullYear();
    const payrolls = await Payroll.find({ month: m, year: y });
    const totalGross = payrolls.reduce((s, p) => s + p.grossPay, 0);
    const totalNet = payrolls.reduce((s, p) => s + p.netPay, 0);
    const totalDeductions = payrolls.reduce((s, p) => s + p.deductions, 0);
    const paid = payrolls.filter((p) => p.status === 'paid').length;
    res.json({
      month: m,
      year: y,
      periodLabel: monthLabel(m, y),
      count: payrolls.length,
      totalGross,
      totalNet,
      totalDeductions,
      paidCount: paid,
      pendingCount: payrolls.length - paid,
    });
  } catch (err) {
    next(err);
  }
});

router.post('/generate', async (req, res, next) => {
  try {
    const month = Number(req.body.month) || new Date().getMonth() + 1;
    const year = Number(req.body.year) || new Date().getFullYear();
    const employees = await Employee.find({ status: 'active' });
    const created = [];
    const skipped = [];

    for (const emp of employees) {
      const exists = await Payroll.findOne({ employee: emp._id, month, year });
      if (exists) {
        skipped.push(emp.employeeId);
        continue;
      }
      const calc = calcPayrollFromEmployee(emp);
      const payroll = await Payroll.create({
        employee: emp._id,
        month,
        year,
        periodLabel: monthLabel(month, year),
        basic: calc.basic,
        allowances: calc.allowances,
        grossPay: calc.grossPay,
        deductions: calc.deductions,
        netPay: calc.netPay,
        breakdown: calc.breakdown,
        status: 'processed',
        processedBy: req.user._id,
      });
      created.push(payroll);
    }

    const populated = await Payroll.find({ _id: { $in: created.map((p) => p._id) } }).populate({
      path: 'employee',
      select: 'firstName lastName employeeId',
      populate: { path: 'department', select: 'name' },
    });

    res.status(201).json({
      message: `Generated ${created.length} payroll records`,
      created: populated,
      skipped,
    });
  } catch (err) {
    next(err);
  }
});

router.patch('/:id/status', async (req, res, next) => {
  try {
    const { status } = req.body;
    const update = { status };
    if (status === 'paid') update.paidAt = new Date();
    const payroll = await Payroll.findByIdAndUpdate(req.params.id, update, { new: true }).populate({
      path: 'employee',
      select: 'firstName lastName employeeId',
    });
    if (!payroll) return res.status(404).json({ message: 'Payroll not found' });
    res.json(payroll);
  } catch (err) {
    next(err);
  }
});

router.delete('/:id', async (req, res, next) => {
  try {
    const payroll = await Payroll.findById(req.params.id);
    if (!payroll) return res.status(404).json({ message: 'Not found' });
    if (payroll.status === 'paid') {
      return res.status(400).json({ message: 'Cannot delete paid payroll' });
    }
    await payroll.deleteOne();
    res.json({ message: 'Deleted' });
  } catch (err) {
    next(err);
  }
});

export default router;
