const {onCall} = require("firebase-functions/v2/https");
const admin = require("firebase-admin");
const nodemailer = require("nodemailer");
const logger = require("firebase-functions/logger");
const {getSmtpConfig, EMAIL_CONFIG} = require("./utils/emailConfig");
const {renderTemplate, getEmailSubject, getAlertTitle, prepareTemplateData, checkAlertPreference} = require("./utils/emailTemplates");

/**
 * Crée une alerte et envoie les notifications
 * Gère tout le processus côté backend de A à Z
 */
const handler = async (request) => {
  try {
    const {auth, data} = request;

    // Vérifier l'authentification
    if (!auth) {
      throw new Error("L'utilisateur doit être authentifié");
    }


    const {
      type,
      severity,
      title,
      message,
      equipmentId,
      eventId,
      actionUrl,
      metadata,
    } = data;

    // Validation des données
    if (!type || !severity || !message) {
      res.status(400).json({error: "type, severity et message sont requis"});
      return;
    }

    // 1. Déterminer les utilisateurs à notifier
    const userIds = await determineTargetUsers(type, severity, eventId);

    if (userIds.length === 0) {
      res.status(400).json({error: "Aucun utilisateur à notifier"});
      return;
    }

    // 2. Créer l'alerte dans Firestore
    const alertRef = admin.firestore().collection("alerts").doc();
    const alertData = {
      id: alertRef.id,
      type,
      severity,
      title: title || getAlertTitle(type),
      message,
      equipmentId: equipmentId || null,
      eventId: eventId || null,
      actionUrl: actionUrl || null,
      metadata: metadata || {},
      assignedTo: userIds,
      createdAt: admin.firestore.FieldValue.serverTimestamp(),
      createdBy: auth.uid,
      isRead: false,
      emailSent: false,
      status: "ACTIVE",
    };

    await alertRef.set(alertData);

    // 3. Envoyer les emails si alerte critique
    let emailResults = {};
    if (severity === "CRITICAL") {
      emailResults = await sendAlertEmails(alertRef.id, alertData, userIds);

      // Mettre à jour le statut d'envoi
      await alertRef.update({
        emailSent: true,
        emailSentAt: admin.firestore.FieldValue.serverTimestamp(),
        emailResults,
      });
    }

    return {
      success: true,
      alertId: alertRef.id,
      usersNotified: userIds.length,
      emailsSent: Object.values(emailResults).filter((v) => v).length,
    };
  } catch (error) {
    logger.error("[createAlert] Erreur:", error);
    throw error;
  }
};

/**
 * Détermine les utilisateurs à notifier selon le type d'alerte
 */
async function determineTargetUsers(alertType, severity, eventId) {
  const db = admin.firestore();
  const targetUserIds = new Set();

  // 1. Récupérer TOUS les utilisateurs pour déterminer lesquels sont admins
  const allUsersSnapshot = await db.collection("users").get();

  allUsersSnapshot.forEach((doc) => {
    const user = doc.data();
    if (user.role) {
      // Le rôle peut être une référence Firestore ou une string
      let rolePath = "";
      if (typeof user.role === "string") {
        rolePath = user.role;
      } else if (user.role.path) {
        rolePath = user.role.path;
      } else if (user.role._path && user.role._path.segments) {
        rolePath = user.role._path.segments.join("/");
      }

      // Vérifier si c'est un admin (path = "roles/ADMIN")
      if (rolePath === "roles/ADMIN" || rolePath === "ADMIN") {
        targetUserIds.add(doc.id);
      }
    }
  });

  // 2. Si un événement est lié, ajouter tous les membres de la workforce
  if (eventId) {
    try {
      const eventDoc = await db.collection("events").doc(eventId).get();

      if (eventDoc.exists) {
        const event = eventDoc.data();
        const workforce = event.workforce || [];

        workforce.forEach((member) => {
          if (member.userId) {
            targetUserIds.add(member.userId);
          }
        });
      } else {
        logger.warn(`[determineTargetUsers] Événement ${eventId} introuvable`);
      }
    } catch (error) {
      logger.error("[determineTargetUsers] Erreur récupération événement:", error);
    }
  }

  return Array.from(targetUserIds);
}

/**
 * Envoie les emails d'alerte à tous les utilisateurs
 */
async function sendAlertEmails(alertId, alertData, userIds) {
  const results = {};
  const transporter = nodemailer.createTransport(getSmtpConfig());

  // Envoyer les emails en parallèle (batch de 5)
  const batches = [];
  for (let i = 0; i < userIds.length; i += 5) {
    batches.push(userIds.slice(i, i + 5));
  }

  for (const batch of batches) {
    const promises = batch.map(async (userId) => {
      try {
        const sent = await sendSingleEmail(transporter, alertId, alertData, userId);
        results[userId] = sent;
      } catch (error) {
        logger.error(`[sendAlertEmails] Erreur email ${userId}:`, error);
        results[userId] = false;
      }
    });

    await Promise.all(promises);
  }


  return results;
}

/**
 * Envoie un email à un utilisateur spécifique
 */
async function sendSingleEmail(transporter, alertId, alertData, userId) {
  const db = admin.firestore();

  // Récupérer l'utilisateur
  const userDoc = await db.collection("users").doc(userId).get();

  if (!userDoc.exists) {
    return false;
  }

  const user = userDoc.data();

  // Vérifier les préférences email
  const prefs = user.notificationPreferences || {};
  if (!prefs.emailEnabled) {
    return false;
  }

  // Vérifier la préférence pour ce type d'alerte
  if (!checkAlertPreference(alertData.type, prefs)) {
    return false;
  }

  if (!user.email) {
    return false;
  }

  try {
    // Préparer les données du template
    const templateData = await prepareTemplateData(alertData, user);

    // Rendre le template
    const html = await renderTemplate("alert-individual", templateData);

    // Envoyer l'email
    await transporter.sendMail({
      from: `"${EMAIL_CONFIG.from.name}" <${EMAIL_CONFIG.from.address}>`,
      to: user.email,
      replyTo: EMAIL_CONFIG.replyTo,
      subject: getEmailSubject(alertData),
      html: html,
      text: alertData.message,
    });

    return true;
  } catch (error) {
    logger.error(`[sendSingleEmail] Erreur envoi à ${userId}:`, error);
    return false;
  }
}

exports.createAlert = onCall({
  cors: true,
  region: "europe-west9",
}, handler);

exports.handler = handler;

