import time
import pandas as pd
import numpy as np
from django.utils import timezone
from django.db.transaction import atomic
from django.http import Http404, HttpResponse
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 ..utils_extraction import APP_NAN
from ..utils.alimentation import BOCols, ReoCols
from ..serializers import ExportationSerializer
from ..models import Administre, Affectation, Administre_Notation, Poste, FichiersExporte
from ..utils.alimentation_decorators import (data_perf_logger_factory,
                                             get_data_logger)
from ..utils.decorators import execution_time, query_count


class ExportationFichiersView(APIView):
    """ Vue pour exporter les données de la base dans des fichiers au format de ceux utilisés pour l'insertion"""

    permission_classes = [IsAuthenticated, IsAdminUser]
    serializer_class = ExportationSerializer

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

    def get(self, request):
        resp = []
        resp.append(["Formulaire d\'OGURE NG permettant d'exporter les données de la base au format des fichiers d'insertion."])
        resp.append(["Selectionnez le fichier que vous souhaitez exporter puis appuyez sur le bouton 'POST' pour lancer l'exportation."])
        resp = pd.DataFrame(resp)
        return Response(resp[0])
    
    def export_adm_bo_df(self):
        self.logger.info("Lecture et traitement de la table des administrés... ")
        start_time_adm = time.time()

        Cols = Administre.Cols
        administres = Administre.objects.all().values_list(
            Cols.PK,
            Cols.REL_GRADE,
            'a_nom',
            'a_prenom',
            'a_id_def',
            'a_eip',
            'a_eis',
            'a_domaine_gestion',
            Cols.REL_DOMAINE,
            Cols.REL_FILIERE,
            'a_nf',
            'a_arme',
            'a_rg_origine_recrutement',
            'a_date_entree_service',
            'a_nombre_enfants',
            'a_origine_recrutement',
            'a_date_naissance',
            'a_fonction',
            'a_diplome_hl',
            'a_dernier_diplome',
            'a_date_rdc',
            'a_credo_fe',
            f'{Cols.REL_FORMATION_EMPLOI}__fe_garnison_lieu',
            'a_date_arrivee_fe',
            'a_date_dernier_acr',
            'a_pos_statuaire',
            'a_date_pos_statuaire',
            'a_interruption_service',
            'a_grade_date_debut',
            'a_profession_conjoint',
            'a_sap_conjoint',
            'a_id_def_conjoint',
            'a_sexe_conjoint',
            'a_date_fonction1',
            'a_fonction1',
            'a_date_fonction2',
            'a_fonction2',
            'a_date_fonction3',
            'a_fonction3',
            'a_date_fonction4',
            'a_fonction4',
            'a_date_fonction5',
            'a_fonction5',
            'a_date_fonction6',
            'a_fonction6',
            'a_date_fonction7',
            'a_fonction7',
            'a_date_fonction8',
            'a_fonction8',
            'a_date_fonction9',
            'a_fonction9',
            'a_date_mariage',
            'a_situation_fam',
            'a_sexe',
            'a_date_fud',
            'a_fud',
            Cols.DATE_STATUT_CONCERTO,
            Cols.STATUT_CONCERTO,
            Cols.DATE_STATUT_CONCERTO_FUTUR,
            Cols.STATUT_CONCERTO_FUTUR,
            'a_domaine_poste',
            'a_filiere_poste',
            'a_nf_poste',
            'a_lien_service',
            'a_marqueur_pn',
            'a_pls_gb_max',
            'a_enfants',
        )

        administres_df = pd.DataFrame.from_records(administres)

        adm_bo_cols = BOCols.columns(
            BOCols.ID_SAP,                           # A
            BOCols.GRADE,                            # B
            BOCols.NOM,                              # C
            BOCols.PRENOM,                           # D
            BOCols.ID_DEF,                           # E
            BOCols.EIP,                              # F
            BOCols.EIS,                              # G
            BOCols.DOMAINE_GESTION,                  # H
            BOCols.DOMAINE,                          # I
            BOCols.FILIERE,                          # J
            BOCols.NF,                               # K
            BOCols.ARME,                             # L
            BOCols.REGROUPEMENT_ORIGINE_RECRUTEMENT, # M
            BOCols.DATE_ENTREE_SERVICE,              # N
            BOCols.NOMBRE_ENFANTS,                   # O
            BOCols.ORIGINE_RECRUTEMENT,              # Q
            BOCols.DATE_NAISSANCE,                   # R
            BOCols.FONCTION,                         # T
            BOCols.DIPLOME_PLUS_HAUT_NIVEAU,         # U
            BOCols.DERNIER_DIPLOME,                  # V
            BOCols.DATE_RDC,                         # W
            BOCols.CREDO_FE,                         # X
            BOCols.GARNISON,                         # Z (utilisé dans la table des garnisons)
            BOCols.DATE_ARRIVEE_FE,                  # AA
            BOCols.DATE_DERNIER_ACR,                 # AC
            BOCols.POSITION_STATUTAIRE,              # AE
            BOCols.DATE_POSITION_STATUAIRE,          # AF
            BOCols.INTERRUPTION_SERVICE,             # AG
            BOCols.DATE_DEBUT_GRADE,                 # AH
            BOCols.PROFESSION_CONJOINT,              # AL
            BOCols.ID_SAP_CONJOINT,                  # AM
            BOCols.ID_DEF_CONJOINT,                  # AN
            BOCols.SEXE_CONJOINT,                    # AT
            BOCols.DATE_FONCTION_1,                  # BM
            BOCols.FONCTION_1,                       # BN
            BOCols.DATE_FONCTION_2,                  # BO
            BOCols.FONCTION_2,                       # BP
            BOCols.DATE_FONCTION_3,                  # BQ
            BOCols.FONCTION_3,                       # BR
            BOCols.DATE_FONCTION_4,                  # BS
            BOCols.FONCTION_4,                       # BT
            BOCols.DATE_FONCTION_5,                  # BU
            BOCols.FONCTION_5,                       # BV
            BOCols.DATE_FONCTION_6,                  # BW
            BOCols.FONCTION_6,                       # BX
            BOCols.DATE_FONCTION_7,                  # BY
            BOCols.FONCTION_7,                       # BZ
            BOCols.DATE_FONCTION_8,                  # CA
            BOCols.FONCTION_8,                       # CB
            BOCols.DATE_FONCTION_9,                  # CC
            BOCols.FONCTION_9,                       # CD
            BOCols.DATE_MARIAGE,                     # CH
            BOCols.SITUATION_FAMILIALE,              # CI
            BOCols.SEXE,                             # CJ
            BOCols.DATE_FUD,                         # DV
            BOCols.FUD,                              # DW
            BOCols.DATE_STATUT_CONCERTO,             # DX
            BOCols.STATUT_CONCERTO,                  # DY
            BOCols.DATE_STATUT_CONCERTO_FUTUR,       # DZ
            BOCols.STATUT_CONCERTO_FUTUR,            # EA
            BOCols.DOMAINE_POSTE,                    # ED (non utilisé)
            BOCols.FILIERE_POSTE,                    # EE (non utilisé)
            BOCols.NF_POSTE,                         # EF (non utilisé)
            BOCols.DATE_LIEN_SERVICE,                # EG
            BOCols.MARQUEUR_PN,                      # EH
            BOCols.PLS_GB_MAX,                       # EI
            BOCols.ENFANTS,                          # EK
        )

        administres_df.columns = adm_bo_cols
                
        # Changement des types des colonnes dates
        administres_df[BOCols.DATE_ARRIVEE_FE]            = pd.to_datetime(administres_df[BOCols.DATE_ARRIVEE_FE], errors='coerce').dt.strftime('%d/%m/%Y')                      # AA
        administres_df[BOCols.DATE_DEBUT_GRADE]           = pd.to_datetime(administres_df[BOCols.DATE_DEBUT_GRADE], errors='coerce').dt.strftime('%d/%m/%Y')                     # AH
        administres_df[BOCols.DATE_DERNIER_ACR]           = pd.to_datetime(administres_df[BOCols.DATE_DERNIER_ACR], errors='coerce').dt.strftime('%d/%m/%Y')                     # AC
        administres_df[BOCols.DATE_ENTREE_SERVICE]        = pd.to_datetime(administres_df[BOCols.DATE_ENTREE_SERVICE], errors='coerce').dt.strftime('%d/%m/%Y')                  # N
        administres_df[BOCols.DATE_FUD]                   = pd.to_datetime(administres_df[BOCols.DATE_FUD], errors='coerce').dt.strftime('%d/%m/%Y')                             # DV
        administres_df[BOCols.DATE_LIEN_SERVICE]          = pd.to_datetime(administres_df[BOCols.DATE_LIEN_SERVICE], errors='coerce').dt.strftime('%d/%m/%Y')                    # EG
        administres_df[BOCols.DATE_NAISSANCE]             = pd.to_datetime(administres_df[BOCols.DATE_NAISSANCE], errors='coerce').dt.strftime('%d/%m/%Y')                       # R
        administres_df[BOCols.DATE_POSITION_STATUAIRE]    = pd.to_datetime(administres_df[BOCols.DATE_POSITION_STATUAIRE], errors='coerce').dt.strftime('%d/%m/%Y')              # AF
        administres_df[BOCols.DATE_RDC]                   = pd.to_datetime(administres_df[BOCols.DATE_RDC], errors='coerce').dt.strftime('%d/%m/%Y')                             # W
        administres_df[BOCols.DATE_STATUT_CONCERTO]       = pd.to_datetime(administres_df[BOCols.DATE_STATUT_CONCERTO], errors='coerce').dt.strftime('%d/%m/%Y')                 # DX
        administres_df[BOCols.DATE_STATUT_CONCERTO_FUTUR] = pd.to_datetime(administres_df[BOCols.DATE_STATUT_CONCERTO_FUTUR], errors='coerce').dt.strftime('%d/%m/%Y')           # DZ
        administres_df[BOCols.DATE_MARIAGE]               = pd.to_datetime(administres_df[BOCols.DATE_MARIAGE], errors='coerce').dt.strftime('%d/%m/%Y')                         # CH
        for i in range(1, 10):
            administres_df[f'Fonction -{i} DD'] = pd.to_datetime(administres_df[f'Fonction -{i} DD']).dt.strftime('%d/%m/%Y')

        # Changement des types des colonnes bool
        administres_df[[BOCols.MARQUEUR_PN]] = administres_df[[BOCols.MARQUEUR_PN]].replace([True, False], ['X', None])

        # CHangement des types des colonnes int
        administres_df[BOCols.ID_SAP_CONJOINT] = administres_df[BOCols.ID_SAP_CONJOINT].fillna(0).astype(int).replace({0: None})
        administres_df[BOCols.PLS_GB_MAX] = administres_df[BOCols.PLS_GB_MAX].fillna(0).astype(int).replace({0: None})
        
        administres_df = (administres_df.fillna(APP_NAN)
                                        .replace({APP_NAN: None})
                                        .replace({np.nan: None})
                                        .replace({'nan': None}))

        self.logger.info("Table des administrés lue et traitée en %d secondes : %s lignes et %s colonnes extraites\n", time.time()-start_time_adm, administres_df.shape[0], administres_df.shape[1])
        return administres_df


    def export_aff_bo_df(self):
        self.logger.info("Lecture et traitement de la table des affectations... ")
        start_time_aff = time.time()

        aff = pd.DataFrame.from_records(Affectation.objects.all().values()).sort_values('affect_date', ascending=False)

        aff_grouped = aff.groupby(['administre_id']).agg(
            affect_libelle=('affect_libelle', ',,,'.join),
            affect_date=('affect_date', ',,,'.join),
        )
        
        aff_date_cols = [f'Affectation -{i} DD' for i in range(1,10)]
        aff_libelle_cols = [f'Affectation -{i} L' for i in range(1,10)]

        aff_date_df = aff_grouped['affect_date'].str.split(',,,', expand=True)
        aff_libelle_df = aff_grouped['affect_libelle'].str.split(',,,', expand=True)

        nb_cols_date = aff_date_df.shape[1]
        nb_cols_libelle = aff_date_df.shape[1]

        aff_date_cols_tronc = aff_date_cols[:nb_cols_date]
        aff_libelle_cols_tronc = aff_libelle_cols[:nb_cols_libelle]

        aff_grouped[aff_date_cols_tronc] = aff_date_df
        aff_grouped[aff_libelle_cols_tronc] = aff_libelle_df

        aff_grouped = (aff_grouped.drop(['affect_libelle', 'affect_date'], axis=1)
                                  .reset_index())

        # Changement des types des colonnes dates
        for i in range(1, 10):
            aff_grouped[f'Affectation -{i} DD'] = pd.to_datetime(aff_grouped[f'Affectation -{i} DD']).dt.strftime('%d/%m/%Y')
        
        aff_grouped = (aff_grouped.fillna(APP_NAN)
                                  .replace({APP_NAN: None})
                                  .replace({np.nan: None})
                                  .replace({'nan': None}))

        self.logger.info("Table des affectations lue et traitée en %d secondes : %s lignes et %s colonnes extraites\n", time.time()-start_time_aff, aff_grouped.shape[0], aff_grouped.shape[1])
        return aff_grouped

    
    def export_no_bo_df(self):
        self.logger.info("Lecture et traitement de la table des notations... ")
        start_time_no = time.time()

        no = pd.DataFrame.from_records(Administre_Notation.objects.all().values()).sort_values('no_age_annees', ascending=False)

        no_grouped = no.groupby(["administre_id"]).agg(
            no_annne_de_notation=("no_annne_de_notation", ",,,".join),
            no_nr_ou_iris=("no_nr_ou_iris", ",,,".join),
            no_rac_ou_iris_cumule=("no_rac_ou_iris_cumule", ",,,".join),
            no_rf_qsr=("no_rf_qsr", ",,,".join),
            no_aptitude_emploie_sup=("no_aptitude_emploie_sup", ",,,".join),
            no_potentiel_responsabilite_sup=("no_potentiel_responsabilite_sup", ",,,".join),
            no_age_annees=("no_age_annees", ",,,".join),
        )

        no_age_annees_cols = ['Age en années (au 31/12)']
        no_annne_de_notation_cols = ['Année notation A'] + [f'Année notation A-{i}' for i in range(1,6)]
        no_nr_ou_iris_cols = ['IRIS / RAC retenu A'] + [f'IRIS / RAC retenu A-{i}' for i in range(1,6)]
        no_rac_ou_iris_cumule_cols = ['NR/NGC cumulé A'] + [f'NR/NGC cumulé A-{i}' for i in range(1,6)]
        no_rf_qsr_cols = ['QSR A'] + [f'QSR A-{i}' for i in range(1,6)]
        no_aptitude_emploie_sup_cols = ['Apt resp / Emp sup A'] + [f'Apt resp / Emp sup A-{i}' for i in range(1,6)]
        no_potentiel_responsabilite_sup_cols = ['Potentiel responsabilités catégorie sup A'] + [f'Potentiel responsabilités catégorie sup A-{i}' for i in range(1,6)]

        no_grouped[no_age_annees_cols] = no_grouped['no_age_annees'].str.split(',,,', expand=True)[0]
        no_grouped[no_annne_de_notation_cols] = no_grouped['no_annne_de_notation'].str.split(',,,', expand=True)
        no_grouped[no_nr_ou_iris_cols] = no_grouped['no_nr_ou_iris'].str.split(',,,', expand=True)
        no_grouped[no_rac_ou_iris_cumule_cols] = no_grouped['no_rac_ou_iris_cumule'].str.split(',,,', expand=True)
        no_grouped[no_rf_qsr_cols] = no_grouped['no_rf_qsr'].str.split(',,,', expand=True)
        no_grouped[no_aptitude_emploie_sup_cols] = no_grouped['no_aptitude_emploie_sup'].str.split(',,,', expand=True)
        no_grouped[no_potentiel_responsabilite_sup_cols] = no_grouped['no_potentiel_responsabilite_sup'].str.split(',,,', expand=True)

        no_grouped = (no_grouped.drop(['no_annne_de_notation',
                                        'no_nr_ou_iris',
                                        'no_rac_ou_iris_cumule',
                                        'no_rf_qsr',                  
                                        'no_aptitude_emploie_sup',
                                        'no_potentiel_responsabilite_sup',
                                        'no_age_annees'], axis=1)
                                .reset_index())

        # Changement des types des colonnes int
        no_grouped[f'Année notation A'] = no_grouped[f'Année notation A'].astype(float).fillna(0).astype(int).replace({0: None})
        no_grouped[f'IRIS / RAC retenu A'] = no_grouped[f'IRIS / RAC retenu A'].astype(float).fillna(0).astype(int).replace({0: None})
        no_grouped[f'NR/NGC cumulé A'] = no_grouped[f'NR/NGC cumulé A'].astype(float).fillna(0).astype(int).replace({0: None})
        for i in range(1, 6):
            no_grouped[f'Année notation A-{i}'] = no_grouped[f'Année notation A-{i}'].astype(float).fillna(0).astype(int).replace({0: None})
            no_grouped[f'IRIS / RAC retenu A-{i}'] = no_grouped[f'IRIS / RAC retenu A-{i}'].astype(float).fillna(0).astype(int).replace({0: None})
            no_grouped[f'NR/NGC cumulé A-{i}'] = no_grouped[f'NR/NGC cumulé A-{i}'].astype(float).fillna(0).astype(int).replace({0: None})

        no_grouped = (no_grouped.fillna(APP_NAN)
                                .replace({APP_NAN: None})
                                .replace({np.nan: None})
                                .replace({'nan': None}))

        self.logger.info("Table des notations lue et traitée en %d secondes : %s lignes et %s colonnes extraites\n", time.time()-start_time_no, no_grouped.shape[0], no_grouped.shape[1])
        return no_grouped


    def export_pos_reo_df(self):
        self.logger.info("Lecture et traitement de la table des postes... ")
        start_time_pos = time.time()

        Cols = Poste.Cols
        postes = Poste.objects.all().values_list(
            'p_annee',
            Cols.REL_FORMATION_EMPLOI,
            'p_dep',
            Cols.CATEGORIE,
            'p_eip',
            Cols.REL_DOMAINE,
            Cols.REL_FILIERE,
            Cols.NIVEAU_FONCTIONNEL,
            Cols.PK,
            f'{Cols.REL_FONCTION}__fon_id',
            f'{Cols.REL_FONCTION}__fon_libelle',
            'p_nfs',
        )

        postes_df = pd.DataFrame.from_records(postes)

        pos_reo_cols = ReoCols.columns(
            ReoCols.ANNEE_PROJET,      # B
            ReoCols.FORMATION_EMPLOI,  # F
            ReoCols.CODE_POSTAL,       # J
            ReoCols.CATEGORIE,         # P
            ReoCols.EIP,               # T
            ReoCols.DOMAINE,           # U
            ReoCols.FILIERE,           # V
            ReoCols.CODE_NF,           # W
            ReoCols.ID_POSTE,          # X
            ReoCols.FONCTION_ID,       # Y
            ReoCols.FONCTION_LIBELLE,  # Z
            ReoCols.DOMAINE_GESTION,   # AA
        )

        postes_df.columns = pos_reo_cols
        
        postes_df = (postes_df.fillna(APP_NAN)
                              .replace({APP_NAN: None})
                              .replace({np.nan: None})
                              .replace({'nan': None}))

        self.logger.info("Table des postes lue et traitée en %d secondes : %s lignes et %s colonnes extraites\n", time.time()-start_time_pos, postes_df.shape[0], postes_df.shape[1])
        return postes_df


    @atomic
    # @execution_time(logger_factory=data_perf_logger_factory)
    @query_count(logger_factory=data_perf_logger_factory)
    def export_bo(self, request):
        self.logger.info("--------- Début de l'exportation du fichier 'Données BO' --------- ")
        start_time_export = time.time()

        administres_df  = self.export_adm_bo_df()
        affectations_df = self.export_aff_bo_df()
        notations_df    = self.export_no_bo_df()

        bo_df = administres_df.merge(affectations_df, how='left', left_on=BOCols.ID_SAP, right_on='administre_id')
        bo_df = bo_df.drop(['administre_id'], axis=1)
        bo_df = bo_df.merge(notations_df, how='left', left_on=BOCols.ID_SAP, right_on='administre_id')
        bo_df = bo_df.drop(['administre_id'], axis=1)

        bo_cols = BOCols.columns(
            BOCols.ID_SAP,                           # A
            BOCols.GRADE,                            # B
            BOCols.NOM,                              # C
            BOCols.PRENOM,                           # D
            BOCols.ID_DEF,                           # E
            BOCols.EIP,                              # F
            BOCols.EIS,                              # G
            BOCols.DOMAINE_GESTION,                  # H
            BOCols.DOMAINE,                          # I
            BOCols.FILIERE,                          # J
            BOCols.NF,                               # K
            BOCols.ARME,                             # L
            BOCols.REGROUPEMENT_ORIGINE_RECRUTEMENT, # M
            BOCols.DATE_ENTREE_SERVICE,              # N
            BOCols.NOMBRE_ENFANTS,                   # O
            BOCols.ORIGINE_RECRUTEMENT,              # Q
            BOCols.DATE_NAISSANCE,                   # R
            BOCols.FONCTION,                         # T
            BOCols.DIPLOME_PLUS_HAUT_NIVEAU,         # U
            BOCols.DERNIER_DIPLOME,                  # V
            BOCols.DATE_RDC,                         # W
            BOCols.CREDO_FE,                         # X
            BOCols.GARNISON,                         # Z (utilisé dans la table des garnisons)
            BOCols.DATE_ARRIVEE_FE,                  # AA
            BOCols.DATE_DERNIER_ACR,                 # AC
            BOCols.POSITION_STATUTAIRE,              # AE
            BOCols.DATE_POSITION_STATUAIRE,          # AF
            BOCols.INTERRUPTION_SERVICE,             # AG
            BOCols.DATE_DEBUT_GRADE,                 # AH
            BOCols.PROFESSION_CONJOINT,              # AL
            BOCols.ID_SAP_CONJOINT,                  # AM
            BOCols.ID_DEF_CONJOINT,                  # AN
            BOCols.SEXE_CONJOINT,                    # AT
            BOCols.DATE_AFFECTATION_1,               # AU
            BOCols.AFFECTATION_1,                    # AV
            BOCols.DATE_AFFECTATION_2,               # AW
            BOCols.AFFECTATION_2,                    # AX
            BOCols.DATE_AFFECTATION_3,               # AY
            BOCols.AFFECTATION_3,                    # AZ
            BOCols.DATE_AFFECTATION_4,               # BA
            BOCols.AFFECTATION_4,                    # BB
            BOCols.DATE_AFFECTATION_5,               # BC
            BOCols.AFFECTATION_5,                    # BD
            BOCols.DATE_AFFECTATION_6,               # BE
            BOCols.AFFECTATION_6,                    # BF
            BOCols.DATE_AFFECTATION_7,               # BG
            BOCols.AFFECTATION_7,                    # BH
            BOCols.DATE_AFFECTATION_8,               # BI
            BOCols.AFFECTATION_8,                    # BJ
            BOCols.DATE_AFFECTATION_9,               # BK
            BOCols.AFFECTATION_9,                    # BL
            BOCols.DATE_FONCTION_1,                  # BM
            BOCols.FONCTION_1,                       # BN
            BOCols.DATE_FONCTION_2,                  # BO
            BOCols.FONCTION_2,                       # BP
            BOCols.DATE_FONCTION_3,                  # BQ
            BOCols.FONCTION_3,                       # BR
            BOCols.DATE_FONCTION_4,                  # BS
            BOCols.FONCTION_4,                       # BT
            BOCols.DATE_FONCTION_5,                  # BU
            BOCols.FONCTION_5,                       # BV
            BOCols.DATE_FONCTION_6,                  # BW
            BOCols.FONCTION_6,                       # BX
            BOCols.DATE_FONCTION_7,                  # BY
            BOCols.FONCTION_7,                       # BZ
            BOCols.DATE_FONCTION_8,                  # CA
            BOCols.FONCTION_8,                       # CB
            BOCols.DATE_FONCTION_9,                  # CC
            BOCols.FONCTION_9,                       # CD
            BOCols.AGE_ANNEES,                       # CG
            BOCols.DATE_MARIAGE,                     # CH
            BOCols.SITUATION_FAMILIALE,              # CI
            BOCols.SEXE,                             # CJ
            BOCols.ANNEE_NOTATION,                   # CL
            BOCols.RAC_OU_IRIS_CUMULE,               # CM
            BOCols.NR_OU_IRIS,                       # CN
            BOCols.RF_QSR,                           # CO
            BOCols.APTITUDE_EMPLOI_SUP,              # CP
            BOCols.POTENTIEL_RESPONSABILITE_SUP,     # CQ
            BOCols.ANNEE_NOTATION_1,                 # CR
            BOCols.RAC_OU_IRIS_CUMULE_1,             # CS
            BOCols.NR_OU_IRIS_1,                     # CT
            BOCols.RF_QSR_1,                         # CU
            BOCols.APTITUDE_EMPLOI_SUP_1,            # CV
            BOCols.POTENTIEL_RESPONSABILITE_SUP_1,   # CW
            BOCols.ANNEE_NOTATION_2,                 # CX
            BOCols.RAC_OU_IRIS_CUMULE_2,             # CY
            BOCols.NR_OU_IRIS_2,                     # CZ
            BOCols.RF_QSR_2,                         # DA
            BOCols.APTITUDE_EMPLOI_SUP_2,            # DB
            BOCols.POTENTIEL_RESPONSABILITE_SUP_2,   # DC
            BOCols.ANNEE_NOTATION_3,                 # DD
            BOCols.RAC_OU_IRIS_CUMULE_3,             # DE
            BOCols.NR_OU_IRIS_3,                     # DF
            BOCols.RF_QSR_3,                         # DG
            BOCols.APTITUDE_EMPLOI_SUP_3,            # DH
            BOCols.POTENTIEL_RESPONSABILITE_SUP_3,   # DI
            BOCols.ANNEE_NOTATION_4,                 # DJ
            BOCols.RAC_OU_IRIS_CUMULE_4,             # DK
            BOCols.NR_OU_IRIS_4,                     # DL
            BOCols.RF_QSR_4,                         # DM
            BOCols.APTITUDE_EMPLOI_SUP_4,            # DN
            BOCols.POTENTIEL_RESPONSABILITE_SUP_4,   # DO
            BOCols.ANNEE_NOTATION_5,                 # DP
            BOCols.RAC_OU_IRIS_CUMULE_5,             # DQ
            BOCols.NR_OU_IRIS_5,                     # DR
            BOCols.RF_QSR_5,                         # DS
            BOCols.APTITUDE_EMPLOI_SUP_5,            # DT
            BOCols.POTENTIEL_RESPONSABILITE_SUP_5,   # DU
            BOCols.DATE_FUD,                         # DV
            BOCols.FUD,                              # DW
            BOCols.DATE_STATUT_CONCERTO,             # DX
            BOCols.STATUT_CONCERTO,                  # DY
            BOCols.DATE_STATUT_CONCERTO_FUTUR,       # DZ
            BOCols.STATUT_CONCERTO_FUTUR,            # EA
            BOCols.DOMAINE_POSTE,                    # ED (non utilisé)
            BOCols.FILIERE_POSTE,                    # EE (non utilisé)
            BOCols.NF_POSTE,                         # EF (non utilisé)
            BOCols.DATE_LIEN_SERVICE,                # EG
            BOCols.MARQUEUR_PN,                      # EH
            BOCols.PLS_GB_MAX,                       # EI
            BOCols.ENFANTS,                          # EK
        )

        bo_df = bo_df.reindex(columns=bo_cols)

        if bo_df.empty:
            return  Response("Aucune donnée à extraire.")
        else:
            try:
                self.logger.info("Exportation du fichier 'Données BO'...")
                start_time_export_bo = time.time()
                
                now = timezone.now().date()
                bo_df.to_excel(f'..\\fichiers_exportes\\{now}_donnees_BO_export.xlsx', index=False, header=True)
                bo_obj = FichiersExporte(nom_fichier=f'{now}_donnees_BO_export.xlsx')
                bo_obj.save()
                
                self.logger.info("Exportation du fichier 'Données BO' réalisée en %d secondes : %s lignes et %s colonnes exportées", time.time()-start_time_export_bo, bo_df.shape[0], bo_df.shape[1])
                self.logger.info("---- Exportation totale réalisée en : %d minutes et %d secondes ----\n", (time.time()-start_time_export)//60, (time.time()-start_time_export)%60)
                return  Response("Exportation terminée. Vous trouverez le fichier 'Données BO' exporté dans le dossier 'fichiers_exportes'.")
            except (Http404, APIException):
                raise
            except BaseException:
                message = "Imposible de réaliser l'exportation du fichier 'Données BO'. Vérifiez que les fichiers Excel d'exportation sont bien fermés."
                self.logger.exception(message)
                raise APIException(message)


    @atomic
    # @execution_time(logger_factory=data_perf_logger_factory)
    @query_count(logger_factory=data_perf_logger_factory)
    def export_reo(self, request):
        self.logger.info("--------- Début de l'exportation du fichier 'REO' --------- ")
        start_time_export = time.time()

        postes_df  = self.export_pos_reo_df()
        reo_df = postes_df

        if reo_df.empty:
            return  Response("Aucune donnée à extraire.")
        else:
            try:
                self.logger.info("Exportation du fichier 'REO'...")
                start_time_export_reo = time.time()
                
                now = timezone.now().date()
                reo_df.to_excel(f'..\\fichiers_exportes\\{now}_REO_export.xlsx', index=False, header=True)
                reo_obj = FichiersExporte(nom_fichier=f'{now}_REO_export.xlsx')
                reo_obj.save()
                
                self.logger.info("Exportation du fichier 'REO' réalisée en %d secondes : %s lignes et %s colonnes exportées", time.time()-start_time_export_reo, reo_df.shape[0], reo_df.shape[1])
                self.logger.info("------- Exportation totale réalisée en : %d secondes ------\n", time.time()-start_time_export)
                return  Response("Exportation terminée. Vous trouverez le fichier 'REO' exporté dans le dossier 'fichiers_exportes'.")
            except (Http404, APIException):
                raise
            except BaseException:
                message = "Imposible de réaliser l'exportation du fichier 'REO'. Vérifiez que les fichiers Excel d'exportation sont bien fermés."
                self.logger.exception(message)
                raise APIException(message)


    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        nom_fichier = serializer.validated_data.get('fichier_exporte')
        
        if nom_fichier == '1':
            resp = self.export_bo(request)
            return resp
        if nom_fichier == '2':
            resp = self.export_reo(request)
            return resp
        return Response("Imposible de réaliser l'exportation.")
        

