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

module.exports = {
  friendlyName: 'Create Multiple PrimEvaluation',
  description: 'Create multiple PrimEvaluation 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 = ['idEvaluation', 'codeEcole', 'libelle'];
      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 => ({
        idEvaluation: item.idEvaluation
      }));
      
      const existingRecordsMap = await PrimEvaluation.find({
        or: keysToFind
      }).then(records => _.keyBy(records, 'idEvaluation'));
      
      const recordsToCreate = [];
      const receivedLength = inputs.listeElementAjout.length;

      for (const item of inputs.listeElementAjout) {
        const key = item.idEvaluation;
        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 PrimEvaluation.createEach(recordsToCreate)
              .usingConnection(db)
              .fetch();
            successes.push(...createdRecords);
          });
        } catch (transactionError) {
          sails.log.error('Transaction failed for creating PrimEvaluation:', transactionError);
          recordsToCreate.forEach(item => {
            failures.push({
              id: item.idEvaluation,
              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 évaluations 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 évaluations du primaire 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. 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 PrimEvaluation 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,
      });
    }
  }
};