import { Router } from 'express';
import bcrypt from 'bcryptjs';
import crypto from 'node:crypto';
import { z } from 'zod';
import db from '../db/index.js';
import { signToken, requireAuth } from '../middleware/auth.js';
import { HttpError } from '../middleware/errorHandler.js';
import { sendMail, buildEmailHtml, getSmtpConfig } from '../utils/mailer.js';
import { createRequire } from 'node:module';
const _require = createRequire(import.meta.url);
const QRCode = _require('qrcode');
import { generateSecret as totpGenerateSecret, generateURI as totpGenerateURI, verifySync as totpVerifySync } from 'otplib';
import { audit } from '../utils/audit.js';

const router = Router();

const RegisterSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
  displayName: z.string().min(1).optional(),
});

const LoginSchema = z.object({
  email: z.string().email(),
  password: z.string().min(1),
});

router.post('/register', async (req, res, next) => {
  try {
    const body = RegisterSchema.parse(req.body);
    const exists = db.prepare('SELECT id FROM users WHERE email = ?').get(body.email);
    if (exists) throw new HttpError(409, 'Email already registered');

    // Le premier utilisateur inscrit devient automatiquement administrateur
    const isFirst = db.prepare('SELECT COUNT(*) AS n FROM users').get().n === 0;
    const role = isFirst ? 'admin' : 'user';

    // Le 1er utilisateur (admin) est auto-vérifié ; les suivants si SMTP désactivé
    const cfg = getSmtpConfig();
    const smtpReady = cfg.enabled && cfg.host && cfg.email;
    const autoVerified = isFirst || !smtpReady ? 1 : 0;

    const hash = bcrypt.hashSync(body.password, 10);
    const result = db
      .prepare('INSERT INTO users (email, password_hash, display_name, role, email_verified) VALUES (?, ?, ?, ?, ?)')
      .run(body.email, hash, body.displayName || null, role, autoVerified);

    const userId = result.lastInsertRowid;

    // Auto-create le premier profil famille (= l'utilisateur lui-même)
    const fullName = body.displayName || 'Mon profil';
    const prenom   = fullName.includes(' ') ? fullName.split(' ')[0] : null;
    const invResult = db.prepare(
      `INSERT INTO investisseurs (user_id, nom, prenom, type, type_fiscal, is_principal) VALUES (?, ?, ?, 'famille', 'PP', 1)`
    ).run(userId, fullName, prenom);

    // Auto-créer un compte courant pour le profil principal
    db.prepare(
      'INSERT INTO comptes (user_id, nom, type, investisseur_id) VALUES (?,?,?,?)'
    ).run(userId, `Compte courant — ${fullName}`, 'compte_courant', invResult.lastInsertRowid);

    // Si l'utilisateur doit vérifier son email → envoyer l'email de bienvenue
    if (!autoVerified) {
      const vToken    = crypto.randomBytes(32).toString('hex');
      const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
      db.prepare('INSERT INTO email_verification_tokens (user_id, token, expires_at) VALUES (?,?,?)').run(userId, vToken, expiresAt);

      const appUrl = cfg.appUrl?.replace(/\/$/, '') || '';
      try {
        await sendMail({
          to:      body.email,
          subject: `Bienvenue sur ${cfg.appName} — Vérifiez votre adresse email`,
          html: buildEmailHtml({
            title: `Bienvenue ${prenom || ''} !`,
            body: `<p>Votre compte a été créé avec succès. Pour commencer à utiliser ${cfg.appName}, veuillez confirmer votre adresse email en cliquant sur le bouton ci-dessous.</p>
                   <p>Ce lien est valable <strong>24 heures</strong>.</p>`,
            ctaLabel: 'Vérifier mon adresse email',
            ctaUrl:   `${appUrl}/verify-email?token=${vToken}`,
          }),
        });
      } catch (mailErr) {
        console.error('[auth] Échec envoi email bienvenue:', mailErr.message);
        // Ne pas faire échouer l'inscription si le mail échoue
      }

      audit(req, { action: 'user_registered', category: 'account', targetUserId: userId, details: { email: body.email, role, auto_verified: false } });
      return res.status(201).json({ requiresVerification: true, email: body.email });
    }

    audit(req, { action: 'user_registered', category: 'account', targetUserId: userId, details: { email: body.email, role, auto_verified: true } });
    const token = signToken({ sub: userId, email: body.email });
    res.status(201).json({
      token,
      user: { id: userId, email: body.email, displayName: body.displayName || null, role, email_verified: 1 },
    });
  } catch (e) { next(e); }
});

const LoginSchema2FA = LoginSchema.extend({
  deviceToken: z.string().optional(),
});

router.post('/login', async (req, res, next) => {
  try {
    const body = LoginSchema2FA.parse(req.body);
    const user = db
      .prepare('SELECT id, email, password_hash, display_name, role, email_verified, totp_enabled, status FROM users WHERE email = ?')
      .get(body.email);
    if (!user) {
      audit(req, { action: 'login_failed', category: 'auth', details: { email: body.email, reason: 'user_not_found' } });
      throw new HttpError(401, 'Invalid credentials');
    }

    const ok = bcrypt.compareSync(body.password, user.password_hash);
    if (!ok) {
      audit(req, { action: 'login_failed', category: 'auth', targetUserId: user.id, details: { email: body.email, reason: 'wrong_password' } });
      throw new HttpError(401, 'Invalid credentials');
    }

    if (user.status === 'deactivated') {
      return res.status(403).json({ error: 'Ce compte a été désactivé. Contactez un administrateur.', code: 'ACCOUNT_DEACTIVATED' });
    }
    if (user.status === 'locked') {
      return res.status(403).json({ error: 'Ce compte est verrouillé. Contactez un administrateur.', code: 'ACCOUNT_LOCKED' });
    }

    if (!user.email_verified) {
      return res.status(403).json({
        error: 'Veuillez vérifier votre adresse email avant de vous connecter.',
        code:  'EMAIL_NOT_VERIFIED',
        email: user.email,
      });
    }

    // ── 2FA ──────────────────────────────────────────────────────────────
    if (user.totp_enabled) {
      // Vérifier si l'appareil est déjà de confiance
      if (body.deviceToken) {
        const dev = db.prepare(
          'SELECT id FROM two_fa_trusted_devices WHERE token = ? AND user_id = ? AND expires_at > datetime(\'now\')'
        ).get(body.deviceToken, user.id);
        if (dev) {
          // Appareil de confiance — émettre le JWT directement
          const token = signToken({ sub: user.id, email: user.email });
          return res.json({
            token,
            user: { id: user.id, email: user.email, displayName: user.display_name, role: user.role, email_verified: 1, totp_enabled: 1 },
          });
        }
      }

      // Créer une session 2FA temporaire (5 minutes)
      const sessionToken = crypto.randomBytes(32).toString('hex');
      const expiresAt    = new Date(Date.now() + 5 * 60 * 1000).toISOString();
      db.prepare('INSERT INTO two_fa_sessions (user_id, token, expires_at) VALUES (?,?,?)').run(user.id, sessionToken, expiresAt);

      return res.json({
        requires2FA: true,
        sessionToken,
        email: user.email,
      });
    }

    audit(req, { action: 'login_success', category: 'auth', actorId: user.id, targetUserId: user.id, details: { email: user.email } });
    const token = signToken({ sub: user.id, email: user.email });
    res.json({
      token,
      user: { id: user.id, email: user.email, displayName: user.display_name, role: user.role, email_verified: 1, totp_enabled: 0 },
    });
  } catch (e) { next(e); }
});

router.get('/me', requireAuth, (req, res) => {
  const user = db
    .prepare('SELECT id, email, display_name, role, email_verified, totp_enabled FROM users WHERE id = ?')
    .get(req.user.id);
  res.json({ user });
});

const UpdateMeSchema = z.object({
  displayName:     z.string().min(1).max(80).optional(),
  email:           z.string().email().optional(),
  currentPassword: z.string().optional(),
  newPassword:     z.string().min(8).optional(),
});

router.put('/me', requireAuth, async (req, res, next) => {
  try {
    const body = UpdateMeSchema.parse(req.body);

    const current = db
      .prepare('SELECT id, email, password_hash, display_name, email_verified FROM users WHERE id = ?')
      .get(req.user.id);

    let newHash = undefined;

    if (body.newPassword) {
      if (!body.currentPassword)
        throw new HttpError(400, 'Mot de passe actuel requis');
      const ok = bcrypt.compareSync(body.currentPassword, current.password_hash);
      if (!ok) throw new HttpError(401, 'Mot de passe actuel incorrect');
      newHash = bcrypt.hashSync(body.newPassword, 10);
    }

    if (body.email && body.email !== current.email) {
      const taken = db.prepare('SELECT id FROM users WHERE email = ? AND id != ?').get(body.email, req.user.id);
      if (taken) throw new HttpError(409, 'Email déjà utilisé par un autre compte');
    }

    const newEmail        = body.email       ?? current.email;
    const newDisplayName  = body.displayName !== undefined ? body.displayName : current.display_name;
    const newPasswordHash = newHash ?? current.password_hash;
    const emailChanged    = newEmail !== current.email;
    const newEmailVerified = emailChanged ? 0 : (current.email_verified ?? 1);

    db.prepare(
      "UPDATE users SET email=?, display_name=?, password_hash=?, email_verified=?, updated_at=datetime('now') WHERE id=?"
    ).run(newEmail, newDisplayName, newPasswordHash, newEmailVerified, req.user.id);

    // Si l'email change, envoyer un email de vérification sur la nouvelle adresse
    if (emailChanged) {
      const cfg = getSmtpConfig();
      if (cfg.enabled && cfg.host) {
        try {
          db.prepare('UPDATE email_verification_tokens SET used=1 WHERE user_id=? AND used=0').run(req.user.id);
          const vToken    = crypto.randomBytes(32).toString('hex');
          const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
          db.prepare('INSERT INTO email_verification_tokens (user_id, token, expires_at) VALUES (?,?,?)').run(req.user.id, vToken, expiresAt);
          const appUrl = cfg.appUrl?.replace(/\/$/, '') || '';
          await sendMail({
            to: newEmail,
            subject: `Vérifiez votre nouvelle adresse email — ${cfg.appName}`,
            html: buildEmailHtml({
              title: 'Vérification de votre nouvel email',
              body: `<p>Vous avez modifié votre adresse email. Cliquez ci-dessous pour confirmer cette nouvelle adresse.</p>`,
              ctaLabel: 'Vérifier mon adresse email',
              ctaUrl:   `${appUrl}/verify-email?token=${vToken}`,
            }),
          });
        } catch (_) { /* Ne pas bloquer la réponse si SMTP échoue */ }
      }
    }

    const newToken    = emailChanged ? signToken({ sub: req.user.id, email: newEmail }) : undefined;
    const updatedUser = db.prepare('SELECT id, email, display_name, role, email_verified FROM users WHERE id=?').get(req.user.id);

    res.json({
      user: updatedUser,
      ...(newToken ? { token: newToken } : {}),
      ...(emailChanged ? { requiresVerification: true } : {}),
    });
  } catch (e) { next(e); }
});

// ── Vérification d'adresse email ──────────────────────────────────────────
router.get('/verify-email', (req, res, next) => {
  try {
    const token = req.query.token;
    if (!token) throw new HttpError(400, 'Token manquant.');

    const row = db.prepare(
      `SELECT evt.*, u.id AS uid FROM email_verification_tokens evt
       JOIN users u ON u.id = evt.user_id
       WHERE evt.token = ? AND evt.used = 0`
    ).get(token);

    if (!row) throw new HttpError(400, 'Lien invalide ou déjà utilisé.');
    if (new Date(row.expires_at) < new Date()) throw new HttpError(400, 'Ce lien a expiré. Demandez un nouvel email de vérification.');

    db.prepare("UPDATE users SET email_verified=1, updated_at=datetime('now') WHERE id=?").run(row.uid);
    db.prepare('UPDATE email_verification_tokens SET used=1 WHERE id=?').run(row.id);

    res.json({ ok: true });
  } catch (e) { next(e); }
});

// ── Renvoi de l'email de vérification ─────────────────────────────────────
router.post('/resend-verification', async (req, res, next) => {
  try {
    const { email } = z.object({ email: z.string().email() }).parse(req.body);
    const user = db.prepare('SELECT id, email, display_name, email_verified FROM users WHERE email=?').get(email);

    // Répondre OK même si l'email n'existe pas
    if (!user || user.email_verified) return res.json({ ok: true });

    const cfg = getSmtpConfig();
    if (!cfg.enabled) throw new HttpError(503, "SMTP désactivé — impossible d'envoyer l'email.");

    // Invalider les anciens tokens
    db.prepare('UPDATE email_verification_tokens SET used=1 WHERE user_id=? AND used=0').run(user.id);

    const vToken    = crypto.randomBytes(32).toString('hex');
    const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
    db.prepare('INSERT INTO email_verification_tokens (user_id, token, expires_at) VALUES (?,?,?)').run(user.id, vToken, expiresAt);

    const appUrl = cfg.appUrl?.replace(/\/$/, '') || '';
    const prenom = (user.display_name || user.email).split(' ')[0];

    await sendMail({
      to:      user.email,
      subject: `Vérifiez votre adresse email — ${cfg.appName}`,
      html: buildEmailHtml({
        title: 'Confirmez votre adresse email',
        body: `<p>Bonjour ${prenom},</p>
               <p>Cliquez sur le bouton ci-dessous pour vérifier votre adresse email. Ce lien est valable <strong>24 heures</strong>.</p>`,
        ctaLabel: 'Vérifier mon adresse email',
        ctaUrl:   `${appUrl}/verify-email?token=${vToken}`,
      }),
    });

    res.json({ ok: true });
  } catch (e) { next(e); }
});

// ── Mot de passe oublié ───────────────────────────────────────────────────
router.post('/forgot-password', async (req, res, next) => {
  try {
    const { email } = z.object({ email: z.string().email() }).parse(req.body);
    const user = db.prepare('SELECT id, email, display_name FROM users WHERE email = ?').get(email);

    // Toujours répondre OK pour ne pas divulguer si l'email existe
    if (!user) return res.json({ ok: true });

    const cfg = getSmtpConfig();
    if (!cfg.enabled) throw new HttpError(503, 'La réinitialisation par email n\'est pas disponible (SMTP désactivé).');

    // Invalider les anciens tokens non utilisés
    db.prepare('UPDATE password_reset_tokens SET used = 1 WHERE user_id = ? AND used = 0').run(user.id);

    // Générer un token sécurisé (1h de validité)
    const token     = crypto.randomBytes(32).toString('hex');
    const expiresAt = new Date(Date.now() + 60 * 60 * 1000).toISOString();
    db.prepare('INSERT INTO password_reset_tokens (user_id, token, expires_at) VALUES (?, ?, ?)').run(user.id, token, expiresAt);

    const appUrl   = cfg.appUrl?.replace(/\/$/, '') || '';
    const resetUrl = `${appUrl}/reset-password?token=${token}`;
    const prenom   = (user.display_name || user.email).split(' ')[0];

    await sendMail({
      to:      user.email,
      subject: `Réinitialisation de votre mot de passe — ${cfg.appName}`,
      html: buildEmailHtml({
        title: 'Réinitialisation du mot de passe',
        body: `<p>Bonjour ${prenom},</p>
               <p>Vous avez demandé la réinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour en définir un nouveau. Ce lien est valable <strong>1 heure</strong>.</p>
               <p>Si vous n'êtes pas à l'origine de cette demande, ignorez simplement cet email.</p>`,
        ctaLabel: 'Réinitialiser mon mot de passe',
        ctaUrl:   resetUrl,
      }),
    });

    res.json({ ok: true });
  } catch (e) { next(e); }
});

// ── Réinitialisation du mot de passe ──────────────────────────────────────
router.post('/reset-password', async (req, res, next) => {
  try {
    const { token, password } = z.object({
      token:    z.string().min(1),
      password: z.string().min(8),
    }).parse(req.body);

    const row = db.prepare(
      `SELECT prt.*, u.id AS uid FROM password_reset_tokens prt
       JOIN users u ON u.id = prt.user_id
       WHERE prt.token = ? AND prt.used = 0`
    ).get(token);

    if (!row) throw new HttpError(400, 'Lien invalide ou déjà utilisé.');
    if (new Date(row.expires_at) < new Date()) throw new HttpError(400, 'Ce lien a expiré. Faites une nouvelle demande.');

    const hash = bcrypt.hashSync(password, 10);
    db.prepare("UPDATE users SET password_hash = ?, updated_at = datetime('now') WHERE id = ?").run(hash, row.uid);
    db.prepare('UPDATE password_reset_tokens SET used = 1 WHERE id = ?').run(row.id);

    res.json({ ok: true });
  } catch (e) { next(e); }
});


// ════════════════════════════════════════════════════════════════════════════
// ── 2FA — Configuration TOTP ─────────────────────────────────────────────
// ════════════════════════════════════════════════════════════════════════════

// GET /2fa/setup — génère un secret TOTP + QR code pour l'utilisateur
router.get('/2fa/setup', requireAuth, async (req, res, next) => {
  try {
    const cfg    = getSmtpConfig();
    const issuer = cfg.appName || 'Crowdlending Tracker';
    const user   = db.prepare('SELECT id, email, totp_secret, totp_enabled FROM users WHERE id=?').get(req.user.id);

    // Générer un nouveau secret (ou réutiliser si setup pas encore confirmé)
    const secret = (user.totp_enabled ? null : user.totp_secret) || totpGenerateSecret();

    if (!user.totp_enabled) {
      db.prepare("UPDATE users SET totp_secret=? WHERE id=?").run(secret, req.user.id);
    }

    const uri     = totpGenerateURI({ issuer, label: user.email, secret });
    const qrCode  = await QRCode.toDataURL(uri);

    res.json({ secret, qrCode, issuer, email: user.email, totp_enabled: !!user.totp_enabled });
  } catch (e) { next(e); }
});

// POST /2fa/confirm-setup — vérifie le code TOTP et active le 2FA
router.post('/2fa/confirm-setup', requireAuth, async (req, res, next) => {
  try {
    const { code } = z.object({ code: z.string().length(6) }).parse(req.body);
    const user = db.prepare('SELECT totp_secret, totp_enabled FROM users WHERE id=?').get(req.user.id);
    if (!user.totp_secret) throw new HttpError(400, 'Lancez d\'abord la configuration 2FA.');
    if (user.totp_enabled)  throw new HttpError(400, 'Le 2FA est déjà activé.');
    const valid = totpVerifySync({ token: code, secret: user.totp_secret, strategy: "totp" });
    if (!valid) throw new HttpError(400, 'Code invalide. Réessayez.');

    db.prepare("UPDATE users SET totp_enabled=1 WHERE id=?").run(req.user.id);
    audit(req, { action: '2fa_enabled', category: '2fa', actorId: req.user.id, targetUserId: req.user.id });
    res.json({ ok: true });
  } catch (e) { next(e); }
});

// POST /2fa/disable — désactive le 2FA (mot de passe requis)
router.post('/2fa/disable', requireAuth, async (req, res, next) => {
  try {
    const { password } = z.object({ password: z.string().min(1) }).parse(req.body);

    const user = db.prepare('SELECT password_hash, totp_enabled FROM users WHERE id=?').get(req.user.id);
    if (!user.totp_enabled) throw new HttpError(400, 'Le 2FA n\'est pas activé.');

    const ok = bcrypt.compareSync(password, user.password_hash);
    if (!ok) throw new HttpError(401, 'Mot de passe incorrect.');

    db.prepare("UPDATE users SET totp_enabled=0, totp_secret=NULL WHERE id=?").run(req.user.id);
    // Supprimer tous les appareils de confiance
    db.prepare('DELETE FROM two_fa_trusted_devices WHERE user_id=?').run(req.user.id);
    audit(req, { action: '2fa_disabled', category: '2fa', actorId: req.user.id, targetUserId: req.user.id });

    res.json({ ok: true });
  } catch (e) { next(e); }
});

// ════════════════════════════════════════════════════════════════════════════
// ── 2FA — Vérification lors de la connexion ──────────────────────────────
// ════════════════════════════════════════════════════════════════════════════

// POST /2fa/send-email-code — envoie un OTP par email (flow 2FA)
router.post('/2fa/send-email-code', async (req, res, next) => {
  try {
    const { sessionToken } = z.object({ sessionToken: z.string().min(1) }).parse(req.body);

    const sess = db.prepare(
      "SELECT * FROM two_fa_sessions WHERE token=? AND used=0 AND expires_at > datetime('now')"
    ).get(sessionToken);
    if (!sess) throw new HttpError(401, 'Session expirée. Reconnectez-vous.');

    const user = db.prepare('SELECT id, email, display_name FROM users WHERE id=?').get(sess.user_id);

    // Invalider les anciens codes
    db.prepare('UPDATE two_fa_email_codes SET used=1 WHERE user_id=? AND used=0').run(user.id);

    const code      = String(Math.floor(100000 + Math.random() * 900000));
    const expiresAt = new Date(Date.now() + 5 * 60 * 1000).toISOString();
    db.prepare('INSERT INTO two_fa_email_codes (user_id, code, expires_at) VALUES (?,?,?)').run(user.id, code, expiresAt);

    const cfg = getSmtpConfig();
    if (!cfg.enabled) throw new HttpError(503, "SMTP désactivé — impossible d'envoyer le code.");

    const prenom = (user.display_name || user.email).split(' ')[0];
    await sendMail({
      to: user.email,
      subject: `${code} — Votre code de connexion`,
      html: buildEmailHtml({
        title: 'Code de vérification',
        body: `<p>Bonjour ${prenom},</p>
               <p>Voici votre code de vérification à usage unique :</p>
               <p style="font-size:32px;font-weight:700;letter-spacing:8px;text-align:center;margin:24px 0;">${code}</p>
               <p>Ce code est valable <strong>5 minutes</strong>. Ne le communiquez à personne.</p>`,
      }),
    });

    res.json({ ok: true });
  } catch (e) { next(e); }
});

// POST /2fa/verify — vérifie le code (TOTP ou email) et émet le JWT final
router.post('/2fa/verify', async (req, res, next) => {
  try {
    const { sessionToken, code, method, trustDevice } = z.object({
      sessionToken: z.string().min(1),
      code:         z.string().min(6).max(6),
      method:       z.enum(['totp', 'email']),
      trustDevice:  z.boolean().optional(),
    }).parse(req.body);

    const sess = db.prepare(
      "SELECT * FROM two_fa_sessions WHERE token=? AND used=0 AND expires_at > datetime('now')"
    ).get(sessionToken);
    if (!sess) throw new HttpError(401, 'Session expirée. Reconnectez-vous.');

    const user = db.prepare('SELECT id, email, display_name, role, totp_secret, totp_enabled FROM users WHERE id=?').get(sess.user_id);

    if (method === 'totp') {
    const valid = totpVerifySync({ token: code, secret: user.totp_secret, strategy: "totp" });
      if (!valid) throw new HttpError(400, 'Code invalide.');
    } else {
      // Email OTP
      const row = db.prepare(
        "SELECT id FROM two_fa_email_codes WHERE user_id=? AND code=? AND used=0 AND expires_at > datetime('now')"
      ).get(user.id, code);
      if (!row) throw new HttpError(400, 'Code invalide ou expiré.');
      db.prepare('UPDATE two_fa_email_codes SET used=1 WHERE id=?').run(row.id);
    }

    // Invalider la session 2FA
    db.prepare('UPDATE two_fa_sessions SET used=1 WHERE id=?').run(sess.id);

    // Appareil de confiance (30 jours)
    let deviceToken = null;
    if (trustDevice) {
      deviceToken = crypto.randomBytes(32).toString('hex');
      const devExpires = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString();
      const ua = req.headers['user-agent'] || null;
      const ip = req.headers['x-forwarded-for']?.split(',')[0]?.trim() || req.socket?.remoteAddress || null;
      db.prepare('INSERT INTO two_fa_trusted_devices (user_id, token, expires_at, user_agent, ip_address) VALUES (?,?,?,?,?)').run(user.id, deviceToken, devExpires, ua, ip);
    }

    audit(req, { action: 'login_2fa_success', category: 'auth', actorId: user.id, targetUserId: user.id, details: { method, trustDevice: !!trustDevice } });
    const token = signToken({ sub: user.id, email: user.email });
    res.json({
      token,
      user: { id: user.id, email: user.email, displayName: user.display_name, role: user.role, email_verified: 1, totp_enabled: 1 },
      ...(deviceToken ? { deviceToken } : {}),
    });
  } catch (e) { next(e); }
});


// ════════════════════════════════════════════════════════════════════════════
// ── Appareils de confiance ───────────────────────────────────────────────
// ════════════════════════════════════════════════════════════════════════════

// GET /auth/trusted-devices — liste les appareils de confiance de l'utilisateur
router.get('/trusted-devices', requireAuth, (req, res, next) => {
  try {
    const currentToken = req.headers['x-device-token'] || null;
    const devices = db.prepare(
      "SELECT id, token, user_agent, ip_address, created_at, expires_at, last_seen_at FROM two_fa_trusted_devices WHERE user_id=? AND expires_at > datetime('now') ORDER BY created_at DESC"
    ).all(req.user.id);

    const result = devices.map(d => ({
      id:           d.id,
      isCurrent:    !!(currentToken && d.token === currentToken),
      user_agent:   d.user_agent,
      ip_address:   d.ip_address,
      created_at:   d.created_at,
      expires_at:   d.expires_at,
      last_seen_at: d.last_seen_at,
    }));

    res.json(result);
  } catch (e) { next(e); }
});

// DELETE /auth/trusted-devices/:id — révoquer un appareil
router.delete('/trusted-devices/:id', requireAuth, (req, res, next) => {
  try {
    const id = parseInt(req.params.id, 10);
    const dev = db.prepare('SELECT id FROM two_fa_trusted_devices WHERE id=? AND user_id=?').get(id, req.user.id);
    if (!dev) throw new HttpError(404, 'Appareil introuvable.');
    db.prepare('DELETE FROM two_fa_trusted_devices WHERE id=?').run(id);    db.prepare('DELETE FROM two_fa_trusted_devices WHERE id=?').run(id);
    res.json({ ok: true });
  } catch (e) { next(e); }
});

// DELETE /auth/trusted-devices — révoquer tous les appareils
router.delete('/trusted-devices', requireAuth, (req, res, next) => {
  try {
    db.prepare('DELETE FROM two_fa_trusted_devices WHERE user_id=?').run(req.user.id);
    res.json({ ok: true });
  } catch (e) { next(e); }
});

export default router;
