const router = require('express').Router();
const { salaryDb, messagesDb, usersDb, uuidv4 } = require('../lib/db');
const { authMiddleware, adminOnly } = require('../lib/auth');

function nowTime() {
  return new Date().toLocaleTimeString('en-IN',{hour:'2-digit',minute:'2-digit',hour12:true});
}
function todayStr() { return new Date().toISOString().slice(0,10); }
function fmtINR(v) { return '₹ ' + Math.round(v).toLocaleString('en-IN'); }

// GET /api/salary
router.get('/', authMiddleware, (req, res) => {
  const all = salaryDb.get('slips').value();
  if (req.user.role === 'admin') return res.json(all);
  res.json(all.filter(s => s.empId === req.user.empId));
});

// GET /api/salary/:id
router.get('/:id', authMiddleware, (req, res) => {
  const slip = salaryDb.get('slips').find({ id: req.params.id }).value();
  if (!slip) return res.status(404).json({ error: 'Not found' });
  if (req.user.role !== 'admin' && slip.empId !== req.user.empId)
    return res.status(403).json({ error: 'Forbidden' });
  res.json(slip);
});

// POST /api/salary  (admin creates slip) — supports both old LPA style and new direct fields
router.post('/', authMiddleware, adminOnly, (req, res) => {
  const {
    empId,
    // New direct fields from updated UI
    ctc, basic, hra, conveyance, medical, special, gross,
    pfAmt, pfDed, ptAmt, ptDed, leaveDed, totalDed, net,
    // Old LPA-based fields (fallback)
    lpa,
    periodFrom, periodTo, notes
  } = req.body;

  if (!empId) return res.status(400).json({ error: 'empId required' });
  if (!ctc && !lpa) return res.status(400).json({ error: 'CTC or LPA required' });

  const emp = usersDb.get('users').find({ empId: empId.toUpperCase() }).value();
  if (!emp) return res.status(404).json({ error: 'Employee not found' });

  // Use pre-calculated values from frontend if provided, else calculate from LPA
  let slipBasic, slipHra, slipConveyance, slipMedical, slipSpecial, slipGross;
  let slipPfDed, slipPtDed, slipLeaveDed, slipTotalDed, slipNet;
  let slipCtc, slipLpa;

  if (ctc) {
    // New UI: all values sent directly from frontend
    slipCtc    = parseFloat(ctc) || 0;
    slipLpa    = slipCtc / 100000;
    slipBasic  = parseFloat(basic) || (slipCtc / 12 * 0.4);
    slipHra    = parseFloat(hra) || (slipCtc / 12 * 0.2);
    slipConveyance = parseFloat(conveyance) || 0;
    slipMedical    = parseFloat(medical) || 0;
    slipSpecial    = parseFloat(special) || 0;
    slipGross  = parseFloat(gross) || (slipBasic + slipHra + slipConveyance + slipMedical + slipSpecial);
    slipPfDed  = parseFloat(pfAmt || pfDed) || 0;
    slipPtDed  = parseFloat(ptAmt || ptDed) || 0;
    slipLeaveDed   = parseFloat(leaveDed) || 0;
    slipTotalDed   = parseFloat(totalDed) || (slipPfDed + slipPtDed + slipLeaveDed);
    slipNet    = parseFloat(net) || (slipGross - slipTotalDed);
  } else {
    // Old LPA style fallback
    slipLpa    = parseFloat(lpa);
    slipCtc    = slipLpa * 100000;
    const monthly = slipCtc / 12;
    slipBasic  = monthly * 0.40;
    slipHra    = monthly * 0.20;
    slipConveyance = monthly * 0.05;
    slipMedical    = 0;
    slipSpecial    = parseFloat(special) || 0;
    slipGross  = slipBasic + slipHra + slipConveyance + slipMedical + slipSpecial;
    slipPfDed  = parseFloat(pfDed) || 0;
    slipPtDed  = parseFloat(ptDed) || 0;
    slipLeaveDed   = parseFloat(leaveDed) || 0;
    slipTotalDed   = slipPfDed + slipPtDed + slipLeaveDed;
    slipNet    = slipGross - slipTotalDed;
  }

  const slip = {
    id: uuidv4(),
    empId: empId.toUpperCase(),
    empName: emp.name,
    dept: emp.dept,
    pos: emp.pos || '',
    ctc: Math.round(slipCtc),
    lpa: parseFloat(slipLpa.toFixed(2)),
    basic: Math.round(slipBasic),
    hra: Math.round(slipHra),
    conveyance: Math.round(slipConveyance),
    medical: Math.round(slipMedical),
    special: Math.round(slipSpecial),
    gross: Math.round(slipGross),
    pfDed: Math.round(slipPfDed),
    pfAmt: Math.round(slipPfDed),
    ptDed: Math.round(slipPtDed),
    ptAmt: Math.round(slipPtDed),
    leaveDed: Math.round(slipLeaveDed),
    // Legacy fields set to 0 (old schema compatibility)
    esiDed: 0,
    tdsDed: 0,
    trans: Math.round(slipConveyance),
    totalDed: Math.round(slipTotalDed),
    net: Math.round(slipNet),
    periodFrom: periodFrom || '',
    periodTo: periodTo || '',
    notes: notes || '',
    notified: false,
    savedAt: new Date().toISOString()
  };

  salaryDb.get('slips').push(slip).write();
  res.status(201).json(slip);
});

// PUT /api/salary/:id  (admin updates)
router.put('/:id', authMiddleware, adminOnly, (req, res) => {
  const existing = salaryDb.get('slips').find({ id: req.params.id }).value();
  if (!existing) return res.status(404).json({ error: 'Not found' });

  const {
    ctc, basic, hra, conveyance, medical, special, gross,
    pfAmt, pfDed, ptAmt, ptDed, leaveDed, totalDed, net,
    lpa, periodFrom, periodTo, notes
  } = req.body;

  // Recalculate if new-style fields sent
  let updateData = { ...req.body };

  if (ctc) {
    const slipCtc    = parseFloat(ctc) || 0;
    const slipLpa    = slipCtc / 100000;
    const slipBasic  = parseFloat(basic) || (slipCtc / 12 * 0.4);
    const slipHra    = parseFloat(hra) || (slipCtc / 12 * 0.2);
    const slipConveyance = parseFloat(conveyance) || 0;
    const slipMedical    = parseFloat(medical) || 0;
    const slipSpecial    = parseFloat(special) || 0;
    const slipGross  = parseFloat(gross) || (slipBasic + slipHra + slipConveyance + slipMedical + slipSpecial);
    const slipPfDed  = parseFloat(pfAmt || pfDed) || 0;
    const slipPtDed  = parseFloat(ptAmt || ptDed) || 0;
    const slipLeaveDed   = parseFloat(leaveDed) || 0;
    const slipTotalDed   = parseFloat(totalDed) || (slipPfDed + slipPtDed + slipLeaveDed);
    const slipNet    = parseFloat(net) || (slipGross - slipTotalDed);

    updateData = {
      ctc: Math.round(slipCtc),
      lpa: parseFloat(slipLpa.toFixed(2)),
      basic: Math.round(slipBasic),
      hra: Math.round(slipHra),
      conveyance: Math.round(slipConveyance),
      trans: Math.round(slipConveyance),
      medical: Math.round(slipMedical),
      special: Math.round(slipSpecial),
      gross: Math.round(slipGross),
      pfDed: Math.round(slipPfDed),
      pfAmt: Math.round(slipPfDed),
      ptDed: Math.round(slipPtDed),
      ptAmt: Math.round(slipPtDed),
      leaveDed: Math.round(slipLeaveDed),
      esiDed: 0,
      tdsDed: 0,
      totalDed: Math.round(slipTotalDed),
      net: Math.round(slipNet),
      periodFrom: periodFrom || existing.periodFrom,
      periodTo: periodTo || existing.periodTo,
      notes: notes !== undefined ? notes : existing.notes
    };
  }

  salaryDb.get('slips').find({ id: req.params.id }).assign(updateData).write();
  res.json(salaryDb.get('slips').find({ id: req.params.id }).value());
});

// POST /api/salary/:id/notify  (admin notifies employee)
router.post('/:id/notify', authMiddleware, adminOnly, (req, res) => {
  const slip = salaryDb.get('slips').find({ id: req.params.id }).value();
  if (!slip) return res.status(404).json({ error: 'Slip not found' });

  const msg = {
    id: uuidv4(), from: 'ADMIN',
    text: `💰 Your salary slip for ${slip.periodFrom} to ${slip.periodTo} is ready. Net Pay: ${fmtINR(slip.net)}.`,
    time: nowTime(), date: todayStr(), createdAt: new Date().toISOString()
  };
  const thread = messagesDb.get('threads').find({ empId: slip.empId }).value();
  if (thread) {
    messagesDb.get('threads').find({ empId: slip.empId }).get('messages').push(msg).write();
  } else {
    messagesDb.get('threads').push({ empId: slip.empId, messages: [msg] }).write();
  }
  salaryDb.get('slips').find({ id: req.params.id }).assign({ notified: true }).write();
  res.json({ message: 'Notification sent' });
});

// DELETE /api/salary/:id
router.delete('/:id', authMiddleware, adminOnly, (req, res) => {
  salaryDb.get('slips').remove({ id: req.params.id }).write();
  res.json({ message: 'Deleted' });
});

module.exports = router;
