import { Router } from 'express';
import { z } from 'zod';
import db from '../db/index.js';
import { HttpError } from '../middleware/errorHandler.js';
import { requireInvestisseur } from '../middleware/investisseurScope.js';
import { buildSchedule, adjustSimulForActuals } from '../utils/schedule.js';

const router = Router();

const Schema = z.object({
  investissement_id: z.number().int().positive(),
  numero_echeance: z.number().int().positive(),
  date_prevue: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
  capital_prevu: z.number().nonnegative().default(0),
  interets_prevus: z.number().nonnegative().default(0),
  total_prevu: z.number().nonnegative().default(0),
  notes: z.string().optional(),
});

/* GET /api/simul/all — toutes les projections pour l'investisseur actif (ou scope=all) */
router.get('/all', (req, res) => {
  const userId   = req.user.id;
  const scopeAll = req.query.scope === 'all';
  const rawInvId = req.header('X-Investisseur-Id');
  const invId    = Number(rawInvId);

  let rows;
  if (scopeAll) {
    rows = db.prepare(`
      SELECT s.*, i.plateforme_id, i.investisseur_id
      FROM simul_remboursements s
      JOIN investissements i ON i.id = s.investissement_id
      JOIN investisseurs inv ON inv.id = i.investisseur_id
      WHERE inv.user_id = ?
      ORDER BY s.date_prevue
    `).all(userId);
  } else {
    if (!invId) return res.status(400).json({ error: 'Missing X-Investisseur-Id' });
    const ok = db.prepare('SELECT id FROM investisseurs WHERE id=? AND user_id=?').get(invId, userId);
    if (!ok) return res.status(403).json({ error: 'Investisseur not owned by user' });
    rows = db.prepare(`
      SELECT s.*, i.plateforme_id, i.investisseur_id
      FROM simul_remboursements s
      JOIN investissements i ON i.id = s.investissement_id
      WHERE i.investisseur_id = ?
      ORDER BY s.date_prevue
    `).all(invId);
  }
  res.json(rows);
});

router.use(requireInvestisseur);

function assertOwnedInvestissement(invId, userId) {
  const row = db.prepare(`
    SELECT i.id, i.montant_investi, i.taux_interet, i.duree_mois, i.type_remb,
           i.freq_interets, i.date_premiere_echeance, i.date_souscription
    FROM investissements i
    JOIN investisseurs inv ON inv.id = i.investisseur_id
    WHERE i.id = ? AND inv.user_id = ?
  `).get(invId, userId);
  if (!row) throw new HttpError(403, 'Investissement not in scope');
  return row;
}

router.get('/', (req, res) => {
  const { investissement_id } = req.query;
  if (!investissement_id) {
    return res.status(400).json({ error: 'investissement_id query param required' });
  }
  assertOwnedInvestissement(Number(investissement_id), req.user.id);
  const rows = db.prepare(
    'SELECT * FROM simul_remboursements WHERE investissement_id=? ORDER BY numero_echeance'
  ).all(investissement_id);
  res.json(rows);
});

router.post('/', (req, res, next) => {
  try {
    const body = Schema.parse(req.body);
    assertOwnedInvestissement(body.investissement_id, req.user.id);
    const r = db.prepare(`
      INSERT INTO simul_remboursements
        (investissement_id, numero_echeance, date_prevue, capital_prevu, interets_prevus, total_prevu, notes)
      VALUES (?,?,?,?,?,?,?)
    `).run(
      body.investissement_id, body.numero_echeance, body.date_prevue,
      body.capital_prevu, body.interets_prevus, body.total_prevu, body.notes || null,
    );
    res.status(201).json({ id: r.lastInsertRowid, ...body });
  } catch (e) { next(e); }
});

/**
 * Auto-generate the simulated repayment schedule for an investissement
 * based on its montant, taux, durée, type_remb and freq_interets.
 *
 * Body: { investissement_id, replace?: boolean }
 */
router.post('/generate', (req, res, next) => {
  try {
    const { investissement_id, replace = true } = req.body;
    if (!investissement_id) throw new HttpError(400, 'investissement_id required');
    const inv = assertOwnedInvestissement(Number(investissement_id), req.user.id);
    if (!inv.taux_interet || !inv.duree_mois) {
      throw new HttpError(400, 'Investissement requires taux_interet and duree_mois');
    }

    const tx = db.transaction(() => {
      if (replace) {
        db.prepare('DELETE FROM simul_remboursements WHERE investissement_id=?').run(investissement_id);
      }
      const start = inv.date_premiere_echeance || inv.date_souscription;
      const echeances = buildSchedule({
        montant: inv.montant_investi,
        taux: inv.taux_interet,
        duree: inv.duree_mois,
        type: inv.type_remb || 'in_fine',
        freq: inv.freq_interets || 'mensuel',
        startDate: start,
      });
      const stmt = db.prepare(`
        INSERT INTO simul_remboursements
          (investissement_id, numero_echeance, date_prevue, capital_prevu, interets_prevus, total_prevu)
        VALUES (?,?,?,?,?,?)
      `);
      for (const e of echeances) {
        stmt.run(investissement_id, e.n, e.date, e.capital, e.interets, e.total);
      }
      return echeances.length;
    });

    const inserted = tx();
    res.status(201).json({ inserted });
  } catch (e) { next(e); }
});

/**
 * Recalcule l'échéancier en tenant compte des remboursements réels enregistrés
 * (remboursements anticipés + première période partielle).
 * Équivalent à ce qui est déclenché automatiquement après chaque saisie de remboursement.
 *
 * Body: { investissement_id }
 */
router.post('/recalculate', (req, res, next) => {
  try {
    const { investissement_id } = req.body;
    if (!investissement_id) throw new HttpError(400, 'investissement_id required');
    assertOwnedInvestissement(Number(investissement_id), req.user.id);
    adjustSimulForActuals(db, Number(investissement_id));
    const rows = db.prepare(
      'SELECT * FROM simul_remboursements WHERE investissement_id=? ORDER BY numero_echeance'
    ).all(investissement_id);
    res.json({ recalculated: rows.length, rows });
  } catch (e) { next(e); }
});

router.delete('/:id', (req, res, next) => {
  try {
    const owns = db.prepare(`
      SELECT s.id FROM simul_remboursements s
      JOIN investissements i ON i.id = s.investissement_id
      WHERE s.id=? AND i.investisseur_id=?
    `).get(req.params.id, req.investisseur.id);
    if (!owns) throw new HttpError(404, 'Not found');
    db.prepare('DELETE FROM simul_remboursements WHERE id=?').run(req.params.id);
    res.status(204).end();
  } catch (e) { next(e); }
});

export default router;
