from peewee import AutoField, CharField, IntegerField, BooleanField, ForeignKeyField
from peewee import SQL, DoesNotExist

from ..base import InnodbModel
from ..constant import TypeDest
from .products import Product
from . import Poste

# TODO: Remove this
SERVICE_LIST = [
    ('SERVICE', 'Ward'),  # Ward/UF
    ('RIEDL', 'Riedl Exit endpoint'),  # Riedl numero de sortie
    ('SECTEUR', 'Sub sector'),  # Sous secteur associé au service
]

SERVICE_TYPE = [s.value for s in TypeDest]


class Service(InnodbModel):
    """USe to declare Ward or Riedl Exit endpoint"""

    pk = AutoField(
        column_name='x_pk', primary_key=True)
    code = CharField(
        column_name='x_dest', unique=True, null=True, constraints=[SQL("DEFAULT ''")])
    libelle = CharField(
        column_name='x_lib_dest', null=True, constraints=[SQL("DEFAULT ''")])
    ordre = IntegerField(
        column_name='x_ordre', null=True, constraints=[SQL("DEFAULT 0")])
    ug = CharField(
        column_name='x_ug', null=True, constraints=[SQL("DEFAULT ''")])
    resp_serv = CharField(
        column_name='x_resp_serv', null=True, constraints=[SQL("DEFAULT ''")])
    cadre_sup = CharField(
        column_name='x_cadre_sup', null=True, constraints=[SQL("DEFAULT ''")])
    cr = CharField(
        column_name='x_cr', null=True, constraints=[SQL("DEFAULT ''")])
    lib_cr = CharField(
        column_name='x_lib_cr', null=True, constraints=[SQL("DEFAULT ''")])
    pole = CharField(
        column_name='x_pole', constraints=[SQL("DEFAULT ''")])
    nb_cde = IntegerField(
        column_name='x_nb_cde', constraints=[SQL("DEFAULT 0")])
    nb_bu = IntegerField(
        column_name='x_nb_bu', constraints=[SQL("DEFAULT 0")])
    nb_item_bu = IntegerField(
        column_name='x_nb_item_bu', constraints=[SQL("DEFAULT 0")])
    type_peigne = IntegerField(
        column_name='x_type_peigne', constraints=[SQL("DEFAULT 0")])
    moment_deb = CharField(
        column_name='x_moment_deb', constraints=[SQL("DEFAULT '0'")], default='matin')
    deb_matin = IntegerField(
        column_name='x_deb_matin', constraints=[SQL("DEFAULT 6")], default=6)
    deb_midi = IntegerField(
        column_name='x_deb_midi', constraints=[SQL("DEFAULT 11")], default=11)
    deb_soir = IntegerField(
        column_name='x_deb_soir', constraints=[SQL("DEFAULT 14")], default=14)
    deb_coucher = IntegerField(
        column_name='x_deb_coucher', constraints=[SQL("DEFAULT 20")], default=20)
    type_dest = CharField(
        column_name='x_type_dest', constraints=[SQL("DEFAULT 'SERVICE'")], default='SERVICE')
    tri = CharField(
        column_name='x_tri', constraints=[SQL("DEFAULT ''")], default='')
    optim_peigne = BooleanField(
        column_name='x_optim_peigne', constraints=[SQL("DEFAULT 0")], default=0)
    nb_jour = IntegerField(
        column_name='x_nb_jour', null=True, constraints=[SQL("DEFAULT 0")], default=0)
    tri_jour = BooleanField(
        column_name='x_tri_jour', constraints=[SQL("DEFAULT 0")], default=0)
    type_carnet = IntegerField(
        column_name='x_type_carnet', null=True, constraints=[SQL("DEFAULT 1")], default=1)
    secteur = CharField(
        column_name='x_secteur', null=True, max_length=40, constraints=[SQL("DEFAULT ''")])
    adr1 = CharField(
        column_name='x_adr1', null=True, max_length=40, constraints=[SQL("DEFAULT ''")], default='')
    adr2 = CharField(
        column_name='x_adr2', null=True, max_length=40, constraints=[SQL("DEFAULT ''")], default='')
    adr3 = CharField(
        column_name='x_adr3', null=True, max_length=40, constraints=[SQL("DEFAULT ''")], default='')
    adr4 = CharField(
        column_name='x_adr4', null=True, max_length=40, constraints=[SQL("DEFAULT ''")], default='')
    riedl_tk_mode = CharField(
        column_name='x_tk_mode', null=True, max_length=2, constraints=[SQL("DEFAULT 'NO'")], default='NO')
    riedl_unload_auto_print = BooleanField(
        column_name='x_rdl_unload_prt_auto', constraints=[SQL("DEFAULT 0")], default=0)
    aideplus_completion = BooleanField(
        column_name='x_plus_completion', constraints=[SQL("DEFAULT 0")], default=0)

    class Meta:
        table_name = 'f_dest'
        indexes = (
            (('x_dest',), True),
            (('x_type_dest',), False),
            (('x_lib_dest',), False),
        )

    def save(self, force_insert=False, only=None):
        """Enforce control on each information passed"""
        if self.type_dest not in SERVICE_TYPE:
            raise ValueError('Type dest must be: %s' % ','.join(SERVICE_TYPE))
        if self.type_dest == 'RIEDL' and self.secteur is None:
            raise ValueError('Riedl equipment must be defined in secteur, must exists in f_poste')
        if self.type_dest == 'RIEDL' and self.secteur is not None:
            # search if riedl is defined on the f_poste table
            try:
                Poste.get(poste=self.secteur)
            except DoesNotExist:
                raise ValueError('Riedl %s equipment not defined in f_poste' % self.secteur)

        return super().save(force_insert, only)


class ReferencePerService(InnodbModel):

    pk = AutoField(
        column_name='x_pk', primary_key=True)
    ref_pk = ForeignKeyField(
        Product, column_name='x_ref_pk', backref="products", lazy_load=False,
        on_delete='CASCADE', on_update='CASCADE')
    dest_pk = ForeignKeyField(
        Service, column_name='x_dest_pk', backref="services", lazy_load=False,
        on_delete='CASCADE', on_update='CASCADE')
    distribution = CharField(
        column_name='x_distribution', max_length=2, constraints=[SQL("DEFAULT 'UN'")], default='UN')
    distribution_type = CharField(
        column_name="x_dist_type", max_length=1, constraints=[SQL("DEFAULT 'n'")], default='N')
    eco_type = CharField(
        column_name="x_eco_type", max_length=1, constraints=[SQL("DEFAULT 'E'")], default='E')

    def save(self, force_insert=False, only=None):
        """Enforce control on each information passed"""
        if self.distribution_type not in ['N', 'G']:
            raise ValueError('bad value %s, only N or G' % self.distribution_type)
        if self.eco_type not in ['E', 'T', 'C']:
            raise ValueError('bad value %s, only E, T, C' % self.eco_type)
        return super().save(force_insert, only)

    class Meta:
        table_name = 'f_ref_dest'
        indexes = (
            (('x_ref_pk', 'x_dest_pk', 'x_dist_type'), True),
        )


Endpoint = Service
