from enum import Enum, auto

from django.db import models

from .administre import Administre, Administres_Pams
from .initial import PAM, Notation
from .poste import Poste, Postes_Pams


class DecisionTree(Enum):
    """ enum pour les types d'arbres de décisions """

    # métropole
    ME  = auto()

    # hors métropole
    HME = auto()

    def __repr__(self):
        return self.__str__()


class DecisionChoices(models.TextChoices):
    """
    Choix pour les statuts de décisions
    attributs supplémentaires :
    - trees : Tuple[DecisionTree], permet de savoir à quel(s) arbre(s) appartient le statut
    """

    # arbre de décision en métropole
    PROPOSITION_FE           = ('PROPOSITION_FE',           DecisionTree.ME),  'Proposition de FE'
    DIALOGUE_EN_COURS        = ('DIALOGUE_EN_COURS',        DecisionTree.ME),  'Dialogue en cours'
    DIALOGUE_TERMINE         = ('DIALOGUE_TERMINE',         DecisionTree.ME),  'Dialogue terminé'
    DIALOGUE_INFRUCTUEUX     = ('DIALOGUE_INFRUCTUEUX',     DecisionTree.ME),  'Dialogue infructueux'
    FOREMP_EN_COURS          = ('FOREMP_EN_COURS',          DecisionTree.ME),  'FOREMP en cours'
    FOREMP_TERMINE           = ('FOREMP_TERMINE',           DecisionTree.ME),  'FOREMP terminé'
    PREPOSITIONNE            = ('PREPOSITIONNE',            DecisionTree.ME),  'Prépositionné'
    POSITIONNE               = ('POSITIONNE',               DecisionTree.ME),  'Positionné'
    OMIP_EN_COURS            = ('OMIP_EN_COURS',            DecisionTree.ME),  'OMIP en cours'
    OMIP_TERMINE             = ('OMIP_TERMINE',             DecisionTree.ME),  'OMIP terminé'
    ATTENTE_AVIONAGE         = ('ATTENTE_AVIONAGE',         DecisionTree.ME),  "En attente d'avionage"
    OMI_EN_COURS             = ('OMI_EN_COURS',             DecisionTree.ME),  'OMI en cours'
    OMI_ACTIVE               = ('OMI_ACTIVE',               DecisionTree.ME),  'OMI terminé'
    OMI_ANNULE               = ('OMI_ANNULE',               DecisionTree.ME),  'OMI annulation'

    # arbre de décision hors métropole
    HME_DIALOGUE_INITIE      = ('HME_DIALOGUE_INITIE',      DecisionTree.HME), 'Dialogue initié (HME)'
    HME_DIALOGUE_EN_COURS    = ('HME_DIALOGUE_EN_COURS',    DecisionTree.HME), 'Dialogue en cours (HME)'
    HME_DIALOGUE_INFRUCTUEUX = ('HME_DIALOGUE_INFRUCTUEUX', DecisionTree.HME), 'Dialogue infructueux (HME)'
    HME_DIALOGUE_TERMINE     = ('HME_DIALOGUE_TERMINE',     DecisionTree.HME), 'Dialogue terminé (HME)'
    HME_PROPOSITION_VIVIER   = ('HME_PROPOSITION_VIVIER',   DecisionTree.HME), 'Proposition vivier HME'
    HME_ETUDE_DESISTEMENT    = ('HME_ETUDE_DESISTEMENT',    DecisionTree.HME), 'Etude désistement (HME)'
    HME_DESISTEMENT          = ('HME_DESISTEMENT',          DecisionTree.HME), 'Désistement activé (HME)'
    HME_PREPOSITIONNE        = ('HME_PREPOSITIONNE',        DecisionTree.HME), 'Prépositionné (HME)'
    HME_VALIDATION_EXPERT    = ('HME_VALIDATION_EXPERT',    DecisionTree.HME), 'Validation HME (HME)'
    HME_REFUS_EXPERT         = ('HME_REFUS_EXPERT',         DecisionTree.HME), 'Refus HME (HME)'
    HME_POSITIONNE           = ('HME_POSITIONNE',           DecisionTree.HME), 'Positionné (HME)'
    HME_FOREMP_EN_COURS      = ('HME_FOREMP_EN_COURS',      DecisionTree.HME), 'FOREMP en cours (HME)'
    HME_FOREMP_TERMINE       = ('HME_FOREMP_TERMINE',       DecisionTree.HME), 'FOREMP terminé (HME)'
    HME_OMIP_EN_COURS        = ('HME_OMIP_EN_COURS',        DecisionTree.HME), 'OMIP en cours (HME)'
    HME_OMIP_TERMINE         = ('HME_OMIP_TERMINE',         DecisionTree.HME), 'OMIP terminé (HME)'
    HME_ATTENTE_AVIONAGE     = ('HME_ATTENTE_AVIONAGE',     DecisionTree.HME), "En attente d'avionage (HME)"
    HME_OMI_EN_COURS         = ('HME_OMI_EN_COURS',         DecisionTree.HME), 'OMI en cours (HME)'
    HME_OMI_ACTIVE           = ('HME_OMI_ACTIVE',           DecisionTree.HME), 'OMI terminé (HME)'
    HME_OMI_ANNULE           = ('HME_OMI_ANNULE',           DecisionTree.ME),  'OMI annulation'

    REMIS_A_DISPOSITION      = ('REMIS_A_DISPOSITION', (DecisionTree.ME, DecisionTree.HME)), 'Remis à disposition'

    def __new__(cls, value):
        obj = str.__new__(cls, value[0])
        obj._value_ = value[0]
        _trees = value[1]
        obj.trees = _trees if isinstance(_trees, tuple) else (_trees,) if _trees else ()
        return obj

    def __repr__(self):
        return "%s.%s" % (self.__class__.__name__, self._name_)


# Modèle pour les décisions
class Decision(models.Model):
    """
    Modèle pour les décisions
    """

    class Cols():
        """ Constantes pour les noms de colonnes """

        STATUT         = 'de_decision'
        DATE           = 'de_date_decision'
        # relations one-to-one ou many-to-one
        REL_ADMINISTRE = 'administre'
        REL_POSTE      = 'poste'

    administre_pam = models.OneToOneField(Administres_Pams, on_delete=models.CASCADE, related_name=Administres_Pams.Cols.REL_DECISION, primary_key=True, default="")
    administre = models.ForeignKey(Administre, on_delete=models.CASCADE,  related_name=Administres_Pams.Cols.REL_DECISION)
    poste = models.ForeignKey(Poste, on_delete=models.CASCADE, related_name= Postes_Pams.Cols.O2M_DECISION)
    poste_pam = models.OneToOneField(Postes_Pams, on_delete=models.CASCADE, related_name= Postes_Pams.Cols.O2M_DECISION, default="")
    de_decision = models.CharField('Décision', max_length=50, choices=DecisionChoices.choices)
    de_date_decision = models.DateTimeField('Date de décision', auto_now=True)
    de_notes_gestionnaire = models.TextField(null=True, blank=True)
    de_notes_partagees = models.TextField(null=True, blank=True)
    notation = models.ForeignKey(Notation, on_delete=models.SET_NULL, null=True, blank=True)

    class Meta:
        constraints = [
            models.CheckConstraint(
                name='%(app_label)s_%(class)s_de_decision_valid',
                check=models.Q(de_decision__in=DecisionChoices.values)
            )
        ]
        verbose_name = 'Décision'
        verbose_name_plural = 'Décisions'
