import json

from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.http import (
    HttpResponse,
    HttpResponseBadRequest,
    HttpResponseNotFound,
    HttpResponseServerError,
    HttpResponseForbidden,
    JsonResponse,
)

from staff.gap.api.forms import GapCreateForm, GapEditForm
from staff.gap.controllers.gap import GapCtl
from staff.gap.controllers.utils import (
    full_day_dates,
    get_extended_localized_person,
    get_short_person_with_department,
)
from staff.lib.decorators import responding_json, available_for_external
from staff.gap.exceptions import GapError, MandatoryVacationError
from staff.gap.permissions import can_see_gap
from staff.gap.workflows import TRIP_WORKFLOWS, WORK_WORKFLOWS
from staff.gap.workflows.utils import find_workflow

import logging
logger = logging.getLogger('staff.gap.api.views.gap_change_views')


@csrf_exempt
@responding_json
@require_POST
@available_for_external('gap.robot_with_gap_api_access')
def gap_create(request):
    try:
        data = json.loads(request.body)
    except ValueError:
        return HttpResponseBadRequest()

    # костылище (c) another
    if data['workflow'] not in ['absence', 'learning', 'duty']:
        data['full_day'] = True

    form = GapCreateForm(data=data)

    if not form.is_valid():
        return form.errors

    data = form.cleaned_data

    try:
        workflow_cls = find_workflow(data['workflow'])
    except KeyError:
        return HttpResponseBadRequest()

    if data['workflow'] in TRIP_WORKFLOWS + WORK_WORKFLOWS:
        return HttpResponseBadRequest()

    try:
        person = get_extended_localized_person(data['person_login'])
    except GapError:
        return HttpResponseNotFound()

    modifier_id = request.user.get_profile().id

    if data['full_day']:
        full_day_dates(data, 1)

    workflow = workflow_cls.init_to_new(modifier_id, person['id'])

    try:
        if data.get('is_periodic_gap'):
            gap = workflow.new_periodic_gap(data)
        else:
            gap = workflow.new_gap(data)

        return {'id': gap['id']}
    except Exception:
        return HttpResponseServerError()


@csrf_exempt
@require_POST
@available_for_external('gap.robot_with_gap_api_access')
def gap_edit(request):
    observer = request.user
    observer_id = observer.get_profile().id

    try:
        data = json.loads(request.body)
    except ValueError:
        return HttpResponseBadRequest()

    form = GapEditForm(data=data)
    if not form.is_valid():
        return form.errors

    data = form.cleaned_data

    try:
        gap = GapCtl().find_gap_by_id(data['gap_id'])
    except GapError:
        return HttpResponseNotFound()

    workflow = gap['workflow']

    if workflow in TRIP_WORKFLOWS + WORK_WORKFLOWS:
        return HttpResponseForbidden()

    if workflow == 'illness' and gap['has_sicklist'] and data['has_sicklist'] is False:
        return HttpResponseBadRequest()

    person = get_short_person_with_department(gap['person_login'])

    if not can_see_gap(gap, observer, person):
        return HttpResponseForbidden()

    try:
        workflow_cls = find_workflow(workflow)
    except KeyError:
        return HttpResponseBadRequest()

    try:
        workflow_cls.init_to_modify(observer_id, gap=gap).edit_gap(data)
    except MandatoryVacationError as err:
        return JsonResponse(err.error_dict, status=400)
    except Exception:
        return HttpResponseServerError()

    return HttpResponse()
