const _ = require('lodash');
require('dotenv').config();

module.exports = {
  friendlyName: 'Create Multiple PrimNoteDet',
  description: 'Create multiple PrimNoteDet records in bulk, with a detailed response format.',

  inputs: {
    listeElementAjout: {
      type: 'ref',
      required: true,
      custom: (value) => Array.isArray(value) && value.length > 0
    },
    logiUsername: {
      type: 'string',
      required: true
    },
    key: {
      type: 'string',
      required: true
    },
    logiPassword: {
      type: 'string',
      required: true
    }
  },

  exits: {
    notFound: {
      description: 'The user or token was not found or is invalid.',
      statusCode: 404
    },
    invalidInput: {
      description: 'Some provided items are missing required fields or the input is not an array.',
      statusCode: 400
    },
    serverError: {
      description: 'An unexpected server error occurred.',
      statusCode: 500
    },
    success: {
      description: 'The batch creation process was completed.',
      statusCode: 200
    }
  },

  fn: async function (inputs, exits) {
    const successes = [];
    const failures = [];
    const existings = [];
    const now = Date.now();

    try {
      // 1. Authentication & Authorization
      const user = await Utilisateurs.findOne({
        login: inputs.logiUsername,
        codeUser: inputs.logiPassword
      });

      if (!user) {
        return exits.notFound({
          message: 'Utilisateur non trouvé ou informations d\'identification non valides.'
        });
      }

      const keyVerify = process.env.KEYVERIFY;
      if (inputs.key !== keyVerify) {
        return exits.notFound({
          message: "Token non valide"
        });
      }

      // 2. Input Validation
      if (!Array.isArray(inputs.listeElementAjout)) {
        return exits.invalidInput({
          message: 'L\'entrée doit être un tableau.',
        });
      }

      const requiredFields = ['IdNoteDet', 'CodNote', 'codeEcole', 'matricule', 'anneeScolaire'];
      const invalidItems = inputs.listeElementAjout.filter(item =>
        !requiredFields.every(field => field in item)
      );

      if (invalidItems.length > 0) {
        return exits.invalidInput({
          message: 'Certains éléments manquent de champs requis.',
          invalidItems: invalidItems.map(item => _.pick(item, requiredFields))
        });
      }

      // 3. Existing Records Check
      const keysToFind = inputs.listeElementAjout.map(item => ({
        IdNoteDet: item.IdNoteDet
      }));

      const existingRecordsMap = await PrimNoteDet.find({
        or: keysToFind
      }).then(records => _.keyBy(records, 'IdNoteDet'));

      const recordsToCreate = [];

      for (const item of inputs.listeElementAjout) {
        const key = item.IdNoteDet;
        if (!existingRecordsMap[key]) {
          recordsToCreate.push(item);
        } else {
          existings.push(existingRecordsMap[key]);
        }
      }

      // 4. Bulk Insert
      if (recordsToCreate.length > 0) {
        try {
          await sails.getDatastore().transaction(async (db) => {
            const createdRecords = await PrimNoteDet.createEach(recordsToCreate)
              .usingConnection(db)
              .fetch();
            successes.push(...createdRecords);
          });
        } catch (transactionError) {
          sails.log.error('Transaction failed for creating PrimNoteDet:', transactionError);
          recordsToCreate.forEach(item => {
            failures.push({
              id: item.IdNoteDet,
              message: `Échec de la sauvegarde en raison d'une erreur de transaction : ${transactionError.message || 'Erreur inconnue'}`
            });
          });
        }
      }

      // 5. Determine overall status and prepare response
      let overallStatus = 'success';
      let message = 'Le traitement par lot des notes détaillées du primaire est terminé.';

      if (failures.length > 0 && successes.length === 0 && existings.length === 0) {
        overallStatus = 'failure';
        message = 'Le traitement par lot a échoué pour tous les éléments fournis.';
      } else if (inputs.listeElementAjout.length === 0) {
        message = 'Aucun élément fourni pour le traitement.';
      } else if (successes.length > 0 || existings.length > 0) {
        overallStatus = failures.length > 0 ? 'partial_success' : 'success';
        if (overallStatus === 'success') {
          message = 'Toutes les nouvelles notes détaillées ont été ajoutées avec succès.';
        } else {
          message = 'Le traitement est terminé avec des succès, des échecs et/ou des éléments existants.';
        }
      }

      // 6. Envoi d'une notification push unique par parent (fin de requête)
      try {
        if (successes.length > 0) {
          const impactedMatricules = _.uniq(successes.map(r => r.matricule).filter(Boolean));
          const impactedEcoles = _.uniq(successes.map(r => r.codeEcole).filter(Boolean));
          if (impactedMatricules.length > 0) {
            const filiations = await Filiation.find({ matricule: { in: impactedMatricules }, codeEcole: { in: impactedEcoles } });
            const codeParents = _.uniq(filiations.map(f => f.codeParent).filter(Boolean));
            if (codeParents.length > 0) {
              const tokens = await PushToken.find({ codeUser: { in: codeParents } });
              const tokenList = _.uniq(tokens.map(t => t.fcmToken).filter(Boolean));
              if (tokenList.length > 0) {
                const title = 'Mise à jour des notes';
                const body = 'De nouvelles notes ont été enregistrées pour votre enfant.';
                const data = { route: '/notifications', type: 'notes_update', createdCount: String(successes.length) };
                await sails.helpers.sendFcm.with({ tokens: tokenList, title, body, data });
              }
            }
          }
        }
      } catch (notifyErr) {
        sails.log.warn('Envoi FCM (note-det-multi) échoué:', notifyErr.message || notifyErr);
      }

      // 7. Return response
      return exits.success({
        status: overallStatus,
        message: message,
        successes: successes,
        failures: failures,
        existings: existings,
        createdAt: now,
      });

    } catch (err) {
      sails.log.error('Error processing batch PrimNoteDet creation:', err);
      return exits.serverError({
        status: 'error',
        message: 'Une erreur interne du serveur est survenue lors du traitement par lot.',
        error: err.message,
        createdAt: now,
      });
    }
  }
};