import csv
import json
import logging
import math
import operator
from functools import reduce

from flask import Blueprint, request

from common.status import HTTP_200_OK, HTTP_400_BAD_REQUEST, HTTP_204_NO_CONTENT
from flask_jwt_extended import jwt_required
from median.models.log import DefDefaut

acced_setting_message_blueprint = Blueprint('acced_setting_message', __name__)

logger = logging.getLogger('median')


@acced_setting_message_blueprint.route('importdefault', methods=['POST'])
@jwt_required()
def import_default():
    file = request.files['file']
    type = request.form['type']
    in_memory_file = file.read()
    text = in_memory_file.decode("ANSI")
    spamreader = csv.reader(text.splitlines(), delimiter=';', quotechar='|')
    (DefDefaut
     .delete()
     .where(DefDefaut.type_machine == type)
     .execute())

    line = 0
    for row in spamreader:
        if (line != 0) & (len(row) >= 7):
            station = row[0].zfill(2)
            index = row[1].zfill(2)
            time_sec = int(row[13]) if len(row) > 13 and row[13] != '' and not math.isnan(float(row[13])) else 0
            obj = DefDefaut(
                num_defaut=station + index,
                niveau=row[6],
                defaut=row[4],
                duration=time_sec,
                type_machine=type)
            obj.save()

        line = line + 1

    return 'success'


@acced_setting_message_blueprint.route('count', methods=['POST'])
@jwt_required()
def getCount():
    data = json.loads(request.data)

    try:
        return {"count": request_setting_message(data).count()}, HTTP_200_OK

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


def request_setting_message(data):
    v_search_list = data['criterias']
    _typeMachines = data['type_machines']
    _default_lvl = data['default_lvl']

    expr = True
    if len(v_search_list) > 0:
        lst = list(map(lambda s: (
            (DefDefaut.num_defaut.contains(s.strip()))
        ), v_search_list))
        search = reduce(operator.and_, lst)
        expr = reduce(operator.and_, [search])

    if len(_typeMachines) > 0:
        expr = reduce(operator.and_, [expr, DefDefaut.type_machine << _typeMachines])

    if len(_default_lvl) > 0:
        expr = reduce(operator.and_, [expr, DefDefaut.defaut << _default_lvl])

    return DefDefaut.select() \
        .where(expr) \
        .order_by(DefDefaut.num_defaut)


@acced_setting_message_blueprint.route('', methods=['PUT'])
@jwt_required()
def update():
    data = json.loads(request.data)
    pk = data['pk']
    duration = data.get('duration', None)

    defect = DefDefaut.select().where(DefDefaut.pk == pk).get()
    defect.duration = int(duration) if duration is not None and not math.isnan(int(duration)) else None
    defect.save()

    return {}, HTTP_204_NO_CONTENT


@acced_setting_message_blueprint.route('', methods=['POST'])
@jwt_required()
def getAll():
    data = json.loads(request.data)

    try:
        v_start = data['pagination']['page']
        v_length = data['pagination']['rowsPerPage']

        req = request_setting_message(data) \
            .limit(v_length).offset(v_start * v_length)

        return {"list": [{
            "pk": msg.pk,
            "type_machine": msg.type_machine,
            "num_default": msg.num_defaut,
            "lvl": msg.niveau,
            "duration": msg.duration,
            "default": msg.defaut
        } for msg in req]}, HTTP_200_OK

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