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

// IRS Pub 946 mid-quarter convention determination. The mid-quarter convention is MANDATORY for all of a
// tax year's MACRS personal property when more than 40% of the aggregate depreciable basis of such
// property is placed in service during the last three months (Q4) of the year. This is a portfolio- and
// year-level fact, computed here once per (company, book, year) and consulted by the depreciation engine
// (depreciation.conventionFor). Real property (mid-month) is excluded. Cached; invalidated on asset writes.

const cache = new Map(); // `${entityId}|${bookCode}|${year}` -> boolean

function clearCache() {
  cache.clear();
}

function bookObject(row, bookCode) {
  return {
    book_type: bookCode,
    cost: row.book_cost,
    depreciation_method: row.depreciation_method,
    convention: row.convention,
    useful_life_months: row.book_life,
    section_179_amount: row.section_179_amount,
    bonus_percent: row.bonus_percent,
    business_use_percent: row.book_bup,
    investment_use_percent: row.book_ivp,
    manual_depreciation: row.manual_depreciation
  };
}

// True when the mid-quarter convention applies to (company, book) MACRS personal property placed in
// service in `year`. No-op-friendly: returns false when the portfolio doesn't trip the 40% threshold.
function applies(entityId, bookCode, year) {
  if (!entityId || !bookCode || !year) return false;
  const key = `${entityId}|${bookCode}|${Number(year)}`;
  if (cache.has(key)) return cache.get(key);

  const dep = require('../depreciation');
  const { ruleSetForBook } = require('./ruleSets');
  const { assetFromRow } = require('./assets');
  const ruleSet = ruleSetForBook(bookCode);
  const rows = all(
    `SELECT a.*, b.cost AS book_cost, b.depreciation_method, b.convention, b.useful_life_months AS book_life,
       b.section_179_amount, b.bonus_percent, b.business_use_percent AS book_bup, b.investment_use_percent AS book_ivp, b.manual_depreciation
     FROM assets a JOIN asset_books b ON b.asset_id = a.id
     WHERE b.book_type = ? AND b.active = 1 AND a.entity_id = ? AND a.status != 'disposed'`,
    [bookCode, entityId]
  );

  let total = 0;
  let lastQuarter = 0;
  for (const row of rows) {
    const pis = row.in_service_date || row.acquired_date;
    if (!pis || dep.yearFromDate(pis) !== Number(year)) continue;
    const book = bookObject(row, bookCode);
    const methodRule = dep.getMethodRule(ruleSet, book.depreciation_method);
    if (!dep.isMidQuarterEligible(book, methodRule)) continue;
    const basis = dep.midQuarterBasis(assetFromRow(row), book);
    if (basis <= 0) continue;
    total += basis;
    if (Math.ceil(dep.monthFromDate(pis) / 3) === 4) lastQuarter += basis;
  }

  const result = total > 0 && lastQuarter / total > 0.4;
  cache.set(key, result);
  return result;
}

module.exports = { applies, clearCache };
