// acquisition-finance.jsx — Quitação, caixa, ROI real e helpers financeiros
window.NA = window.NA || {};
const CASHBOOK_KEY = "nau_cashbook_v1";

const COST_CATEGORY_PT = {
  mecanica: "Manutenção",
  ipva: "Imposto",
  cartorio: "Cartório",
  comissao: "Comissões pagas",
  combustivel: "Combustível",
  outros: "Outros",
};

const COST_CATEGORY_EN = {
  mecanica: "Maintenance",
  ipva: "Tax",
  cartorio: "Notary",
  comissao: "Commissions",
  combustivel: "Fuel",
  outros: "Other",
};

function parsePtDate(str) {
  if (!str || str === "—") return null;
  if (str.includes("-") && str.length >= 10) {
    const d = new Date(str + (str.length === 10 ? "T12:00:00" : ""));
    return isNaN(d.getTime()) ? null : d;
  }
  const p = String(str).split("/");
  if (p.length !== 3) return null;
  const d = new Date(`${p[2]}-${p[1]}-${p[0]}T12:00:00`);
  return isNaN(d.getTime()) ? null : d;
}

function fmtPtDate(d) {
  if (!d) return "—";
  const dt = d instanceof Date ? d : new Date(d);
  if (isNaN(dt.getTime())) return "—";
  return dt.toLocaleDateString("pt-BR");
}

function sumExtras(extras) {
  if (!extras || typeof extras !== "object") return 0;
  return Object.values(extras).reduce((s, n) => s + (Number(n) || 0), 0);
}

function getNextInstallmentDue(vehicle) {
  if (!vehicle) return null;
  if (vehicle.nextInstallmentDue) {
    const d = parsePtDate(vehicle.nextInstallmentDue);
    if (d) return d;
  }
  const acquired = parsePtDate(vehicle.acquiredOn);
  if (!acquired) return null;
  const paid = Number(vehicle.parcels?.paid || 0);
  const d = new Date(acquired);
  d.setMonth(d.getMonth() + paid + 1);
  return d;
}

function advanceDueDate(vehicle, months = 1) {
  const base = getNextInstallmentDue(vehicle) || new Date();
  const d = new Date(base);
  d.setMonth(d.getMonth() + months);
  return d.toISOString().slice(0, 10);
}

function installmentAmount(vehicle) {
  const explicit = Number(vehicle.installmentValue || 0);
  if (explicit > 0) return explicit;
  const rem = Math.max(1, Number(vehicle.parcels?.total || 0) - Number(vehicle.parcels?.paid || 0));
  return Number(vehicle.settlementValue || 0) / rem;
}

function computeRealFinance(vehicle, costs = []) {
  const costsSum = (costs || []).reduce((s, c) => s + Number(c.amount || 0), 0);
  const extrasSum = sumExtras(vehicle?.extras);
  const estimatedInvest = Number(vehicle?.investimento || 0) || (Number(vehicle?.purchasePrice || 0) + extrasSum);
  const realInvest = estimatedInvest + costsSum;
  const estimatedRoi = Number(vehicle?.roi || 0);
  const fipeHalf = Number(vehicle?.fipeMax || vehicle?.fipeMin || 0) * 0.5;
  const realLucro = fipeHalf - realInvest;
  const realRoi = realInvest > 0 ? (realLucro / realInvest) * 100 : 0;
  return {
    estimatedInvest,
    realInvest,
    estimatedRoi,
    realRoi,
    realLucro,
    costsSum,
    extrasSum,
    roiDelta: realRoi - estimatedRoi,
  };
}

function getSettlementsDueWithinDays(vehicles, days = 7) {
  const now = new Date();
  now.setHours(0, 0, 0, 0);
  const limit = new Date(now);
  limit.setDate(limit.getDate() + days);
  return (vehicles || [])
    .filter(v => {
      if (!["in_settlement", "in_stock", "overdue", "in_process"].includes(v.status)) return false;
      const paid = Number(v.parcels?.paid || 0);
      const total = Number(v.parcels?.total || 0);
      if (total > 0 && paid >= total) return false;
      const due = getNextInstallmentDue(v);
      if (!due) return false;
      const dd = new Date(due);
      dd.setHours(0, 0, 0, 0);
      return dd >= now && dd <= limit;
    })
    .sort((a, b) => getNextInstallmentDue(a) - getNextInstallmentDue(b));
}

function isPermanentArchive(vehicle, years = 2) {
  if (!vehicle || !["settled", "sold"].includes(vehicle.status)) return false;
  const ref = parsePtDate(vehicle.soldAt || vehicle.acquiredOn || vehicle.updatedAt || vehicle.createdAt);
  if (!ref) return false;
  const cutoff = new Date();
  cutoff.setFullYear(cutoff.getFullYear() - years);
  return ref < cutoff;
}

function getOldPendingDocuments(vehicles, docsByAcq = {}, days = 7) {
  const cutoff = new Date();
  cutoff.setDate(cutoff.getDate() - days);
  const rows = [];
  (vehicles || []).forEach(v => {
    const docs = docsByAcq[v.id] || docsByAcq[v.id?.toString?.()] || [];
    docs.forEach(d => {
      if (d.status && d.status !== "pending") return;
      const created = d.created_at ? new Date(d.created_at) : parsePtDate(v.acquiredOn);
      if (created && !isNaN(created.getTime()) && created <= cutoff) {
        rows.push({ vehicle: v, doc: d, ageDays: Math.floor((Date.now() - created.getTime()) / 86400000) });
      }
    });
  });
  return rows;
}

function countAcquisitionAlerts(vehicles) {
  const set = new Set();
  (vehicles || []).forEach(v => {
    if (v.status === "overdue" || (v.parcels?.overdue || 0) > 0) set.add(v.id);
  });
  getSettlementsDueWithinDays(vehicles, 7).forEach(v => set.add(v.id));
  return set.size;
}

function loadLocalCashbook() {
  try {
    const raw = localStorage.getItem(CASHBOOK_KEY);
    return raw ? JSON.parse(raw) : [];
  } catch (e) {
    return [];
  }
}

function saveLocalCashbook(entries) {
  try {
    localStorage.setItem(CASHBOOK_KEY, JSON.stringify(entries));
  } catch (e) {}
}

function normalizeCashbookRow(row) {
  if (!row) return null;
  const amount = Number(row.amount ?? row.value ?? 0);
  const type = row.entry_type || row.type || (amount >= 0 ? "in" : "out");
  const signed = type === "out" ? -Math.abs(amount) : Math.abs(amount);
  const dateRaw = row.entry_date || row.date;
  return {
    id: row.id,
    date: typeof dateRaw === "string" && dateRaw.includes("/") ? dateRaw : fmtPtDate(dateRaw),
    type,
    cat: row.category || row.cat || "—",
    desc: row.description || row.desc || "",
    value: signed,
    origin: row.origin || "manual",
    acquisitionId: row.acquisition_id || row.acquisitionId || null,
    sourceRef: row.source_ref || row.sourceRef || null,
  };
}

const Cashbook = {
  listEntries() {
    const db = window.NA.db;
    if (db?.listCashbookEntries) {
      return db.listCashbookEntries().then(rows => (rows || []).map(normalizeCashbookRow));
    }
    return Promise.resolve(loadLocalCashbook().map(normalizeCashbookRow));
  },

  listEntriesSync() {
    return loadLocalCashbook().map(normalizeCashbookRow);
  },

  async addEntry(entry) {
    const db = window.NA.db;
    if (db?.addCashbookEntry) {
      const row = await db.addCashbookEntry(entry);
      window.dispatchEvent(new Event("na:cashbook-changed"));
      return normalizeCashbookRow(row);
    }
    const local = loadLocalCashbook();
    const amount = Number(entry.amount || 0);
    const type = entry.type || entry.entryType || (amount >= 0 ? "in" : "out");
    const item = normalizeCashbookRow({
      id: "cb_" + Date.now() + "_" + Math.random().toString(36).slice(2, 6),
      entry_date: entry.entryDate || new Date().toISOString().slice(0, 10),
      entry_type: type,
      category: entry.category,
      description: entry.description,
      amount: type === "out" ? -Math.abs(amount) : Math.abs(amount),
      origin: entry.origin || "manual",
      acquisition_id: entry.acquisitionId || null,
      source_ref: entry.sourceRef || null,
    });
    local.unshift(item);
    saveLocalCashbook(local);
    window.dispatchEvent(new Event("na:cashbook-changed"));
    return item;
  },

  totals(entries) {
    const list = entries || loadLocalCashbook().map(normalizeCashbookRow);
    const totalIn = list.filter(e => e.value > 0).reduce((s, e) => s + e.value, 0);
    const totalOut = list.filter(e => e.value < 0).reduce((s, e) => s + e.value, 0);
    return { totalIn, totalOut, net: totalIn + totalOut, autoCount: list.filter(e => e.origin === "auto").length };
  },
};

const AcquisitionFinance = {
  COST_CATEGORY_PT,
  COST_CATEGORY_EN,
  parsePtDate,
  fmtPtDate,
  sumExtras,
  getNextInstallmentDue,
  advanceDueDate,
  installmentAmount,
  computeRealFinance,
  getSettlementsDueWithinDays,
  getOldPendingDocuments,
  isPermanentArchive,
  countAcquisitionAlerts,
  costCategoryLabel(type, lang) {
    const map = lang === "en" ? COST_CATEGORY_EN : COST_CATEGORY_PT;
    return map[type] || type;
  },

  vehicleLabel(v) {
    return `${v.brand || ""} ${v.model || ""} — ${v.plate || ""}`.trim();
  },

  async registerInstallmentPayment(acquisitionId, lang) {
    const db = window.NA.db;
    if (!db?.registerInstallmentPayment) throw new Error("Integração financeira indisponível");
    return db.registerInstallmentPayment(acquisitionId, lang);
  },

  async registerSale(acquisitionId, salePrice, soldBy, lang) {
    const db = window.NA.db;
    if (!db?.registerAcquisitionSale) throw new Error("Integração financeira indisponível");
    return db.registerAcquisitionSale(acquisitionId, salePrice, soldBy, lang);
  },

  async recalculateFinance(acquisitionId) {
    const db = window.NA.db;
    if (!db?.recalculateAcquisitionFinance) return null;
    return db.recalculateAcquisitionFinance(acquisitionId);
  },
};

window.NA.Cashbook = Cashbook;
window.NA.AcquisitionFinance = AcquisitionFinance;
