import operator

from functools import reduce
import logging
from flask import send_file
import os
import uuid
from flask import Blueprint, request
from flask_jwt_extended import jwt_required
from median.models import Magasin, Stock, Product
from peewee import fn
import json

from ressources.astus.utils import generate_excel_file

from common.status import HTTP_200_OK

astus_nurse_stock_blueprint = Blueprint('astus_nurse_stock', __name__)
logger = logging.getLogger('median.webserver')


def get_all_stocks(v_search_list):
    andexpr = (Magasin.eco_type == 'A')

    if len(v_search_list) > 0:
        lst = list(map(lambda s: (
            (Product.designation.contains(s.strip())) |
            (Magasin.libelle.contains(s.strip())) |
            (Stock.reference.contains(s.strip())) |
            (Product.dci.contains(s.strip())) |
            (Magasin.mag.contains(s.strip()))
        ), v_search_list))
        search = reduce(operator.and_, lst)
        expr = reduce(operator.and_, [andexpr, search])
    else:
        expr = andexpr

    stocks = Stock.select(
        Stock.reference,
        Product.dci,
        Product.designation, Magasin.libelle, Magasin.mag,
        fn.SUM(Stock.quantite).alias('quantity')) \
        .join(Magasin, on=(Magasin.mag == Stock.magasin)) \
        .switch(Stock) \
        .join(Product, on=(Product.reference == Stock.reference)) \
        .where(expr) \
        .group_by(Stock.reference, Product.dci, Product.designation, Magasin.libelle, Magasin.mag)

    return stocks


def getObjStock(stk):
    obj = {
        'code': stk.magasin.mag,
        'magasin': stk.magasin.libelle,
        'dci': stk.product.dci,
        'reference': stk.reference,
        'quantity': stk.quantity,
        'designation': stk.product.designation
    }
    return obj


@astus_nurse_stock_blueprint.route('/export', methods=['PATCH'])
@jwt_required()
def export_stock():
    data = json.loads(request.data)

    v_search_list = data['search']
    headers = data['headers']

    name = os.sep.join(
        [os.getcwd(), "tmp_export", "%s.xlsx" % uuid.uuid4()])

    stocks = get_all_stocks(v_search_list=v_search_list)
    generate_excel_file(name, headers, stocks, getObjStock)

    return send_file(name, as_attachment=True)


@astus_nurse_stock_blueprint.route('/list', methods=['PATCH'])
@jwt_required()
def get_stock():
    data = json.loads(request.data)

    v_search_list = data['search']

    stocks = get_all_stocks(v_search_list=v_search_list)

    count = stocks.count()

    stocks = stocks.limit(int(data.get('length'))) \
        .offset(int(data.get('start'))) \
        .order_by(Product.designation)

    list_stock = []
    for stock in stocks:
        obj = getObjStock(stock)
        list_stock.append(obj)

    return {
        'total': count,
        'data': list_stock
    }, HTTP_200_OK
