#! /usr/bin/env python3.6
"""
Python 3.6 or newer required.
"""
import pymongo
import stripe
import json
import os

from flask import Flask, render_template, jsonify, request
from dotenv import load_dotenv, find_dotenv
import GlobalVariable as MYSY_GV
from pymongo import ReturnDocument
import prj_common as mycommon

import inspect
import sys, os
import time
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
import email_mgt as email_mgt
import lms_chamilo.mysy_lms as mysy_lms

# Setup Stripe python client library
load_dotenv(find_dotenv())

# For sample support and debugging, not required for production:
stripe.set_app_info(
    'stripe-samples/subscription-use-cases/fixed-price',
    version='0.0.1',
    url='https://github.com/stripe-samples/subscription-use-cases/fixed-price')

stripe.api_version = '2020-08-27'
stripe.api_key = MYSY_GV.STRIPE_CONFIG_API_KEY

#static_dir = str(os.path.abspath(os.path.join(__file__, "..", os.getenv("STATIC_DIR"))))
static_dir = "./"
app = Flask(__name__, static_folder=static_dir, static_url_path="", template_folder=static_dir)


@app.route('/', methods=['GET'])
def get_index():
    return render_template('register.html')


@app.route('/config', methods=['GET'])
def get_config():
    # Retrieves two prices with the lookup_keys
    # `sample_basic` and `sample_premium`.  To
    # create these prices, you can use the Stripe
    # CLI fixtures command with the supplied
    # `seed.json` fixture file like so:
    #
    #    stripe fixtures seed.json
    #

    prices = stripe.Price.list(

    )

    return jsonify(
        publishableKey= MYSY_GV.STRIPE_CONFIG_KEY_PUB,
        prices=prices.data,
    )

"""
Creation d'un client dans Stripe
"""

def create_customer(diction):
    # Reads application/json and returns a response
    #data = json.loads(request.data)
    try:

        field_list = ['name', 'email', 'country', 'city']

        # recuperation des infos du partenaire
        cust_name = ""
        if ("name" in diction.keys()):
            if diction['name']:
                cust_name = diction['name']

        cust_email = ""
        if ("email" in diction.keys()):
            if diction['email']:
                cust_email = diction['email']

        cust_country = ""
        if ("country" in diction.keys()):
            if diction['country']:
                cust_country = diction['country']

        cust_city = ""
        if ("city" in diction.keys()):
            if diction['city']:
                cust_city = diction['city']


        # Create a new customer object
        #customer = stripe.Customer.create(email=data['email'])
        customer = stripe.Customer.create(
            email=cust_email,
            name=cust_name,
            address={
                "city": cust_city,
                "country": cust_country,
            },
        )

        if( customer and customer.id ):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - le partenaire "+str(cust_email)+" a été correctement créé dans Stripe. Son Id = "+str(customer.id))
            return True, str(customer.id)
        else:
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " WARNING - Impossble de créer le partenaire " + str(
                    cust_email) + " Stripe.")
            return False, False


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, False


"""
Recuperation des mode de payement d'un customer
"""
def get_customer_payement_cards(diction):
    try:

        field_list = ['stripe_account_id']
        # recuperation des infos du partenaire
        stripe_account_id = ""
        if ("stripe_account_id" in diction.keys()):
            if diction['stripe_account_id']:
                stripe_account_id = diction['stripe_account_id']

        customer_payments = stripe.Customer.list_payment_methods(
            str(stripe_account_id),
            type="card",
        )

        #print(" ### customer_payments = "+str(customer_payments.data))

        RetObject = []
        nb_carte = 0
        for val in customer_payments.data :
            nb_carte = nb_carte + 1
            my_card = {}
            my_card['nom_carte'] = str(val.billing_details.name)
            my_card['brand'] = str(val.card.brand)
            my_card['exp_month'] = str(val.card.exp_month)
            my_card['exp_year'] = str(val.card.exp_year)
            my_card['last4'] = str(val.card.last4)
            my_card['createdatetime'] = str( datetime.fromtimestamp(int(str(val.created))) )


            RetObject.append(mycommon.JSONEncoder().encode(my_card))



        #print(" ### RetObject = "+str( RetObject ))

        return True, RetObject, str(nb_carte)
    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, False, False

"""
Creation d'une carte de payement
"""
def create_update_payment_card(diction):
    try:

        field_list_obligatoire = ['name', 'number', 'exp_month', 'exp_year', 'cvc', 'customerid', 'stripe_paymentmethod_id']
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de créer el moyen de payement"

        name = ""
        if ("name" in diction.keys()):
            if diction['name']:
                name = diction['name']

        number = ""
        if ("number" in diction.keys()):
            if diction['number']:
                number = diction['number']

        exp_month = ""
        if ("exp_month" in diction.keys()):
            if diction['exp_month']:
                exp_month = diction['exp_month']

        exp_year = ""
        if ("exp_year" in diction.keys()):
            if diction['exp_year']:
                exp_year = diction['exp_year']

        cvc = ""
        if ("cvc" in diction.keys()):
            if diction['cvc']:
                cvc = diction['cvc']

        customer_id = ""
        if ("customerid" in diction.keys()):
            if diction['customerid']:
                customer_id = diction['customerid']

        stripe_paymentmethod_id = ""
        if ("stripe_paymentmethod_id" in diction.keys()):
            if diction['stripe_paymentmethod_id']:
                stripe_paymentmethod_id = diction['stripe_paymentmethod_id']


        """
        /!\ IMPORTANT : 
        Si Le champ "stripe_paymentmethod_id" est rempli alors c'est une mise à jour :
         a) on detache
         b) on créer la nouvelle carte 
         c) on rattacjhe
        
        Si Le champ "stripe_paymentmethod_id" est vide, alors c'est une creation + Attachement au client
        """
        print(" ## stripe_paymentmethod_id existe. donc suppression de  = "+str(stripe_paymentmethod_id))
        if (len(stripe_paymentmethod_id) > 2):
            print(" ### UPDATE  ==> detache")
            detache = stripe.PaymentMethod.detach(
                stripe_paymentmethod_id,
            )

            #print(" #### detache "+str(detache))




        #print(" ### CREATE ")
        new_card = stripe.PaymentMethod.create(
              type="card",
              card={
                "number": number,
                "exp_month": int(exp_month),
                "exp_year": int(exp_year),
                "cvc": cvc,
              },
            billing_details={
                "name": str(name)
                },
            )

        #print(" new_card = "+str(new_card))

        #print(" l'ID de la carte est : "+str(new_card.id))



        attache = stripe.PaymentMethod.attach(
            str(new_card.id),
            customer=str(customer_id),
        )

        #print(" attache = "+str(attache))

        return True, new_card
    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, False


"""
Cette fonction confirme un abonnement 
"""
def confirm_suscription(diction):
    try:
        field_list_obligatoire = ['stripe_payment_id','token']
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de créer el moyen de payement", False, False


        stripe_payment_id = ""
        if ("stripe_payment_id" in diction.keys()):
            if diction['stripe_payment_id']:
                stripe_payment_id = diction['stripe_payment_id']

        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        # Recuperation du payement methode du client.
        local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
            {'token': token, 'active': '1', 'locked': '0'})

        if (local_ret_val['stripe_paymentmethod_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible de finaliser le payement")
            return False, " Impossible de finaliser le payement  ", False, False

         # Recuperation de la dernière commande du client
        cmd_ret_val = MYSY_GV.dbname['sales_order'].find(
            {'client_recid': str(local_ret_val['recid']), 'valide': '1'}).sort([("_id",pymongo.DESCENDING) ])

        if(cmd_ret_val[0] is None or cmd_ret_val[0]['order_id'] is None ):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible de finaliser le payement")
            return False, " Impossible de finaliser le payement  ", False, False

        cmd_order_id = cmd_ret_val[0]['order_id']
        mydata_update = {'stripe_pi':stripe_payment_id}

        ### Mise à jour de la commande avec le payement id
        local_update_val = MYSY_GV.dbname['sales_order'].find_one_and_update(
            {'order_id':str(cmd_order_id)},
            {"$set": mydata_update},
            upsert=False,
            return_document=ReturnDocument.AFTER
        )

        if (local_update_val['_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible de finaliser le payement 2")
            return False, " Impossible de finaliser le payement (2) ", False, False

        #print(" ### stripe_payment_id = ", stripe_payment_id, "  ### stripe_paymentmethod_id = ", local_ret_val['stripe_paymentmethod_id'])
        confirmation_payement  = stripe.PaymentIntent.confirm(
            stripe_payment_id,
            payment_method=str(local_ret_val['stripe_paymentmethod_id']),
            return_url= MYSY_GV.CLIENT_URL_BASE+"OrderConfirmation_3DS/"+str(cmd_order_id)+"/"+str(local_ret_val['pack_service'])

        )

        """
        /!\ : le client a demarré un payement.
        1 - je supprimer son pack abonnement  pour se premunir d'un echec au prelevement
        2 - Je remettrai le bon pack lors qu'il aura confirmé
        
        """
        ### Mise à jour de la commande avec le payement id
        local_update_cust = MYSY_GV.dbname['partnair_account'].find_one_and_update(
            {'token': token, 'active': '1', 'locked': '0'},
            {"$set": {'pack_service':'', }},
            upsert=False,
            return_document=ReturnDocument.AFTER
        )

        if (local_update_cust['_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible de finaliser le payement 3")
            return False, " Impossible de finaliser le payement (3) ", False, False

        #print(' #### confirmation_payement = ', confirmation_payement)
        myredirect_to_url = ""
        if( confirmation_payement.next_action and confirmation_payement.next_action.redirect_to_url and confirmation_payement.next_action.redirect_to_url.url ):
            myredirect_to_url = confirmation_payement.next_action.redirect_to_url.url
        else:
            myredirect_to_url = MYSY_GV.CLIENT_URL_BASE+"OrderConfirmation_3DS/"+str(cmd_order_id)+"/"+str(local_ret_val['pack_service'])

        return True, confirmation_payement.id, confirmation_payement.status, myredirect_to_url


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, False, False, False

"""
Cette fonction verifier si un payement est ok ou Ko"""
def payment_retrieve_status(diction):
    try:
        field_list_obligatoire = ['stripe_payment_id','token', 'packs']
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de verifier le payement les données obligatoires ne sont pas fournies",


        stripe_payment_id = ""
        if ("stripe_payment_id" in diction.keys()):
            if diction['stripe_payment_id']:
                stripe_payment_id = diction['stripe_payment_id']

        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        packs = ""
        if ("packs" in diction.keys()):
            if diction['packs']:
                packs = diction['packs']

        # Recuperation du payement methode du client.
        local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
            {'token': token, 'active': '1', 'locked': '0'})

        if (local_ret_val['stripe_paymentmethod_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible de verifier le payement 'stripe_paymentmethod_id' instrouvable  ")
            return False, " Impossible de verifier le payement 'stripe_paymentmethod_id' instrouvable  "


        payement_retrive_status  = stripe.PaymentIntent.retrieve(
            stripe_payment_id,
        )

        #print(" ### payement_retrive_status = ", payement_retrive_status, )

        if( payement_retrive_status is None or payement_retrive_status['status'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " le Payement "+str(stripe_payment_id)+" n'est pas validé")
            return False, " le Payement "+str(stripe_payment_id)+" n'est pas validé"

        if( payement_retrive_status['status']  and str(payement_retrive_status['status'] ).strip() == "succeeded" ):

            #On reactive le pack du partner
            local_coll_name = MYSY_GV.dbname['partnair_account']

            now = datetime.now()
            ret_val = local_coll_name.find_one_and_update({'token': token, 'active': '1', 'locked': '0', 'pack_service':''},
                                                          {"$set":
                                                               {"pack_service": str(packs).lower(),
                                                                "date_update": str(now)}
                                                           },
                                                          upsert=False,
                                                          return_document=ReturnDocument.AFTER
                                                          )

            mycommon.myprint(
                str(inspect.stack()[0][3]) + " le Payement "+str(stripe_payment_id)+" est  validé")
            return True, " le Payement "+str(stripe_payment_id)+" est  validé"

        mycommon.myprint(
            str(inspect.stack()[0][3]) + " Impossible de connaitre le status du payement " + str(stripe_payment_id) + " ")
        return False, " Impossible de connaitre le status du payement " + str(stripe_payment_id) + " "


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, False


"""
Cette fonction schedul un payeement 
"""
def Schedule_Stripe_Payement(diction):
    try:

        field_list_obligatoire = ['token', ]
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " - La valeur '" + val + "' n'est pas presente dans liste "


        mytoken = ""
        if ("token" in diction.keys()):
            if (str(diction['token'])):
                mytoken = str(diction['token'])

        # recuperation de la susbscription du client
        local_ret_val = MYSY_GV.dbname['partnair_account'].find_one({'token':mytoken,'active':'1', 'locked':'0'})

        if( local_ret_val['stripe_subscription_id'] is None ):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible de trouver la suscritpion, planification annulée ")
            return False, " Impossible de trouver la suscritpion, planification annulée  "

        schedul = stripe.SubscriptionSchedule.create(
            from_subscription=str(local_ret_val['stripe_subscription_id']),
        )

        print(" ### Schedule id  = ", schedul['id'])

        """
        Mise à jour du partenaire avec la valeur du suscription id
        """
        local_coll_name = MYSY_GV.dbname['partnair_account']

        now = datetime.now()
        ret_val = local_coll_name.find_one_and_update({'token':mytoken, 'active': '1', 'locked': '0'},
                                                      {"$set":
                                                           {"stripe_subscription_schedule_id": str(schedul['id']),
                                                            "date_update": str(now)}
                                                       },
                                                      upsert=False,
                                                      return_document=ReturnDocument.AFTER
                                                      )

        if (ret_val is None or ret_val['_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - planification des payement : impossible de mettre à jour le client")
            return False, False, "Planification des payement : impossible de mettre à jour le client"

        return True, " La planification des payement a bien été activée"


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible d'activer la plafinification recurrente du payement",


def create_subscription(diction):
    try:
        """
        Controle des champs autorisés
        """
        field_list = ['customerid', 'pack', 'qty', 'discount_code', 'discount_type','discount_valeur']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list  and val.startswith('my_') is False:
                mycommon.myprint(str(
                    inspect.stack()[0][3]) + "  Le champ  '" + val + "' n'existe pas. ")
                return False, " Les informations fournies sont incorrecte",

        """
                Controle des champs Obligatoires
                """
        field_list_obligatoire = ['customerid', 'pack', 'qty']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de créer la souscription La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de créer le souscription. Toutes les données obligatoires ne sont pas fournies"

        # Simulating authenticated user. Lookup the logged in user in your
        # database, and set customer_id to the Stripe Customer ID of that user.
        customer_id = ""
        if ("customerid" in diction.keys()):
            if diction['customerid']:
                customer_id = diction['customerid']

        pack = ""
        if ("pack" in diction.keys()):
            if diction['pack']:
                pack = diction['pack']

        discount_code = ""
        if ("discount_code" in diction.keys()):
            if diction['discount_code']:
                discount_code = diction['discount_code']

        discount_type = ""
        if ("discount_type" in diction.keys()):
            if diction['discount_type']:
                discount_type = diction['discount_type']

        discount_valeur = ""
        if ("discount_valeur" in diction.keys()):
            if diction['discount_valeur']:
                discount_valeur = diction['discount_valeur']


        price_id = ""
        if( str(pack).lower() == "gold" ):
            price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID
            # On ecrase la valeur celle du discount si il existe une discount
            if( str(discount_valeur) == "50" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_50_OFF
            elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_95_OFF



        elif( str(pack).lower() == "standard"):
            price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID
            # On ecrase la valeur celle du discount si il existe une discount
            if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_50_OFF
            elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_95_OFF


        elif (str(pack).lower() == "test"):
            price_id = MYSY_GV.STRIPE_TEST_PRICE_ID

        qty = ""
        if ("qty" in diction.keys()):
            if diction['qty']:
                qty = diction['qty']

        local_status, new_int = mycommon.IsInt(qty)
        if ( local_status is False ):
            mycommon.myprint(str(inspect.stack()[0][
                                     3]) + " - Impossible de realiser le souscription. La quantité n'est pas correcte")
            return False, " - Impossible de realiser le souscription. La quantité n'est pas correcte"

        # Extract the price ID from environment variables given the name
        # of the price passed from the front end.
        #

        print(" ### price_id = ", price_id)

        # Create the subscription. Note we're using
        # expand here so that the API will return the Subscription's related
        # latest invoice, and that latest invoice's payment_intent
        # so we can collect payment information and confirm the payment on the front end.

        # Create the subscription
        subscription = stripe.Subscription.create(
            customer=customer_id,
            items=[{
                'price': price_id,
                'quantity': qty,
            }],
            payment_behavior='default_incomplete',
            expand=['latest_invoice.payment_intent'],
        )

        print(" ### subscription ID =", subscription['id'])
        print(" ### customer_id = ", customer_id)
        ##print(" ### payment_intent = id = " + str(subscription.latest_invoice.payment_intent.id))

        """
        Mise à jour du partenaire avec la valeur du suscription id
        """
        local_coll_name = MYSY_GV.dbname['partnair_account']

        now = datetime.now()
        ret_val = local_coll_name.find_one_and_update({'stripe_account_id':customer_id, 'active':'1', 'locked':'0'},
                                                {"$set":
                                                     {"stripe_subscription_id":str(subscription['id']),
                                                      "stripe_subscription_created_timestemp": str(subscription['created']),
                                                      "date_update": str(now)}
                                                 },
                                                      upsert=False,
                                                return_document=ReturnDocument.AFTER
                                                )

        if ('_id' not in  ret_val.keys()):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Creation payement : impossible de mettre à jour le client")
            return False, False,  "Creation payement : impossible de mettre à jour le client"


        """
        /!\ Une fois l'abonnement créer, il faut l'enregistrer dans la collection 'abonnement'
        """
        # Recuperation du recid du client dans mysy
        local_partner_data = MYSY_GV.dbname['partnair_account'].find_one({'stripe_account_id':customer_id, 'active':'1', 'locked':'0'})

        if( 'recid' not in local_partner_data):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Creation payement : impossible de récupérer les données client (3)")
            return False, False, "Creation payement : impossible de récupérer les données client (3) "


        abonnement_data = {}

        abonnement_data['partner_recid'] = local_partner_data['recid']

        print(" ### ret_val apres souscription id = ", str(ret_val))
        print(" ### ret_val apres subscription = ", str(subscription))

        if ('_id' in ret_val.keys()):
            abonnement_data['stripe_subscription_id'] = str(ret_val['stripe_subscription_id'])

        if ('billing_cycle_anchor' in ret_val.keys()):
            abonnement_data['billing_cycle_anchor'] = subscription['billing_cycle_anchor']

        if ('created' in ret_val.keys()):
            abonnement_data['created'] = subscription['created']

        if ('current_period_end' in ret_val.keys()):
            abonnement_data['current_period_end'] = subscription['current_period_end']

        if ('customer' in ret_val.keys()):
            abonnement_data['stripe_customer_id'] = subscription['customer']

        if ('latest_invoice' in ret_val.keys()):
            abonnement_data['latest_invoice'] = subscription['latest_invoice']

        if ('status' in ret_val.keys()):
            abonnement_data['status'] = subscription['status']

        now = datetime.now()
        abonnement_data['date_update'] = str(now)

        ret_val_abonnement = MYSY_GV.dbname['abonnement'].find_one_and_update(
            {'stripe_subscription_id': str(ret_val['_id']), },
                                                      {"$set":
                                                           abonnement_data
                                                       },
                                                      upsert=True,
                                                      return_document=ReturnDocument.AFTER
                                                      )

        if ('_id' not in ret_val_abonnement.keys()):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Creation payement : impossible de finaliser la creation de l'abonnement")
            return False, False, "Creation payement : impossible de finaliser la creation de l'abonnement"

        return True, subscription.latest_invoice.payment_intent.id, subscription.latest_invoice.payment_intent.client_secret


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, False, False,


@app.route('/cancel-subscription', methods=['POST'])
def cancel_subscription():
    data = json.loads(request.data)
    try:
        # Cancel the subscription by deleting it
        deletedSubscription = stripe.Subscription.delete(data['subscriptionId'])
        return jsonify(subscription=deletedSubscription)
    except Exception as e:
        return jsonify(error=str(e)), 403


@app.route('/subscriptions', methods=['GET'])
def list_subscriptions():
    # Simulating authenticated user. Lookup the logged in user in your
    # database, and set customer_id to the Stripe Customer ID of that user.
    customer_id = request.cookies.get('customer')

    try:
        # Cancel the subscription by deleting it
        subscriptions = stripe.Subscription.list(
            customer=customer_id,
            status='all',
            expand=['data.default_payment_method']
        )
        return jsonify(subscriptions=subscriptions)
    except Exception as e:
        return jsonify(error=str(e)), 403


@app.route('/invoice-preview', methods=['GET'])
def preview_invoice():
    # Simulating authenticated user. Lookup the logged in user in your
    # database, and set customer_id to the Stripe Customer ID of that user.
    customer_id = request.cookies.get('customer')

    subscription_id = request.args.get('subscriptionId')
    new_price_lookup_key = request.args.get('newPriceLookupKey')

    try:
        # Retrieve the subscription
        subscription = stripe.Subscription.retrieve(subscription_id)

        # Retrive the Invoice
        invoice = stripe.Invoice.upcoming(
            customer=customer_id,
            subscription=subscription_id,
            subscription_items=[{
                'id': subscription['items']['data'][0].id,
                'price': os.getenv(new_price_lookup_key),
            }],
        )
        return jsonify(invoice=invoice)
    except Exception as e:
        return jsonify(error=str(e)), 403


@app.route('/update-subscription', methods=['POST'])
def update_subscription():
    data = json.loads(request.data)
    try:
        subscription = stripe.Subscription.retrieve(data['subscriptionId'])

        update_subscription = stripe.Subscription.modify(
            data['subscriptionId'],
            items=[{
                'id': subscription['items']['data'][0].id,
                'price': os.getenv(data['newPriceLookupKey'].upper()),
            }]
        )
        return jsonify(update_subscription)
    except Exception as e:
        return jsonify(error=str(e)), 403


"""
Cette fonction arrete la prelevement d'un payement à la fin du mois en cours
"""
def stop_strip_subscription(diction):
    try:

        field_list_obligatoire = ['token',]
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste , toutes le données obligatoire ne sont pas fournies ")
                return False, " Impossible de supprimer le moyen de payement, toutes le données obligatoire ne sont pas fournies"

        mytoken = ""
        if ("token" in diction.keys()):
            if diction['token']:
                mytoken = diction['token']

        retval = mycommon.check_partner_token_validity("", str(mytoken))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - La session de connexion n'est pas valide")
            return False, "Les informations d'identification ne sont pas valident"

        # Recuperation du recid du partenaire
        partner_recid = mycommon.get_parnter_recid_from_token(str(mytoken))
        if partner_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer le recid du partenaire")
            return False, " Les informations d'identification sont incorrectes"

        # recuperation de la susbscription du client
        local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
            {'token': mytoken, 'active': '1', 'locked': '0'})

        if (local_ret_val['stripe_subscription_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible d'annuler le payement ")
            return False, " Impossible d'annuler le payement  "



        #a = stripe.SubscriptionSchedule.release(  str(local_ret_val['stripe_subscription_id']), )
        a = stripe.Subscription.modify(
            str(local_ret_val['stripe_subscription_id']),
            cancel_at_period_end=True
        )


        arret_abonnement = datetime.today().date() + relativedelta(months=+1)
        arrete_abonnement_formated =  arret_abonnement.strftime("%d/%m/%Y")

        #mise à jour du partenaire
        local_coll_name = MYSY_GV.dbname['partnair_account']

        now = datetime.now()
        ret_val = local_coll_name.find_one_and_update({'token': mytoken, 'active': '1', 'locked': '0'},
                                                      {"$set":
                                                           {"end_date_abonnement": str(arrete_abonnement_formated),
                                                            "date_update": str(now)}
                                                       },
                                                      upsert=False,
                                                      return_document=ReturnDocument.AFTER
                                                      )

        if (ret_val is None or ret_val['_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Arret abonnement : impossible de mettre à jour le client")
            return False, False, "Arret abonnement : impossible de mettre à jour le client"

        partners_email = local_ret_val['email']
        partners_nom = local_ret_val['nom']
        partners_pack_service = local_ret_val['pack_service']
        partners_date_arret = arrete_abonnement_formated

        local_ret_val = email_mgt.EmailStopAbonnement( partners_email, partners_pack_service, partners_date_arret, partners_nom)

        if( local_ret_val is False):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - WARNING : Arret abonnement, Impossible d'envoyer le mail de notification au partenaire")

        return True, " Votre abonnement va s'arreter le "+str(arrete_abonnement_formated)


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, "Impossible d'annuler votre abonnement"


"""
Cette fonction permet de modifier la quantité d'un abonnement
par exemple lorqu'un partenaire change de nombre de formation sur le meme pack
"""

def strip_update_subscription_qty(diction):
    try:
        """
                Controle des champs autorisés
                """
        field_list = ['token','qty', 'old_qty','discount_code', 'discount_type','discount_valeur']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list  and val.startswith('my_') is False:
                mycommon.myprint(str(
                    inspect.stack()[0][3]) + "  Le champ  '" + val + "' n'existe pas. ")
                return False, " Les informations fournies sont incorrecte",

        print(" ### strip_update_subscription_qty : diction = ", diction)
        """
                Controle des champs Obligatoires
                """

        field_list_obligatoire = ['token','qty', 'old_qty']
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste , toutes le données obligatoire ne sont pas fournies ")
                return False, " Impossible de supprimer le moyen de payement, toutes le données obligatoire ne sont pas fournies"

        mytoken = ""
        if ("token" in diction.keys()):
            if diction['token']:
                mytoken = diction['token']

        qty = ""
        if ("qty" in diction.keys()):
            if diction['qty']:
                qty = diction['qty']

        old_qty = ""
        if ("old_qty" in diction.keys()):
            if diction['old_qty']:
                old_qty = diction['old_qty']

        retval = mycommon.check_partner_token_validity("", str(mytoken))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - La session de connexion n'est pas valide")
            return False, "Les informations d'identification ne sont pas valident"

        # Recuperation du recid du partenaire
        partner_recid = mycommon.get_parnter_recid_from_token(str(mytoken))
        if partner_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer le recid du partenaire")
            return False, " Les informations d'identification sont incorrectes"

        # recuperation de la susbscription du client
        local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
            {'token': mytoken, 'active': '1', 'locked': '0'})

        if (local_ret_val['stripe_subscription_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible d'annuler le payement ")
            return False, " Impossible de changer la quantité de l'abonnement  "

        print(" ### local_ret_val = ", local_ret_val)
        pack = ""
        if ("pack_service" in local_ret_val.keys()):
            if local_ret_val['pack_service']:
                pack = local_ret_val['pack_service']

        print(" ### pack = ", pack)
        discount_code = ""
        if ("discount_code" in diction.keys()):
            if diction['discount_code']:
                discount_code = diction['discount_code']

        discount_type = ""
        if ("discount_type" in diction.keys()):
            if diction['discount_type']:
                discount_type = diction['discount_type']

        discount_valeur = ""
        if ("discount_valeur" in diction.keys()):
            if diction['discount_valeur']:
                discount_valeur = diction['discount_valeur']

        price_id = ""
        if (str(pack).lower() == "gold"):
            price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID
            # On ecrase la valeur celle du discount si il existe une discount
            if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_50_OFF
            elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_95_OFF



        elif (str(pack).lower() == "standard" ):
            price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID
            # On ecrase la valeur celle du discount si il existe une discount
            if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_50_OFF
            elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_95_OFF


        elif (str(pack).lower() == "test"):
            price_id = MYSY_GV.STRIPE_TEST_PRICE_ID


        print(" #### str(local_ret_val['stripe_subscription_id']) = ", str(local_ret_val['stripe_subscription_id']))

        print(" ### price_id = ", price_id)

        current_subscription = stripe.Subscription.retrieve(str(local_ret_val['stripe_subscription_id']))

        #a = stripe.SubscriptionSchedule.release(  str(local_ret_val['stripe_subscription_id']), )
        if( discount_code ):
            a = stripe.Subscription.modify(
                str(local_ret_val['stripe_subscription_id']),
                proration_behavior='create_prorations',
                items=[{
                    'id': current_subscription['items'].data[0].id,
                    'price': price_id,
                    'quantity': qty,
                }]
            )

        else:
            a = stripe.Subscription.modify(
                str(local_ret_val['stripe_subscription_id']),
                proration_behavior='create_prorations',
                items=[{
                    'id': current_subscription['items'].data[0].id,
                    'price': price_id,
                    'quantity': qty,
                }]
            )


        #print(" ### aa = ", a)
        arret_abonnement = datetime.today().date() + relativedelta(months=+1)
        arrete_abonnement_formated =  arret_abonnement.strftime("%d/%m/%Y")

        now = datetime.now()



        partners_email = local_ret_val['email']
        partners_nom = local_ret_val['nom']
        partners_pack_service = local_ret_val['pack_service']
        partners_date_arret = arrete_abonnement_formated

        local_ret_val = email_mgt.EmailChangeAbonnementQty( partners_email, partners_pack_service, partners_date_arret, partners_nom, old_qty, qty)

        if( local_ret_val is False):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - WARNING : changement qté abonnement, Impossible d'envoyer le mail de notification au partenaire")

        return True, " ok"


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de changer la quantité de l'abonnement  "


"""
Cette fonction permet de changer l'abonnement d'un partenaire.
Par exemple cas d'un "standard" qui passe "Gold" ou vice-versa.

IMPORTANT : 
Le changement de plan d'abonnement entraine la desactivation et depublucation
des formations dans MySy et dans le LMS.

Par la suite, le client pourra reactivier et republier ses formations selon
les nouvelles conditions de son abonnement.

"""
def strip_update_subscription_plan(diction):
    try:

        """
                Controle des champs autorisés
                """
        field_list = ['token','pack', 'qty', 'discount_code', 'discount_type','discount_valeur']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list  and val.startswith('my_') is False:
                mycommon.myprint(str(
                    inspect.stack()[0][3]) + "  Le champ  '" + val + "' n'existe pas. ")
                return False, " Les informations fournies sont incorrecte",

        print(" ### strip_update_subscription_plan : diction = ", diction)
        """
                Controle des champs Obligatoires
                """

        field_list_obligatoire = ['token','pack', 'qty']
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste , toutes le données obligatoire ne sont pas fournies ")
                return False, "  Toutes le données obligatoire ne sont pas fournies"

        mytoken = ""
        if ("token" in diction.keys()):
            if diction['token']:
                mytoken = diction['token']

        pack = ""
        if ("pack" in diction.keys()):
            if diction['pack']:
                pack = diction['pack']

        qty = ""
        if ("qty" in diction.keys()):
            if diction['qty']:
                qty = diction['qty']


        retval = mycommon.check_partner_token_validity("", str(mytoken))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - La session de connexion n'est pas valide")
            return False, "Les informations d'identification ne sont pas valident"

        # Recuperation du recid du partenaire
        partner_recid = mycommon.get_parnter_recid_from_token(str(mytoken))
        if partner_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer le recid du partenaire")
            return False, " Les informations d'identification sont incorrectes"

        # recuperation de la susbscription du client
        local_ret_val = MYSY_GV.dbname['partnair_account'].find_one(
            {'token': mytoken, 'active': '1', 'locked': '0'})

        if (local_ret_val['stripe_subscription_id'] is None):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " Impossible d'annuler le payement ")
            return False, " Impossible de changer l'abonnement  "


        lms_user_id = ""
        if ("mysy_lms_user_id" in local_ret_val.keys()):
            if local_ret_val['mysy_lms_user_id']:
                lms_user_id = local_ret_val['mysy_lms_user_id']
        """
        qty = ""
        if ("nb_formation" in local_ret_val.keys()):
            if local_ret_val['nb_formation']:
                qty = local_ret_val['nb_formation']
        """

        discount_code = ""
        if ("discount_code" in diction.keys()):
            if diction['discount_code']:
                discount_code = diction['discount_code']

        discount_type = ""
        if ("discount_type" in diction.keys()):
            if diction['discount_type']:
                discount_type = diction['discount_type']

        discount_valeur = ""
        if ("discount_valeur" in diction.keys()):
            if diction['discount_valeur']:
                discount_valeur = diction['discount_valeur']

        price_id = ""
        if (str(pack).lower() == "gold"):
            price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID
            # On ecrase la valeur celle du discount si il existe une discount
            if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_50_OFF
            elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_GOLD_PRICE_ID_95_OFF


        elif (str(pack).lower() == "standard"):
            price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID
            # On ecrase la valeur celle du discount si il existe une discount
            if (str(discount_valeur) == "50" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_50_OFF
            elif (str(discount_valeur) == "95" and str(discount_type) == "percent"):
                price_id = MYSY_GV.STRIPE_STANDARD_PRICE_ID_95_OFF


        elif (str(pack).lower() == "test"):
            price_id = MYSY_GV.STRIPE_TEST_PRICE_ID


        print(" ### pack = ", pack, " ## price_id = ", price_id, " ### qty = ", qty)
        print(" #### str(local_ret_val['stripe_subscription_id']) = ", str(local_ret_val['stripe_subscription_id']))

        current_subscription = stripe.Subscription.retrieve(str(local_ret_val['stripe_subscription_id']))

        #a = stripe.SubscriptionSchedule.release(  str(local_ret_val['stripe_subscription_id']), )
        a = stripe.Subscription.modify(
            str(local_ret_val['stripe_subscription_id']),
            cancel_at_period_end=False,
            proration_behavior='create_prorations',
            items=[{
                'id': current_subscription['items'].data[0].id,
                'price': price_id,
                'quantity': qty,

            }]
        )

        #print(" ### aa = ", a)
        arret_abonnement = datetime.today().date() + relativedelta(months=+1)
        arrete_abonnement_formated =  arret_abonnement.strftime("%d/%m/%Y")

        now = datetime.now()


        partners_email = local_ret_val['email']
        partners_nom = local_ret_val['nom']
        partners_pack_service = local_ret_val['pack_service']

        local_ret_val = email_mgt.EmailChangeAbonnementPlan( partners_email, pack,  partners_nom,  qty, )

        if( local_ret_val is False):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - WARNING : changement qté abonnement, Impossible d'envoyer le mail de notification au partenaire")


        """
        Important : 
        Le changement de plan d'abonnement entraine la desactivation et depublucation
        des formations dans MySy et dans le LMS.
        
        Par la suite, le client pourra reactivier et republier ses formations selon
        les nouvelles conditions de son abonnement.
        """

        # 1 - Depublication des formations dans MySy
        #print(" ###  str(local_ret_val['recid']) = ", str(partner_recid))
        local_result = MYSY_GV.dbname['myclass'].update_many({'partner_owner_recid':str(partner_recid)}, {"$set":{'published':'0'}})
        #print(" #### "+str(local_result.matched_count)+" Formations ont été depubliées dans MySy ")

        # 2 - Desactivation des formations dans le LMS
        new_diction = {}
        new_diction['lms_user_id'] = lms_user_id
        print(" #### new_diction = ", new_diction)
        local_status, local_message = mysy_lms.Disable_MySy_LMS_Class_Of_User(new_diction)
        print(" ### local_status = "+str(local_status)+" mysy_lms.Disable_MySy_LMS_Class_Of_User = "+str(local_message))
        return True, " ok"

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de changer l'abonnement   "




@app.route('/webhook', methods=['POST'])
def webhook_received():
    # You can use webhooks to receive information about asynchronous payment events.
    # For more about our webhook events check out https://stripe.com/docs/webhooks.
    webhook_secret = os.getenv('STRIPE_WEBHOOK_SECRET')
    request_data = json.loads(request.data)

    if webhook_secret:
        # Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
        signature = request.headers.get('stripe-signature')
        try:
            event = stripe.Webhook.construct_event(
                payload=request.data, sig_header=signature, secret=webhook_secret)
            data = event['data']
        except Exception as e:
            return e
        event_type = event['type']
    else:
        data = request_data['data']
        event_type = request_data['type']

    data_object = data['object']

    if event_type == 'invoice.payment_succeeded':
        if data_object['billing_reason'] == 'subscription_create':
            # The subscription automatically activates after successful payment
            # Set the payment method used to pay the first invoice
            # as the default payment method for that subscription
            subscription_id = data_object['subscription']
            payment_intent_id = data_object['payment_intent']

            # Retrieve the payment intent used to pay the subscription
            payment_intent = stripe.PaymentIntent.retrieve(payment_intent_id)

            # Set the default payment method
            stripe.Subscription.modify(
              subscription_id,
              default_payment_method=payment_intent.payment_method
            )

            print("Default payment method set for subscription:" + payment_intent.payment_method)
    elif event_type == 'invoice.payment_failed':
        # If the payment fails or the customer does not have a valid payment method,
        # an invoice.payment_failed event is sent, the subscription becomes past_due.
        # Use this webhook to notify your user that their payment has
        # failed and to retrieve new card details.
        # print(data)
        print('Invoice payment failed: %s', event.id)

    elif event_type == 'invoice.finalized':
        # If you want to manually send out invoices to your customers
        # or store them locally to reference to avoid hitting Stripe rate limits.
        # print(data)
        print('Invoice finalized: %s', event.id)

    elif event_type == 'customer.subscription.deleted':
        # handle subscription cancelled automatically based
        # upon your subscription settings. Or if the user cancels it.
        # print(data)
        print('Subscription canceled: %s', event.id)

    return jsonify({'status': 'success'})



"""
Cette fonction récupérer les informations sur l'abonnement
 d'un client. Par exemple, 
 - date de prochaine facturation
 - montant de prochaine facture
 """
def Strip_Get_Customer_Abonnement_Data(diction):
    try:

        field_list_obligatoire = ['recid']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][
                            3]) + "  La valeur '" + val + "' n'est pas presente dans liste ")
                return False, "  Les informations fournies sont incorrectes"

        recid = ""
        if ("recid" in diction.keys()):
            if diction['recid']:
                recid = diction['recid']


        # Recuperation 	du 	recid 	du 	partenaire
        local_status, partner_data = mycommon.get_partner_data_from_recid(str(recid))
        if local_status is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " -  Impossible de récupérer les données du partenaire")
            return False, " Impossible de récupérer les données du partenaire"

        if ("stripe_account_id" not in partner_data.keys()):
            mycommon.myprint(str(inspect.stack()[0][3]) + " -  Impossible de récupérer les données du partenaire (2)")
            return False, " Impossible de récupérer les données du partenaire (2)"


        stripe_account_id = partner_data["stripe_account_id"]
        local_ret_val = stripe.Invoice.upcoming(
            customer=stripe_account_id,
        )

        #print(" #### local_ret_val :  ", str(local_ret_val))


        lines_to_invoice = local_ret_val.lines.list()

        stripe_account_id_JSON = json.loads(str(local_ret_val))

        lines_to_invoice_JSON = json.loads(str(lines_to_invoice))

        return_data = {}
        return_data['recid'] = str(recid)
        period_start = ""
        period_end = ""
        total = ""

        if( "period_start" in stripe_account_id_JSON.keys()):
            # convert the timestamp to a datetime object in the local timezone
            dt_object = datetime.fromtimestamp(stripe_account_id_JSON["period_start"]).strftime("%d/%m/%Y")
            return_data['period_start'] = str(dt_object)[0:10]
            period_start = str(dt_object)[0:10]

        if ("period_end" in stripe_account_id_JSON.keys()):
            # convert the timestamp to a datetime object in the local timezone
            dt_object = datetime.fromtimestamp(stripe_account_id_JSON["period_end"]).strftime("%d/%m/%Y")
            return_data['period_end'] = str(dt_object)[0:10]
            period_end = str(dt_object)[0:10]

        if ("total" in stripe_account_id_JSON.keys()):
            total_local = mycommon.tryFloat(str(stripe_account_id_JSON["total"])) / 100
            return_data['total'] = str(total_local)
            total = str(total_local)

        return_data['main_description'] = "Facture à venir : Ceci est un aperçu de la facture qui sera émise "+str(period_end)+"." \
                                          " Elle est susceptible d'être modifiée si l'abonnement est mis à jour."

        return_data['lines'] = []


        for val in lines_to_invoice_JSON['data']:

            local_diction = {}

            local_diction['id'] = str(val['id'])

            period = val['period']

            local_diction['period_end'] =  str(datetime.fromtimestamp(period['end']).strftime("%d/%m/%Y-%H:%M:%S"))
            local_diction['period_start'] = str(datetime.fromtimestamp(period['start']).strftime("%d/%m/%Y-%H:%M:%S"))

            local_diction['period_end_month'] = str(datetime.fromtimestamp(period['end']).strftime("%m"))


            local_diction['unit_amount'] =   mycommon.tryFloat(str(val['price']['unit_amount'])) / 100

            local_diction['quantity'] = str(val['quantity'])

            local_diction['description'] = str(val['description']).replace("Unused time on", "Temps non utilisé sur").replace("Remaining time on", "Temps restant sur").replace("after", "apres")

            local_diction['amount'] =  mycommon.tryFloat(str(val['amount'])) / 100
            return_data['lines'].append(local_diction)




        print(" ## return_data = ", return_data)

        RetObject = []
        RetObject.append(mycommon.JSONEncoder().encode(return_data))
        return True, RetObject

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer les données de l'abonnement   "



""" 
Cette fonction est un job qui va aller chercher tous les client/partner
pour lesquels il faut envoyer les elements de facturation
"send_pre_invoice_data" : '1', 
"datetime_pre_invoice_created"  < date_time_now + 5 min.

"""
def Cron_Strip_Get_Customer_Abonnement_Data():
    try:

        query = {}
        query['send_pre_invoice_data'] = '1'
        query['datetime_pre_invoice_created'] = { '$lte' : str( datetime.now()  -  timedelta(minutes=3) )}
        #{}: {"$lte" :1355414400}  #datetime.datetime.now() - datetime.timedelta(minutes=5)
        query['locked'] = '0'
        query['active'] = '1'



        #print(" ### query = ", query)

        cpt = 0
        cpt_erreur = 0
        cpt_ok = 0

        for val in MYSY_GV.dbname['partnair_account'].find(query):
            cpt = cpt + 1
            data = {}
            data['recid'] = val['recid']
            local_status, local_retval = email_mgt.Strip_Get_Customer_Upcoming_Invoice(data)
            if( local_status is False):
                cpt_erreur = cpt_erreur +1
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " -  WARNING : impossible d'envoyer les elements de prefacturation pour le recid : "+str(val['recid']))
            else:
                cpt_ok = cpt_ok + 1
                # Les elements ont bien ete envoyé, alors on fait la mise à jour du partenaire en mettant : "send_pre_invoice_data" : '2', (2 veut dire que c'est fait)
                ret_val_local = MYSY_GV.dbname['partnair_account'].find_one_and_update(
                    {"recid": str(val['recid']), 'active': '1', 'locked': '0'},
                    {"$set": {'send_pre_invoice_data': '2', 'datetime_pre_invoice_created': str(datetime.now())}},
                    upsert=False,
                    return_document=ReturnDocument.AFTER
                    )

        output_message = time.strftime("%A, %d. %B %Y %I:%M:%S %p")+" : Envoie des données de prefacturation : - "+str(cpt)+ " clients ==> A traiter.  - "+str(cpt_ok)+ " clients==>  traiter OKK. - "+str(cpt_erreur)+ " clients ==>  traiter ERREUR. "
        mycommon.myprint(str(output_message))
        return True, str(output_message)

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False,  time.strftime("%A, %d. %B %Y %I:%M:%S %p")+" Impossible d'executer le job :  Cron_Strip_Get_Customer_Abonnement_Data  "



"""
Cette fonction verifie si un client a deja une facture stripe.
si c'est le cas, ca veut qu'on est en mode update avec ce client
si non il faut créer la première facture
"""
def Stripe_Customer_Has_Invoice(stripe_customer_id):
    try:

        retval = stripe.Invoice.search(query="customer:'"+str(stripe_customer_id)+"'")

        stripe_list_invoice_JSON = json.loads(str(retval))

        for val in  stripe_list_invoice_JSON["data"] :
            if( "id" in val.keys() ):
                return True

        return False

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False



"""
fonction de test stripe
"""
def test_stripe():
    try:

        retval = stripe.Invoice.search(query="customer:'cus_OEsPgUkuj2UIES'")
        #print(" #### retval = ", str(retval))

        stripe_list_invoice_JSON = json.loads(str(retval))


        for val in  stripe_list_invoice_JSON["data"] :
            print(" #### stripe_list_invoice_JSON_data = ", str(val))
            if( "id" in val.keys() ):
                print(" ### l'id de la facture est ", str(val['id']))

        return "OK"

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False

