const { getSetting } = require('../db/database');

/**
 * Resolves the due date for a bill in a given year/month.
 * Bills use a recurring day-of-month template field. Legacy override_due_date
 * values are intentionally ignored by the current product behavior.
 */
function resolveDueDate(bill, year, month) {
  const daysInMonth = new Date(year, month, 0).getDate();
  const day = Math.min(bill.due_day, daysInMonth);
  return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
}

/**
 * Auto-assigns bucket from due_day: 1–14 → '1st', 15+ → '15th'
 */
function resolveBucket(bill) {
  if (bill.bucket) return bill.bucket;
  return bill.due_day <= 14 ? '1st' : '15th';
}

/**
 * Computes the payment cycle start/end for a bill in a given month.
 * For monthly bills the cycle is the calendar month.
 */
function getCycleRange(year, month) {
  const start = `${year}-${String(month).padStart(2, '0')}-01`;
  const daysInMonth = new Date(year, month, 0).getDate();
  const end = `${year}-${String(month).padStart(2, '0')}-${String(daysInMonth).padStart(2, '0')}`;
  return { start, end };
}

/**
 * Returns status for a bill given its payments and due date.
 *
 * Statuses:
 *  paid       — total payments >= expected_amount
 *  autodraft  — autopay_enabled and assumed_paid (no confirmed payment yet)
 *  upcoming   — due_date in the future
 *  due_soon   — due within 3 days
 *  late       — past due, within grace period
 *  missed     — past grace period, unpaid
 */
function calculateStatus(bill, payments, dueDate, today) {
  const gracePeriodDays = parseInt(getSetting('grace_period_days') || '5', 10);
  const totalPaid = payments.reduce((sum, p) => sum + p.amount, 0);
  const isPaid = totalPaid >= bill.expected_amount;

  if (isPaid) return 'paid';

  if (bill.autopay_enabled && bill.autodraft_status === 'assumed_paid') {
    return 'autodraft';
  }

  const due = new Date(dueDate + 'T00:00:00');
  const todayDate = new Date(today + 'T00:00:00');
  const diffDays = Math.floor((due - todayDate) / 86400000);

  if (diffDays > 3) return 'upcoming';
  if (diffDays >= 0) return 'due_soon';
  if (Math.abs(diffDays) <= gracePeriodDays) return 'late';
  return 'missed';
}

/**
 * Builds a full tracker row for a bill in a given month.
 */
function buildTrackerRow(bill, payments, year, month, todayStr) {
  const dueDate = resolveDueDate(bill, year, month);
  const bucket = resolveBucket(bill);
  const status = calculateStatus(bill, payments, dueDate, todayStr);
  const totalPaid = payments.reduce((sum, p) => sum + p.amount, 0);
  const lastPayment = payments.length
    ? payments.sort((a, b) => b.paid_date.localeCompare(a.paid_date))[0]
    : null;

  return {
    id: bill.id,
    name: bill.name,
    category_id: bill.category_id,
    category_name: bill.category_name || null,
    due_date: dueDate,
    due_day: bill.due_day,
    bucket,
    expected_amount: bill.expected_amount,
    total_paid: totalPaid,
    balance: bill.expected_amount - totalPaid,
    last_paid_date: lastPayment ? lastPayment.paid_date : null,
    last_payment_amount: lastPayment ? lastPayment.amount : null,
    status,
    autopay_enabled: !!bill.autopay_enabled,
    autodraft_status: bill.autodraft_status,
    billing_cycle: bill.billing_cycle,
    payments,
  };
}

module.exports = { resolveDueDate, resolveBucket, getCycleRange, calculateStatus, buildTrackerRow };
