"""
Ce document permet de gerer les prix d'achat / Groupe de prix d'achat.
Ceci s'applique aussi bien au cout des ressources humaines qu'au prix du materiel.
cout location materiel

"""
import ast
import dateutil
import pymongo
from flask import send_file
from pymongo import MongoClient
import json
from bson import ObjectId
import re
from datetime import datetime, timezone, date
import prj_common as mycommon
import secrets
import inspect
import sys, os
import csv
import pandas as pd
from pymongo import ReturnDocument
import GlobalVariable as MYSY_GV
from math import isnan
import GlobalVariable as MYSY_GV
from datetime import timedelta
from datetime import timedelta

"""
Fonction ajout un groupe de prix d'achat
"""
def Add_Group_Purchase_Price(diction):
    try:
        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', 'code_groupe_prix', 'periodicite', 'date_debut',  'date_fin', 'fournisseur', 'prix' ]

        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 incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', 'code_groupe_prix', 'periodicite', 'date_debut',  'date_fin', 'fournisseur', 'prix' ]
        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",

        """
        Verification de l'identité et autorisation de l'entité qui
        appelle cette API
        """
        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        # S'il ya des date, verifier la validité des dates
        date_debut = ""
        if ("date_debut" in diction.keys() and diction['date_debut']):
            date_debut = str(diction['date_debut'])
        local_status = mycommon.CheckisDate(date_debut)
        if (local_status is False):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " La date de debut  n'est pas au format jj/mm/aaaa.")
            return False, " La date de debut  n'est pas au format jj/mm/aaaa."

        date_fin = ""
        if ("date_fin" in diction.keys() and diction['date_fin']):
            date_fin = str(diction['date_fin'])
        local_status = mycommon.CheckisDate(date_fin)
        if (local_status is False):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " La date de fin  n'est pas au format jj/mm/aaaa.")
            return False, " La date de fin  n'est pas au format jj/mm/aaaa. "

        # verifier la cohérence des dates
        if (datetime.strptime(str(date_debut), '%d/%m/%Y') >= datetime.strptime(str(date_fin), '%d/%m/%Y')):
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + " La date de fin  " + str(
                    date_fin) + " doit être postérieure à la date de début  " + str(
                    diction['date_debut']) + " ")
            return False, " La date de fin  " + str(
                diction['date_fin']) + " doit être postérieure à la date de début  " + str(
                diction['date_debut']) + " "

        # Verification de la périodicité
        if( str(diction['periodicite']) not in MYSY_GV.PURCHASE_PRICE_PERIODICITY ):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " La périodicité est invalide ")
            return False, "  La périodicité est invalide  "


        # Verifier qu'il n'existe pas un groupe de prix d'achat avec le meme code
        is_purchase_groupe_exist = MYSY_GV.dbname['purchase_prices'].count_documents({'code_groupe_prix':str(diction['code_groupe_prix']),
                                                                                      'valide':'1',
                                                                                      'partner_owner_recid':str(my_partner['recid'])})

        if( is_purchase_groupe_exist > 0 ):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " Il exist déjà un goupe de prix avec le même code ")
            return False, " Il exist déjà un goupe de prix avec le même code  "

        # Verifier que le prix est bien un flottant
        local_stat, local_val = mycommon.IsFloat(str(diction['prix']))

        if( local_stat is False ):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " Le prix n'est pas un decimal  ")
            return False, " Le prix n'est pas un decimal  "

        new_data = diction
        del new_data['token']

        new_data['valide'] = "1"
        new_data['locked'] = "0"
        new_data['partner_owner_recid'] = str(my_partner['recid'])
        new_data['update_by'] = str(my_partner['_id'])
        new_data['date_update'] = str(datetime.now())

        inserted_id = ""
        inserted_id = MYSY_GV.dbname['purchase_prices'].insert_one(new_data).inserted_id
        if (not inserted_id):
            mycommon.myprint(
                " Impossible de créer le groupe de prix d'achat (1) ")
            return False, " Impossible de créer le groupe de prix d'achat (1) "

        return True, " Le groupe de prix d'achat a été correctement ajouté "


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de créer le groupe de prix d'achat "

"""
Mise à jour d'un groupe de prix d'achat 
"""
def Update_Group_Purchase_Price(diction):
    try:
        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', '_id', 'code_groupe_prix', 'periodicite', 'date_debut',  'date_fin', 'fournisseur', 'prix' ]

        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 incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', '_id', 'code_groupe_prix', 'periodicite', 'date_debut',  'date_fin', 'fournisseur', 'prix' ]
        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",

        """
        Verification de l'identité et autorisation de l'entité qui
        appelle cette API
        """
        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        # Verifier que ce code de type client existe  pas pour ce partner
        is_code_exist_valide = MYSY_GV.dbname["purchase_prices"].count_documents({'_id':ObjectId(str(diction['_id'])),
                                                                               'valide':'1',
                                                                                'locked':'0',
                                                                               'partner_owner_recid':str(my_partner['recid'])})

        if( is_code_exist_valide != 1 ):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - L'identifiant du groupe de prix d'achat est invalide ")
            return False, " L'identifiant du groupe de prix d'achat est invalide  ",


        # S'il ya des date, verifier la validité des dates
        date_debut = ""
        if ("date_debut" in diction.keys() and diction['date_debut']):
            date_debut = str(diction['date_debut'])
        local_status = mycommon.CheckisDate(date_debut)
        if (local_status is False):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " La date de debut  n'est pas au format jj/mm/aaaa.")
            return False, " La date de debut  n'est pas au format jj/mm/aaaa."


        date_fin = ""
        if ("date_fin" in diction.keys() and diction['date_fin']):
            date_fin = str(diction['date_fin'])
        local_status = mycommon.CheckisDate(date_fin)
        if (local_status is False):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " La date de fin  n'est pas au format jj/mm/aaaa.")
            return False, " La date de fin  n'est pas au format jj/mm/aaaa. "

         # verifier la cohérence des dates
        if (datetime.strptime(str(date_debut), '%d/%m/%Y') >= datetime.strptime(str(date_fin), '%d/%m/%Y')):
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + " La date de fin  " + str(
                    date_fin) + " doit être postérieure à la date de début  " + str(
                    diction['date_debut']) + " ")
            return False, " La date de fin  " + str(
                diction['date_fin']) + " doit être postérieure à la date de début  " + str(diction['date_debut']) + " "

        # Verification de la périodicité
        if (str(diction['periodicite']) not in MYSY_GV.PURCHASE_PRICE_PERIODICITY):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " La périodicité est invalide ")
            return False, "  La périodicité est invalide  "

        local_id = str(diction['_id'])
        new_data = diction
        del new_data['token']
        del new_data['_id']

        new_data['date_update'] = str(datetime.now())
        new_data['update_by'] = str(my_partner['_id'])

        update = MYSY_GV.dbname['purchase_prices'].update_one({'_id': ObjectId(str(local_id)),
                                                      'partner_owner_recid': str(my_partner['recid']),
                                                      'valide': '1',
                                                      'locked': '0'},
                                                     {'$set': new_data}
                                                     )


        return True, " Le groupe de prix d'achat a été correctement mis à jour "
    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de mettre à jour le groupe de prix d'achat"


"""
Suppression d'un groupe de prix d'achat 
/!\ :
Si le groupe de prix est deja utilisé, alors il est impossible de le supprimer
"""
def Delete_Group_Purchase_Price(diction):
    try:
        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', '_id']

        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 incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', '_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, " Les informations fournies sont incorrectes",

        """
        Verification de l'identité et autorisation de l'entité qui
        appelle cette API
        """
        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        # Verifier que ce code de type client existe  pas pour ce partner
        is_code_exist_valide = MYSY_GV.dbname["purchase_prices"].count_documents(
            {'_id': ObjectId(str(diction['_id'])),
             'valide': '1',
             'locked': '0',
             'partner_owner_recid': str(my_partner['recid'])})

        if (is_code_exist_valide != 1):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - L'identifiant du groupe de prix d'achat  est invalide ")
            return False, " L'identifiant du groupe de prix d'achat  est invalide ",


        # Verifier que ce groupe de prix d'achat n'est utilisé par aucune ressource (humaine ou materielle)
        # Si non on refuse la suppression car cela peut entrainter une incohérence d'info
        # -- ressource humaine
        groupe_prix_used_count = MYSY_GV.dbname['ressource_humaine'].count_documents({'partner_recid':str(my_partner['recid']),
                                                                                   'valide':'1',
                                                                                   'purchase_price_group_id':str(diction['_id'])})

        if( groupe_prix_used_count > 0 ):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Le groupe de prix d'achat est utilisé par "+str(groupe_prix_used_count)+" ressource(s) humaine(s) ")
            return False, " Le groupe de prix d'achat est utilisé par "+str(groupe_prix_used_count)+" ressource(s) humaine(s) ",

        # -- ressource materielle
        groupe_prix_used_count = MYSY_GV.dbname['ressource_materielle'].count_documents(
            {'partner_recid': str(my_partner['recid']),
             'valide': '1',
             'purchase_price_group_id': str(diction['_id'])})

        if (groupe_prix_used_count > 0):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Le groupe de prix d'achat est utilisé par " + str(
                    groupe_prix_used_count) + " ressource(s) materielle(s) ")
            return False, " Le groupe de prix d'achat est utilisé par " + str(
                groupe_prix_used_count) + " ressource(s) materielle(s) ",



        new_data = diction

        delete_retval = MYSY_GV.dbname['purchase_prices'].delete_one(
            {'_id': ObjectId(str(diction['_id'])),
             'valide': '1',
             'locked': '0',
             'partner_owner_recid': str(my_partner['recid'])})


        return True, " Le groupe de prix d'achat a été correctement supprimé "

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de supprimer le groupe de prix d'achat  "


"""
Recuperation de la liste des groupe de prix d'achat d'un partenaire
"""
def Get_Partner_Group_Purchase_Price_List(diction):
    try:
        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token',]

        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 incorrectes",

        """
        Verification des champs obligatoires
        """
        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, " Les informations fournies sont incorrectes",

        """
        Verification de l'identité et autorisation de l'entité qui
        appelle cette API
        """
        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        """
                Clés de mise à jour 
                """
        data_cle = {}
        data_cle['partner_owner_recid'] = str(my_partner['recid'])
        data_cle['valide'] = "1"
        data_cle['locked'] = "0"

        #print(" ### Get_Partner_List_Partner_Client data_cle = ", data_cle)
        RetObject = []
        val_tmp = 1

        for retval in MYSY_GV.dbname['purchase_prices'].find(data_cle):
            user = retval
            user['id'] = str(val_tmp)
            val_tmp = val_tmp + 1
            RetObject.append(mycommon.JSONEncoder().encode(user))

        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) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer la liste des groupe de prix d'achat "


"""
Recuperation des données d'un groupe de prix d'achat donnee
"""
def Get_Partner_Given_Group_Purchase_Price(diction):
    try:
        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', '_id']

        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 incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', '_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, " Les informations fournies sont incorrectes",

        """
        Verification de l'identité et autorisation de l'entité qui
        appelle cette API
        """
        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        # Verifier que ce code de type client existe  pas pour ce partner
        is_code_exist_valide = MYSY_GV.dbname["purchase_prices"].count_documents(
            {'_id': ObjectId(str(diction['_id'])),
             'valide': '1',
             'locked': '0',
             'partner_owner_recid': str(my_partner['recid'])})

        if (is_code_exist_valide != 1):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - L'identifiant du groupe de prix d'achat est invalide ")
            return False, " L'identifiant du groupe de prix d'achat est invalide  ",

        """
                Clés de mise à jour 
                """
        data_cle = {}
        data_cle['_id'] = ObjectId(str(diction['_id']))
        data_cle['partner_owner_recid'] = str(my_partner['recid'])
        data_cle['valide'] = "1"
        data_cle['locked'] = "0"

        #print(" ### Get_Partner_List_Partner_Client data_cle = ", data_cle)
        RetObject = []
        val_tmp = 1

        for retval in MYSY_GV.dbname['purchase_prices'].find(data_cle):
            user = retval
            user['id'] = str(val_tmp)
            val_tmp = val_tmp + 1
            RetObject.append(mycommon.JSONEncoder().encode(user))

        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) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer les données du groupe de prix d'achat "
