const express = require('express');
const router  = express.Router();
const { getDb } = require('../db/database');
const { buildTrackerRow, getCycleRange, resolveDueDate } = require('../services/statusService');

// GET /api/tracker?year=2026&month=5
router.get('/', (req, res) => {
  const db = getDb();
  const now   = new Date();
  const year  = parseInt(req.query.year  || now.getFullYear(),    10);
  const month = parseInt(req.query.month || now.getMonth() + 1,   10);

  if (isNaN(year) || year < 2000 || year > 2100)
    return res.status(400).json({ error: 'year must be a 4-digit integer between 2000 and 2100' });
  if (isNaN(month) || month < 1 || month > 12)
    return res.status(400).json({ error: 'month must be an integer between 1 and 12' });

  const todayStr = now.toISOString().slice(0, 10);

  const { start, end } = getCycleRange(year, month);

  const bills = db.prepare(`
    SELECT b.*, c.name AS category_name
    FROM bills b
    LEFT JOIN categories c ON b.category_id = c.id
    WHERE b.active = 1 AND b.user_id = ?
    ORDER BY b.due_day ASC, b.name ASC
  `).all(req.user.id);

  const mbsStmt = db.prepare(
    'SELECT actual_amount, notes, is_skipped FROM monthly_bill_state WHERE bill_id=? AND year=? AND month=?'
  );

  const rows = bills.map(bill => {
    // Only count non-deleted payments for status/totals
    const payments = db.prepare(`
      SELECT * FROM payments
      WHERE bill_id = ? AND paid_date BETWEEN ? AND ?
        AND deleted_at IS NULL
      ORDER BY paid_date DESC
    `).all(bill.id, start, end);

    const row = buildTrackerRow(bill, payments, year, month, todayStr);

    // Overlay monthly state overrides
    const mbs = mbsStmt.get(bill.id, year, month);
    row.actual_amount  = mbs?.actual_amount  ?? null;
    row.monthly_notes  = mbs?.notes          ?? null;
    row.is_skipped     = !!(mbs?.is_skipped);

    return row;
  });

  const totalExpected = rows.reduce((s, r) => s + r.expected_amount, 0);
  const totalPaid     = rows.reduce((s, r) => s + r.total_paid,      0);
  const totalOverdue  = rows
    .filter(r => !r.is_skipped && (r.status === 'late' || r.status === 'missed'))
    .reduce((s, r) => s + r.balance, 0);

  const activeRows = rows.filter(r => !r.is_skipped);

  res.json({
    year, month, today: todayStr,
    summary: {
      total_expected:  activeRows.reduce((s, r) => s + r.expected_amount, 0),
      total_paid:      activeRows.reduce((s, r) => s + r.total_paid,      0),
      remaining:       Math.max(0, activeRows.reduce((s, r) => s + r.expected_amount, 0) - activeRows.reduce((s, r) => s + r.total_paid, 0)),
      overdue:         totalOverdue,
      count_paid:      activeRows.filter(r => r.status === 'paid').length,
      count_upcoming:  activeRows.filter(r => r.status === 'upcoming' || r.status === 'due_soon').length,
      count_late:      activeRows.filter(r => r.status === 'late' || r.status === 'missed').length,
      count_autodraft: activeRows.filter(r => r.status === 'autodraft').length,
    },
    rows,
  });
});

// GET /api/tracker/upcoming?days=30
// Returns active bills with a due date in the next N days, sorted by due_date asc.
router.get('/upcoming', (req, res) => {
  const db   = getDb();
  const days = Math.min(parseInt(req.query.days || '30', 10), 365);
  const now  = new Date();
  const todayStr = now.toISOString().slice(0, 10);

  const year  = now.getFullYear();
  const month = now.getMonth() + 1;
  const { start, end } = getCycleRange(year, month);

  const bills = db.prepare(`
    SELECT b.*, c.name AS category_name
    FROM bills b
    LEFT JOIN categories c ON b.category_id = c.id
    WHERE b.active = 1 AND b.user_id = ?
  `).all(req.user.id);

  const cutoff = new Date(now);
  cutoff.setDate(cutoff.getDate() + days);
  const cutoffStr = cutoff.toISOString().slice(0, 10);

  const upcoming = [];

  for (const bill of bills) {
    const dueDate = resolveDueDate(bill, year, month);
    if (dueDate < todayStr || dueDate > cutoffStr) continue;

    const payments = db.prepare(`
      SELECT * FROM payments
      WHERE bill_id = ? AND paid_date BETWEEN ? AND ?
        AND deleted_at IS NULL
      ORDER BY paid_date DESC
    `).all(bill.id, start, end);

    const row = buildTrackerRow(bill, payments, year, month, todayStr);
    if (row.status === 'paid') continue; // skip already paid

    upcoming.push({
      id:              bill.id,
      name:            bill.name,
      category_name:   bill.category_name,
      due_date:        dueDate,
      expected_amount: bill.expected_amount,
      status:          row.status,
      days_until_due:  Math.floor((new Date(dueDate) - now) / 86400000),
    });
  }

  upcoming.sort((a, b) => a.due_date.localeCompare(b.due_date));
  res.json({ days, today: todayStr, upcoming });
});

module.exports = router;
