/**
 * webhook.js
 *
 * @description :: Webhook FedaPay: réception des événements de transaction
 */

module.exports = {
    friendlyName: 'Webhook FedaPay',

    description: 'Réception et traitement des événements de paiement FedaPay',

    inputs: {},

    exits: {
        success: {
            description: 'Webhook traité',
            responseType: 'ok'
        },
        badRequest: {
            description: 'Requête invalide',
            responseType: 'badRequest'
        },
        tooManyRequests: {
            description: 'Trop de requêtes',
            responseType: 'tooManyRequests'
        }
    },

    fn: async function (inputs, exits) {
        try {
            const axios = require('axios');
            const cfg = sails.config.externalApis.fedapay || {};
            const base = cfg.env === 'live' ? 'https://api.fedapay.com/v1' : 'https://sandbox-api.fedapay.com/v1';
            const apiKey = cfg.apiKey;

            // === FONCTION MAPPING MÉTHODE DE PAIEMENT FEDAPAY ===
            const mapFedaPayModeToMethod = (fedapayMode) => {
                if (!fedapayMode) return 'fedapay';

                const mode = fedapayMode.toLowerCase();

                // Mobile Money
                if (['moov', 'mtn', 'celtis', 'orange', 'm-pesa', 'mobile_money'].includes(mode)) {
                    return 'mobile_money';
                }

                // Cartes bancaires
                if (['visa', 'mastercard', 'card', 'carte'].includes(mode)) {
                    return 'carte_bancaire';
                }

                // Virements
                if (['virement', 'transfer', 'bank', 'banque'].includes(mode)) {
                    return 'virement';
                }

                // Par défaut, retourner 'fedapay' pour traçabilité
                return 'fedapay';
            };

            // === RATE LIMITING ===
            const clientIP = this.req.ip || this.req.connection.remoteAddress;
            const rateLimitKey = `fedapay_webhook:${clientIP}`;
            const maxRequests = 10; // Max 10 webhooks par minute par IP
            const windowMs = 60 * 1000; // 1 minute

            // Vérifier le rate limiting si Redis est disponible
            if (sails.redis) {
                try {
                    const currentCount = await sails.redis.get(rateLimitKey);

                    if (currentCount && parseInt(currentCount) >= maxRequests) {
                        sails.log.warn('Rate limit dépassé pour webhook FedaPay', {
                            ip: clientIP,
                            count: currentCount,
                            max: maxRequests,
                            timestamp: new Date().toISOString()
                        });
                        return exits.tooManyRequests({
                            message: 'Trop de requêtes, veuillez réessayer plus tard',
                            retryAfter: Math.ceil(windowMs / 1000)
                        });
                    }

                    // Incrémenter le compteur
                    await sails.redis.incr(rateLimitKey);
                    await sails.redis.expire(rateLimitKey, windowMs / 1000);
                } catch (error) {
                    sails.log.error('Erreur rate limiting webhook FedaPay:', error);
                    // En cas d'erreur Redis, permettre la requête mais logger
                }
            }

            // === LOGS DE SÉCURITÉ ===
            const securityLog = {
                timestamp: new Date().toISOString(),
                ip: clientIP,
                userAgent: this.req.headers['user-agent'] || 'Unknown',
                method: this.req.method,
                url: this.req.url,
                headers: {
                    'x-fedapay-signature': this.req.headers['x-fedapay-signature'] ? 'PRESENT' : 'MISSING',
                    'x-signature': this.req.headers['x-signature'] ? 'PRESENT' : 'MISSING',
                    'content-type': this.req.headers['content-type'] || 'MISSING'
                }
            };

            // Récupération du payload webhook
            const event = this.req.body || {};

            // === ADAPTATION FEDAPAY ===
            // FedaPay peut envoyer les données via query parameters OU body JSON
            // Format détecté: /webhook?status=approved&id=351756
            const queryParams = this.req.query || {};

            // Fusion des données: body JSON + query parameters
            const fedapayData = {
                ...event,
                status: event?.data?.status || event?.status || queryParams.status || '',
                id: event?.data?.id || event?.transaction_id || event?.id || queryParams.id || null,
                // Si pas de metadata dans le body, essayer de les récupérer via l'API FedaPay
                metadata: event?.data?.metadata || event?.metadata || {}
            };

            securityLog.payloadSize = JSON.stringify(fedapayData).length;
            securityLog.eventType = fedapayData?.type || fedapayData?.event || 'unknown';
            securityLog.queryParams = Object.keys(queryParams).length > 0 ? queryParams : 'NONE';
            securityLog.bodyData = Object.keys(event).length > 0 ? 'PRESENT' : 'EMPTY';

            // Vérification (optionnelle) signature si FEDAPAY_WEBHOOK_SECRET fourni
            const providedSig = this.req.headers['x-fedapay-signature'] || this.req.headers['x-signature'];
            if (cfg.webhookSecret) {
                if (!providedSig || providedSig !== cfg.webhookSecret) {
                    securityLog.signatureValidation = 'FAILED';
                    securityLog.reason = 'Signature invalide ou manquante';
                    sails.log.warn('Webhook FedaPay signature invalide - Log de sécurité:', securityLog);
                    return exits.badRequest({ message: 'Signature invalide' });
                }
                securityLog.signatureValidation = 'SUCCESS';
            } else {
                securityLog.signatureValidation = 'SKIPPED';
                securityLog.reason = 'Aucune clé secrète configurée';
            }

            // Extraire l'id de transaction Fedapay si présent
            const fedapayId = fedapayData.id;
            let meta = fedapayData.metadata;
            let status = fedapayData.status.toString().toLowerCase();

            // Initialiser trx avec un objet vide pour éviter "trx is not defined"
            let trx = {};

            securityLog.fedapayId = fedapayId;
            securityLog.status = status;
            securityLog.metadata = {
                codeAbonnement: meta?.codeAbonnement ? 'PRESENT' : 'MISSING',
                codeParent: meta?.codeParent ? 'PRESENT' : 'MISSING',
                codeEcole: meta?.codeEcole ? 'PRESENT' : 'MISSING'
            };

            // Si id présent, récupérer l'objet transaction pour fiabiliser
            if (fedapayId && apiKey) {
                try {
                    const headers = { Authorization: `Bearer ${apiKey}` };
                    const resp = await axios.get(`${base}/transactions/${fedapayId}`, { headers });

                    // === STRUCTURE FEDAPAY RÉELLE ===
                    // FedaPay retourne "v1/transaction" et non "transaction"
                    const trx = resp.data?.['v1/transaction'] || resp.data?.transaction || resp.data || {};

                    // === GESTION MÉTADONNÉES FEDAPAY ===
                    // FedaPay retourne à la fois metadata ET custom_metadata
                    // Priorité: custom_metadata > metadata (nouveau format)
                    const customMetadata = trx.custom_metadata || {};
                    const oldMetadata = trx.metadata || {};

                    // === NORMALISATION DES NOMS DE CHAMPS ===
                    // FedaPay utilise des underscores, nous utilisons du camelCase
                    const normalizedCustomMetadata = {
                        codeAbonnement: customMetadata.code_abonnement || customMetadata.codeAbonnement,
                        codeParent: customMetadata.code_parent || customMetadata.codeParent,
                        codeEcole: customMetadata.code_ecole || customMetadata.codeEcole,
                        codeOffre: customMetadata.code_offre || customMetadata.codeOffre,
                        reference: customMetadata.reference
                    };

                    // Fusion intelligente des métadonnées (priorité custom_metadata normalisé)
                    meta = { ...oldMetadata, ...normalizedCustomMetadata };

                    // Mise à jour du statut et autres données selon la structure FedaPay exacte
                    status = (trx.status || status || '').toLowerCase();
                    fedapayData.amount = trx.amount;
                    // FedaPay retourne currency_id, pas l'objet devise
                    fedapayData.currency = trx.currency_id ? `CURRENCY_${trx.currency_id}` : 'XOF';
                    fedapayData.reference = trx.merchant_reference || trx.reference;

                    // === MAPPING MÉTHODE DE PAIEMENT FEDAPAY ===
                    // FedaPay retourne "mode" (ex: "moov", "mtn", "orange", "visa", "mastercard")
                    const fedapayMode = trx.mode || trx.payment_method || 'unknown';
                    const mappedPaymentMethod = mapFedaPayModeToMethod(fedapayMode);
                    fedapayData.paymentMethod = mappedPaymentMethod;
                    fedapayData.fedaPayMode = fedapayMode;

                    securityLog.apiValidation = 'SUCCESS';
                    securityLog.verifiedAmount = trx.amount;
                    securityLog.verifiedCurrencyId = trx.currency_id;
                    securityLog.retrievedMetadata = meta;
                    securityLog.merchantReference = trx.merchant_reference;
                    securityLog.customMetadata = customMetadata;
                    securityLog.oldMetadata = oldMetadata;
                    securityLog.normalizedMetadata = normalizedCustomMetadata;
                    securityLog.metadataFusion = 'SUCCESS';
                    securityLog.fedaPayMode = fedapayMode;
                    securityLog.mappedPaymentMethod = mappedPaymentMethod;

                    sails.log.info('Métadonnées FedaPay récupérées et normalisées:', {
                        custom_metadata: customMetadata,
                        metadata: oldMetadata,
                        normalized: normalizedCustomMetadata,
                        fusion: meta,
                        transactionId: fedapayId,
                        currency_id: trx.currency_id,
                        merchant_reference: trx.merchant_reference,
                        responseStructure: Object.keys(resp.data || {})
                    });

                } catch (e) {
                    securityLog.apiValidation = 'FAILED';
                    securityLog.apiError = e.response?.data || e.message;
                    sails.log.warn('Impossible de récupérer la transaction FedaPay:', e.response?.data || e.message);
                }
            } else {
                securityLog.apiValidation = 'SKIPPED';
                securityLog.reason = 'Pas d\'ID ou d\'API key';
            }

            const codeAbonnement = meta?.codeAbonnement;
            const codeParent = meta?.codeParent;
            const codeEcole = meta?.codeEcole;

            // === GESTION MÉTADONNÉES MANQUANTES ===
            if (!codeAbonnement) {
                // Essayer de récupérer les métadonnées via l'API FedaPay si pas encore fait
                if (fedapayId && apiKey && !meta?.codeAbonnement) {
                    try {
                        sails.log.info('Tentative de récupération des métadonnées via API FedaPay pour ID:', fedapayId);
                        const headers = { Authorization: `Bearer ${apiKey}` };
                        const resp = await axios.get(`${base}/transactions/${fedapayId}`, { headers });
                        const trx = resp.data?.transaction || resp.data || {};

                        // === RÉCUPÉRATION MÉTADONNÉES FEDAPAY ===
                        const customMetadata = trx.custom_metadata || {};
                        const oldMetadata = trx.metadata || {};

                        // === NORMALISATION DES NOMS DE CHAMPS ===
                        const normalizedCustomMetadata = {
                            codeAbonnement: customMetadata.code_abonnement || customMetadata.codeAbonnement,
                            codeParent: customMetadata.code_parent || customMetadata.codeParent,
                            codeEcole: customMetadata.code_ecole || customMetadata.codeEcole,
                            codeOffre: customMetadata.code_offre || customMetadata.codeOffre,
                            reference: customMetadata.reference
                        };

                        // Fusion des métadonnées (priorité custom_metadata normalisé)
                        const recoveredMetadata = { ...oldMetadata, ...normalizedCustomMetadata };

                        if (recoveredMetadata && recoveredMetadata.codeAbonnement) {
                            meta = recoveredMetadata;
                            securityLog.metadataRecovery = 'SUCCESS';
                            securityLog.recoveredMetadata = meta;
                            securityLog.recoverySource = 'custom_metadata + metadata fusion (normalisé)';
                            securityLog.recoveryDetails = {
                                custom_metadata: customMetadata,
                                metadata: oldMetadata,
                                normalized: normalizedCustomMetadata,
                                fusion: recoveredMetadata
                            };
                            sails.log.info('Métadonnées récupérées avec succès via API FedaPay:', {
                                custom_metadata: customMetadata,
                                metadata: oldMetadata,
                                normalized: normalizedCustomMetadata,
                                fusion: recoveredMetadata,
                                transactionId: fedapayId,
                                currency_id: trx.currency_id,
                                merchant_reference: trx.merchant_reference
                            });
                        } else {
                            securityLog.metadataRecovery = 'FAILED';
                            securityLog.reason = 'Aucune métadonnée trouvée dans custom_metadata ou metadata de la transaction FedaPay';
                            securityLog.transactionData = {
                                id: trx.id,
                                status: trx.status,
                                merchant_reference: trx.merchant_reference,
                                custom_metadata: customMetadata,
                                metadata: oldMetadata,
                                normalized_metadata: normalizedCustomMetadata,
                                reference: trx.reference,
                                currency_id: trx.currency_id
                            };
                            sails.log.warn('Aucune métadonnée trouvée dans la transaction FedaPay:', {
                                id: trx.id,
                                custom_metadata: customMetadata,
                                metadata: oldMetadata,
                                normalized_metadata: normalizedCustomMetadata,
                                merchant_reference: trx.merchant_reference,
                                currency_id: trx.currency_id
                            });
                        }
                    } catch (e) {
                        securityLog.metadataRecovery = 'ERROR';
                        securityLog.recoveryError = e.response?.data || e.message;
                        sails.log.error('Erreur lors de la récupération des métadonnées:', e.message);
                    }
                }

                // Vérifier à nouveau après tentative de récupération
                if (!meta?.codeAbonnement) {
                    securityLog.abonnementValidation = 'FAILED';
                    securityLog.reason = 'Metadata codeAbonnement manquant - Impossible de récupérer via API FedaPay';
                    securityLog.finalMetadata = meta;
                    securityLog.availableFields = {
                        custom_metadata: meta,
                        merchant_reference: fedapayData.reference,
                        transaction_id: fedapayId,
                        metadata_structure: {
                            has_custom_metadata: Object.keys(meta).length > 0,
                            has_codeAbonnement: !!meta?.codeAbonnement,
                            available_keys: Object.keys(meta)
                        }
                    };
                    sails.log.warn('Webhook FedaPay - Metadata manquant après tentative de récupération - Log de sécurité:', securityLog);
                    return exits.badRequest({
                        message: 'Metadata codeAbonnement manquant',
                        fedapayId: fedapayId,
                        availableMetadata: meta,
                        merchantReference: fedapayData.reference,
                        suggestion: 'Vérifiez que custom_metadata ou metadata contient codeAbonnement lors de la création de la transaction FedaPay',
                        debug: {
                            transactionId: fedapayId,
                            availableKeys: Object.keys(meta),
                            metadataStructure: {
                                custom_metadata: Object.keys(meta).length > 0 ? 'PRESENT' : 'EMPTY',
                                has_codeAbonnement: !!meta?.codeAbonnement
                            }
                        }
                    });
                }
            }

            // Mettre à jour les variables après récupération potentielle des métadonnées
            const finalCodeAbonnement = meta?.codeAbonnement;
            const finalCodeParent = meta?.codeParent;
            const finalCodeEcole = meta?.codeEcole;

            // Charger l'abonnement
            const abonnement = await Abonnement.findOne({ codeAbonnement: finalCodeAbonnement, codeEcole: finalCodeEcole });
            if (!abonnement) {
                securityLog.abonnementValidation = 'NOT_FOUND';
                securityLog.reason = 'Abonnement introuvable';
                securityLog.searchedCodeAbonnement = finalCodeAbonnement;
                securityLog.searchedCodeEcole = finalCodeEcole;
                sails.log.warn('Abonnement introuvable pour webhook FedaPay:', finalCodeAbonnement, finalCodeEcole);
                sails.log.info('Log de sécurité webhook FedaPay:', securityLog);
                return exits.success({ message: 'Ok (abonnement introuvable)' });
            }

            securityLog.abonnementValidation = 'SUCCESS';
            securityLog.abonnementId = abonnement.id;

            // Déterminer succès/échec
            const successStatuses = ['approved', 'completed', 'paid', 'succeeded', 'success'];
            const failedStatuses = ['canceled', 'failed', 'expired', 'refused', 'declined', 'error'];

            if (successStatuses.includes(status)) {
                securityLog.paymentStatus = 'SUCCESS';

                // Tolérance sur le montant si envoyé
                const tolerance = 100;
                const paidAmount = Number(fedapayData.amount || abonnement.montantFinal);
                if (Math.abs(paidAmount - abonnement.montantFinal) > tolerance) {
                    securityLog.amountValidation = 'WARNING';
                    securityLog.amountDiscrepancy = Math.abs(paidAmount - abonnement.montantFinal);
                    sails.log.warn('Montant incohérent FedaPay', { paidAmount, attendu: abonnement.montantFinal });
                } else {
                    securityLog.amountValidation = 'SUCCESS';
                }

                // Créer la transaction interne si non déjà existante (idempotence simple via reference)
                const reference = fedapayData.reference || `FDY_${finalCodeAbonnement}`;
                // Utiliser la méthode de paiement mappée depuis FedaPay
                const finalPaymentMethod = fedapayData.paymentMethod || 'fedapay';

                // Récupérer les informations de frais depuis FedaPay
                const fraisTransaction = Number(trx?.fees || 0);
                const receiptUrl = trx?.receipt_url || '';

                // Pas d'unicité stricte ici, on peut ajouter une vérification simple selon ref
                await TransactionAbonnement.create({
                    codeEcole: abonnement.codeEcole,
                    abonnement: abonnement.id,
                    codeAbonnement: abonnement.codeAbonnement,
                    codeParent: abonnement.codeParent,
                    typeTransaction: 'paiement',
                    statut: status, // Utiliser le statut FedaPay directement
                    montant: paidAmount,
                    devise: (abonnement.devise || 'XOF'),
                    methodePaiement: finalPaymentMethod,
                    operateur: 'fedapay',
                    operateurId: fedapayId,
                    modePaiement: fedapayData.fedaPayMode || 'unknown',
                    referencePaiement: reference,
                    fraisTransaction: fraisTransaction,
                    montantNet: paidAmount - fraisTransaction,
                    receiptUrl: receiptUrl,
                    dateTransaction: new Date(), // Ajout de la date de transaction
                    description: `Paiement FedaPay (${fedapayData.fedaPayMode || 'unknown'}) pour abonnement ${abonnement.codeAbonnement}`,
                    donneesTechniques: {
                        webhook: fedapayData,
                        fedapayId,
                        queryParams,
                        fedaPayMode: fedapayData.fedaPayMode,
                        mappedPaymentMethod: finalPaymentMethod,
                        frais: fraisTransaction,
                        receiptUrl: receiptUrl,
                        commission: trx?.commission,
                        amountTransferred: trx?.amount_transferred,
                        amountDebited: trx?.amount_debited
                    }
                });

                securityLog.transactionCreated = 'SUCCESS';
                securityLog.transactionReference = reference;

                // Activer l'abonnement avec recalage des dates
                const now = new Date();
                const offreActivation = await OffreAbonnement.findOne({ codeOffre: abonnement.codeOffre });
                let newDateDebut = abonnement.dateDebut;
                let newDateFin = abonnement.dateFin;
                if (offreActivation && now > new Date(abonnement.dateDebut)) {
                    newDateDebut = now;
                    const tmpFin = new Date(newDateDebut);
                    tmpFin.setDate(tmpFin.getDate() + (offreActivation.dureeJours || 0));
                    newDateFin = tmpFin;
                }
                const abonnementMisAJour = await Abonnement.updateOne({ codeAbonnement: abonnement.codeAbonnement, codeEcole: abonnement.codeEcole })
                    .set({ statut: 'actif', methodePaiement: 'fedapay', referencePaiement: reference, datePaiement: now, dateDebut: newDateDebut, dateFin: newDateFin });

                securityLog.abonnementActivated = 'SUCCESS';

                // Notifier l'utilisateur
                const utilisateur = await Utilisateurs.findOne({ codeUser: abonnement.codeParent, codeEcole: abonnement.codeEcole });
                const offre = await OffreAbonnement.findOne({ codeOffre: abonnement.codeOffre });

                // Vérifier que l'offre existe
                if (!offre) {
                    securityLog.offreValidation = 'NOT_FOUND';
                    securityLog.reason = 'Offre introuvable pour la notification';
                    securityLog.searchedCodeOffre = abonnement.codeOffre;
                    securityLog.searchedCodeEcole = abonnement.codeEcole;
                    sails.log.warn('Offre introuvable pour la notification webhook FedaPay:', abonnement.codeOffre, abonnement.codeEcole);
                    sails.log.info('Log de sécurité webhook FedaPay (offre manquante):', securityLog);
                    return exits.success({ message: 'OK (offre introuvable)' });
                }

                securityLog.offreValidation = 'SUCCESS';
                securityLog.offreId = offre.id;

                // Vérifier que l'utilisateur existe (optionnel mais recommandé)
                if (!utilisateur) {
                    securityLog.utilisateurValidation = 'NOT_FOUND';
                    securityLog.reason = 'Utilisateur introuvable pour la notification';
                    securityLog.searchedCodeUser = abonnement.codeParent;
                    securityLog.searchedCodeEcole = abonnement.codeEcole;
                    sails.log.warn('Utilisateur introuvable pour la notification webhook FedaPay:', abonnement.codeParent, abonnement.codeEcole);
                    // On continue car on peut utiliser les données du parent comme fallback
                } else {
                    securityLog.utilisateurValidation = 'SUCCESS';
                    securityLog.utilisateurId = utilisateur.id;
                }

                const notification = await NotificationAbonnement.create({
                    abonnement: abonnement.id,
                    codeEcole: abonnement.codeEcole,
                    codeAbonnement: abonnement.codeAbonnement,
                    codeParent: abonnement.codeParent,
                    typeNotification: 'paiement_reussi',
                    titre: 'Paiement réussi',
                    message: `Votre paiement a été confirmé. Votre abonnement est maintenant actif.`,
                    priorite: 'normale',
                    statut: 'non_lue',
                    dateEnvoi: new Date() // Ajout de la date d'envoi
                }).fetch();

                // === ENVOI IMMÉDIAT DE LA NOTIFICATION (APPROCHE HYBRIDE) ===
                try {
                    sails.log.info(`Tentative d'envoi immédiat de la notification ${notification.codeNotification}...`);

                    await sails.helpers.sendAbonnementNotification.with({
                        notification,
                        user: utilisateur,
                        abonnement: abonnementMisAJour || abonnement,
                        offre,
                        transaction: {
                            montant: paidAmount,
                            devise: abonnement.devise || 'XOF',
                            methodePaiement: finalPaymentMethod,
                            referencePaiement: reference,
                            dateTransaction: new Date(),
                            fedaPayMode: fedapayData.fedaPayMode
                        }
                    });

                    // Mise à jour du statut de la notification
                    await NotificationAbonnement.updateOne({ codeNotification: notification.codeNotification, codeEcole: abonnement.codeEcole })
                        .set({
                            statut: 'envoyee',
                            statutEnvoi: {
                                email: 'envoye',
                                whatsapp: 'envoye',
                                sms: 'envoye'
                            },
                            dateDerniereTentative: new Date(),
                            nombreTentatives: 1
                        });

                    securityLog.notificationSent = 'IMMEDIATE_SUCCESS';
                    securityLog.notificationChannels = 'email,whatsapp,sms';
                    sails.log.info(`✅ Notification ${notification.codeNotification} envoyée immédiatement avec succès`);

                } catch (e) {
                    // En cas d'échec, la notification reste en statut 'non_lue' pour traitement différé
                    securityLog.notificationSent = 'IMMEDIATE_FAILED';
                    securityLog.notificationError = e.message;
                    securityLog.notificationRetryStrategy = 'DIFFERED_PROCESSING';

                    // Mise à jour du statut pour indiquer l'échec de l'envoi immédiat
                    try {
                        await NotificationAbonnement.updateOne({ codeNotification: notification.codeNotification, codeEcole: abonnement.codeEcole })
                            .set({
                                statut: 'non_lue', // Reste en attente pour le helper
                                statutEnvoi: {
                                    email: 'non_envoye',
                                    whatsapp: 'non_envoye',
                                    sms: 'non_envoye'
                                },
                                erreurEnvoi: `Envoi immédiat échoué: ${e.message}`,
                                dateDerniereTentative: new Date(),
                                nombreTentatives: 1
                            });
                    } catch (updateError) {
                        sails.log.error('Erreur lors de la mise à jour du statut de notification:', updateError);
                    }

                    sails.log.warn(`⚠️ Envoi immédiat de la notification ${notification.codeNotification} échoué. Sera traité par le helper. Erreur: ${e.message}`);
                }

                // Log final de succès
                sails.log.info('Webhook FedaPay traité avec succès - Log de sécurité:', securityLog);
                return exits.success({ message: 'OK' });
            }

            if (failedStatuses.includes(status)) {
                securityLog.paymentStatus = 'FAILED';

                // Enregistrer une transaction échouée
                const failedPaymentMethod = fedapayData.paymentMethod || 'fedapay';
                const fraisTransaction = Number(trx?.fees || 0);
                const receiptUrl = trx?.receipt_url || '';

                await TransactionAbonnement.create({
                    codeEcole: abonnement.codeEcole,
                    abonnement: abonnement.id,
                    codeAbonnement: abonnement.codeAbonnement,
                    codeParent: abonnement.codeParent,
                    typeTransaction: 'paiement',
                    statut: status, // Utiliser le statut FedaPay (failed, declined, etc.)
                    montant: Number(fedapayData.amount || 0),
                    devise: abonnement.devise || 'XOF',
                    methodePaiement: failedPaymentMethod,
                    operateur: 'fedapay',
                    operateurId: fedapayId,
                    modePaiement: fedapayData.fedaPayMode || 'unknown',
                    referencePaiement: fedapayData.reference,
                    fraisTransaction: fraisTransaction,
                    montantNet: Number(fedapayData.amount || 0) - fraisTransaction,
                    receiptUrl: receiptUrl,
                    dateTransaction: new Date(), // Ajout de la date de transaction
                    donneesTechniques: {
                        webhook: fedapayData,
                        fedapayId,
                        queryParams,
                        fedaPayMode: fedapayData.fedaPayMode,
                        mappedPaymentMethod: failedPaymentMethod,
                        frais: fraisTransaction,
                        receiptUrl: receiptUrl,
                        commission: trx?.commission,
                        amountTransferred: trx?.amount_transferred,
                        amountDebited: trx?.amount_debited
                    }
                });

                securityLog.transactionCreated = 'FAILED_TRANSACTION';
                sails.log.info('Webhook FedaPay - Paiement échoué - Log de sécurité:', securityLog);
                return exits.success({ message: 'OK (échec)' });
            }

            // Statut non décisif (pending, etc.)
            securityLog.paymentStatus = 'PENDING';
            securityLog.reason = 'Statut non décisif';
            sails.log.info('Webhook FedaPay - Statut en attente - Log de sécurité:', securityLog);
            return exits.success({ message: 'OK (pending)' });

        } catch (error) {
            // Log d'erreur avec contexte de sécurité
            const errorLog = {
                timestamp: new Date().toISOString(),
                ip: this.req?.ip || this.req?.connection?.remoteAddress || 'Unknown',
                error: error.message,
                stack: error.stack,
                context: 'Webhook FedaPay'
            };

            sails.log.error('Erreur webhook FedaPay:', error);
            sails.log.error('Log d\'erreur de sécurité:', errorLog);
            return exits.badRequest({ message: 'Bad webhook', error: error.message });
        }
    }
}; 