const crypto = require('crypto');
const bcrypt = require('bcrypt');
const { sendEmail } = require('../utils/email');

module.exports = async function (fastify, opts) {
  // Middleware d'authentification pour les routes protégées
  const authenticateUser = async (request, reply) => {
    try {
      await fastify.authenticate(request, reply);
    } catch (err) {
      reply.code(401).send({ error: 'Authentification requise' });
    }
  };

  // Récupérer le profil utilisateur
  fastify.get('/profile', { preHandler: authenticateUser }, async (request, reply) => {
    try {
      const user = await fastify.prisma.user.findUnique({
        where: { id: request.user.id },
        select: {
          id: true,
          email: true,
          name: true,
          subscription: true,
          createdAt: true
        }
      });

      if (!user) {
        return reply.code(404).send({ error: 'Utilisateur non trouvé' });
      }

      return { user };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la récupération du profil' });
    }
  });

  // Mettre à jour le profil utilisateur
  fastify.put('/profile', { preHandler: authenticateUser }, async (request, reply) => {
    try {
      const { name } = request.body;

      if (!name) {
        return reply.code(400).send({ error: 'Le nom est requis' });
      }

      const updatedUser = await fastify.prisma.user.update({
        where: { id: request.user.id },
        data: { name },
        select: {
          id: true,
          email: true,
          name: true,
          subscription: true
        }
      });

      return { user: updatedUser };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la mise à jour du profil' });
    }
  });

  // Changer le mot de passe (utilisateur connecté)
  fastify.put('/change-password', { preHandler: authenticateUser }, async (request, reply) => {
    try {
      const { currentPassword, newPassword } = request.body;

      if (!currentPassword || !newPassword) {
        return reply.code(400).send({ error: 'Les mots de passe actuels et nouveaux sont requis' });
      }

      if (newPassword.length < 8) {
        return reply.code(400).send({ error: 'Le nouveau mot de passe doit contenir au moins 8 caractères' });
      }

      // Vérifier l'utilisateur et son mot de passe actuel
      const user = await fastify.prisma.user.findUnique({
        where: { id: request.user.id }
      });

      if (!user || !user.password) {
        return reply.code(400).send({ error: 'Utilisateur non trouvé ou connecté via Google' });
      }

      const isPasswordValid = await bcrypt.compare(currentPassword, user.password);
      if (!isPasswordValid) {
        return reply.code(400).send({ error: 'Mot de passe actuel incorrect' });
      }

      // Hasher et mettre à jour le nouveau mot de passe
      const hashedPassword = await bcrypt.hash(newPassword, 10);
      await fastify.prisma.user.update({
        where: { id: request.user.id },
        data: { password: hashedPassword }
      });

      return { success: true, message: 'Mot de passe mis à jour avec succès' };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors du changement de mot de passe' });
    }
  });

  // Changer l'email (utilisateur connecté)
  fastify.put('/change-email', { preHandler: authenticateUser }, async (request, reply) => {
    try {
      const { newEmail, password } = request.body;

      if (!newEmail || !password) {
        return reply.code(400).send({ error: 'Le nouvel email et le mot de passe sont requis' });
      }

      // Vérifier si l'email est déjà utilisé
      const existingUser = await fastify.prisma.user.findUnique({
        where: { email: newEmail }
      });

      if (existingUser) {
        return reply.code(400).send({ error: 'Cet email est déjà utilisé' });
      }

      // Vérifier l'utilisateur et son mot de passe
      const user = await fastify.prisma.user.findUnique({
        where: { id: request.user.id }
      });

      if (!user || !user.password) {
        return reply.code(400).send({ error: 'Utilisateur non trouvé ou connecté via Google' });
      }

      const isPasswordValid = await bcrypt.compare(password, user.password);
      if (!isPasswordValid) {
        return reply.code(400).send({ error: 'Mot de passe incorrect' });
      }

      // Mettre à jour l'email
      await fastify.prisma.user.update({
        where: { id: request.user.id },
        data: { email: newEmail }
      });

      return { success: true, message: 'Email mis à jour avec succès' };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors du changement d\'email' });
    }
  });

  // Demande de réinitialisation de mot de passe (utilisateur non connecté)
  fastify.post('/forgot-password', async (request, reply) => {
    try {
      const { email } = request.body;

      if (!email) {
        return reply.code(400).send({ error: 'Email requis' });
      }

      // Vérifier si l'utilisateur existe
      const user = await fastify.prisma.user.findUnique({
        where: { email }
      });

      if (!user) {
        // Pour des raisons de sécurité, ne pas indiquer si l'email existe ou non
        return reply.code(200).send({
          success: true,
          message: 'Si un compte existe avec cet email, un lien de réinitialisation a été envoyé'
        });
      }

      // Générer un token de réinitialisation
      const resetToken = crypto.randomBytes(32).toString('hex');
      const resetTokenExpiry = new Date(Date.now() + 3600000); // 1 heure

      // Stocker le token dans la base de données
      await fastify.prisma.user.update({
        where: { id: user.id },
        data: {
          resetToken,
          resetTokenExpiry
        }
      });

      // Construire l'URL de réinitialisation
      const resetUrl = `${process.env.FRONTEND_URL || 'http://localhost:3000'}/reset-password?token=${resetToken}`;

      try {
        // Envoyer l'email avec Resend
        await sendEmail({
          to: user.email,
          subject: 'Réinitialisation de votre mot de passe',
          text: `Pour réinitialiser votre mot de passe, cliquez sur ce lien: ${resetUrl}`,
          html: `
            <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e0e0e0; border-radius: 5px;">
              <h2 style="color: #f97316;">Réinitialisation de votre mot de passe</h2>
              <p>Bonjour,</p>
              <p>Vous avez demandé la réinitialisation de votre mot de passe. Cliquez sur le bouton ci-dessous pour créer un nouveau mot de passe :</p>
              <div style="text-align: center; margin: 30px 0;">
                <a href="${resetUrl}" style="background-color: #f97316; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; font-weight: bold;">Réinitialiser mon mot de passe</a>
              </div>
              <p>Si vous n'avez pas demandé cette réinitialisation, vous pouvez ignorer cet email.</p>
              <p>Ce lien expirera dans 1 heure.</p>
              <p>Cordialement,<br>L'équipe Freedge</p>
            </div>
          `
        });

        fastify.log.info(`Email de réinitialisation envoyé à ${user.email}`);
      } catch (emailError) {
        // Journaliser l'erreur mais ne pas échouer la requête
        fastify.log.error(`Erreur d'envoi d'email: ${emailError.message}`);

        // En mode développement, afficher le lien dans les logs pour faciliter les tests
        if (process.env.NODE_ENV === 'development') {
          fastify.log.info(`Lien de réinitialisation (DEV ONLY): ${resetUrl}`);
        }
      }

      return {
        success: true,
        message: 'Si un compte existe avec cet email, un lien de réinitialisation a été envoyé'
      };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la demande de réinitialisation de mot de passe' });
    }
  });

  // Réinitialiser le mot de passe avec un token (utilisateur non connecté)
  fastify.post('/reset-password', async (request, reply) => {
    try {
      const { token, newPassword } = request.body;

      if (!token || !newPassword) {
        return reply.code(400).send({ error: 'Token et nouveau mot de passe requis' });
      }

      if (newPassword.length < 8) {
        return reply.code(400).send({ error: 'Le nouveau mot de passe doit contenir au moins 8 caractères' });
      }

      // Trouver l'utilisateur avec ce token
      const user = await fastify.prisma.user.findFirst({
        where: {
          resetToken: token,
          resetTokenExpiry: {
            gt: new Date()
          }
        }
      });

      if (!user) {
        return reply.code(400).send({ error: 'Token invalide ou expiré' });
      }

      // Hasher et mettre à jour le nouveau mot de passe
      const hashedPassword = await bcrypt.hash(newPassword, 10);

      await fastify.prisma.user.update({
        where: { id: user.id },
        data: {
          password: hashedPassword,
          resetToken: null,
          resetTokenExpiry: null
        }
      });

      return { success: true, message: 'Mot de passe réinitialisé avec succès' };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la réinitialisation du mot de passe' });
    }
  });

  // Supprimer le compte utilisateur
  fastify.delete('/account', { preHandler: authenticateUser }, async (request, reply) => {
    try {
      const { password } = request.body;

      // Vérifier l'utilisateur et son mot de passe
      const user = await fastify.prisma.user.findUnique({
        where: { id: request.user.id }
      });

      if (!user) {
        return reply.code(404).send({ error: 'Utilisateur non trouvé' });
      }

      // Si l'utilisateur a un mot de passe (pas connecté via Google), vérifier le mot de passe
      if (user.password) {
        if (!password) {
          return reply.code(400).send({ error: 'Mot de passe requis' });
        }

        const isPasswordValid = await bcrypt.compare(password, user.password);
        if (!isPasswordValid) {
          return reply.code(400).send({ error: 'Mot de passe incorrect' });
        }
      }

      // Supprimer toutes les recettes de l'utilisateur
      await fastify.prisma.recipe.deleteMany({
        where: { userId: user.id }
      });

      // Supprimer l'utilisateur
      await fastify.prisma.user.delete({
        where: { id: user.id }
      });

      return { success: true, message: 'Compte supprimé avec succès' };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la suppression du compte' });
    }
  });
}; 