const {onCall} = require("firebase-functions/v2/https");
const admin = require("firebase-admin");
const logger = require("firebase-functions/logger");

/**
 * Reverts the validation progress of an event to a target step.
 * Resets subsequent step statuses and validation flags of assigned equipment.
 * If rolling back from a completed return, it decrements the consumable stock quantities
 * that were restored during return validation.
 */
const handler = async (request) => {
  try {
    const {auth, data} = request;
    if (!auth) {
      throw new Error("L'utilisateur doit être authentifié");
    }

    const {eventId, targetStep} = data;
    if (!eventId || !targetStep) {
      throw new Error("eventId et targetStep sont requis");
    }

    const db = admin.firestore();
    const eventRef = db.collection("events").doc(eventId);

    await db.runTransaction(async (transaction) => {
      const eventDoc = await transaction.get(eventRef);
      if (!eventDoc.exists) {
        throw new Error("Événement introuvable");
      }

      const event = eventDoc.data();
      const assignedEquipment = event.assignedEquipment || [];

      // Si le retour était complété et qu'on revient en arrière, on doit annuler la restauration des stocks
      const shouldRevertStocks = event.stocksRestored === true;

      if (shouldRevertStocks) {
        // Charger tous les équipements uniques de l'événement pour ajuster leur stock
        const equipmentIds = Array.from(new Set(assignedEquipment.map((eq) => eq.equipmentId).filter(Boolean)));
        const equipmentDocsMap = {};

        for (const eqId of equipmentIds) {
          const eqRef = db.collection("equipments").doc(eqId);
          const eqDoc = await transaction.get(eqRef);
          if (eqDoc.exists) {
            equipmentDocsMap[eqId] = eqDoc.data();
          }
        }

        for (const eq of assignedEquipment) {
          const eqId = eq.equipmentId;
          const equipmentData = equipmentDocsMap[eqId];
          if (!equipmentData) continue;

          const hasQuantity = equipmentData.hasQuantity === true ||
                              equipmentData.category === "CABLE" ||
                              equipmentData.category === "CONSUMABLE";

          if (hasQuantity) {
            // C'est un consommable, on doit déduire la quantité qui avait été restaurée
            const qtyAtRet = Number(eq.quantityAtReturn) || 0;
            if (qtyAtRet > 0) {
              const eqRef = db.collection("equipments").doc(eqId);
              const currentAvailable = Number(equipmentData.availableQuantity) || 0;
              // S'assurer de ne pas descendre en dessous de 0 (ou autoriser le négatif si stock virtuel)
              const newAvailable = Math.max(0, currentAvailable - qtyAtRet);
              transaction.update(eqRef, {
                availableQuantity: newAvailable,
                updatedAt: admin.firestore.FieldValue.serverTimestamp(),
              });
              logger.info(`[rollbackEventStep] Annulé la restauration de ${qtyAtRet} pour ${eqId}. Ancien stock: ${currentAvailable}, Nouveau stock: ${newAvailable}`);
            }
          }
        }
      }

      // Préparer les nouvelles valeurs des étapes
      let prepStatus = event.preparationStatus;
      let loadStatus = event.loadingStatus;
      let unloadStatus = event.unloadingStatus;
      let retStatus = event.returnStatus;

      if (targetStep === 'PREPARATION') {
        prepStatus = 'IN_PROGRESS';
        loadStatus = 'NOT_STARTED';
        unloadStatus = 'NOT_STARTED';
        retStatus = 'NOT_STARTED';
      } else if (targetStep === 'LOADING') {
        loadStatus = 'IN_PROGRESS';
        unloadStatus = 'NOT_STARTED';
        retStatus = 'NOT_STARTED';
      } else if (targetStep === 'UNLOADING') {
        unloadStatus = 'IN_PROGRESS';
        retStatus = 'NOT_STARTED';
      } else if (targetStep === 'RETURN') {
        retStatus = 'IN_PROGRESS';
      } else {
        throw new Error("targetStep invalide. Doit être PREPARATION, LOADING, UNLOADING ou RETURN");
      }

      // Nettoyer les champs de validation des équipements pour les étapes annulées
      const updatedEquipment = assignedEquipment.map((eq) => {
        let isPrepared = eq.isPrepared;
        let isMissingAtPreparation = eq.isMissingAtPreparation;
        let quantityAtPreparation = eq.quantityAtPreparation;

        let isLoaded = eq.isLoaded;
        let isMissingAtLoading = eq.isMissingAtLoading;
        let quantityAtLoading = eq.quantityAtLoading;

        let isUnloaded = eq.isUnloaded;
        let isMissingAtUnloading = eq.isMissingAtUnloading;
        let quantityAtUnloading = eq.quantityAtUnloading;

        let isReturned = eq.isReturned;
        let isMissingAtReturn = eq.isMissingAtReturn;
        let quantityAtReturn = eq.quantityAtReturn;

        if (targetStep === 'PREPARATION') {
          isLoaded = false;
          isMissingAtLoading = false;
          quantityAtLoading = null;
          isUnloaded = false;
          isMissingAtUnloading = false;
          quantityAtUnloading = null;
          isReturned = false;
          isMissingAtReturn = false;
          quantityAtReturn = null;
        } else if (targetStep === 'LOADING') {
          isUnloaded = false;
          isMissingAtUnloading = false;
          quantityAtUnloading = null;
          isReturned = false;
          isMissingAtReturn = false;
          quantityAtReturn = null;
        } else if (targetStep === 'UNLOADING') {
          isReturned = false;
          isMissingAtReturn = false;
          quantityAtReturn = null;
        }

        return {
          ...eq,
          isPrepared,
          isMissingAtPreparation,
          quantityAtPreparation,
          isLoaded,
          isMissingAtLoading,
          quantityAtLoading,
          isUnloaded,
          isMissingAtUnloading,
          quantityAtUnloading,
          isReturned,
          isMissingAtReturn,
          quantityAtReturn,
        };
      });

      // Mettre à jour le document de l'événement
      transaction.update(eventRef, {
        preparationStatus: prepStatus,
        loadingStatus: loadStatus,
        unloadingStatus: unloadStatus,
        returnStatus: retStatus,
        assignedEquipment: updatedEquipment,
        stocksRestored: false,
        updatedAt: admin.firestore.FieldValue.serverTimestamp(),
      });
    });

    logger.info(`[rollbackEventStep] Événement ${eventId} réinitialisé avec succès à l'étape ${targetStep}`);
    return {success: true};
  } catch (error) {
    logger.error("[rollbackEventStep] Erreur:", error);
    throw error;
  }
};

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

exports.handler = handler;
