from outils.common_imports import *
from outils.for_view_imports import *
from outils.common import Verification

from shifts.models import CagetteShift
from members.models import CagetteMember
import shifts.fonctions

tz = pytz.timezone("Europe/Paris")


def _is_middled_filled_considered(reserved, max):
    """Added to fit with new LaCagette need. (based on num rather than %)."""
    answer = False
    toggle_num = 0
    try:
        toggle_num = int(getattr(settings, 'SHIFT_COLOR_TOGGLE_NUM', 0))
    except:
        coop_logger.warning("Wrong value for SHIFT_COLOR_TOGGLE_NUM : %s",
                            str(getattr(settings, 'SHIFT_COLOR_TOGGLE_NUM', 0))
                            )
    if toggle_num == 0:
        if int(reserved) / int(max) < 0.5:
            answer = True
    else:
        answer = int(reserved) <= toggle_num
    return answer


def get_list_shift_calendar(request, partner_id):
    cs = CagetteShift()
    [registerPartner, is_ftop] = shifts.fonctions.get_shift_partner(cs.o_api, partner_id)

    listRegisterPartner = []
    listMakeUpShift = []
    for v in registerPartner:
        listRegisterPartner.append(v['id'])
        if v['is_makeup']:
            listMakeUpShift.append(v['id'])

    start = request.GET.get('start')
    end = request.GET.get('end')
    listService = cs.get_shift_calendar(is_ftop, start, end)

    events = []
    for value in listService:
        if value['shift_type_id'][0] == 1 or getattr(settings, 'USE_STANDARD_SHIFT', True) is False:
            #  Standard ou volant si on n'utilise pas les services standards (config)
            l = set(value['registration_ids']) & set(listRegisterPartner)
            # if (int(value['seats_reserved']) == int(value['seats_max']) and len(l) > 0 ) or (int(value['seats_reserved']) < int(value['seats_max'])):
            if (int(value['seats_available']) > 0 or len(l) > 0 ):
                event = {}
                event["id"] = value['id']
                smax = int(value['seats_available']) + int(value['seats_reserved'])
 
                company_code = getattr(settings, 'COMPANY_CODE', '')
                title_prefix = ''
                if company_code != "lacagette" and len(value['address_id']) == 2 and ',' in value['address_id'][1]:
                    title_prefix = str(value['address_id'][1]).split(",")[1] + " --"
                elif company_code == "lacagette":
                    title_prefix = " - "

                event["title"] = title_prefix + str(value['seats_reserved']) + "/" + str(smax)


                event["start"] = shifts.fonctions.dateIsoUTC(value['date_begin_tz'])

                datetime_object = datetime.datetime.strptime(value['date_end_tz'], "%Y-%m-%d %H:%M:%S")
                event["end"] = shifts.fonctions.dateIsoUTC(datetime_object.strftime("%Y-%m-%d %H:%M:%S"))

                if len(l) > 0:
                    if set(value['registration_ids']) & set(listRegisterPartner) & set(listMakeUpShift):
                        event["classNames"] = ["shift_booked_makeup"]
                    else:
                        event["classNames"] = ["shift_booked"]
                    event["changed"] = False
                # elif int(value['seats_reserved']) == int(value['seats_max']):
                #     event["className"] = "shift_full"
                #     event["changed"] = False
                elif int(value['seats_reserved']) == 0:
                    event["classNames"] = ["shift_empty"]
                    event["changed"] = True
                elif _is_middled_filled_considered(value['seats_reserved'], smax) is True:
                    event["classNames"] = ["shift_less_alf"]
                    event["changed"] = True
                else:
                    event["classNames"] = ["shift_other"]
                    event["changed"] = True

                event["registration_ids"] = value['registration_ids']
                events.append(event)

    response = JsonResponse(events, safe=False)
    return response

def get_list_shift_partner(request, partner_id):
    cs = CagetteShift()
    [shiftData, is_ftop] = shifts.fonctions.get_shift_partner(cs.o_api, partner_id)

    for value in shiftData:
        value['date_begin'] = value['date_begin'] + "Z"
        value['date_end'] = value['date_end'] + "Z"

    return JsonResponse(shiftData, safe=False)

def change_shift(request):
    if 'verif_token' in request.POST:
        idPartner = int(request.POST.get('idPartner'))
        if Verification.verif_token(request.POST.get('verif_token'), idPartner) is True:
            cs = CagetteShift()
            if 'idNewShift' in request.POST and 'idOldShift' in request.POST:
                idNewShift = int(request.POST['idNewShift'])
                # Make sure the new shift is not inside an exempted leave period
                in_exempting_leave_msg = cs.check_new_shift_not_in_exempting_leave(idNewShift,idPartner)
                if in_exempting_leave_msg:
                    response = {'msg': in_exempting_leave_msg}
                    return JsonResponse(response, status=200)
                idOldShift = request.POST['idOldShift']
                listRegister = [int(request.POST['idRegister'])]
                data = {
                    "idPartner": idPartner,
                    "idShift": idNewShift,
                    "shift_type": request.POST['shift_type'],
                    "is_makeup": cs.shift_is_makeup(listRegister[0]),
                    "origin": "Espace membre : changement de service"
                }
                
                should_block_service_exchange = getattr(settings, 'BLOCK_SERVICE_EXCHANGE_24H_BEFORE', False)
                if should_block_service_exchange:
                    # Block change if old shift is to happen in less than 24 hours
                    now = datetime.datetime.now(tz)

                    old_shift = cs.get_shift(idOldShift)
                    day_before_old_shift_date_start = tz.localize(datetime.datetime.strptime(old_shift['date_begin_tz'], '%Y-%m-%d %H:%M:%S') - datetime.timedelta(hours=24))

                    if now > day_before_old_shift_date_start:
                        response = {'msg': "Old service in less than 24hours."}
                        return JsonResponse(response, status=400)

                st_r_id = False
                #Insertion du nouveau shift
                try:
                    st_r_id, res_decrement = cs.set_shift(data)
                except Exception as e:
                    coop_logger.error("Change shift : %s, %s", str(e), str(data))
                if st_r_id:
                    reg_ids = [int(request.POST['idRegister'])]

                    # Annule l'ancien shift
                    c_o = "Espace membre",
                    c_d = "Déplacement de shift"
                    if data['is_makeup']:
                        cs.unselect_makeup(reg_ids, cancellation_origin=c_o, cancellation_description=c_d)
                    else:
                        cs.cancel_shift(reg_ids, cancellation_origin=c_o, cancellation_description=c_d)

                    response = {'result': True}
                else:
                    response = {'msg': "Fail to create shift"}
                    return JsonResponse(response, status=500)
            else:
                response = {'msg': "Bad arguments"}
                return JsonResponse(response, status=400)
            return JsonResponse(response)
        else:
            return HttpResponseForbidden()
    else:
        return HttpResponseForbidden()

def affect_shift(request):
    if 'verif_token' in request.POST:
        if Verification.verif_token(request.POST.get('verif_token'), int(request.POST.get('idPartner'))) is True:
            cs = CagetteShift()
            if 'idShiftRegistration' in request.POST and 'affected_partner' in request.POST:
                #  if request is made by associated people, idPartner is it's id, not "master" res.partner
                #  it's will be handled in model's method (affect_shift)
                data = {
                    "idPartner": int(request.POST['idPartner']),
                    "idShiftRegistration": int(request.POST['idShiftRegistration']),
                    "affected_partner": request.POST['affected_partner'],
                }
                st_r_id = None
                try:
                    st_r_id = cs.affect_shift(data)
                except Exception as e:
                    coop_logger.error("affect shift : %s, %s", str(e), str(data))
                if st_r_id:
                    response = {'result': True}
                else:
                    response = {'msg': "Internal Error"}
                    return JsonResponse(response, status=500)
                return(JsonResponse({'result': True}))
            else:
                response = {'msg': "Bad args"}
                return JsonResponse(response, status=400)
        else:
            return HttpResponseForbidden()
    else:
        return HttpResponseForbidden()

def add_shift(request):
    if 'verif_token' in request.POST:
        if Verification.verif_token(request.POST.get('verif_token'), int(request.POST.get('idPartner'))) is True:
            cs = CagetteShift()

            if 'idNewShift' in request.POST and 'idPartner' in request.POST:
                partner_id = int(request.POST['idPartner'])
                id_shift = int(request.POST['idNewShift'])
                in_exempting_leave_msg = cs.check_new_shift_not_in_exempting_leave(id_shift,partner_id)
                if in_exempting_leave_msg:
                    response = {'result': False, 'msg': in_exempting_leave_msg}
                    return JsonResponse(response, status=200)
                data = {
                    "idPartner": partner_id, 
                    "idShift": id_shift, 
                    "shift_type": request.POST['shift_type'],
                    "is_makeup": False,
                    "origin": "Espace membre : ajout de service"
                }

                if 'is_makeup' in request.POST and request.POST['is_makeup'] == "1":
                    data['is_makeup'] = True
                    data['origin'] = "Espace membre : sélection de rattrapage"
                
                #Insertion du nouveau shift
                st_r_id = False
                try:
                    st_r_id, res_decrement = cs.set_shift(data)
                except Exception as e:
                    coop_logger.error("Add shift : %s, %s", str(e), str(data))

                if st_r_id:
                    response = {'result': True, 'decrement_makeups' : res_decrement}
                else:
                    response = {'result': False}
            else:
                response = {'result': False}
            return JsonResponse(response)
        else:
            return HttpResponseForbidden()
    else:
        return HttpResponseForbidden()

def cancel_shift_case_extra_shift_done(request):
    """ Annule une présence à un shift """
    if 'verif_token' in request.POST:
        partner_id = int(request.POST.get('idPartner'))
        if Verification.verif_token(request.POST.get('verif_token'), partner_id) is True:

            cs = CagetteShift()
            listRegister = [int(request.POST['idRegister'])]

            try:
                # decrement extra_shift_done if param exists
                if 'extra_shift_done' in request.POST:
                    cs.cancel_shift(
                        listRegister,
                        cancellation_origin='Espace membre',
                        cancellation_description='Suite service fait à deux',
                        #To print in counter event in the case when shift is a makeup
                        counter_event_name='Suppression d\'un rattrapage depuis l\'espace membre suite à un service fait à deux.'
                    )
                    target = int(request.POST["extra_shift_done"]) - 1

                    # extra security
                    if target < 0:
                        target = 0

                    cm = CagetteMember(partner_id)
                    cm.update_extra_shift_done(target)

                    return JsonResponse({"res": 'response'})

                return JsonResponse({"error" : "Cette méthode ne peut être appelée que pour annuler"
                                                   "un service suite à un service fait à deux"}, status=500)
            except Exception as e:
                return JsonResponse({"error" : str(e)}, status=500)
        else:
            return HttpResponseForbidden()
    else:
        return HttpResponseForbidden()

def reset_members_positive_points(request):
    """Called by a cron script"""
    return JsonResponse({'res': CagetteShift.reset_members_positive_points()})

def get_test(request):
    cs = CagetteShift()

    fields = ['shift_ticket_ids', 'shift_type_id']  # res.partner
    cond = []
    # cond = [['partner_id','=',1522],['start_date','<',datetime.datetime.now().isoformat()],['stop_date','>',datetime.datetime.now().isoformat()]]
    # registerPartner = cs.get_test('shift.shift',cond,fields)
    registerPartner =  cs.get_shift_calendar(1018)  # cs.get_data_partner(1538)

    response = JsonResponse(registerPartner, safe=False)
    return response
    #return  HttpResponse(shiftData)

def get_list(request):
    cs = CagetteShift()

    fields = ['cooperative_state']  # res.partner
    cond = []
    registerPartner = cs.get_test('res.partner', cond, fields)
    liste = []
    for val in registerPartner:
        if val[fields[0]] not in liste:
            liste.append(val[fields[0]])

    return JsonResponse(liste, safe=False)

def get_current_cycle_week(request):
    cs = CagetteShift()
    return JsonResponse(cs.get_current_cycle_week_data(), safe=False)
