import click
from median.models import ListeModel, ListeItemModel, Magasin, Config, Product, Seuil, Stock
from median.constant import TypeListe, TypeServiListe, PatientGlobal
from datetime import datetime
import time
from peewee import DoesNotExist, fn
from common.util import logger, get_counter
from common.exception import RiedlDispatcherException
import requests


@click.command("inventory")
@click.option('--riedl', is_flag=True, help="Compose inventory list and call dispatcher")
@click.option('--clean', is_flag=True, help="Clean all riedl demo data")
def inventory(riedl=False, clean=False):
    """
    Call inventory per equipement
    """

    print("Start to generate inventory")
    if riedl:
        mags = Magasin.select(Magasin).where(Magasin.eco_type == 'L')
        for m in mags:
            print("== Warehouse: %s" % m.mag)
            inventory_riedl(m, clean)

    print("End generate inventory")


def inventory_riedl(warehouse: Magasin = None, clean: bool = False) -> None:
    """
    Generate an inventory list and call the dispatcher
    """
    if clean:
        for lst in ListeModel.select().where(
            ListeModel.type_servi == TypeServiListe.Inventory.value,
            ListeModel.mode == TypeListe.Inventory.value,
            ListeModel.zone_deb == 'RIEDL'
        ):
            lst.delete_instance()

        return True

    liste = "%s-%s" % (warehouse.mag, time.strftime("%Y%m%d-%H%M%S"))
    cpt = 0
    print("-- Riedl Inventory --")
    lst = ListeModel()
    lst.mode = TypeListe.Inventory.value
    lst.liste = liste
    lst.service = 'TRAN'
    lst.type_servi = TypeServiListe.Inventory.value
    lst.id_servi = 8
    lst.fusion = 'INVENTAIRE'
    lst.nb_item = 0
    lst.num_ipp = PatientGlobal.Ipp.value
    lst.num_sej = PatientGlobal.Sejour.value
    lst.zone_deb = 'RIEDL'
    lst.zone_fin = warehouse.type_mag
    lst.date_reception = datetime.now()
    lst.save()

    # Retrieve the list of the product who have threashold to create items
    pro_rec = Product.select(Product.reference).join(
        Seuil, on=(Seuil.reference == Product.reference)
    ).where(Seuil.zone == warehouse.type_mag).order_by(Product.reference)

    for pro in pro_rec:
        # For each product we retrieve all GTIN version 0
        gtin_version_zero = []
        gtins = pro.gtin_list()
        for g in gtins:
            if g.dossier == "0" and g.cip not in gtin_version_zero:
                gtin_version_zero.append(g.cip)

        for gtin in gtin_version_zero:
            # For each GTIN we create an item
            cpt += 1

            stk = Stock.select(
                fn.COUNT(Stock.pk).alias('boites'),
                fn.IFNULL(fn.SUM(Stock.quantite), 0).alias('total')
            ).where(
                Stock.magasin == warehouse.mag, Stock.reference == pro.reference,
                Stock.cip == gtin
            )

            logger.info("item new")
            itm = ListeItemModel()
            itm.mode = lst.mode
            itm.liste = lst.liste
            itm.item = '%06d' % cpt
            itm.dest = lst.service
            itm.magasin = warehouse.mag
            itm.qte_dem = stk[0].total
            itm.qte_serv = 0
            itm.quantite_disp = stk[0].boites
            itm.num_ipp = lst.num_ipp
            itm.num_sej = lst.num_sej
            itm.reference = pro.reference
            itm.user = 'MEDIANWEB'
            itm.lot = ""
            itm.tperemp = ""
            itm.code_liv = gtin
            itm.contenant = gtin
            itm.type_servi = lst.type_servi
            itm.id_chargement = get_counter('RIEDL_INVENTORY')
            itm.cip = gtin
            itm.save()

    lst.nb_item = cpt
    lst.date_modification = datetime.now()
    lst.save()

    print("-- Call the dispatcher API")
    url = ''
    try:
        url = get_url_dispatcher(warehouse.type_mag)
    except RiedlDispatcherException:
        return ''

    print('URL dispatcher %s -> %s' % (warehouse.mag, url))
    # send list to the dispatcher.
    try:
        print('Call list id %s' % str(lst.pk))
        resp = requests.patch('%s/RiedlVMessage' % url, json={
            'id': lst.pk,
        })
        print('Code retour dipatcher %s' % resp.status_code)
    except Exception:
        print("Error when call the the dispatcher")

    print("-- End Riedl inventory --")


def get_url_dispatcher(r_poste: str) -> str:
    """
    Retrieve the URL of the dispatcher

    :param r_poste: Name of the poste relate to the equipement
    :type  r_poste: str
    :return: URL of the dispatcher
    :rtype: str
    """
    url = ''
    try:
        cfg = Config.get(poste=r_poste, cle='cfg', propriete='k_rdl_dispatcher_url')
        url = cfg.value
        if url.endswith('/'):
            url = url[:-1]
    except DoesNotExist:
        logger.error('dispatcher URL for rield [%s] does not exists' % (r_poste,))
        raise RiedlDispatcherException('dispatcher URL for rield %s does not exists' % (r_poste,))

    return url
