const { all, audit, now, one, run } = require('../db');
const { money } = require('../depreciation');

const FREQUENCIES = { monthly: 12, quarterly: 4, semiannual: 2, annual: 1 };

function periodsPerYear(frequency) {
  return FREQUENCIES[frequency] || 12;
}

function addMonths(date, count) {
  const next = new Date(date.getTime());
  next.setMonth(next.getMonth() + count);
  return next;
}

function listLeases(query = {}) {
  return all(
    `SELECT l.*, a.asset_id AS asset_code, a.description AS asset_description
     FROM leases l
     LEFT JOIN assets a ON a.id = l.asset_id
     WHERE (? IS NULL OR l.asset_id = ?)
     ORDER BY l.start_date DESC, l.id DESC`,
    [query.asset_id || null, query.asset_id || null]
  );
}

function getLease(id) {
  return one('SELECT * FROM leases WHERE id = ?', [id]);
}

function createLease(input, userId) {
  const timestamp = now();
  const result = run(
    `INSERT INTO leases (asset_id, lessor, contract_value, start_date, end_date, discount_rate, payment_frequency, notes, created_at, updated_at)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      input.asset_id || null,
      input.lessor || null,
      Number(input.contract_value || 0),
      input.start_date || null,
      input.end_date || null,
      Number(input.discount_rate || 0),
      input.payment_frequency || 'monthly',
      input.notes || null,
      timestamp,
      timestamp
    ]
  );
  audit(userId, 'create', 'lease', result.lastInsertRowid, null, input);
  return getLease(result.lastInsertRowid);
}

function updateLease(id, input, userId) {
  const before = getLease(id);
  if (!before) return null;
  run(
    `UPDATE leases SET
      lessor = ?, contract_value = ?, start_date = ?, end_date = ?, discount_rate = ?,
      payment_frequency = ?, notes = ?, updated_at = ?
     WHERE id = ?`,
    [
      input.lessor ?? before.lessor,
      Number(input.contract_value ?? before.contract_value),
      input.start_date ?? before.start_date,
      input.end_date ?? before.end_date,
      Number(input.discount_rate ?? before.discount_rate),
      input.payment_frequency ?? before.payment_frequency,
      input.notes ?? before.notes,
      now(),
      id
    ]
  );
  audit(userId, 'update', 'lease', id, before, input);
  return getLease(id);
}

function deleteLease(id, userId) {
  const before = getLease(id);
  if (!before) return false;
  run('DELETE FROM leases WHERE id = ?', [id]);
  audit(userId, 'delete', 'lease', id, before, null);
  return true;
}

// Straight-line ROU amortization with an ASC 842-style liability schedule.
function leaseSchedule(lease) {
  if (!lease) return null;
  const ppy = periodsPerYear(lease.payment_frequency);
  const monthsPerPeriod = 12 / ppy;
  const start = lease.start_date ? new Date(`${lease.start_date}T00:00:00`) : new Date();
  const end = lease.end_date ? new Date(`${lease.end_date}T00:00:00`) : addMonths(start, 12);

  const totalMonths = Math.max(monthsPerPeriod, (end.getFullYear() - start.getFullYear()) * 12 + (end.getMonth() - start.getMonth()));
  const periods = Math.max(1, Math.round(totalMonths / monthsPerPeriod));

  const contractValue = Number(lease.contract_value || 0);
  const payment = contractValue / periods;
  const rate = Number(lease.discount_rate || 0) / 100 / ppy;
  const presentValue = rate > 0 ? payment * (1 - (1 + rate) ** -periods) / rate : contractValue;

  const rouAmortization = presentValue / periods;
  let liability = presentValue;
  let rouBalance = presentValue;
  let totalInterest = 0;
  const rows = [];

  for (let period = 1; period <= periods; period += 1) {
    const interest = liability * rate;
    const principal = payment - interest;
    liability = Math.max(0, liability - principal);
    rouBalance = Math.max(0, rouBalance - rouAmortization);
    totalInterest += interest;
    rows.push({
      period,
      date: addMonths(start, period * monthsPerPeriod).toISOString().slice(0, 10),
      payment: money(payment),
      interest: money(interest),
      principal: money(principal),
      liability_balance: money(liability),
      rou_amortization: money(rouAmortization),
      rou_balance: money(rouBalance)
    });
  }

  return {
    summary: {
      periods,
      frequency: lease.payment_frequency,
      periodic_payment: money(payment),
      present_value: money(presentValue),
      total_payments: money(payment * periods),
      total_interest: money(totalInterest)
    },
    rows
  };
}

module.exports = {
  FREQUENCIES,
  createLease,
  deleteLease,
  getLease,
  leaseSchedule,
  listLeases,
  updateLease
};
