/**
 * ImmoBelRent — Moteur de Calcul Financier
 * Basé sur la législation fiscale belge 2024
 */

export interface CalcInputs {
  prixAchat: number;
  loyer: number;           // mensuel
  rc: number;              // Revenu Cadastral
  surface: number;         // m²
  centimes: number;        // centimes additionnels commune
  fraisNotaire: number;    // % du prix (12.5% ancien, 1-3% neuf)
  travaux?: number;        // travaux de rénovation
  credit?: number;         // mensualité crédit
}

export interface CalcResults {
  invest: number;          // prix de revient total
  brutAn: number;          // loyer annuel brut
  rentBrut: number;        // rendement brut %
  rentNetIPP: number;      // rendement net IPP %
  rentNetIsoc: number;     // rendement net ISoc %
  impotIPP: number;        // impôt annuel IPP
  impotIsoc: number;       // impôt annuel ISoc
  chargesTotal: number;    // charges annuelles totales
  precompte: number;       // précompte immobilier annuel
  cashflow: number;        // cashflow mensuel
  drb: number;             // délai remboursement brut (années)
  netIPP: number;          // revenu net annuel IPP
  netIsoc: number;         // revenu net annuel ISoc
  gainIsoc: number;        // gain ISoc vs IPP
}

export function calcFinancials(f: CalcInputs): CalcResults {
  const invest = f.prixAchat * (1 + f.fraisNotaire / 100) + (f.travaux || 0);
  const brutAn = f.loyer * 12;
  const rentBrut = invest > 0 ? (brutAn / invest) * 100 : 0;

  // Précompte immobilier = RC × (centimes additionnels / 100)
  const precompte = f.rc * (f.centimes / 100);

  // Charges annuelles réelles estimées
  const syndic    = f.surface * 1.2 * 12;    // ~1.2€/m²/mois
  const assurance = invest * 0.002;            // 0.2% valeur bien
  const entretien = invest * 0.004;            // 0.4% valeur bien
  const chargesTotal = syndic + assurance + entretien + precompte;

  // ── IPP (personne physique) ──────────────────────────────────────────────
  // Base imposable = RC × 1.4 (coefficient indexation) × (1 − 40% forfait charges)
  // Art. 14 CIR92 : déduction forfaitaire de 40% pour habitations données en location
  const rcImpute = f.rc * 1.4;         // indexation coefficient 2024
  const baseIPP  = rcImpute * 0.60;    // − 40% forfait
  const impotIPP = baseIPP * 0.45;     // taux marginal moyen (tranche 26 830–46 440 €)
  const netIPP   = brutAn - chargesTotal - impotIPP;
  const rentNetIPP = invest > 0 ? (netIPP / invest) * 100 : 0;

  // ── ISoc (société — taux normal 25%) ─────────────────────────────────────
  // Base = loyer réel − 30% charges forfaitaires − amortissements 3%/an
  const amort       = f.prixAchat * 0.03;
  const chargesIsoc = brutAn * 0.30 + amort;
  const baseIsoc    = Math.max(brutAn - chargesIsoc, 0);
  const impotIsoc   = baseIsoc * 0.25;
  const netIsoc     = brutAn - brutAn * 0.30 - impotIsoc;
  const rentNetIsoc = invest > 0 ? (netIsoc / invest) * 100 : 0;

  const cashflow = f.loyer - (f.credit || 0) - chargesTotal / 12 - impotIPP / 12;
  const drb = brutAn > 0 ? invest / brutAn : 0;

  return {
    invest:       Math.round(invest),
    brutAn:       Math.round(brutAn),
    rentBrut:     +rentBrut.toFixed(2),
    rentNetIPP:   +rentNetIPP.toFixed(2),
    rentNetIsoc:  +rentNetIsoc.toFixed(2),
    impotIPP:     Math.round(impotIPP),
    impotIsoc:    Math.round(impotIsoc),
    chargesTotal: Math.round(chargesTotal),
    precompte:    Math.round(precompte),
    cashflow:     Math.round(cashflow),
    drb:          +drb.toFixed(1),
    netIPP:       Math.round(netIPP),
    netIsoc:      Math.round(netIsoc),
    gainIsoc:     Math.round(netIsoc - netIPP),
  };
}

// Barèmes IPP 2024 (revenus nets imposables)
export const IPP_BRACKETS = [
  { max: 15200,  rate: 0.25 },
  { max: 26830,  rate: 0.40 },
  { max: 46440,  rate: 0.45 },
  { max: Infinity, rate: 0.50 },
];

export function calcIPP(baseImposable: number): number {
  let impot = 0;
  let prev  = 0;
  for (const bracket of IPP_BRACKETS) {
    if (baseImposable <= prev) break;
    const tranche = Math.min(baseImposable, bracket.max) - prev;
    impot += tranche * bracket.rate;
    prev = bracket.max;
  }
  return Math.round(impot);
}
