import { Router } from 'express';
import db from '../db/index.js';

const router = Router();

/**
 * GET /api/dashboard
 *
 * ?scope=all  → agrège tous les investisseurs de l'utilisateur
 * (défaut)    → filtre sur l'investisseur donné par X-Investisseur-Id
 */
router.get('/', (req, res) => {
  const scopeAll = req.query.scope === 'all';
  const userId   = req.user.id;

  /* ── Résolution de l'investisseur cible ─────────────────────── */
  let invWhere, invParams, invId;

  if (scopeAll) {
    invWhere  = 'investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?)';
    invParams = [userId];
  } else {
    const raw = req.header('X-Investisseur-Id');
    invId = Number(raw);
    if (!invId) return res.status(400).json({ error: 'Missing investisseur id (header X-Investisseur-Id)' });
    const row = db.prepare('SELECT id FROM investisseurs WHERE id = ? AND user_id = ?').get(invId, userId);
    if (!row) return res.status(403).json({ error: 'Investisseur not found or not owned by user' });
    invWhere  = 'investisseur_id = ?';
    invParams = [invId];
  }

  /* ── Cash global ─────────────────────────────────────────────── */
  const cash = db.prepare(`
    SELECT
      COALESCE(SUM(CASE WHEN type='depot'   THEN montant END),0) AS total_depots,
      COALESCE(SUM(CASE WHEN type='retrait' THEN montant END),0) AS total_retraits
    FROM depots_retraits WHERE ${invWhere}
  `).get(...invParams);

  /* ── Cash par plateforme ─────────────────────────────────────── */
  const cashByPlatform = db.prepare(`
    SELECT p.id AS plateforme_id, p.nom,
      plat_inv.nom AS detenteur_nom,
      COALESCE(SUM(CASE WHEN dr.type='depot'   THEN dr.montant END),0) AS depots,
      COALESCE(SUM(CASE WHEN dr.type='retrait' THEN dr.montant END),0) AS retraits,
      COALESCE(SUM(CASE WHEN dr.type='depot'   THEN dr.montant
                        WHEN dr.type='retrait' THEN -dr.montant END),0) AS solde_net
    FROM plateformes p
    LEFT JOIN investisseurs plat_inv ON plat_inv.id = p.investisseur_id
    LEFT JOIN depots_retraits dr ON dr.plateforme_id = p.id AND ${invWhere.replace('investisseur_id', 'dr.investisseur_id')}
    WHERE p.user_id = ?
    GROUP BY p.id, p.nom, plat_inv.nom
    ORDER BY p.nom
  `).all(...invParams, userId);

  /* ── Solde porte-monnaie par plateforme ──────────────────────── */
  const drManuelPerPlat = db.prepare(`
    SELECT plateforme_id,
      COALESCE(SUM(CASE WHEN type='depot' THEN montant ELSE 0 END), 0) AS depots,
      COALESCE(SUM(CASE WHEN type='retrait' AND COALESCE(source,'') != 'auto_remboursement'
                        THEN montant ELSE 0 END), 0) AS retraits_manuels
    FROM depots_retraits
    WHERE ${invWhere}
    GROUP BY plateforme_id
  `).all(...invParams);

  const rembWalletPerPlat = db.prepare(`
    SELECT i.plateforme_id,
      COALESCE(SUM(
        CASE p.fiscalite
          WHEN 'flat_tax' THEN r.net_recu
          -- Plateformes hors France : pas de PFU prélevé à la source.
          -- interets_bruts est déjà net de la retenue locale si applicable.
          ELSE r.capital + r.cashback + r.interets_bruts
        END
      ), 0) AS remb_wallet
    FROM remboursements r
    JOIN investissements i ON i.id = r.investissement_id
    JOIN plateformes p ON p.id = i.plateforme_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND r.type = 'normal'
      AND r.methode_remboursement = 'portefeuille'
    GROUP BY i.plateforme_id
  `).all(...invParams);

  const bonusWalletPerPlat = db.prepare(`
    SELECT bonus_plateforme_id AS plateforme_id,
      COALESCE(SUM(cashback), 0) AS bonus_wallet
    FROM remboursements
    WHERE ${invWhere.replace('investisseur_id', 'bonus_investisseur_id')}
      AND type IN ('bonus_parrainage', 'bonus_plateforme')
    GROUP BY bonus_plateforme_id
  `).all(...invParams);

  const capitalInvestiPerPlat = db.prepare(`
    SELECT i.plateforme_id,
      COALESCE(SUM(
        i.montant_investi
        + COALESCE((SELECT SUM(rv.montant) FROM reinvestissements rv WHERE rv.investissement_id = i.id), 0)
      ), 0) AS capital_investi
    FROM investissements i
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
    GROUP BY i.plateforme_id
  `).all(...invParams);

  // Corrections de solde (micro-ecarts fiscaux sur plateformes flat_tax)
  const correctionsPerPlat = db.prepare(`
    SELECT plateforme_id,
      COALESCE(SUM(montant), 0) AS total_correction
    FROM corrections_solde
    WHERE ${invWhere}
    GROUP BY plateforme_id
  `).all(...invParams);

  // Fusion en une map plateforme_id → solde_portefeuille
  const walletMap = {};
  for (const r of drManuelPerPlat)       walletMap[r.plateforme_id] = (walletMap[r.plateforme_id] || 0) + r.depots - r.retraits_manuels;
  for (const r of rembWalletPerPlat)     walletMap[r.plateforme_id] = (walletMap[r.plateforme_id] || 0) + r.remb_wallet;
  for (const r of bonusWalletPerPlat)    walletMap[r.plateforme_id] = (walletMap[r.plateforme_id] || 0) + r.bonus_wallet;
  for (const r of capitalInvestiPerPlat) walletMap[r.plateforme_id] = (walletMap[r.plateforme_id] || 0) - r.capital_investi;
  for (const r of correctionsPerPlat)    walletMap[r.plateforme_id] = (walletMap[r.plateforme_id] || 0) + r.total_correction;

  const cashByPlatformEnriched = cashByPlatform.map(p => ({
    ...p,
    solde_portefeuille: Math.round((walletMap[p.plateforme_id] || 0) * 100) / 100,
  }));

  const solde_portefeuille_total = Math.round(
    cashByPlatformEnriched.reduce((s, p) => s + p.solde_portefeuille, 0) * 100
  ) / 100;

  /* ── Portfolio ───────────────────────────────────────────────── */
  const portfolio = db.prepare(`
    SELECT
      COUNT(*) AS nb_projets,
      COALESCE(SUM(i.montant_investi),0) AS total_investi,
      COALESCE(SUM(CASE WHEN i.statut='en_cours' THEN
        i.montant_investi
        + COALESCE((SELECT SUM(rv.montant) FROM reinvestissements rv WHERE rv.investissement_id = i.id), 0)
        - COALESCE((SELECT SUM(rb.capital) FROM remboursements rb WHERE rb.investissement_id = i.id AND rb.type = 'normal'), 0)
      END), 0) AS encours,
      COALESCE(SUM(CASE WHEN i.statut='rembourse' THEN i.montant_investi END),0) AS rembourse,
      COALESCE(SUM(CASE WHEN i.statut IN ('en_retard','procedure') THEN
        i.montant_investi
        + COALESCE((SELECT SUM(rv.montant) FROM reinvestissements rv WHERE rv.investissement_id = i.id), 0)
        - COALESCE((SELECT SUM(rb.capital) FROM remboursements rb WHERE rb.investissement_id = i.id AND rb.type = 'normal'), 0)
      END), 0) AS en_defaut
    FROM investissements i WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
  `).get(...invParams);

  /* ── Interets ────────────────────────────────────────────────── */
  const interets = db.prepare(`
    SELECT
      COALESCE(SUM(r.interets_bruts),0)     AS interets_bruts,
      COALESCE(SUM(r.prelev_sociaux),0)     AS prelev_sociaux,
      COALESCE(SUM(r.prelev_forfaitaire),0) AS prelev_forfaitaire,
      COALESCE(SUM(r.net_recu),0)           AS net_recu
    FROM remboursements r
    JOIN investissements i ON i.id = r.investissement_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
  `).get(...invParams);

  /* ── Interets par annee ──────────────────────────────────────── */
  const interetsParAnnee = scopeAll
    ? db.prepare(`
        SELECT annee,
          SUM(interets_bruts)     AS interets_bruts,
          SUM(prelev_sociaux)     AS prelev_sociaux,
          SUM(prelev_forfaitaire) AS prelev_forfaitaire,
          SUM(net_recu)           AS net_recu
        FROM v_interets_annuels
        WHERE investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?)
        GROUP BY annee ORDER BY annee DESC
      `).all(userId)
    : db.prepare(`
        SELECT * FROM v_interets_annuels WHERE investisseur_id = ? ORDER BY annee DESC
      `).all(invId);

  /* ── Prochaines echeances ────────────────────────────────────── */
  const upcoming = db.prepare(`
    SELECT s.*, i.nom_projet, p.nom AS plateforme_nom,
      plat_inv.nom AS plateforme_detenteur_nom,
      (SELECT r.date_remb FROM remboursements r
       WHERE r.investissement_id = s.investissement_id
         AND r.date_remb = s.date_prevue
       LIMIT 1) AS remb_date_exact,
      (SELECT r.date_remb FROM remboursements r
       WHERE r.investissement_id = s.investissement_id
         AND strftime('%Y-%m', r.date_remb) = strftime('%Y-%m', s.date_prevue)
         AND r.date_remb != s.date_prevue
       LIMIT 1) AS remb_date_mois
    FROM simul_remboursements s
    JOIN investissements i ON i.id = s.investissement_id
    JOIN plateformes p ON p.id = i.plateforme_id
    LEFT JOIN investisseurs plat_inv ON plat_inv.id = p.investisseur_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND s.date_prevue >= date('now','start of month')
      AND s.date_prevue <  date('now','start of month','+1 month')
    ORDER BY s.date_prevue
    LIMIT 50
  `).all(...invParams);

  /* ── En retard / procedure ───────────────────────────────────── */
  const enDefaut = db.prepare(`
    SELECT i.*, p.nom AS plateforme_nom,
           plat_inv.nom AS plateforme_detenteur_nom
    FROM investissements i
    JOIN plateformes p ON p.id = i.plateforme_id
    LEFT JOIN investisseurs plat_inv ON plat_inv.id = p.investisseur_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND i.statut IN ('en_retard','procedure')
    ORDER BY i.date_souscription DESC
  `).all(...invParams);

  res.json({ cash, cashByPlatform: cashByPlatformEnriched, solde_portefeuille_total, portfolio, interets, interetsParAnnee, upcoming, enDefaut });
});


/**
 * GET /api/dashboard/solde-historique
 *
 * Retourne le solde porte-monnaie calculé pour une plateforme à une date donnée.
 * Utilise la même formule que solde_portefeuille mais filtrée par date <= :date.
 *
 * Query params : plateforme_id (requis), date YYYY-MM-DD (requis)
 */
router.get('/solde-historique', (req, res) => {
  const { plateforme_id, date } = req.query;
  if (!plateforme_id || !date) {
    return res.status(400).json({ error: 'plateforme_id et date sont requis' });
  }

  const userId = req.user.id;
  const platId = Number(plateforme_id);

  // Vérifier que la plateforme appartient à l'utilisateur
  const plat = db.prepare('SELECT id FROM plateformes WHERE id = ? AND user_id = ?').get(platId, userId);
  if (!plat) return res.status(403).json({ error: 'Plateforme non trouvée' });

  /* ── Résolution du scope investisseur (même logique que GET /) ── */
  let invWhere, invParams;
  const raw = req.header('X-Investisseur-Id');
  const invId = Number(raw);

  if (invId) {
    const row = db.prepare('SELECT id FROM investisseurs WHERE id = ? AND user_id = ?').get(invId, userId);
    if (!row) return res.status(403).json({ error: 'Investisseur non trouvé' });
    invWhere  = 'investisseur_id = ?';
    invParams = [invId];
  } else {
    invWhere  = 'investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?)';
    invParams = [userId];
  }

  /* ── 1. Dépôts − retraits manuels (jusqu'à :date) ─────────────── */
  const dr = db.prepare(`
    SELECT
      COALESCE(SUM(CASE WHEN type='depot' THEN montant ELSE 0 END), 0)            AS depots,
      COALESCE(SUM(CASE WHEN type='retrait'
                         AND COALESCE(source,'') != 'auto_remboursement'
                        THEN montant ELSE 0 END), 0)                               AS retraits_manuels
    FROM depots_retraits
    WHERE plateforme_id = ? AND ${invWhere} AND date_operation <= ?
  `).get(platId, ...invParams, date);

  /* ── 2. Remboursements vers porte-monnaie (jusqu'à :date) ──────── */
  const remb = db.prepare(`
    SELECT COALESCE(SUM(
      CASE p.fiscalite
        WHEN 'flat_tax' THEN r.net_recu
        ELSE r.capital + r.cashback + r.interets_bruts
      END
    ), 0) AS remb_wallet
    FROM remboursements r
    JOIN investissements i ON i.id = r.investissement_id
    JOIN plateformes p     ON p.id = i.plateforme_id
    WHERE i.plateforme_id = ? AND ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND r.type = 'normal' AND r.methode_remboursement = 'portefeuille'
      AND r.date_remb <= ?
  `).get(platId, ...invParams, date);

  /* ── 3. Bonus porte-monnaie (jusqu'à :date) ────────────────────── */
  const bonus = db.prepare(`
    SELECT COALESCE(SUM(cashback), 0) AS bonus_wallet
    FROM remboursements
    WHERE bonus_plateforme_id = ? AND ${invWhere.replace('investisseur_id', 'bonus_investisseur_id')}
      AND type IN ('bonus_parrainage', 'bonus_plateforme')
      AND date_remb <= ?
  `).get(platId, ...invParams, date);

  /* ── 4. Capital investi (souscriptions + réinvestissements jusqu'à :date) ── */
  const capital = db.prepare(`
    SELECT COALESCE(SUM(
      i.montant_investi
      + COALESCE((
          SELECT SUM(rv.montant)
          FROM reinvestissements rv
          WHERE rv.investissement_id = i.id
            AND rv.date_reinvestissement <= ?
        ), 0)
    ), 0) AS capital_investi
    FROM investissements i
    WHERE i.plateforme_id = ? AND ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND i.date_souscription <= ?
  `).get(date, platId, ...invParams, date);

  /* ── 5. Corrections de solde (jusqu'à :date) ───────────────────── */
  const corrections = db.prepare(`
    SELECT COALESCE(SUM(montant), 0) AS total_correction
    FROM corrections_solde
    WHERE plateforme_id = ? AND ${invWhere} AND date <= ?
  `).get(platId, ...invParams, date);

  const solde = Math.round((
      dr.depots
    - dr.retraits_manuels
    + remb.remb_wallet
    + bonus.bonus_wallet
    - capital.capital_investi
    + corrections.total_correction
  ) * 100) / 100;

  res.json({ solde });
});


/**
 * GET /api/dashboard/interets-mensuels
 *
 * Retourne les intérêts réels (remboursements) et projetés (simul_remboursements)
 * groupés par mois YYYY-MM pour l'année demandée.
 *
 * Query params : annee (int, défaut = année courante), scope=all (optionnel)
 */
router.get('/interets-mensuels', (req, res) => {
  const annee    = parseInt(req.query.annee) || new Date().getFullYear();
  const scopeAll = req.query.scope === 'all';
  const userId   = req.user.id;
  const anneeStr = String(annee);

  let invWhere, invParams, invId;

  if (scopeAll) {
    invWhere  = 'investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?)';
    invParams = [userId];
  } else {
    const raw = req.header('X-Investisseur-Id');
    invId = Number(raw);
    if (!invId) return res.status(400).json({ error: 'Missing investisseur id (header X-Investisseur-Id)' });
    const row = db.prepare('SELECT id FROM investisseurs WHERE id = ? AND user_id = ?').get(invId, userId);
    if (!row) return res.status(403).json({ error: 'Investisseur not found or not owned by user' });
    invWhere  = 'investisseur_id = ?';
    invParams = [invId];
  }

  /* ── Intérêts réels groupés par mois ─────────────────────────── */
  // Inclut les remboursements normaux (via investissement) ET les bonus (via bonus_investisseur_id)
  let rembourses;
  if (scopeAll) {
    rembourses = db.prepare(`
      SELECT
        strftime('%Y-%m', r.date_remb) AS mois,
        COALESCE(SUM(r.interets_bruts), 0) AS interets_bruts,
        COALESCE(SUM(r.interets_bruts - r.prelev_sociaux - r.prelev_forfaitaire), 0) AS interets_nets,
        COALESCE(SUM(r.capital), 0) AS capital,
        COALESCE(SUM(r.cashback), 0) AS cashback
      FROM remboursements r
      LEFT JOIN investissements inv ON inv.id = r.investissement_id
      LEFT JOIN investisseurs own ON own.id = inv.investisseur_id
      LEFT JOIN investisseurs bonus_own ON bonus_own.id = r.bonus_investisseur_id
      WHERE strftime('%Y', r.date_remb) = ?
        AND (
          (r.investissement_id IS NOT NULL AND own.user_id = ?)
          OR (r.bonus_investisseur_id IS NOT NULL AND bonus_own.user_id = ?)
        )
      GROUP BY mois
      ORDER BY mois
    `).all(anneeStr, userId, userId);
  } else {
    rembourses = db.prepare(`
      SELECT
        strftime('%Y-%m', r.date_remb) AS mois,
        COALESCE(SUM(r.interets_bruts), 0) AS interets_bruts,
        COALESCE(SUM(r.interets_bruts - r.prelev_sociaux - r.prelev_forfaitaire), 0) AS interets_nets,
        COALESCE(SUM(r.capital), 0) AS capital,
        COALESCE(SUM(r.cashback), 0) AS cashback
      FROM remboursements r
      LEFT JOIN investissements inv ON inv.id = r.investissement_id
      LEFT JOIN investisseurs bonus_own ON bonus_own.id = r.bonus_investisseur_id
      WHERE strftime('%Y', r.date_remb) = ?
        AND (
          (r.investissement_id IS NOT NULL AND inv.investisseur_id = ?)
          OR (r.bonus_investisseur_id IS NOT NULL AND r.bonus_investisseur_id = ?)
        )
      GROUP BY mois
      ORDER BY mois
    `).all(anneeStr, invId, invId);
  }

  /* ── Projections groupées par mois ───────────────────────────── */
  // Exclure les investissements qui ont déjà un remboursement réel dans le même mois
  // (évite le double-comptage pour le mois en cours)
  const projections = db.prepare(`
    SELECT
      strftime('%Y-%m', s.date_prevue) AS mois,
      COALESCE(SUM(s.interets_prevus), 0) AS interets_prevus,
      COALESCE(SUM(s.capital_prevu), 0) AS capital_prevu
    FROM simul_remboursements s
    JOIN investissements i ON i.id = s.investissement_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND strftime('%Y', s.date_prevue) = ?
      AND NOT EXISTS (
        SELECT 1 FROM remboursements r
        WHERE r.investissement_id = s.investissement_id
          AND strftime('%Y-%m', r.date_remb) = strftime('%Y-%m', s.date_prevue)
      )
    GROUP BY mois
    ORDER BY mois
  `).all(...invParams, anneeStr);

  /* ── Années disponibles (remboursements + projections) ─── */
  const annees = db.prepare(`
    SELECT DISTINCT CAST(strftime('%Y', r.date_remb) AS INTEGER) AS annee
    FROM remboursements r
    JOIN investissements i ON i.id = r.investissement_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
    UNION
    SELECT DISTINCT CAST(strftime('%Y', s.date_prevue) AS INTEGER) AS annee
    FROM simul_remboursements s
    JOIN investissements i ON i.id = s.investissement_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND CAST(strftime('%Y', s.date_prevue) AS INTEGER) <= CAST(strftime('%Y', 'now') AS INTEGER) + 10
    ORDER BY annee
  `).all(...invParams, ...invParams).map(r => r.annee);

  res.json({ rembourses, projections, annees });
});


/**
 * GET /api/dashboard/interets-annuels
 *
 * Retourne les intérêts réels et projetés groupés par ANNÉE (toutes années).
 * Les projections excluent les échéances déjà passées (>= début du mois courant).
 *
 * Query params : scope=all (optionnel)
 */
router.get('/interets-annuels', (req, res) => {
  const scopeAll = req.query.scope === 'all';
  const userId   = req.user.id;

  let invWhere, invParams, invId;

  if (scopeAll) {
    invWhere  = 'investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?)';
    invParams = [userId];
  } else {
    const raw = req.header('X-Investisseur-Id');
    invId = Number(raw);
    if (!invId) return res.status(400).json({ error: 'Missing investisseur id (header X-Investisseur-Id)' });
    const row = db.prepare('SELECT id FROM investisseurs WHERE id = ? AND user_id = ?').get(invId, userId);
    if (!row) return res.status(403).json({ error: 'Investisseur not found or not owned by user' });
    invWhere  = 'investisseur_id = ?';
    invParams = [invId];
  }

  /* ── Intérêts réels groupés par année ────────────────────────── */
  let rembourses;
  if (scopeAll) {
    rembourses = db.prepare(`
      SELECT
        CAST(strftime('%Y', r.date_remb) AS INTEGER) AS annee,
        COALESCE(SUM(r.interets_bruts), 0) AS interets_bruts,
        COALESCE(SUM(r.interets_bruts - r.prelev_sociaux - r.prelev_forfaitaire), 0) AS interets_nets,
        COALESCE(SUM(r.capital), 0) AS capital,
        COALESCE(SUM(r.cashback), 0) AS cashback
      FROM remboursements r
      LEFT JOIN investissements inv ON inv.id = r.investissement_id
      LEFT JOIN investisseurs own ON own.id = inv.investisseur_id
      LEFT JOIN investisseurs bonus_own ON bonus_own.id = r.bonus_investisseur_id
      WHERE (
        (r.investissement_id IS NOT NULL AND own.user_id = ?)
        OR (r.bonus_investisseur_id IS NOT NULL AND bonus_own.user_id = ?)
      )
      GROUP BY annee
      ORDER BY annee
    `).all(userId, userId);
  } else {
    rembourses = db.prepare(`
      SELECT
        CAST(strftime('%Y', r.date_remb) AS INTEGER) AS annee,
        COALESCE(SUM(r.interets_bruts), 0) AS interets_bruts,
        COALESCE(SUM(r.interets_bruts - r.prelev_sociaux - r.prelev_forfaitaire), 0) AS interets_nets,
        COALESCE(SUM(r.capital), 0) AS capital,
        COALESCE(SUM(r.cashback), 0) AS cashback
      FROM remboursements r
      LEFT JOIN investissements inv ON inv.id = r.investissement_id
      LEFT JOIN investisseurs bonus_own ON bonus_own.id = r.bonus_investisseur_id
      WHERE (
        (r.investissement_id IS NOT NULL AND inv.investisseur_id = ?)
        OR (r.bonus_investisseur_id IS NOT NULL AND r.bonus_investisseur_id = ?)
      )
      GROUP BY annee
      ORDER BY annee
    `).all(invId, invId);
  }

  /* ── Projections groupées par année (uniquement futures/en cours) */
  const projections = db.prepare(`
    SELECT
      CAST(strftime('%Y', s.date_prevue) AS INTEGER) AS annee,
      COALESCE(SUM(s.interets_prevus), 0) AS interets_prevus,
      COALESCE(SUM(s.capital_prevu), 0) AS capital_prevu
    FROM simul_remboursements s
    JOIN investissements i ON i.id = s.investissement_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND s.date_prevue >= date('now', 'start of month')
    GROUP BY annee
    ORDER BY annee
  `).all(...invParams);

  /* ── Années disponibles (remboursements + projections) ───────── */
  const annees = db.prepare(`
    SELECT DISTINCT CAST(strftime('%Y', r.date_remb) AS INTEGER) AS annee
    FROM remboursements r
    JOIN investissements i ON i.id = r.investissement_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
    UNION
    SELECT DISTINCT CAST(strftime('%Y', s.date_prevue) AS INTEGER) AS annee
    FROM simul_remboursements s
    JOIN investissements i ON i.id = s.investissement_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND CAST(strftime('%Y', s.date_prevue) AS INTEGER) <= CAST(strftime('%Y', 'now') AS INTEGER) + 10
    ORDER BY annee
  `).all(...invParams, ...invParams).map(r => r.annee);

  /* ── Capital souscrit par année (pour KPI "Capital investi" filtré) ── */
  const capitalParAnnee = db.prepare(`
    SELECT
      CAST(strftime('%Y', i.date_souscription) AS INTEGER) AS annee,
      COALESCE(SUM(
        i.montant_investi
        + COALESCE((SELECT SUM(rv.montant) FROM reinvestissements rv WHERE rv.investissement_id = i.id), 0)
      ), 0) AS capital_souscrit
    FROM investissements i
    WHERE ${invWhere}
    GROUP BY annee
    ORDER BY annee
  `).all(...invParams);

  res.json({ rembourses, projections, annees, capitalParAnnee });
});



/**
 * GET /api/dashboard/interets-par-plateforme
 *
 * Retourne les intérêts réels + projetés groupés par plateforme et par mois
 * pour l'année demandée, ainsi que le capital investi estimé chaque mois.
 *
 * Query params : annee (int, défaut = année courante), scope=all (optionnel)
 */
router.get('/interets-par-plateforme', (req, res) => {
  const annee    = parseInt(req.query.annee) || new Date().getFullYear();
  const scopeAll = req.query.scope === 'all';
  const userId   = req.user.id;
  const anneeStr = String(annee);

  let invWhere, invParams, invId;

  if (scopeAll) {
    invWhere  = 'investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?)';
    invParams = [userId];
  } else {
    const raw = req.header('X-Investisseur-Id');
    invId = Number(raw);
    if (!invId) return res.status(400).json({ error: 'Missing investisseur id (header X-Investisseur-Id)' });
    const row = db.prepare('SELECT id FROM investisseurs WHERE id = ? AND user_id = ?').get(invId, userId);
    if (!row) return res.status(403).json({ error: 'Investisseur not found or not owned by user' });
    invWhere  = 'investisseur_id = ?';
    invParams = [invId];
  }

  /* ── Intérêts réels par plateforme et par mois ───────────────── */
  const remboursesByPlat = db.prepare(`
    SELECT
      p.id   AS plateforme_id,
      p.nom  AS plateforme_nom,
      strftime('%Y-%m', r.date_remb) AS mois,
      COALESCE(SUM(r.interets_bruts), 0) AS interets_bruts,
      COALESCE(SUM(r.interets_bruts - r.prelev_sociaux - r.prelev_forfaitaire), 0) AS interets_nets,
      COALESCE(SUM(r.cashback), 0) AS cashback,
      COALESCE(SUM(r.capital), 0) AS capital
    FROM remboursements r
    JOIN investissements i ON i.id = r.investissement_id
    JOIN plateformes p ON p.id = i.plateforme_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND strftime('%Y', r.date_remb) = ?
      AND r.type = 'normal'
    GROUP BY p.id, p.nom, mois
    ORDER BY p.nom, mois
  `).all(...invParams, anneeStr);

  /* ── Cashback bonus (parrainage / plateforme) par plateforme et par mois ── */
  const bonusCashbackByPlat = db.prepare(`
    SELECT
      r.bonus_plateforme_id AS plateforme_id,
      p.nom                 AS plateforme_nom,
      strftime('%Y-%m', r.date_remb) AS mois,
      COALESCE(SUM(r.cashback), 0) AS cashback
    FROM remboursements r
    JOIN plateformes p ON p.id = r.bonus_plateforme_id
    WHERE ${invWhere.replace('investisseur_id', 'bonus_investisseur_id')}
      AND r.type IN ('bonus_parrainage', 'bonus_plateforme')
      AND strftime('%Y', r.date_remb) = ?
    GROUP BY r.bonus_plateforme_id, p.nom, mois
    ORDER BY p.nom, mois
  `).all(...invParams, anneeStr);

  /* ── Projections par plateforme et par mois ──────────────────── */
  // Exclure les investissements qui ont déjà un remboursement réel dans le même mois
  const projectionsByPlat = db.prepare(`
    SELECT
      p.id   AS plateforme_id,
      p.nom  AS plateforme_nom,
      strftime('%Y-%m', s.date_prevue) AS mois,
      COALESCE(SUM(s.interets_prevus), 0) AS interets_prevus,
      COALESCE(SUM(s.capital_prevu), 0) AS capital_prevu
    FROM simul_remboursements s
    JOIN investissements i ON i.id = s.investissement_id
    JOIN plateformes p ON p.id = i.plateforme_id
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
      AND strftime('%Y', s.date_prevue) = ?
      AND NOT EXISTS (
        SELECT 1 FROM remboursements r
        WHERE r.investissement_id = s.investissement_id
          AND strftime('%Y-%m', r.date_remb) = strftime('%Y-%m', s.date_prevue)
      )
    GROUP BY p.id, p.nom, mois
    ORDER BY p.nom, mois
  `).all(...invParams, anneeStr);

  /* ── Capital investi mensuel ─────────────────────────────────── */
  // Récupérer tous les investissements avec leurs dates pour calculer
  // le capital restant dû chaque mois (montant_investi + reinvests − capital_remboursé_cumulé)
  const invs = db.prepare(`
    SELECT
      i.id,
      i.montant_investi,
      i.date_souscription,
      i.date_cible,
      i.statut,
      (SELECT MAX(r.date_remb) FROM remboursements r WHERE r.investissement_id = i.id) AS last_remb_date
    FROM investissements i
    WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
  `).all(...invParams);

  const invIds = invs.map(i => i.id);
  const placeholder = invIds.map(() => '?').join(',');

  // Remboursements de capital par investissement avec leur date (tous types normaux)
  const capitalRembRows = invIds.length ? db.prepare(`
    SELECT investissement_id, date_remb, SUM(capital) AS capital_remb
    FROM remboursements
    WHERE investissement_id IN (${placeholder})
      AND type = 'normal'
    GROUP BY investissement_id, date_remb
  `).all(...invIds) : [];

  // Réinvestissements par investissement avec leur date
  const reinvestRows = invIds.length ? db.prepare(`
    SELECT investissement_id, date_reinvestissement, SUM(montant) AS montant
    FROM reinvestissements
    WHERE investissement_id IN (${placeholder})
    GROUP BY investissement_id, date_reinvestissement
  `).all(...invIds) : [];

  // Capital projeté par investissement (simul_remboursements) — pour les mois futurs
  const capitalSimulRows = invIds.length ? db.prepare(`
    SELECT investissement_id, date_prevue, SUM(capital_prevu) AS capital_prevu
    FROM simul_remboursements
    WHERE investissement_id IN (${placeholder})
    GROUP BY investissement_id, date_prevue
  `).all(...invIds) : [];

  // Map : inv_id → [{date, capital}]
  const capitalRembMap = {};
  for (const r of capitalRembRows) {
    if (!capitalRembMap[r.investissement_id]) capitalRembMap[r.investissement_id] = [];
    capitalRembMap[r.investissement_id].push({ date: r.date_remb, capital: r.capital_remb });
  }

  // Map : inv_id → [{date, montant}]
  const reinvestMap = {};
  for (const r of reinvestRows) {
    if (!reinvestMap[r.investissement_id]) reinvestMap[r.investissement_id] = [];
    reinvestMap[r.investissement_id].push({ date: r.date_reinvestissement, montant: r.montant });
  }

  // Map : inv_id → [{date, capital}]
  const capitalSimulMap = {};
  for (const r of capitalSimulRows) {
    if (!capitalSimulMap[r.investissement_id]) capitalSimulMap[r.investissement_id] = [];
    capitalSimulMap[r.investissement_id].push({ date: r.date_prevue, capital: r.capital_prevu });
  }

  // Date du jour au format YYYY-MM-DD (locale) pour distinguer passé/futur
  const _today = new Date();
  const todayStr = `${_today.getFullYear()}-${String(_today.getMonth() + 1).padStart(2, '0')}-${String(_today.getDate()).padStart(2, '0')}`;

  const capitalMensuel = [];
  for (let m = 1; m <= 12; m++) {
    const moisStr   = `${anneeStr}-${String(m).padStart(2, '0')}`;
    const firstDay  = `${moisStr}-01`;
    // Dernier jour du mois (calcul local pour éviter le décalage UTC)
    const _d      = new Date(annee, m, 0);
    const lastDay = `${_d.getFullYear()}-${String(_d.getMonth() + 1).padStart(2, '0')}-${String(_d.getDate()).padStart(2, '0')}`;

    let capital = 0;
    let enDefaut = 0;
    for (const inv of invs) {
      if (inv.date_souscription > lastDay) continue; // pas encore débuté

      // Capital réellement remboursé jusqu'à la fin de ce mois
      const rembs = capitalRembMap[inv.id] ?? [];
      const capitalRembCumul = rembs
        .filter(r => r.date <= lastDay)
        .reduce((s, r) => s + r.capital, 0);

      // Capital projeté pour les échéances futures (après le dernier remb réel et après aujourd'hui)
      const lastRembDate = inv.last_remb_date ?? '0000-00-00';
      const capitalSimulCumul = (capitalSimulMap[inv.id] ?? [])
        .filter(r => r.date > todayStr && r.date > lastRembDate && r.date <= lastDay)
        .reduce((s, r) => s + r.capital, 0);

      const reinvestsCumul = (reinvestMap[inv.id] ?? [])
        .filter(r => r.date <= lastDay)
        .reduce((s, r) => s + r.montant, 0);
      const capitalRestant = Math.max(0, inv.montant_investi + reinvestsCumul - capitalRembCumul - capitalSimulCumul);

      const actif = ['en_cours', 'en_retard', 'procedure'].includes(inv.statut);
      if (actif) {
        capital += capitalRestant;
        if (['en_retard', 'procedure'].includes(inv.statut)) enDefaut += capitalRestant;
      } else {
        // Remboursé/clôturé : était-il encore actif ce mois-ci ?
        // Priorité : date_cible → dernier remboursement réel → exclure
        const fin = inv.date_cible ?? inv.last_remb_date ?? null;
        if (fin && fin >= firstDay) {
          capital += capitalRestant;
        }
      }
    }
    capitalMensuel.push({ mois: moisStr, capital: Math.round(capital * 100) / 100, en_defaut: Math.round(enDefaut * 100) / 100 });
  }

  /* ── Noms des détenteurs par plateforme ─────────────────────── */
  const detenteurRows = db.prepare(`
    SELECT p.id AS plateforme_id, inv.nom AS detenteur_nom
    FROM plateformes p
    LEFT JOIN investisseurs inv ON inv.id = p.investisseur_id
    WHERE p.user_id = ?
  `).all(userId);
  const detenteurMap = {};
  for (const d of detenteurRows) detenteurMap[d.plateforme_id] = d.detenteur_nom;

  /* ── Construire la réponse par plateforme ────────────────────── */
  // Indexer les rembs et projections par plateforme_id puis mois
  const rembMap = {};
  for (const r of remboursesByPlat) {
    if (!rembMap[r.plateforme_id]) rembMap[r.plateforme_id] = { id: r.plateforme_id, nom: r.plateforme_nom, detenteur_nom: detenteurMap[r.plateforme_id] ?? null, rembourses: {}, projections: {} };
    rembMap[r.plateforme_id].rembourses[r.mois] = { interets_bruts: r.interets_bruts, interets_nets: r.interets_nets, cashback: r.cashback, capital: r.capital };
  }
  // Ajouter le cashback bonus (parrainage/plateforme) aux remboursements par mois
  for (const b of bonusCashbackByPlat) {
    if (!rembMap[b.plateforme_id]) rembMap[b.plateforme_id] = { id: b.plateforme_id, nom: b.plateforme_nom, detenteur_nom: detenteurMap[b.plateforme_id] ?? null, rembourses: {}, projections: {} };
    const entry = rembMap[b.plateforme_id].rembourses[b.mois];
    if (entry) {
      entry.cashback = (entry.cashback ?? 0) + b.cashback;
    } else {
      rembMap[b.plateforme_id].rembourses[b.mois] = { interets_bruts: 0, interets_nets: 0, cashback: b.cashback, capital: 0 };
    }
  }

  for (const p of projectionsByPlat) {
    if (!rembMap[p.plateforme_id]) rembMap[p.plateforme_id] = { id: p.plateforme_id, nom: p.plateforme_nom, detenteur_nom: detenteurMap[p.plateforme_id] ?? null, rembourses: {}, projections: {} };
    rembMap[p.plateforme_id].projections[p.mois] = { interets_prevus: p.interets_prevus, capital_prevu: p.capital_prevu };
  }

  const plateformes = Object.values(rembMap).sort((a, b) => a.nom.localeCompare(b.nom));

  res.json({ annee, plateformes, capitalMensuel });
});


/**
 * GET /api/dashboard/detail-cellule
 *
 * Retourne le détail ligne par ligne d'une cellule du tableau mensuel :
 * - recus   : remboursements réels pour plateforme_id + YYYY-MM
 * - projetes : simul_remboursements pour plateforme_id + YYYY-MM
 *              (uniquement les projections sans remboursement réel dans ce mois)
 *
 * Query params : plateforme_id (int), annee (4 chiffres), mois (01-12), scope=all (opt)
 */
router.get('/detail-cellule', (req, res) => {
  const { plateforme_id, annee, mois } = req.query;
  const scopeAll = req.query.scope === 'all';
  const userId   = req.user.id;

  if (!annee || !mois)
    return res.status(400).json({ error: 'annee et mois sont requis' });

  const moisStr  = `${annee}-${String(mois).padStart(2, '0')}`;
  const platId   = plateforme_id ? Number(plateforme_id) : null;
  const platFilter = platId ? 'AND i.plateforme_id = ?' : '';

  let invWhere, invParams;
  if (scopeAll) {
    invWhere  = 'i.investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?)';
    invParams = [userId];
  } else {
    const raw   = req.header('X-Investisseur-Id');
    const invId = Number(raw);
    if (!invId) return res.status(400).json({ error: 'Missing X-Investisseur-Id' });
    const row = db.prepare('SELECT id FROM investisseurs WHERE id=? AND user_id=?').get(invId, userId);
    if (!row) return res.status(403).json({ error: 'Investisseur not owned by user' });
    invWhere  = 'i.investisseur_id = ?';
    invParams = [invId];
  }

  const recusParams    = platId ? [...invParams, platId, moisStr]        : [...invParams, moisStr];
  const projetesParams = platId ? [...invParams, platId, moisStr, moisStr] : [...invParams, moisStr, moisStr];

  /* ── Remboursements reçus ─────────────────────────────────── */
  const recus = db.prepare(`
    SELECT
      r.id, r.investissement_id, r.date_remb,
      r.capital, r.cashback,
      r.interets_bruts, r.prelev_sociaux, r.prelev_forfaitaire,
      r.interets_nets, r.net_recu,
      i.nom_projet, i.plateforme_id,
      p.nom AS plateforme_nom,
      inv.nom AS detenteur_nom
    FROM remboursements r
    JOIN investissements i  ON i.id  = r.investissement_id
    JOIN investisseurs   inv ON inv.id = i.investisseur_id
    LEFT JOIN plateformes p ON p.id = i.plateforme_id
    WHERE ${invWhere}
      ${platFilter}
      AND strftime('%Y-%m', r.date_remb) = ?
      AND r.type = 'normal'
    ORDER BY p.nom, r.date_remb, i.nom_projet
  `).all(...recusParams);

  /* ── Projections (sans remb réel dans le même mois) ─────── */
  const projetes = db.prepare(`
    SELECT
      s.id, s.investissement_id, s.date_prevue,
      s.capital_prevu, s.interets_prevus, s.total_prevu,
      s.numero_echeance,
      i.nom_projet, i.plateforme_id,
      p.nom AS plateforme_nom,
      inv.nom AS detenteur_nom
    FROM simul_remboursements s
    JOIN investissements i   ON i.id  = s.investissement_id
    JOIN investisseurs   inv ON inv.id = i.investisseur_id
    LEFT JOIN plateformes p ON p.id = i.plateforme_id
    WHERE ${invWhere}
      ${platFilter}
      AND strftime('%Y-%m', s.date_prevue) = ?
      AND NOT EXISTS (
        SELECT 1 FROM remboursements r
        WHERE r.investissement_id = s.investissement_id
          AND strftime('%Y-%m', r.date_remb) = ?
      )
    ORDER BY p.nom, s.date_prevue, i.nom_projet
  `).all(...projetesParams);

  res.json({ recus, projetes });
});

export default router;
