from django.db.transaction import atomic
from django.http import Http404
from rest_framework.exceptions import APIException
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from django.db.models import Q
import datetime
from typing import Any, List, Tuple, Union

from ..utils_extraction import to_table_pam

from ..utils.alimentation_decorators import (data_perf_logger_factory,
                                             get_data_logger)
from ..utils.decorators import execution_time, query_count
from ..utils_insertion import insert_PAM
from ..models import Administres_Pams, Postes_Pams,Calcul, Poste, PAM, StatutPamChoices as StatutPam, AvisPosteChoices
from ..utils.insertion.commun import batch_iterator

class AlimentationPamView(APIView):
    """ Vue pour charger un nouveau PAM """

    permission_classes = [IsAuthenticated, IsAdminUser]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.logger = get_data_logger(self)
    
    


    def get(self, request):
        try:
            self.logger.debug('Début de la mise à jour de la table PAM, veuillez patienter...') 
            # today = datetime.date(2023,1,1)
            today = datetime.datetime.now()
            insert_PAM(to_table_pam(today))

            self.logger.debug('Insertion/Mise à jour de la table PAM --------------------------------------------> Success') 

            annee_pam = PAM.objects.filter(pam_statut='PAM en cours')[0].pam_id
            annee_pam_suivant = PAM.objects.filter(pam_statut='PAM A+1')[0].pam_id

            self.logger.debug('Mise à jour des données des administrés pour les PAM A et A+1, veuillez patienter ...') 
            dict_create_administres = {}
            dict_update_administres = {}

            qs = Administres_Pams.objects.all().filter(pam_id=annee_pam).values('administre_id')

            batch_size = 50
            admin_suivant = dict((f"{o.administre_id}", o) for o in  Administres_Pams.objects.all().filter(pam_id=annee_pam_suivant))

            for a_id_sap in qs:
                administre_id=a_id_sap['administre_id']
                pk = str(administre_id) + str(annee_pam_suivant)

                model_administre = Administres_Pams(**{
                    'id'                                    :pk,
                    'pam_id'                                :annee_pam_suivant,
                    'administre_id'                         :administre_id,
                    'a_statut_pam_annee'                    :StatutPam.NON_ETUDIE,
                    'notes_pam'                             :None,
                    'a_ciat_pam'                            :False,
                    'a_specifique_pam'                      :None,
                    'a_liste_depts_souhaites_pam'           :None,
                    'a_liste_zones_geographiques_shm_pam'   :None,
                    'a_situationfuture_notes_fe'            :None,                  
                })

                if str(administre_id) not in admin_suivant :
                    dict_create_administres.setdefault(pk, model_administre)

                else:
                    dict_update_administres.setdefault(pk, model_administre)


            if dict_create_administres:
                self.logger.debug("Nombre d'administrés à créer dans l'année %s : %s'",annee_pam_suivant,len(dict_create_administres))
                for idx, data_batch in enumerate(batch_iterator(list(dict_create_administres.values()), batch_size)):
                    try:
                        Administres_Pams.objects.bulk_create(data_batch)
                    except Exception as e:
                        self.logger.exception("Cet administré existe déjà dans la base : %s", e)

            self.logger.debug('Mise à jour des liens Administres/Pams terminés.')

            self.logger.debug('Mise à jour des données des postes pour les PAM A et A+1, veuillez patienter ...') 
            dict_create_postes = {}
            dict_update_postes = {}

            # def mise_a_jour_info_reo(info_reo, annee_pam):
            #     if "SUREFF" in info_reo:
            #         model.info_reo=info_reo
            #     else:
            #         model.info_reo=f'REO {annee_pam}'
            #     return model.info_reo

            qs = Postes_Pams.objects.all().filter(p_pam_id=annee_pam).values_list('poste_id','info_reo')

            batch_size = 50
            poste_suivant = dict((f"{o.poste_id}", o) for o in  Postes_Pams.objects.all().filter(p_pam_id=annee_pam_suivant))

            for poste in qs:
                poste_id=poste[0]
                info_reo= poste[1]
                pk = str(poste_id) + str(annee_pam_suivant)
                model_poste = Postes_Pams(**{
                    'id'                                    :pk,
                    'p_pam_id'                              :annee_pam_suivant,
                    'poste_id'                              :poste_id,
                    'p_avis_pam'                            :StatutPam.NON_ETUDIE,
                    'p_avis_fe_pam'                         :StatutPam.NON_ETUDIE,
                    'p_direct_commissionne_pam'             :None,
                    'p_notes_gestionnaire_pam'              :None,
                    'p_priorisation_pcp_pam'                :None,
                    'info_reo'                              :info_reo if "SUREFF" in info_reo else f'REO {annee_pam}',
                })

                if str(poste_id) not in poste_suivant :
                    dict_create_postes.setdefault(pk, model_poste)

                else:
                    dict_update_postes.setdefault(pk, model_poste)

            if dict_create_postes:
                self.logger.debug("Nombre de postes à créer dans l'année %s : %s'",annee_pam_suivant,len(dict_create_postes))
                for idx, data_batch in enumerate(batch_iterator(list(dict_create_postes.values()), batch_size)):
                    try:
                        Postes_Pams.objects.bulk_create(data_batch)
                    except Exception as e:
                        self.logger.exception("Ce poste existe déjà dans la base : %s", e)

            self.logger.debug('Mise à jour des liens Postes/Pams terminés.')

            self.logger.debug(f'Début de la suppression des données du PAM {int(annee_pam)-1}, veuillez patienter ...')
            PAM.objects.filter(pam_id=int(annee_pam)-1).delete()  
            self.logger.debug("Fin de l'initialisation/Mise à jour du PAM")
  
        
            return Response({'Initialisation/Mise à jour du Pam réussie'})

        except (Http404, APIException):
            message = "Impossible de mettre à jour ce PAM"
            self.logger.exception(message)
            raise APIException(message)

class NettoyagePamView(APIView):
    """ Vue pour nettoyer les postes tagués en SUP REO """

    permission_classes = [IsAuthenticated, IsAdminUser]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.logger = get_data_logger(self)

    def get(self, request):
        try:

            self.logger.debug("Suppression des postes tagués en SUP REO de l'année A --------------------------------------------> Success") 

            annee_pam = PAM.objects.filter(pam_statut='PAM en cours')[0].pam_id

            qs = Postes_Pams.objects.all().filter(p_pam_id=annee_pam).values('poste_id')

            for p_id in qs:
                poste_id=p_id['poste_id']

                if Postes_Pams.objects.filter(Q(info_reo='SUP REO') & Q(poste_id=poste_id)):
                    self.logger.debug(f'Suppression du poste {poste_id}')
                    Poste.objects.filter(p_id=poste_id).delete()
               
               #Mise à jour des postes tagues CREE REO A en REO A
                if not Postes_Pams.objects.filter(Q(p_pam_id=annee_pam) & Q(poste_id=poste_id) & Q(info_reo__contains='SUREFF')):
                    Postes_Pams.objects.filter(Q(p_pam_id=annee_pam) & Q(poste_id=poste_id)).update(info_reo=f'REO {annee_pam}')  

            self.logger.debug(f'Début de la suppression des administrés du PAM {int(annee_pam)-1}')
            Administres_Pams.objects.filter(pam_id=int(annee_pam)-1).delete() 
            self.logger.debug(f'Début de la suppression des postes du PAM {int(annee_pam)-1}')
            Postes_Pams.objects.filter(p_pam_id=int(annee_pam)-1).delete()
            Calcul.objects.filter(pam_id=int(annee_pam)-1).delete()
            self.logger.debug(f'Fin de la suppression des données du PAM {int(annee_pam)-1}')
    
        
            return Response({'Mise à jour du Pam réussie'})

        except (Http404, APIException):
            message = "Impossible de mettre à jour ce PAM"
            self.logger.exception(message)
            raise APIException(message)