/**
 * create.js
 *
 * @description :: Créer un nouvel abonnement pour un parent
 * @help        :: Voir http://sailsjs.com/#!/documentation/concepts/Controllers
 */

module.exports = {
    friendlyName: 'Créer un abonnement',

    description: 'Créer un nouvel abonnement pour un parent',

    inputs: {
        /*codeParent: {
            type: 'string',
            //required: true,
            description: 'Code du parent'
        },
        codeEcole: {
            type: 'string',
            //required: true,
            description: 'Code de l\'école'
        },*/
        codeOffre: {
            type: 'string',
            required: true,
            description: 'Code de l\'offre d\'abonnement'
        },
        codePromotion: {
            type: 'string',
            allowNull: true,
            description: 'Code promotionnel optionnel'
        },
        // Paiement optionnel inline
        methodePaiement: {
            type: 'string',
            isIn: ['mobile_money', 'carte_bancaire', 'virement', 'especes', 'gratuit'],
            allowNull: true,
            description: 'Méthode de paiement'
        },
        montant: {
            type: 'number',
            description: 'Montant payé (pour paiement inline)'
        },
        devise: {
            type: 'string',
            description: 'Devise du paiement (ex: XOF)'
        },
        referencePaiement: {
            type: 'string',
            description: 'Référence de paiement externe'
        },
        operateur: {
            type: 'string',
            description: 'Opérateur de paiement (pour mobile money)'
        },
        numeroTelephone: {
            type: 'string',
            description: 'Numéro de téléphone utilisé pour le paiement'
        },
        fraisTransaction: {
            type: 'number',
            description: 'Frais de transaction'
        },
        description: {
            type: 'string',
            description: 'Description du paiement (optionnel)'
        },
        donneesTechniques: {
            type: 'json',
            description: 'Données techniques du paiement (optionnel)'
        },
        renouvellementAuto: {
            type: 'boolean',
            defaultsTo: false,
            description: 'Activer le renouvellement automatique'
        },
        commentaires: {
            type: 'string',
            allowNull: true,
            description: 'Commentaires additionnels'
        }
    },

    exits: {
        success: {
            description: 'Abonnement créé avec succès',
            responseType: 'ok'
        },
        offreNonTrouvee: {
            description: 'L\'offre spécifiée n\'existe pas',
            responseType: 'notFound'
        },
        parentNonTrouve: {
            description: 'Le parent spécifié n\'existe pas',
            responseType: 'notFound'
        },
        promotionInvalide: {
            description: 'Le code promotionnel est invalide',
            responseType: 'badRequest'
        },
        abonnementExistant: {
            description: 'Un abonnement actif existe déjà pour ce parent',
            responseType: 'conflict'
        },
        montantIncorrect: {
            description: 'Le montant payé ne correspond pas au montant attendu',
            responseType: 'badRequest'
        },
        essaiDejaUtilise: {
            description: 'Un abonnement d\'essai a déjà été utilisé par ce parent',
            responseType: 'conflict'
        },
        error: {
            description: 'Erreur interne'
        }
    },

    fn: async function (inputs, exits) {
        const { id, user } = this.req.token;
        console.log('inputs', inputs);
        // VERIFICATION DU CODE ECOLE
        if (user.codeEcole === '' || user.codeEcole === null || user.codeEcole === undefined) {
            return exits.notFound({ message: "Veuillez préciser le code Ecole pour cet utulisateur pour a accéder a cette page!" })
        }
        const ecoleVerif = await Ecoles.find({ codeEcole: user.codeEcole }).then(_.first)
        if (!ecoleVerif) {
            return exits.notFound({ message: "Cet utilisateur n'est attribué a aucune classe!" })
        }

        try {
            // Vérifier que le parent existe
            const parent = await Parents.findOne({ codeParent: user.codeUser, codeEcole: user.codeEcole });
            if (!parent) {
                return exits.parentNonTrouve({
                    message: 'Parent non trouvé',
                    code: 'PARENT_NOT_FOUND'
                });
            }

            // Charger l'utilisateur (coordonnées à jour)
            const utilisateur = await Utilisateurs.findOne({ codeUser: user.codeUser, codeEcole: user.codeEcole });

            // Vérifier que l'offre existe et est active
            const offre = await OffreAbonnement.findOne({
                //codeEcole: user.codeEcole,
                codeOffre: inputs.codeOffre,
                actif: true
            });
            if (!offre) {
                return exits.offreNonTrouvee({
                    message: 'Offre non trouvée ou inactive',
                    code: 'OFFRE_NOT_FOUND'
                });
            }

            // Règle: un parent ne peut avoir qu'un seul abonnement d'essai à vie (pas de renouvellement)
            if (offre.typeAbonnement === 'essai') {
                const essaiExistant = await Abonnement.find({
                    codeParent: user.codeUser,
                    codeEcole: user.codeEcole,
                    typeAbonnement: 'essai'
                }).limit(1);
                if (essaiExistant && essaiExistant.length) {
                    return exits.essaiDejaUtilise({
                        message: "L'abonnement d'essai a déjà été utilisé pour ce parent.",
                        code: 'TRIAL_ALREADY_USED'
                    });
                }
            }

            // Vérifier qu'il n'y a pas déjà un abonnement actif
            const abonnementExistant = await Abonnement.findOne({
                codeParent: user.codeUser,
                codeEcole: user.codeEcole,
                statut: { in: ['actif', 'essai'] }
            });
            if (abonnementExistant) {
                return exits.abonnementExistant({
                    message: 'Un abonnement actif existe déjà pour ce parent',
                    code: 'SUBSCRIPTION_ALREADY_EXISTS'
                });
            }

            // Réutiliser un abonnement en attente de paiement existant pour la même offre
            const enAttenteList = await Abonnement.find({
                codeParent: user.codeUser,
                codeEcole: user.codeEcole,
                codeOffre: inputs.codeOffre,
                statut: 'en_attente_paiement'
            }).sort('createdAt DESC').limit(1);
            const abonnementEnAttente = enAttenteList && enAttenteList.length ? enAttenteList[0] : null;
            if (abonnementEnAttente) {
                return exits.success({
                    message: 'Abonnement en attente existant. Reprenez le paiement.',
                    data: abonnementEnAttente
                });
            }

            // Valider le code promotionnel si fourni
            let montantReduction = 0;
            let promotion = null;
            if (inputs.codePromotion) {
                promotion = await PromotionAbonnement.findOne({
                    codePromotion: inputs.codePromotion,
                    //codeEcole: user.codeEcole,
                    actif: true
                });

                if (!promotion) {
                    return exits.promotionInvalide({
                        message: 'Code promotionnel invalide',
                        code: 'INVALID_PROMOTION'
                    });
                }

                // Vérifier la validité temporelle
                const maintenant = new Date();
                if (promotion.dateDebut > maintenant || promotion.dateFin < maintenant) {
                    return exits.promotionInvalide({
                        message: 'Code promotionnel expiré ou non encore valide',
                        code: 'PROMOTION_EXPIRED'
                    });
                }

                // Vérifier le nombre d'utilisations
                if (promotion.nombreUtilisationsMax &&
                    promotion.nombreUtilisationsActuelles >= promotion.nombreUtilisationsMax) {
                    return exits.promotionInvalide({
                        message: 'Code promotionnel épuisé',
                        code: 'PROMOTION_EXHAUSTED'
                    });
                }

                // Vérifier les utilisations par parent
                const utilisationsParent = promotion.parentsUtilises.filter(p => p.codeParent === user.codeUser).length;
                if (utilisationsParent >= promotion.nombreUtilisationsParParent) {
                    return exits.promotionInvalide({
                        message: 'Code promotionnel déjà utilisé par ce parent',
                        code: 'PROMOTION_ALREADY_USED'
                    });
                }

                // Calculer la réduction
                if (promotion.typeReduction === 'pourcentage') {
                    montantReduction = (offre.montant * promotion.valeurReduction) / 100;
                } else if (promotion.typeReduction === 'montant_fixe') {
                    montantReduction = promotion.valeurReduction;
                } else if (promotion.typeReduction === 'gratuit') {
                    montantReduction = offre.montant;
                }
            }

            // Calculer les dates
            const dateDebut = new Date();
            const dateFin = new Date(dateDebut);
            dateFin.setDate(dateFin.getDate() + offre.dureeJours);

            // Déterminer le statut initial
            let statutInitial = 'en_attente_paiement';
            if (offre.montant === 0 || inputs.methodePaiement === 'gratuit') {
                statutInitial = 'actif';
            } else if (offre.typeAbonnement === 'essai') {
                statutInitial = 'essai';
            }

            // Créer l'abonnement
            const nouvelAbonnement = await Abonnement.create({
                offre: offre.id,
                codeParent: user.codeUser,
                codeEcole: user.codeEcole,
                codeOffre: inputs.codeOffre,
                codePromotion: inputs.codePromotion,
                typeAbonnement: offre.typeAbonnement,
                statut: statutInitial,
                dateDebut: dateDebut,
                dateFin: dateFin,
                montant: offre.montant,
                devise: offre.devise,
                montantReduction: montantReduction,
                montantFinal: offre.montant - montantReduction,
                methodePaiement: inputs.methodePaiement,
                renouvellementAuto: inputs.renouvellementAuto,
                commentaires: inputs.commentaires
            }).fetch();

            // Mettre à jour le compteur d'utilisations de la promotion
            if (promotion) {
                await PromotionAbonnement.updateOne({ codePromotion: inputs.codePromotion, codeEcole: user.codeEcole })
                    .set({
                        nombreUtilisationsActuelles: promotion.nombreUtilisationsActuelles + 1,
                        parentsUtilises: [...promotion.parentsUtilises, {
                            codeParent: user.codeUser,
                            dateUtilisation: new Date()
                        }]
                    });
            }

            // Notifications immédiates si actif/essai
            if (statutInitial === 'actif' || statutInitial === 'essai') {
                const notification = await NotificationAbonnement.create({
                    abonnement: nouvelAbonnement.id,
                    codeEcole: user.codeEcole,
                    codeAbonnement: nouvelAbonnement.codeAbonnement,
                    codeParent: user.codeUser,
                    typeNotification: statutInitial === 'essai' ? 'essai_commence' : 'abonnement_active',
                    titre: statutInitial === 'essai' ? 'Période d\'essai commencée' : 'Abonnement activé',
                    message: statutInitial === 'essai'
                        ? `Votre période d'essai de ${offre.nom} a commencé. Elle se termine le ${dateFin.toLocaleDateString('fr-FR')}.`
                        : `Votre abonnement ${offre.nom} a été activé avec succès.`,
                    priorite: 'normale',
                    statut: 'non_lue',
                    dateEnvoi: new Date(), // Champ requis manquant
                    canauxEnvoi: ['push', 'email', 'sms'], // Valeur par défaut
                    statutEnvoi: { // Valeur par défaut
                        push: 'non_envoye',
                        email: 'non_envoye',
                        sms: 'non_envoye'
                    }
                }).fetch();

                try {
                    await sails.helpers.sendAbonnementNotification.with({
                        notification: notification,
                        user: utilisateur,
                        parent: parent,
                        abonnement: nouvelAbonnement,
                        offre: offre
                    });
                } catch (notificationError) {
                    sails.log.error('Erreur lors de l\'envoi de la notification:', notificationError);
                }
            }

            // Paiement inline (optionnel): si encore en attente de paiement et infos fournies
            let transaction = null;
            let abonnementFinal = nouvelAbonnement;
            if (
                statutInitial === 'en_attente_paiement' &&
                inputs.methodePaiement && inputs.montant && inputs.devise
            ) {
                const tolerance = 100; // 100 XOF de tolérance
                if (Math.abs(inputs.montant - nouvelAbonnement.montantFinal) > tolerance) {
                    return exits.montantIncorrect({
                        message: `Le montant payé (${inputs.montant}) ne correspond pas au montant attendu (${nouvelAbonnement.montantFinal})`,
                        code: 'INCORRECT_AMOUNT',
                        montantAttendu: nouvelAbonnement.montantFinal,
                        montantPaye: inputs.montant
                    });
                }

                // Créer la transaction
                const frais = inputs.fraisTransaction || 0;
                transaction = await TransactionAbonnement.create({
                    abonnement: nouvelAbonnement.id,
                    codeEcole: user.codeEcole,
                    codeAbonnement: nouvelAbonnement.codeAbonnement,
                    codeParent: nouvelAbonnement.codeParent,
                    typeTransaction: 'paiement',
                    statut: 'reussi',
                    montant: inputs.montant,
                    devise: inputs.devise,
                    methodePaiement: inputs.methodePaiement,
                    referencePaiement: inputs.referencePaiement,
                    operateur: inputs.operateur,
                    numeroTelephone: inputs.numeroTelephone,
                    fraisTransaction: frais,
                    montantNet: inputs.montant - frais,
                    description: inputs.description || `Paiement pour abonnement ${nouvelAbonnement.codeAbonnement}`,
                    donneesTechniques: inputs.donneesTechniques || {},
                    dateTransaction: new Date(),
                    dateConfirmation: new Date()
                }).fetch();

                // Mettre à jour l'abonnement -> actif
                abonnementFinal = await Abonnement.updateOne({ codeAbonnement: nouvelAbonnement.codeAbonnement, codeEcole: user.codeEcole })
                    .set({
                        statut: 'actif',
                        methodePaiement: inputs.methodePaiement,
                        referencePaiement: inputs.referencePaiement,
                        datePaiement: new Date()
                    });

                // Notification de paiement réussi
                const notifPay = await NotificationAbonnement.create({
                    abonnement: nouvelAbonnement.id,
                    codeEcole: user.codeEcole,
                    codeAbonnement: nouvelAbonnement.codeAbonnement,
                    codeParent: nouvelAbonnement.codeParent,
                    typeNotification: 'paiement_reussi',
                    titre: 'Paiement réussi',
                    message: `Votre paiement de ${inputs.montant} ${inputs.devise} a été traité avec succès. Votre abonnement est maintenant actif.`,
                    priorite: 'normale',
                    statut: 'non_lue',
                    dateEnvoi: new Date(), // Champ requis manquant
                    canauxEnvoi: ['push', 'email', 'sms'], // Valeur par défaut
                    statutEnvoi: { // Valeur par défaut
                        push: 'non_envoye',
                        email: 'non_envoye',
                        sms: 'non_envoye'
                    }
                }).fetch();

                try {
                    await sails.helpers.sendAbonnementNotification.with({
                        notification: notifPay,
                        user: utilisateur,
                        parent: parent,
                        abonnement: abonnementFinal,
                        offre: offre,
                        transaction: transaction
                    });
                } catch (notificationError) {
                    sails.log.error('Erreur lors de l\'envoi de la notification de paiement:', notificationError);
                }
            }

            console.log('📦 Réponse create abonnement:', {
                message: transaction ? 'Abonnement créé et paiement effectué avec succès' : 'Abonnement créé avec succès',
                data: transaction ? { abonnement: abonnementFinal, transaction } : nouvelAbonnement
            });
            return exits.success({
                message: transaction ? 'Abonnement créé et paiement effectué avec succès' : 'Abonnement créé avec succès',
                data: transaction ? { abonnement: abonnementFinal, transaction } : nouvelAbonnement
            });


        } catch (error) {
            sails.log.error('Erreur lors de la création de l\'abonnement:', error);
            const errMsg = error && error.message ? error.message : 'Erreur interne du serveur';
            return exits.error(new Error(errMsg));
        }
    }
}; 