/**
 * update-password-mobile.js
 *
 * @description :: Modification de mot de passe pour l'application mobile
 * @usage :: POST /api/auth/update-password-mobile
 */

let moment = require('moment');

module.exports = {
    friendlyName: 'Update Password Mobile',

    description: 'Modifier le mot de passe depuis l\'application mobile',

    inputs: {
        oldPassword: {
            type: 'string',
            required: true,
            description: 'Ancien mot de passe'
        },
        password: {
            type: 'string',
            required: true,
            description: 'Nouveau mot de passe'
        }
    },

    exits: {
        success: {
            description: 'Mot de passe modifié avec succès'
        },
        invalidInput: {
            description: 'Données d\'entrée invalides',
            statusCode: 400
        },
        userNotFound: {
            description: 'Utilisateur non trouvé',
            statusCode: 404
        },
        invalidOldPassword: {
            description: 'Ancien mot de passe incorrect',
            statusCode: 401
        },
        serverError: {
            description: 'Erreur serveur',
            statusCode: 500
        }
    },

    fn: async function ({ oldPassword, password }, exits) {
        //console.log("🔐 UPDATE PASSWORD MOBILE - Début");
        //console.log("📱 Paramètres:", { oldPassword: oldPassword ? '***' : 'NULL', password: password ? '***' : 'NULL' });

        const ouestDate = moment.utc(new Date()).utcOffset('+01:00');
        const date = ouestDate.format('YYYY-MM-DD');
        const heure = ouestDate.format('HH:mm:ss');

        try {
            // 1. Validation des entrées
            if (!oldPassword || !password) {
                //console.log("❌ Validation échouée: champs manquants");
                await ActivityLogs.create({
                    date,
                    heure,
                    username: this.req.token?.user?.login || 'UNKNOWN',
                    action: "UPDATE_PASSWORD_MOBILE",
                    status: "failed",
                    errorMessage: "Ancien et nouveau mot de passe requis",
                    device: "Mobile"
                });

                return exits.invalidInput({
                    success: false,
                    message: 'Ancien et nouveau mot de passe requis',
                    code: 'MISSING_FIELDS'
                });
            }

            // Validation de la longueur du nouveau mot de passe
            if (password.length < 6) {
                //console.log("❌ Validation échouée: mot de passe trop court");
                await ActivityLogs.create({
                    date,
                    heure,
                    username: this.req.token?.user?.login || 'UNKNOWN',
                    action: "UPDATE_PASSWORD_MOBILE",
                    status: "failed",
                    errorMessage: "Le nouveau mot de passe doit contenir au moins 6 caractères",
                    device: "Mobile"
                });

                return exits.invalidInput({
                    success: false,
                    message: 'Le nouveau mot de passe doit contenir au moins 6 caractères',
                    code: 'PASSWORD_TOO_SHORT'
                });
            }

            // 2. Récupération de l'utilisateur depuis le token
            const { id, user } = this.req.token;
            if (!user || !user.login) {
                //console.log("❌ Token invalide ou utilisateur manquant");
                await ActivityLogs.create({
                    date,
                    heure,
                    username: 'UNKNOWN',
                    action: "UPDATE_PASSWORD_MOBILE",
                    status: "failed",
                    errorMessage: "Token invalide ou utilisateur manquant",
                    device: "Mobile"
                });

                return exits.userNotFound({
                    success: false,
                    message: 'Token invalide ou utilisateur manquant',
                    code: 'INVALID_TOKEN'
                });
            }

            //console.log("👤 Utilisateur identifié:", user.login);

            // 3. Chiffrement de l'ancien mot de passe pour vérification
            let encryptedOldPassword;
            try {
                encryptedOldPassword = await new Promise((resolve, reject) => {
                    sails.config.cryptoUtils.encrypt(oldPassword, (err, result) => {
                        if (err) reject(err);
                        else resolve(result);
                    });
                });
            } catch (encryptError) {
                //console.log("❌ Erreur de chiffrement de l'ancien mot de passe:", encryptError.message);
                await ActivityLogs.create({
                    date,
                    heure,
                    username: user.login,
                    action: "UPDATE_PASSWORD_MOBILE",
                    status: "failed",
                    errorMessage: "Erreur de chiffrement de l'ancien mot de passe",
                    device: "Mobile"
                });

                return exits.serverError({
                    success: false,
                    message: 'Erreur de chiffrement',
                    code: 'ENCRYPTION_ERROR'
                });
            }

            // 4. Vérification de l'ancien mot de passe
            let userToUpdate = await Utilisateurs.findOne({
                id: user.id,
                password: encryptedOldPassword,
                desactiverCompte: false
            });

            // Si l'utilisateur n'est pas trouvé, essayer avec l'ancien format DES
            if (!userToUpdate) {
                try {
                    //console.log("🔄 Tentative avec l'ancien format DES...");

                    // Essayer de déchiffrer avec l'ancien algorithme DES
                    const oldEncryptedPassword = await new Promise((resolve, reject) => {
                        // Utiliser l'ancienne configuration DES
                        const oldCryptoConfig = {
                            password: 'EsupportL@chef@2020',
                            iterations: 20,
                            salt: Buffer.from('de331012de331012', 'hex'),

                            KDF: function (password, salt, iterations) {
                                var pwd = Buffer.from(password, 'utf-8');
                                var key = Buffer.concat([pwd, salt]);
                                var i;
                                for (i = 0; i < iterations; i += 1) {
                                    key = require('crypto').createHash("md5").update(key).digest();
                                }
                                return key;
                            },

                            getKeyIV: function (password, salt, iterations) {
                                var key = this.KDF(password, salt, iterations);
                                var keybuf = Buffer.from(key, 'binary').slice(0, 8);
                                var ivbuf = Buffer.from(key, 'binary').slice(8, 16);
                                return [keybuf, ivbuf];
                            },

                            encrypt: function (payload) {
                                var kiv = this.getKeyIV(this.password, this.salt, this.iterations);
                                var cipher = require('crypto').createCipheriv('des', kiv[0], kiv[1]);
                                var encrypted = [];
                                encrypted.push(cipher.update(payload, 'utf-8', 'hex'));
                                encrypted.push(cipher.final('hex'));
                                return Buffer.from(encrypted.join(''), 'hex').toString('base64');
                            }
                        };

                        resolve(oldCryptoConfig.encrypt(oldPassword));
                    });

                    // Rechercher avec l'ancien format
                    userToUpdate = await Utilisateurs.findOne({
                        id: user.id,
                        password: oldEncryptedPassword,
                        desactiverCompte: false
                    });

                    if (userToUpdate) {
                        //console.log("✅ Utilisateur trouvé avec l'ancien format DES");
                    }
                } catch (migrationError) {
                    //console.log("⚠️ Erreur lors de la vérification avec l'ancien format:", migrationError.message);
                }
            }

            if (!userToUpdate) {
                //console.log("❌ Ancien mot de passe incorrect");
                await ActivityLogs.create({
                    date,
                    heure,
                    username: user.login,
                    action: "UPDATE_PASSWORD_MOBILE",
                    status: "failed",
                    errorMessage: "Ancien mot de passe incorrect",
                    device: "Mobile"
                });

                return exits.invalidOldPassword({
                    success: false,
                    message: 'Ancien mot de passe incorrect',
                    code: 'INVALID_OLD_PASSWORD'
                });
            }

            //console.log("✅ Ancien mot de passe vérifié");

            // 5. Chiffrement du nouveau mot de passe
            let encryptedNewPassword;
            try {
                encryptedNewPassword = await new Promise((resolve, reject) => {
                    sails.config.cryptoUtils.encrypt(password, (err, result) => {
                        if (err) reject(err);
                        else resolve(result);
                    });
                });
            } catch (encryptError) {
                //console.log("❌ Erreur de chiffrement du nouveau mot de passe:", encryptError.message);
                await ActivityLogs.create({
                    date,
                    heure,
                    username: user.login,
                    action: "UPDATE_PASSWORD_MOBILE",
                    status: "failed",
                    errorMessage: "Erreur de chiffrement du nouveau mot de passe",
                    device: "Mobile"
                });

                return exits.serverError({
                    success: false,
                    message: 'Erreur de chiffrement du nouveau mot de passe',
                    code: 'ENCRYPTION_ERROR'
                });
            }

            // 6. Mise à jour du mot de passe
            try {
                await Utilisateurs.updateOne({ id: user.id })
                    .set({
                        password: encryptedNewPassword,
                        dateModification: new Date()
                    });

                //console.log("✅ Mot de passe mis à jour avec succès");
            } catch (updateError) {
                //console.log("❌ Erreur lors de la mise à jour:", updateError.message);
                await ActivityLogs.create({
                    date,
                    heure,
                    username: user.login,
                    action: "UPDATE_PASSWORD_MOBILE",
                    status: "failed",
                    errorMessage: "Erreur lors de la mise à jour du mot de passe",
                    device: "Mobile"
                });

                return exits.serverError({
                    success: false,
                    message: 'Erreur lors de la mise à jour du mot de passe',
                    code: 'UPDATE_ERROR'
                });
            }

            // 7. Journalisation du succès
            await ActivityLogs.create({
                date,
                heure,
                username: user.login,
                action: "UPDATE_PASSWORD_MOBILE",
                status: "success",
                errorMessage: null,
                device: "Mobile"
            });

            // 8. Invalidation des anciens tokens (optionnel - sécurité renforcée)
            try {
                await Token.destroy({ owner: user.id });
                //console.log("🔒 Anciens tokens invalidés pour sécurité");
            } catch (tokenError) {
                //console.log("⚠️ Erreur lors de l'invalidation des tokens:", tokenError.message);
                // Ne pas faire échouer la modification de mot de passe
            }

            // 9. Préparation de la réponse
            const response = {
                success: true,
                message: 'Mot de passe modifié avec succès',
                code: 'PASSWORD_UPDATED',
                timestamp: new Date().toISOString(),
                user: {
                    id: user.id,
                    login: user.login,
                    typeUser: user.typeUser
                }
            };

            //console.log("🎉 UPDATE PASSWORD MOBILE - Succès");
            return exits.success(response);

        } catch (error) {
            //console.error("💥 UPDATE PASSWORD MOBILE - Erreur:", error);
            //console.error("💥 Stack trace:", error.stack);

            // Journalisation de l'erreur
            try {
                await ActivityLogs.create({
                    date,
                    heure,
                    username: this.req.token?.user?.login || 'UNKNOWN',
                    action: "UPDATE_PASSWORD_MOBILE",
                    status: "failed",
                    errorMessage: (error && error.message) || 'Erreur inconnue',
                    device: "Mobile"
                });
            } catch (logError) {
                //console.error("❌ Erreur lors de la journalisation:", logError.message);
            }

            return exits.serverError({
                success: false,
                message: 'Une erreur est survenue lors de la modification du mot de passe',
                code: 'SERVER_ERROR',
                details: error.message
            });
        }
    }
};
