import json
import logging
from datetime import datetime

from flask import Blueprint, request, session
from flask_jwt_extended import jwt_required
from median.constant import HistoryType, EcoType
from median.models import Magasin, Stock, Product, Gpao, FListe, FItem, Patient, Historique
from peewee import fn

from common.status import HTTP_200_OK, HTTP_500_INTERNAL_SERVER_ERROR

from ressources.acced.acced_output_blueprint import _getPatient

astus_output_blueprint = Blueprint('astus_output', __name__)

logger = logging.getLogger('median')


@astus_output_blueprint.route('', methods=['POST'])
@jwt_required()
def get_all():
    logger.info("Récupérer les listes de sorties...")
    data = json.loads(request.data)
    acced_list = _getPatient(_ipp=None, equipment='ASTUS', criterias=data.get('criterias', []))

    return {'list': acced_list}, HTTP_200_OK


@astus_output_blueprint.route('deletelists', methods=['POST'])
@jwt_required()
def deleteElts():
    data = json.loads(request.data)
    logger.info("Start delete lists by %s " % session['username'])

    try:

        FListe.delete().where(FListe.pk << data).execute()

        return 'Success'
    except Exception as error:
        logger.error(error.args)
        return {'message': error.args}, HTTP_500_INTERNAL_SERVER_ERROR


@astus_output_blueprint.route('<string:list_pk>/<string:item_pk>', methods=['DELETE'])
@jwt_required()
def deleteItem(list_pk, item_pk):
    """Delete one item by PK"""
    try:
        logger.info("delete item %s" % item_pk)
        itm = ((FItem.select().join(FListe, on=FItem.liste == FListe.liste)
                .where((FListe.pk == list_pk) & (FItem.pk == item_pk)))
               .get())

        mag = Magasin.select(Magasin).where(Magasin.eco_type == EcoType.Astus).order_by(Magasin.pk)
        qte_tot = Stock.select(fn.SUM(Stock.quantite)).where(Stock.reference == itm.reference).scalar()

        # Create a GPAO line
        logger.info('Create a GPAO line for item %s in list [%s]' % (item_pk, itm.liste))
        Gpao.create(
            chrono=datetime.now(),
            poste='MEDIANWEB',
            etat='A',
            ref=itm.reference,
            qte=0,
            type_mvt='S',
            liste=itm.liste,
            dest=itm.dest,
            user=session['username'],
            item=itm.item,
            info=itm.info,
            solde=1,
            item_wms=itm.item_wms,
            fraction=itm.fraction,
            qte_dem=itm.qte_dem,
            ipp=itm.num_ipp,
            sejour=itm.num_sej,
            id_robot=mag and mag[0].id_robot or 1,
            id_zone=mag and mag[0].id_zone or 1,
            magasin=mag and mag[0].mag or '',
        )

        # Create an history
        logger.info('Create a GPAO line for item %s' % item_pk)
        Historique.create(
            chrono=datetime.now(),
            reference=itm.reference,
            adresse='',
            magasin=mag and mag[0].mag or '',
            quantite_mouvement=0,
            quantite_totale=qte_tot,
            quantite_demande=itm.qte_dem,
            date_prise=itm.dtprise,
            heure=itm.heure,
            moment=itm.moment,
            service=itm.dest,
            liste=itm.liste,
            item=itm.item,
            type_mouvement=HistoryType.Sortie.value,
            pmp=0,
            poste='MEDIANWEB',
            ipp=itm.num_ipp,
            sejour=itm.num_sej,
            fraction=itm.fraction,
            item_wms=itm.item_wms,
            utilisateur=session['username'],
            info="MedianWeb -> Supp item",
            commentaire="Manual",
        )
        itm.delete_instance()

        nb_items = FItem.select(FItem.pk).where(FItem.liste == itm.liste).count()

        pk_list = None
        if nb_items == 0:
            lst = FListe.get(liste=itm.liste)
            pk_list = lst.pk
            lst.delete_instance()

        return {'result': nb_items, 'deletedList': pk_list}, HTTP_200_OK

    except Exception as error:
        logger.error(error.args)
        return {'message': error.args}, HTTP_500_INTERNAL_SERVER_ERROR


@astus_output_blueprint.route('<string:patient_pk>', methods=['GET'])
@jwt_required()
def get_(patient_pk):
    logger.info("Récupérer les items de listes de sorties de la liste : '%s'" % patient_pk)
    try:

        _items = (FListe.select(FListe.pk.alias('list_pk'),
                                FListe.liste.alias('list'),
                                FItem.moment.alias('moment'),
                                FItem.heure.alias('hour'),
                                FItem.pk.alias('pk'),
                                FListe.ddeb.alias('ddeb'),
                                FItem.etat.alias('state'),
                                FItem.fraction.alias('fraction'),
                                FItem.qte_prescrite.alias('qty_prescription'),
                                FItem.qte_serv.alias('qty_served'),
                                FItem.reference.alias('reference'),
                                Product.pk.alias('reference_pk'),
                                Product.designation.alias('designation'),
                                Product.risque.alias('risky'),
                                Product.stup.alias('narcotic'),
                                FItem.readonly.alias('ifNeeded'))
                  .join(Patient, on=(FListe.num_ipp == Patient.ipp))
                  .switch(FListe)
                  .join(FItem, on=(FListe.liste == FItem.liste).alias('itemList'))
                  .switch(FListe)
                  .join(Product, on=(FItem.reference == Product.reference).alias('reference'))
                  .distinct()
                  .where((FListe.mode == 'S') & (Patient.pk == patient_pk) & (FListe.type_servi == 'EXOTIQUE')))

        if len(_items) == 0:
            logger.error('No list for id %s' % patient_pk)
            return {'data': []}, HTTP_200_OK

        output_list = []
        for item in _items.objects():

            date = next(filter(lambda i: i['list_pk'] == item.list_pk, output_list), None)

            if date is None:

                if item.ddeb is None:
                    date_elt = None
                else:
                    date_elt = datetime.utcfromtimestamp(datetime.timestamp(item.ddeb))

                date = {
                    'date': date_elt,
                    'list_pk': item.list_pk,
                    'name': item.list,
                    'moments': []
                }

                output_list.append(date)

            elt = next(filter(lambda i: item.hour == i['heure'], date['moments']), None)

            product = {
                'pk': item.pk,
                'reference': item.reference,
                'reference_pk': item.reference_pk,
                'designation': item.designation,
                'risky': item.risky,
                'narcotic': item.narcotic,
                'ifNeeded': item.ifNeeded,
                'moment': item.moment,
                'heure': item.hour,
                'etat': item.state,
                'fraction': item.fraction,
                'qte_demandee': item.qty_prescription * item.fraction / 100.0,
                'qte_servie': item.qty_served * item.fraction / 100,
            }

            if elt is not None:
                elt['list_item'].append(product)
            else:
                items = []
                items.append(product)
                date['moments'].append({
                    'heure': item.hour,
                    'moment': item.moment,
                    'list_item': items
                })

        return {'data': output_list}, HTTP_200_OK
    except Exception as error:
        logger.error(('Get reappro items Datatables raised an exception: ', error.args))
        return {'message': error.args}, HTTP_500_INTERNAL_SERVER_ERROR
